From: Sage Weil Date: Fri, 23 Jan 2009 22:50:13 +0000 (-0800) Subject: kclient: do sync writepages if FILE_WRBUFFER is being revoked X-Git-Tag: v0.7~326 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=c4760afe685156680f7e904f3ef9f540883a2b41;p=ceph.git kclient: do sync writepages if FILE_WRBUFFER is being revoked This doesn't capture the case where we already started writeout and _then_ the MDS tries to revoke, but that's probably not worth the complexity. --- diff --git a/src/kernel/addr.c b/src/kernel/addr.c index eeb3cbf07d5d9..5eb529b72e931 100644 --- a/src/kernel/addr.c +++ b/src/kernel/addr.c @@ -545,6 +545,9 @@ static int ceph_writepages_start(struct address_space *mapping, struct ceph_osd_request *req = NULL; int do_sync = atomic_read(&ci->i_want_sync_writeout); + if (ceph_caps_revoking(ci) & CEPH_CAP_FILE_WRBUFFER) + do_sync = 1; + client = ceph_inode_to_client(inode); if (client->mount_state == CEPH_MOUNT_SHUTDOWN) { dout(1, "writepage on forced umount\n"); diff --git a/src/kernel/caps.c b/src/kernel/caps.c index da1ae54dcb912..e277b091aac4b 100644 --- a/src/kernel/caps.c +++ b/src/kernel/caps.c @@ -276,6 +276,38 @@ retry: return 0; } +/* + * Return true if cap has not timed out and belongs to the current + * generation of the MDS session. + */ +static int __cap_is_valid(struct ceph_cap *cap) +{ + unsigned long ttl; + u32 gen; + + spin_lock(&cap->session->s_cap_lock); + gen = cap->session->s_cap_gen; + ttl = cap->session->s_cap_ttl; + spin_unlock(&cap->session->s_cap_lock); + + if (cap->gen < gen || time_after_eq(jiffies, ttl)) { + dout(30, "__cap_is_valid %p cap %p issued %s " + "but STALE (gen %u vs %u)\n", &cap->ci->vfs_inode, + cap, ceph_cap_string(cap->issued), cap->gen, gen); + return 0; + } + + if (time_after_eq(jiffies, cap->expires) && + (cap->issued & ~CEPH_CAP_EXPIREABLE) == 0) { + dout(30, "__cap_is_valid %p cap %p issued %s " + "but readonly and expired\n", &cap->ci->vfs_inode, + cap, ceph_cap_string(cap->issued)); + return 0; + } + + return 1; +} + /* * Return set of valid cap bits issued to us. Note that caps time * out, and may be invalidated in bulk if the client session times out @@ -285,35 +317,14 @@ int __ceph_caps_issued(struct ceph_inode_info *ci, int *implemented) { int have = ci->i_snap_caps; struct ceph_cap *cap; - u32 gen; - unsigned long ttl; struct rb_node *p; if (implemented) *implemented = 0; for (p = rb_first(&ci->i_caps); p; p = rb_next(p)) { cap = rb_entry(p, struct ceph_cap, ci_node); - - spin_lock(&cap->session->s_cap_lock); - gen = cap->session->s_cap_gen; - ttl = cap->session->s_cap_ttl; - spin_unlock(&cap->session->s_cap_lock); - - if (cap->gen < gen || time_after_eq(jiffies, ttl)) { - dout(30, "__ceph_caps_issued %p cap %p issued %s " - "but STALE (gen %u vs %u)\n", &ci->vfs_inode, - cap, ceph_cap_string(cap->issued), cap->gen, gen); - continue; - } - - if (time_after_eq(jiffies, cap->expires) && - (cap->issued & ~CEPH_CAP_EXPIREABLE) == 0) { - dout(30, "__ceph_caps_issued %p cap %p issued %s " - "but readonly and expired\n", &ci->vfs_inode, - cap, ceph_cap_string(cap->issued)); + if (!__cap_is_valid(cap)) continue; - } - dout(30, "__ceph_caps_issued %p cap %p issued %s\n", &ci->vfs_inode, cap, ceph_cap_string(cap->issued)); have |= cap->issued; @@ -336,6 +347,8 @@ int __ceph_caps_dirty(struct ceph_inode_info *ci) for (p = rb_first(&ci->i_caps); p; p = rb_next(p)) { cap = rb_entry(p, struct ceph_cap, ci_node); + if (!__cap_is_valid(cap)) + continue; dout(30, "__ceph_caps_dirty %p cap %p flushing %s\n", inode, cap, ceph_cap_string(cap->flushing)); dirty |= cap->flushing; @@ -345,6 +358,28 @@ int __ceph_caps_dirty(struct ceph_inode_info *ci) return dirty; } +/* + * Return mask of caps currently being revoked by an MDS. + */ +int ceph_caps_revoking(struct ceph_inode_info *ci) +{ + struct inode *inode = &ci->vfs_inode; + struct ceph_cap *cap; + struct rb_node *p; + int revoking = 0; + + spin_lock(&inode->i_lock); + for (p = rb_first(&ci->i_caps); p; p = rb_next(p)) { + cap = rb_entry(p, struct ceph_cap, ci_node); + if (__cap_is_valid(cap)) + revoking |= cap->implemented & ~cap->issued; + } + spin_unlock(&inode->i_lock); + dout(30, "ceph_caps_revoking %p revoking %s\n", inode, + ceph_cap_string(revoking)); + return revoking; +} + /* * called under i_lock */ diff --git a/src/kernel/super.h b/src/kernel/super.h index b6087e99cc088..79946318c78a7 100644 --- a/src/kernel/super.h +++ b/src/kernel/super.h @@ -435,6 +435,7 @@ static inline int ceph_caps_issued(struct ceph_inode_info *ci) } extern int __ceph_caps_dirty(struct ceph_inode_info *ci); +extern int ceph_caps_revoking(struct ceph_inode_info *ci); static inline int __ceph_caps_used(struct ceph_inode_info *ci) {