From 3772d26d87efc2d91b2e4247e0001c89ed09a980 Mon Sep 17 00:00:00 2001 From: Sage Weil Date: Tue, 3 May 2011 09:28:08 -0700 Subject: ceph: use ihold() when i_lock is held See 0444d76ae64fffc7851797fc1b6ebdbb44ac504a. Signed-off-by: Sage Weil --- fs/ceph/caps.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'fs') diff --git a/fs/ceph/caps.c b/fs/ceph/caps.c index 5323c330bbf3..010ba9c52e9b 100644 --- a/fs/ceph/caps.c +++ b/fs/ceph/caps.c @@ -1357,7 +1357,7 @@ void __ceph_mark_dirty_caps(struct ceph_inode_info *ci, int mask) list_add(&ci->i_dirty_item, &mdsc->cap_dirty); spin_unlock(&mdsc->cap_dirty_lock); if (ci->i_flushing_caps == 0) { - igrab(inode); + ihold(inode); dirty |= I_DIRTY_SYNC; } } @@ -1991,7 +1991,7 @@ static void __take_cap_refs(struct ceph_inode_info *ci, int got) ci->i_wr_ref++; if (got & CEPH_CAP_FILE_BUFFER) { if (ci->i_wrbuffer_ref == 0) - igrab(&ci->vfs_inode); + ihold(&ci->vfs_inode); ci->i_wrbuffer_ref++; dout("__take_cap_refs %p wrbuffer %d -> %d (?)\n", &ci->vfs_inode, ci->i_wrbuffer_ref-1, ci->i_wrbuffer_ref); -- cgit v1.2.3 From 8c71897be2ddfd84969412635ca42fa9e137f7b6 Mon Sep 17 00:00:00 2001 From: Henry C Chang Date: Tue, 3 May 2011 09:45:16 +0000 Subject: ceph: handle ceph_osdc_new_request failure in ceph_writepages_start We should unlock the page and return -ENOMEM if ceph_osdc_new_request failed. Signed-off-by: Henry C Chang Signed-off-by: Sage Weil --- fs/ceph/addr.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'fs') diff --git a/fs/ceph/addr.c b/fs/ceph/addr.c index e159c529fd2b..38b8ab554924 100644 --- a/fs/ceph/addr.c +++ b/fs/ceph/addr.c @@ -775,6 +775,13 @@ get_more_pages: ci->i_truncate_seq, ci->i_truncate_size, &inode->i_mtime, true, 1, 0); + + if (!req) { + rc = -ENOMEM; + unlock_page(page); + break; + } + max_pages = req->r_num_pages; alloc_page_vec(fsc, req); -- cgit v1.2.3 From fca65b4ad72d28cbb43a029114d04b89f06faadb Mon Sep 17 00:00:00 2001 From: Sage Weil Date: Wed, 4 May 2011 11:33:47 -0700 Subject: ceph: do not call __mark_dirty_inode under i_lock The __mark_dirty_inode helper now takes i_lock as of 250df6ed. Fix the one ceph callers that held i_lock (__ceph_mark_dirty_caps) to return the flags value so that the callers can do it outside of i_lock. Signed-off-by: Sage Weil --- fs/ceph/caps.c | 10 +++++----- fs/ceph/file.c | 5 ++++- fs/ceph/inode.c | 6 +++++- fs/ceph/super.h | 2 +- fs/ceph/xattr.c | 12 ++++++++---- 5 files changed, 23 insertions(+), 12 deletions(-) (limited to 'fs') diff --git a/fs/ceph/caps.c b/fs/ceph/caps.c index 010ba9c52e9b..9fa08662a88d 100644 --- a/fs/ceph/caps.c +++ b/fs/ceph/caps.c @@ -1331,10 +1331,11 @@ static void ceph_flush_snaps(struct ceph_inode_info *ci) } /* - * Mark caps dirty. If inode is newly dirty, add to the global dirty - * list. + * Mark caps dirty. If inode is newly dirty, return the dirty flags. + * Caller is then responsible for calling __mark_inode_dirty with the + * returned flags value. */ -void __ceph_mark_dirty_caps(struct ceph_inode_info *ci, int mask) +int __ceph_mark_dirty_caps(struct ceph_inode_info *ci, int mask) { struct ceph_mds_client *mdsc = ceph_sb_to_client(ci->vfs_inode.i_sb)->mdsc; @@ -1365,9 +1366,8 @@ void __ceph_mark_dirty_caps(struct ceph_inode_info *ci, int mask) if (((was | ci->i_flushing_caps) & CEPH_CAP_FILE_BUFFER) && (mask & CEPH_CAP_FILE_BUFFER)) dirty |= I_DIRTY_DATASYNC; - if (dirty) - __mark_inode_dirty(inode, dirty); __cap_delay_requeue(mdsc, ci); + return dirty; } /* diff --git a/fs/ceph/file.c b/fs/ceph/file.c index 159b512d5a27..203252d88d9f 100644 --- a/fs/ceph/file.c +++ b/fs/ceph/file.c @@ -734,9 +734,12 @@ retry_snap: } } if (ret >= 0) { + int dirty; spin_lock(&inode->i_lock); - __ceph_mark_dirty_caps(ci, CEPH_CAP_FILE_WR); + dirty = __ceph_mark_dirty_caps(ci, CEPH_CAP_FILE_WR); spin_unlock(&inode->i_lock); + if (dirty) + __mark_inode_dirty(inode, dirty); } out: diff --git a/fs/ceph/inode.c b/fs/ceph/inode.c index b54c97da1c43..03d6dafda61f 100644 --- a/fs/ceph/inode.c +++ b/fs/ceph/inode.c @@ -1567,6 +1567,7 @@ int ceph_setattr(struct dentry *dentry, struct iattr *attr) int release = 0, dirtied = 0; int mask = 0; int err = 0; + int inode_dirty_flags = 0; if (ceph_snap(inode) != CEPH_NOSNAP) return -EROFS; @@ -1725,13 +1726,16 @@ int ceph_setattr(struct dentry *dentry, struct iattr *attr) dout("setattr %p ATTR_FILE ... hrm!\n", inode); if (dirtied) { - __ceph_mark_dirty_caps(ci, dirtied); + inode_dirty_flags = __ceph_mark_dirty_caps(ci, dirtied); inode->i_ctime = CURRENT_TIME; } release &= issued; spin_unlock(&inode->i_lock); + if (inode_dirty_flags) + __mark_inode_dirty(inode, inode_dirty_flags); + if (mask) { req->r_inode = igrab(inode); req->r_inode_drop = release; diff --git a/fs/ceph/super.h b/fs/ceph/super.h index 619fe719968f..b1f1b8bb1271 100644 --- a/fs/ceph/super.h +++ b/fs/ceph/super.h @@ -506,7 +506,7 @@ static inline int __ceph_caps_dirty(struct ceph_inode_info *ci) { return ci->i_dirty_caps | ci->i_flushing_caps; } -extern void __ceph_mark_dirty_caps(struct ceph_inode_info *ci, int mask); +extern int __ceph_mark_dirty_caps(struct ceph_inode_info *ci, int mask); extern int ceph_caps_revoking(struct ceph_inode_info *ci, int mask); extern int __ceph_caps_used(struct ceph_inode_info *ci); diff --git a/fs/ceph/xattr.c b/fs/ceph/xattr.c index 8c9eba6ef9df..f2b628696180 100644 --- a/fs/ceph/xattr.c +++ b/fs/ceph/xattr.c @@ -703,6 +703,7 @@ int ceph_setxattr(struct dentry *dentry, const char *name, struct ceph_inode_xattr *xattr = NULL; int issued; int required_blob_size; + int dirty; if (ceph_snap(inode) != CEPH_NOSNAP) return -EROFS; @@ -763,11 +764,12 @@ retry: dout("setxattr %p issued %s\n", inode, ceph_cap_string(issued)); err = __set_xattr(ci, newname, name_len, newval, val_len, 1, 1, 1, &xattr); - __ceph_mark_dirty_caps(ci, CEPH_CAP_XATTR_EXCL); + dirty = __ceph_mark_dirty_caps(ci, CEPH_CAP_XATTR_EXCL); ci->i_xattrs.dirty = true; inode->i_ctime = CURRENT_TIME; spin_unlock(&inode->i_lock); - + if (dirty) + __mark_inode_dirty(inode, dirty); return err; do_sync: @@ -810,6 +812,7 @@ int ceph_removexattr(struct dentry *dentry, const char *name) struct ceph_vxattr_cb *vxattrs = ceph_inode_vxattrs(inode); int issued; int err; + int dirty; if (ceph_snap(inode) != CEPH_NOSNAP) return -EROFS; @@ -833,12 +836,13 @@ int ceph_removexattr(struct dentry *dentry, const char *name) goto do_sync; err = __remove_xattr_by_name(ceph_inode(inode), name); - __ceph_mark_dirty_caps(ci, CEPH_CAP_XATTR_EXCL); + dirty = __ceph_mark_dirty_caps(ci, CEPH_CAP_XATTR_EXCL); ci->i_xattrs.dirty = true; inode->i_ctime = CURRENT_TIME; spin_unlock(&inode->i_lock); - + if (dirty) + __mark_inode_dirty(inode, dirty); return err; do_sync: spin_unlock(&inode->i_lock); -- cgit v1.2.3