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
This commit is contained in:
commit
bd355f8ae6
9 changed files with 49 additions and 31 deletions
|
@ -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,
|
||||||
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)
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* 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)
|
||||||
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)
|
||||||
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)
|
||||||
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,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
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)
|
||||||
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)
|
||||||
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)
|
||||||
{
|
{
|
||||||
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,
|
||||||
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,
|
||||||
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)
|
||||||
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)
|
||||||
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)
|
||||||
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)
|
||||||
}
|
}
|
||||||
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,
|
||||||
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);
|
||||||
|
|
Loading…
Reference in a new issue