From 362846f5c7a0921a319b17bfdc2b08bd51b60af9 Mon Sep 17 00:00:00 2001 From: Sage Weil Date: Wed, 9 Apr 2008 18:30:10 -0700 Subject: [PATCH] kclient: request max_size explicitly went necessary --- src/kernel/file.c | 15 +++++++++++++++ src/kernel/inode.c | 41 +++++++++++++++++++---------------------- src/kernel/super.c | 4 ++++ src/kernel/super.h | 4 +++- 4 files changed, 41 insertions(+), 23 deletions(-) diff --git a/src/kernel/file.c b/src/kernel/file.c index 359a572beea4c..6dc760313d15b 100644 --- a/src/kernel/file.c +++ b/src/kernel/file.c @@ -265,6 +265,21 @@ ssize_t ceph_write(struct file *filp, const char __user *buf, struct ceph_inode_info *ci = ceph_inode(inode); ssize_t ret; int got = 0; + int check = 0; + + /* do we need to explicitly request a larger max_size? */ + spin_lock(&inode->i_lock); + if (*ppos > ci->i_max_size && + *ppos > (inode->i_size << 1) && + *ppos > ci->i_wanted_max_size) { + dout(10, "write %p at large offset %llu, requesting max_size\n", + inode, *ppos); + ci->i_wanted_max_size = *ppos; + check = 1; + } + spin_unlock(&inode->i_lock); + if (check) + ceph_check_caps(ci); dout(10, "write trying to get caps. i_size %llu\n", inode->i_size); ret = wait_event_interruptible(ci->i_cap_wq, diff --git a/src/kernel/inode.c b/src/kernel/inode.c index a1eb98fa95941..90ee5385683d8 100644 --- a/src/kernel/inode.c +++ b/src/kernel/inode.c @@ -765,7 +765,7 @@ void ceph_remove_cap(struct ceph_inode_cap *cap) * examine currently used, wanted versus held caps. * release, ack revoked caps to mds as appropriate. */ -void ceph_check_caps(struct ceph_inode_info *ci, gfp_t gfpmask) +void ceph_check_caps(struct ceph_inode_info *ci) { struct ceph_client *client = ceph_inode_to_client(&ci->vfs_inode); struct ceph_mds_client *mdsc = &client->mdsc; @@ -787,6 +787,10 @@ retry: int revoking, dropping; cap = list_entry(p, struct ceph_inode_cap, ci_caps); + if (ci->i_wanted_max_size > ci->i_max_size && + ci->i_wanted_max_size > ci->i_requested_max_size) + goto ack; + /* completed revocation? */ revoking = cap->implemented & ~cap->issued; dout(20, "cap %p issued %d impl %d revoking %d used %d\n", @@ -811,20 +815,14 @@ retry: continue; /* nothing extra, all good */ ack: - if (gfpmask != GFP_KERNEL) { - /* put on examine list */ - dout(10, "** dropping caps, but bad gfpmask, " - "IMPLEMENT ME *************\n"); - goto out; - } - dropping = cap->issued & ~wanted; cap->issued &= wanted; /* drop bits we don't want */ keep = cap->issued; seq = cap->seq; size = ci->vfs_inode.i_size; - max_size = ci->i_max_size; + max_size = ci->i_wanted_max_size; + ci->i_requested_max_size = max_size; mtime = ci->vfs_inode.i_mtime; atime = ci->vfs_inode.i_atime; mds = cap->mds; @@ -834,7 +832,7 @@ retry: ceph_mdsc_send_cap_ack(mdsc, ceph_ino(&ci->vfs_inode), keep, wanted, seq, - size, 0, &mtime, &atime, mds); + size, max_size, &mtime, &atime, mds); if (dropping & CEPH_CAP_RDCACHE) { dout(20, "invalidating pages on %p\n", &ci->vfs_inode); @@ -846,7 +844,6 @@ retry: } /* okay */ -out: spin_unlock(&ci->vfs_inode.i_lock); } @@ -863,7 +860,7 @@ void ceph_inode_set_size(struct inode *inode, loff_t size) if ((size << 1) >= ci->i_max_size && (ci->i_reported_size << 1) < ci->i_max_size) { spin_unlock(&inode->i_lock); - ceph_check_caps(ci, GFP_KERNEL); + ceph_check_caps(ci); } else spin_unlock(&inode->i_lock); } @@ -889,7 +886,7 @@ void ceph_put_mode(struct ceph_inode_info *ci, int mode) spin_unlock(&ci->vfs_inode.i_lock); if (last) - ceph_check_caps(ci, GFP_KERNEL); + ceph_check_caps(ci); } @@ -946,6 +943,10 @@ int ceph_handle_cap_grant(struct inode *inode, struct ceph_mds_file_caps *grant, if (max_size != ci->i_max_size) { dout(10, "max_size %lld -> %llu\n", ci->i_max_size, max_size); ci->i_max_size = max_size; + if (max_size >= ci->i_wanted_max_size) { + ci->i_wanted_max_size = 0; /* reset */ + ci->i_requested_max_size = 0; + } wake = 1; } @@ -1091,17 +1092,13 @@ int ceph_get_cap_refs(struct ceph_inode_info *ci, int need, int want, int *got, { int ret = 0; int have; + dout(10, "get_cap_refs on %p need %d want %d\n", &ci->vfs_inode, need, want); spin_lock(&ci->vfs_inode.i_lock); if (offset >= 0 && offset >= (loff_t)ci->i_max_size) { - if (offset > (ci->vfs_inode.i_size << 1)) { - dout(20, "get_cap_refs offset %llu >= max_size %llu\n", - offset, ci->i_max_size); - - } else - dout(20, "get_cap_refs offset %llu >= max_size %llu\n", - offset, ci->i_max_size); + dout(20, "get_cap_refs offset %llu >= max_size %llu\n", + offset, ci->i_max_size); goto sorry; } have = __ceph_caps_issued(ci); @@ -1141,7 +1138,7 @@ void ceph_put_cap_refs(struct ceph_inode_info *ci, int had) last ? "last":""); if (last) - ceph_check_caps(ci, GFP_KERNEL); + ceph_check_caps(ci); } void ceph_put_wrbuffer_cap_refs(struct ceph_inode_info *ci, int nr) @@ -1159,7 +1156,7 @@ void ceph_put_wrbuffer_cap_refs(struct ceph_inode_info *ci, int nr) last ? "last":""); if (last) - ceph_check_caps(ci, GFP_KERNEL); + ceph_check_caps(ci); } diff --git a/src/kernel/super.c b/src/kernel/super.c index 0a874f3010864..d692c8d53ceb4 100644 --- a/src/kernel/super.c +++ b/src/kernel/super.c @@ -144,6 +144,9 @@ static struct inode *ceph_alloc_inode(struct super_block *sb) ci->i_nr_by_mode[i] = 0; init_waitqueue_head(&ci->i_cap_wq); + ci->i_wanted_max_size = 0; + ci->i_requested_max_size = 0; + ci->i_rd_ref = ci->i_rdcache_ref = 0; ci->i_wr_ref = ci->i_wrbuffer_ref = 0; @@ -413,6 +416,7 @@ static int ceph_set_super(struct super_block *s, void *data) dout(10, "set_super %p data %p\n", s, data); s->s_flags = args->mntflags; + s->s_maxbytes = 1ULL << (32 + 20); /* assuming objects >= 1MB */ /* create client */ client = ceph_create_client(args, s); diff --git a/src/kernel/super.h b/src/kernel/super.h index 622cae935b86f..939aaf9dc32df 100644 --- a/src/kernel/super.h +++ b/src/kernel/super.h @@ -158,6 +158,8 @@ struct ceph_inode_info { int i_nr_by_mode[4]; loff_t i_max_size; /* size authorized by mds */ loff_t i_reported_size; /* (max_)size reported to or requested of mds */ + loff_t i_wanted_max_size; /* offset we'd like to write too */ + loff_t i_requested_max_size; /* max_size we've requested */ struct timespec i_old_atime; /* held references to caps */ @@ -376,7 +378,7 @@ extern int ceph_get_cap_refs(struct ceph_inode_info *ci, int need, int want, int extern void ceph_take_cap_refs(struct ceph_inode_info *ci, int got); extern void ceph_put_cap_refs(struct ceph_inode_info *ci, int had); extern void ceph_put_wrbuffer_cap_refs(struct ceph_inode_info *ci, int nr); -extern void ceph_check_caps(struct ceph_inode_info *ci, gfp_t gfpmask); +extern void ceph_check_caps(struct ceph_inode_info *ci); extern void ceph_get_mode(struct ceph_inode_info *ci, int mode); extern void ceph_put_mode(struct ceph_inode_info *ci, int mode); extern void ceph_inode_set_size(struct inode *inode, loff_t size); -- 2.39.5