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",
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);
ci);
}
spin_unlock(&inode->i_lock);
+ if (!new_dirty)
+ iput(inode);
if (removed_last)
iput(inode);
}
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",
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) {
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);
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);
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);
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;
}
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;
}
}
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)