Commit bd355f8a authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/sage/ceph-client

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/sage/ceph-client:
  ceph: do not call __mark_dirty_inode under i_lock
  libceph: fix ceph_osdc_alloc_request error checks
  ceph: handle ceph_osdc_new_request failure in ceph_writepages_start
  libceph: fix ceph_msg_new error path
  ceph: use ihold() when i_lock is held
parents 1c08232c fca65b4a
...@@ -777,9 +777,9 @@ static int rbd_do_request(struct request *rq, ...@@ -777,9 +777,9 @@ static int rbd_do_request(struct request *rq,
ops, ops,
false, false,
GFP_NOIO, pages, bio); GFP_NOIO, pages, bio);
if (IS_ERR(req)) { if (!req) {
up_read(&header->snap_rwsem); up_read(&header->snap_rwsem);
ret = PTR_ERR(req); ret = -ENOMEM;
goto done_pages; goto done_pages;
} }
......
...@@ -775,6 +775,13 @@ static int ceph_writepages_start(struct address_space *mapping, ...@@ -775,6 +775,13 @@ static int ceph_writepages_start(struct address_space *mapping,
ci->i_truncate_seq, ci->i_truncate_seq,
ci->i_truncate_size, ci->i_truncate_size,
&inode->i_mtime, true, 1, 0); &inode->i_mtime, true, 1, 0);
if (!req) {
rc = -ENOMEM;
unlock_page(page);
break;
}
max_pages = req->r_num_pages; max_pages = req->r_num_pages;
alloc_page_vec(fsc, req); alloc_page_vec(fsc, req);
......
...@@ -1331,10 +1331,11 @@ static void ceph_flush_snaps(struct ceph_inode_info *ci) ...@@ -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 * Mark caps dirty. If inode is newly dirty, return the dirty flags.
* list. * 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 = struct ceph_mds_client *mdsc =
ceph_sb_to_client(ci->vfs_inode.i_sb)->mdsc; ceph_sb_to_client(ci->vfs_inode.i_sb)->mdsc;
...@@ -1357,7 +1358,7 @@ void __ceph_mark_dirty_caps(struct ceph_inode_info *ci, int mask) ...@@ -1357,7 +1358,7 @@ void __ceph_mark_dirty_caps(struct ceph_inode_info *ci, int mask)
list_add(&ci->i_dirty_item, &mdsc->cap_dirty); list_add(&ci->i_dirty_item, &mdsc->cap_dirty);
spin_unlock(&mdsc->cap_dirty_lock); spin_unlock(&mdsc->cap_dirty_lock);
if (ci->i_flushing_caps == 0) { if (ci->i_flushing_caps == 0) {
igrab(inode); ihold(inode);
dirty |= I_DIRTY_SYNC; dirty |= I_DIRTY_SYNC;
} }
} }
...@@ -1365,9 +1366,8 @@ void __ceph_mark_dirty_caps(struct ceph_inode_info *ci, int mask) ...@@ -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) && if (((was | ci->i_flushing_caps) & CEPH_CAP_FILE_BUFFER) &&
(mask & CEPH_CAP_FILE_BUFFER)) (mask & CEPH_CAP_FILE_BUFFER))
dirty |= I_DIRTY_DATASYNC; dirty |= I_DIRTY_DATASYNC;
if (dirty)
__mark_inode_dirty(inode, dirty);
__cap_delay_requeue(mdsc, ci); __cap_delay_requeue(mdsc, ci);
return dirty;
} }
/* /*
...@@ -1991,7 +1991,7 @@ static void __take_cap_refs(struct ceph_inode_info *ci, int got) ...@@ -1991,7 +1991,7 @@ static void __take_cap_refs(struct ceph_inode_info *ci, int got)
ci->i_wr_ref++; ci->i_wr_ref++;
if (got & CEPH_CAP_FILE_BUFFER) { if (got & CEPH_CAP_FILE_BUFFER) {
if (ci->i_wrbuffer_ref == 0) if (ci->i_wrbuffer_ref == 0)
igrab(&ci->vfs_inode); ihold(&ci->vfs_inode);
ci->i_wrbuffer_ref++; ci->i_wrbuffer_ref++;
dout("__take_cap_refs %p wrbuffer %d -> %d (?)\n", dout("__take_cap_refs %p wrbuffer %d -> %d (?)\n",
&ci->vfs_inode, ci->i_wrbuffer_ref-1, ci->i_wrbuffer_ref); &ci->vfs_inode, ci->i_wrbuffer_ref-1, ci->i_wrbuffer_ref);
......
...@@ -734,9 +734,12 @@ static ssize_t ceph_aio_write(struct kiocb *iocb, const struct iovec *iov, ...@@ -734,9 +734,12 @@ static ssize_t ceph_aio_write(struct kiocb *iocb, const struct iovec *iov,
} }
} }
if (ret >= 0) { if (ret >= 0) {
int dirty;
spin_lock(&inode->i_lock); 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); spin_unlock(&inode->i_lock);
if (dirty)
__mark_inode_dirty(inode, dirty);
} }
out: out:
......
...@@ -1567,6 +1567,7 @@ int ceph_setattr(struct dentry *dentry, struct iattr *attr) ...@@ -1567,6 +1567,7 @@ int ceph_setattr(struct dentry *dentry, struct iattr *attr)
int release = 0, dirtied = 0; int release = 0, dirtied = 0;
int mask = 0; int mask = 0;
int err = 0; int err = 0;
int inode_dirty_flags = 0;
if (ceph_snap(inode) != CEPH_NOSNAP) if (ceph_snap(inode) != CEPH_NOSNAP)
return -EROFS; return -EROFS;
...@@ -1725,13 +1726,16 @@ int ceph_setattr(struct dentry *dentry, struct iattr *attr) ...@@ -1725,13 +1726,16 @@ int ceph_setattr(struct dentry *dentry, struct iattr *attr)
dout("setattr %p ATTR_FILE ... hrm!\n", inode); dout("setattr %p ATTR_FILE ... hrm!\n", inode);
if (dirtied) { if (dirtied) {
__ceph_mark_dirty_caps(ci, dirtied); inode_dirty_flags = __ceph_mark_dirty_caps(ci, dirtied);
inode->i_ctime = CURRENT_TIME; inode->i_ctime = CURRENT_TIME;
} }
release &= issued; release &= issued;
spin_unlock(&inode->i_lock); spin_unlock(&inode->i_lock);
if (inode_dirty_flags)
__mark_inode_dirty(inode, inode_dirty_flags);
if (mask) { if (mask) {
req->r_inode = igrab(inode); req->r_inode = igrab(inode);
req->r_inode_drop = release; req->r_inode_drop = release;
......
...@@ -506,7 +506,7 @@ static inline int __ceph_caps_dirty(struct ceph_inode_info *ci) ...@@ -506,7 +506,7 @@ static inline int __ceph_caps_dirty(struct ceph_inode_info *ci)
{ {
return ci->i_dirty_caps | ci->i_flushing_caps; 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_revoking(struct ceph_inode_info *ci, int mask);
extern int __ceph_caps_used(struct ceph_inode_info *ci); extern int __ceph_caps_used(struct ceph_inode_info *ci);
......
...@@ -703,6 +703,7 @@ int ceph_setxattr(struct dentry *dentry, const char *name, ...@@ -703,6 +703,7 @@ int ceph_setxattr(struct dentry *dentry, const char *name,
struct ceph_inode_xattr *xattr = NULL; struct ceph_inode_xattr *xattr = NULL;
int issued; int issued;
int required_blob_size; int required_blob_size;
int dirty;
if (ceph_snap(inode) != CEPH_NOSNAP) if (ceph_snap(inode) != CEPH_NOSNAP)
return -EROFS; return -EROFS;
...@@ -763,11 +764,12 @@ int ceph_setxattr(struct dentry *dentry, const char *name, ...@@ -763,11 +764,12 @@ int ceph_setxattr(struct dentry *dentry, const char *name,
dout("setxattr %p issued %s\n", inode, ceph_cap_string(issued)); dout("setxattr %p issued %s\n", inode, ceph_cap_string(issued));
err = __set_xattr(ci, newname, name_len, newval, err = __set_xattr(ci, newname, name_len, newval,
val_len, 1, 1, 1, &xattr); 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; ci->i_xattrs.dirty = true;
inode->i_ctime = CURRENT_TIME; inode->i_ctime = CURRENT_TIME;
spin_unlock(&inode->i_lock); spin_unlock(&inode->i_lock);
if (dirty)
__mark_inode_dirty(inode, dirty);
return err; return err;
do_sync: do_sync:
...@@ -810,6 +812,7 @@ int ceph_removexattr(struct dentry *dentry, const char *name) ...@@ -810,6 +812,7 @@ int ceph_removexattr(struct dentry *dentry, const char *name)
struct ceph_vxattr_cb *vxattrs = ceph_inode_vxattrs(inode); struct ceph_vxattr_cb *vxattrs = ceph_inode_vxattrs(inode);
int issued; int issued;
int err; int err;
int dirty;
if (ceph_snap(inode) != CEPH_NOSNAP) if (ceph_snap(inode) != CEPH_NOSNAP)
return -EROFS; return -EROFS;
...@@ -833,12 +836,13 @@ int ceph_removexattr(struct dentry *dentry, const char *name) ...@@ -833,12 +836,13 @@ int ceph_removexattr(struct dentry *dentry, const char *name)
goto do_sync; goto do_sync;
err = __remove_xattr_by_name(ceph_inode(inode), name); 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; ci->i_xattrs.dirty = true;
inode->i_ctime = CURRENT_TIME; inode->i_ctime = CURRENT_TIME;
spin_unlock(&inode->i_lock); spin_unlock(&inode->i_lock);
if (dirty)
__mark_inode_dirty(inode, dirty);
return err; return err;
do_sync: do_sync:
spin_unlock(&inode->i_lock); spin_unlock(&inode->i_lock);
......
...@@ -2267,6 +2267,19 @@ struct ceph_msg *ceph_msg_new(int type, int front_len, gfp_t flags) ...@@ -2267,6 +2267,19 @@ struct ceph_msg *ceph_msg_new(int type, int front_len, gfp_t flags)
m->more_to_follow = false; m->more_to_follow = false;
m->pool = NULL; m->pool = NULL;
/* middle */
m->middle = NULL;
/* data */
m->nr_pages = 0;
m->page_alignment = 0;
m->pages = NULL;
m->pagelist = NULL;
m->bio = NULL;
m->bio_iter = NULL;
m->bio_seg = 0;
m->trail = NULL;
/* front */ /* front */
if (front_len) { if (front_len) {
if (front_len > PAGE_CACHE_SIZE) { if (front_len > PAGE_CACHE_SIZE) {
...@@ -2286,19 +2299,6 @@ struct ceph_msg *ceph_msg_new(int type, int front_len, gfp_t flags) ...@@ -2286,19 +2299,6 @@ struct ceph_msg *ceph_msg_new(int type, int front_len, gfp_t flags)
} }
m->front.iov_len = front_len; m->front.iov_len = front_len;
/* middle */
m->middle = NULL;
/* data */
m->nr_pages = 0;
m->page_alignment = 0;
m->pages = NULL;
m->pagelist = NULL;
m->bio = NULL;
m->bio_iter = NULL;
m->bio_seg = 0;
m->trail = NULL;
dout("ceph_msg_new %p front %d\n", m, front_len); dout("ceph_msg_new %p front %d\n", m, front_len);
return m; return m;
......
...@@ -470,8 +470,8 @@ struct ceph_osd_request *ceph_osdc_new_request(struct ceph_osd_client *osdc, ...@@ -470,8 +470,8 @@ struct ceph_osd_request *ceph_osdc_new_request(struct ceph_osd_client *osdc,
snapc, ops, snapc, ops,
use_mempool, use_mempool,
GFP_NOFS, NULL, NULL); GFP_NOFS, NULL, NULL);
if (IS_ERR(req)) if (!req)
return req; return NULL;
/* calculate max write size */ /* calculate max write size */
calc_layout(osdc, vino, layout, off, plen, req, ops); calc_layout(osdc, vino, layout, off, plen, req, ops);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment