From 3e69829ace4fb2fa22a95d083c8957ea6acb4541 Mon Sep 17 00:00:00 2001 From: Sage Weil Date: Mon, 30 Mar 2009 15:01:05 -0700 Subject: [PATCH] kclient: pin dirty caps --- src/TODO | 5 +++-- src/kernel/caps.c | 5 +++++ src/kernel/file.c | 11 +++++++++-- src/kernel/inode.c | 21 +++++++++++++++------ src/kernel/super.h | 6 ++++++ 5 files changed, 38 insertions(+), 10 deletions(-) diff --git a/src/TODO b/src/TODO index 3c9cf3aa71929..a60bf9934360c 100644 --- a/src/TODO +++ b/src/TODO @@ -44,8 +44,9 @@ v0.8 kclient caps /- two session lists: dirty_caps, clean_caps /- time out and release clean caps explicitly - -- pin dirty caps only +/- pin dirty caps +- don't pin clean caps +- release on destroy_inode alternative #1: - keep CAP_PIN on _all_ inodes, and don't pin inodes with caps. diff --git a/src/kernel/caps.c b/src/kernel/caps.c index f13561f4db277..77419c5522220 100644 --- a/src/kernel/caps.c +++ b/src/kernel/caps.c @@ -1446,6 +1446,7 @@ static void handle_cap_flush_ack(struct inode *inode, int dirty = le32_to_cpu(m->dirty); int cleaned = dirty & ~caps; int removed_last = 0; + int new_dirty = 0; dout(10, "handle_cap_flush_ack inode %p mds%d seq %d cleaned %s," " flushing %s -> %s\n", @@ -1454,6 +1455,8 @@ static void handle_cap_flush_ack(struct inode *inode, ceph_cap_string(cap->flushing & ~cleaned)); cap->flushing &= ~cleaned; + new_dirty = __ceph_caps_dirty(ci); + /* did we release this cap, too? */ if (caps == 0 && seq == cap->seq) { BUG_ON(cap->flushing); @@ -1463,6 +1466,8 @@ static void handle_cap_flush_ack(struct inode *inode, ci); } spin_unlock(&inode->i_lock); + if (!new_dirty) + iput(inode); if (removed_last) iput(inode); } diff --git a/src/kernel/file.c b/src/kernel/file.c index d8b89f91a3eb3..0db16d9f9acc0 100644 --- a/src/kernel/file.c +++ b/src/kernel/file.c @@ -737,8 +737,15 @@ retry_snap: ret = sync_page_range(inode, mapping, pos, ret); } } - if (ret >= 0) - ci->i_dirty_caps |= CEPH_CAP_FILE_WR; + if (ret >= 0) { + int was_dirty; + + spin_lock(&inode->i_lock); + was_dirty = __ceph_mark_dirty_caps(ci, CEPH_CAP_FILE_WR); + spin_unlock(&inode->i_lock); + if (!was_dirty) + igrab(inode); + } out: dout(10, "aio_write %p %llu~%u dropping cap refs on %s\n", diff --git a/src/kernel/inode.c b/src/kernel/inode.c index ebdb20bea50c5..91d43f5758753 100644 --- a/src/kernel/inode.c +++ b/src/kernel/inode.c @@ -1242,6 +1242,7 @@ static int ceph_setattr_chown(struct dentry *dentry, struct iattr *attr) struct ceph_mds_request *req; int err; int mask = 0; + int was_dirty; spin_lock(&inode->i_lock); if (__ceph_caps_issued(ci, NULL) & CEPH_CAP_AUTH_EXCL) { @@ -1251,8 +1252,10 @@ static int ceph_setattr_chown(struct dentry *dentry, struct iattr *attr) if (ia_valid & ATTR_GID) inode->i_gid = attr->ia_gid; inode->i_ctime = CURRENT_TIME; - ci->i_dirty_caps |= CEPH_CAP_AUTH_EXCL; + was_dirty = __ceph_mark_dirty_caps(ci, CEPH_CAP_AUTH_EXCL); spin_unlock(&inode->i_lock); + if (!was_dirty) + igrab(inode); return 0; } spin_unlock(&inode->i_lock); @@ -1285,15 +1288,17 @@ static int ceph_setattr_chmod(struct dentry *dentry, struct iattr *attr) struct ceph_client *client = ceph_sb_to_client(inode->i_sb); struct ceph_mds_client *mdsc = &client->mdsc; struct ceph_mds_request *req; - int err; + int err, was_dirty; spin_lock(&inode->i_lock); if (__ceph_caps_issued(ci, NULL) & CEPH_CAP_AUTH_EXCL) { dout(10, "chmod holding auth EXCL, doing locally\n"); inode->i_mode = attr->ia_mode; inode->i_ctime = CURRENT_TIME; - ci->i_dirty_caps |= CEPH_CAP_AUTH_EXCL; + was_dirty = __ceph_mark_dirty_caps(ci, CEPH_CAP_AUTH_EXCL); spin_unlock(&inode->i_lock); + if (!was_dirty) + igrab(inode); return 0; } spin_unlock(&inode->i_lock); @@ -1320,7 +1325,7 @@ static int ceph_setattr_time(struct dentry *dentry, struct iattr *attr) const unsigned int ia_valid = attr->ia_valid; struct ceph_mds_request *req; int err; - int issued; + int issued, was_dirty; spin_lock(&inode->i_lock); issued = __ceph_caps_issued(ci, NULL); @@ -1334,8 +1339,10 @@ static int ceph_setattr_time(struct dentry *dentry, struct iattr *attr) if (ia_valid & ATTR_MTIME) inode->i_mtime = attr->ia_mtime; inode->i_ctime = CURRENT_TIME; - ci->i_dirty_caps |= CEPH_CAP_FILE_EXCL; + was_dirty = __ceph_mark_dirty_caps(ci, CEPH_CAP_FILE_EXCL); spin_unlock(&inode->i_lock); + if (!was_dirty) + igrab(inode); return 0; } @@ -1351,8 +1358,10 @@ static int ceph_setattr_time(struct dentry *dentry, struct iattr *attr) if (ia_valid & ATTR_MTIME) inode->i_mtime = attr->ia_mtime; inode->i_ctime = CURRENT_TIME; - ci->i_dirty_caps |= CEPH_CAP_FILE_WR; + was_dirty = __ceph_mark_dirty_caps(ci, CEPH_CAP_FILE_WR); spin_unlock(&inode->i_lock); + if (!was_dirty) + igrab(inode); return 0; } diff --git a/src/kernel/super.h b/src/kernel/super.h index f9499306b3400..d7c293ec0d522 100644 --- a/src/kernel/super.h +++ b/src/kernel/super.h @@ -463,6 +463,12 @@ static inline int ceph_caps_issued_mask(struct ceph_inode_info *ci, int mask) } extern int __ceph_caps_dirty(struct ceph_inode_info *ci); +static inline int __ceph_mark_dirty_caps(struct ceph_inode_info *ci, int mask) +{ + int was = __ceph_caps_dirty(ci); + ci->i_dirty_caps |= mask; + return was; +} extern int ceph_caps_revoking(struct ceph_inode_info *ci, int mask); static inline int __ceph_caps_used(struct ceph_inode_info *ci) -- 2.39.5