ceph: refactor remove_session_caps_cb
Move remove_capsnaps to caps.c. Move the part of remove_session_caps_cb under i_ceph_lock into a separate function that lives in caps.c. Have remove_session_caps_cb call the new helper after taking the lock. Signed-off-by: Jeff Layton <jlayton@kernel.org> Signed-off-by: Ilya Dryomov <idryomov@gmail.com>
This commit is contained in:
parent
3c3050267e
commit
36e6da987e
116
fs/ceph/caps.c
116
fs/ceph/caps.c
@ -4561,3 +4561,119 @@ int ceph_encode_dentry_release(void **p, struct dentry *dentry,
|
||||
spin_unlock(&dentry->d_lock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int remove_capsnaps(struct ceph_mds_client *mdsc, struct inode *inode)
|
||||
{
|
||||
struct ceph_inode_info *ci = ceph_inode(inode);
|
||||
struct ceph_cap_snap *capsnap;
|
||||
int capsnap_release = 0;
|
||||
|
||||
lockdep_assert_held(&ci->i_ceph_lock);
|
||||
|
||||
dout("removing capsnaps, ci is %p, inode is %p\n", ci, inode);
|
||||
|
||||
while (!list_empty(&ci->i_cap_snaps)) {
|
||||
capsnap = list_first_entry(&ci->i_cap_snaps,
|
||||
struct ceph_cap_snap, ci_item);
|
||||
__ceph_remove_capsnap(inode, capsnap, NULL, NULL);
|
||||
ceph_put_snap_context(capsnap->context);
|
||||
ceph_put_cap_snap(capsnap);
|
||||
capsnap_release++;
|
||||
}
|
||||
wake_up_all(&ci->i_cap_wq);
|
||||
wake_up_all(&mdsc->cap_flushing_wq);
|
||||
return capsnap_release;
|
||||
}
|
||||
|
||||
int ceph_purge_inode_cap(struct inode *inode, struct ceph_cap *cap, bool *invalidate)
|
||||
{
|
||||
struct ceph_fs_client *fsc = ceph_inode_to_client(inode);
|
||||
struct ceph_mds_client *mdsc = fsc->mdsc;
|
||||
struct ceph_inode_info *ci = ceph_inode(inode);
|
||||
bool is_auth;
|
||||
bool dirty_dropped = false;
|
||||
int iputs = 0;
|
||||
|
||||
lockdep_assert_held(&ci->i_ceph_lock);
|
||||
|
||||
dout("removing cap %p, ci is %p, inode is %p\n",
|
||||
cap, ci, &ci->vfs_inode);
|
||||
|
||||
is_auth = (cap == ci->i_auth_cap);
|
||||
__ceph_remove_cap(cap, false);
|
||||
if (is_auth) {
|
||||
struct ceph_cap_flush *cf;
|
||||
|
||||
if (READ_ONCE(fsc->mount_state) >= CEPH_MOUNT_SHUTDOWN) {
|
||||
if (inode->i_data.nrpages > 0)
|
||||
*invalidate = true;
|
||||
if (ci->i_wrbuffer_ref > 0)
|
||||
mapping_set_error(&inode->i_data, -EIO);
|
||||
}
|
||||
|
||||
spin_lock(&mdsc->cap_dirty_lock);
|
||||
|
||||
/* trash all of the cap flushes for this inode */
|
||||
while (!list_empty(&ci->i_cap_flush_list)) {
|
||||
cf = list_first_entry(&ci->i_cap_flush_list,
|
||||
struct ceph_cap_flush, i_list);
|
||||
list_del_init(&cf->g_list);
|
||||
list_del_init(&cf->i_list);
|
||||
if (!cf->is_capsnap)
|
||||
ceph_free_cap_flush(cf);
|
||||
}
|
||||
|
||||
if (!list_empty(&ci->i_dirty_item)) {
|
||||
pr_warn_ratelimited(
|
||||
" dropping dirty %s state for %p %lld\n",
|
||||
ceph_cap_string(ci->i_dirty_caps),
|
||||
inode, ceph_ino(inode));
|
||||
ci->i_dirty_caps = 0;
|
||||
list_del_init(&ci->i_dirty_item);
|
||||
dirty_dropped = true;
|
||||
}
|
||||
if (!list_empty(&ci->i_flushing_item)) {
|
||||
pr_warn_ratelimited(
|
||||
" dropping dirty+flushing %s state for %p %lld\n",
|
||||
ceph_cap_string(ci->i_flushing_caps),
|
||||
inode, ceph_ino(inode));
|
||||
ci->i_flushing_caps = 0;
|
||||
list_del_init(&ci->i_flushing_item);
|
||||
mdsc->num_cap_flushing--;
|
||||
dirty_dropped = true;
|
||||
}
|
||||
spin_unlock(&mdsc->cap_dirty_lock);
|
||||
|
||||
if (dirty_dropped) {
|
||||
mapping_set_error(inode->i_mapping, -EIO);
|
||||
|
||||
if (ci->i_wrbuffer_ref_head == 0 &&
|
||||
ci->i_wr_ref == 0 &&
|
||||
ci->i_dirty_caps == 0 &&
|
||||
ci->i_flushing_caps == 0) {
|
||||
ceph_put_snap_context(ci->i_head_snapc);
|
||||
ci->i_head_snapc = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (atomic_read(&ci->i_filelock_ref) > 0) {
|
||||
/* make further file lock syscall return -EIO */
|
||||
ci->i_ceph_flags |= CEPH_I_ERROR_FILELOCK;
|
||||
pr_warn_ratelimited(" dropping file locks for %p %lld\n",
|
||||
inode, ceph_ino(inode));
|
||||
}
|
||||
|
||||
if (!ci->i_dirty_caps && ci->i_prealloc_cap_flush) {
|
||||
cf = ci->i_prealloc_cap_flush;
|
||||
ci->i_prealloc_cap_flush = NULL;
|
||||
if (!cf->is_capsnap)
|
||||
ceph_free_cap_flush(cf);
|
||||
}
|
||||
|
||||
if (!list_empty(&ci->i_cap_snaps))
|
||||
iputs = remove_capsnaps(mdsc, inode);
|
||||
}
|
||||
if (dirty_dropped)
|
||||
++iputs;
|
||||
return iputs;
|
||||
}
|
||||
|
@ -1590,125 +1590,23 @@ out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int remove_capsnaps(struct ceph_mds_client *mdsc, struct inode *inode)
|
||||
{
|
||||
struct ceph_inode_info *ci = ceph_inode(inode);
|
||||
struct ceph_cap_snap *capsnap;
|
||||
int capsnap_release = 0;
|
||||
|
||||
lockdep_assert_held(&ci->i_ceph_lock);
|
||||
|
||||
dout("removing capsnaps, ci is %p, inode is %p\n", ci, inode);
|
||||
|
||||
while (!list_empty(&ci->i_cap_snaps)) {
|
||||
capsnap = list_first_entry(&ci->i_cap_snaps,
|
||||
struct ceph_cap_snap, ci_item);
|
||||
__ceph_remove_capsnap(inode, capsnap, NULL, NULL);
|
||||
ceph_put_snap_context(capsnap->context);
|
||||
ceph_put_cap_snap(capsnap);
|
||||
capsnap_release++;
|
||||
}
|
||||
wake_up_all(&ci->i_cap_wq);
|
||||
wake_up_all(&mdsc->cap_flushing_wq);
|
||||
return capsnap_release;
|
||||
}
|
||||
|
||||
static int remove_session_caps_cb(struct inode *inode, struct ceph_cap *cap,
|
||||
void *arg)
|
||||
{
|
||||
struct ceph_fs_client *fsc = (struct ceph_fs_client *)arg;
|
||||
struct ceph_mds_client *mdsc = fsc->mdsc;
|
||||
struct ceph_inode_info *ci = ceph_inode(inode);
|
||||
bool is_auth;
|
||||
bool dirty_dropped = false;
|
||||
bool invalidate = false;
|
||||
int capsnap_release = 0;
|
||||
int iputs;
|
||||
|
||||
dout("removing cap %p, ci is %p, inode is %p\n",
|
||||
cap, ci, &ci->vfs_inode);
|
||||
spin_lock(&ci->i_ceph_lock);
|
||||
is_auth = (cap == ci->i_auth_cap);
|
||||
__ceph_remove_cap(cap, false);
|
||||
if (is_auth) {
|
||||
struct ceph_cap_flush *cf;
|
||||
|
||||
if (READ_ONCE(fsc->mount_state) >= CEPH_MOUNT_SHUTDOWN) {
|
||||
if (inode->i_data.nrpages > 0)
|
||||
invalidate = true;
|
||||
if (ci->i_wrbuffer_ref > 0)
|
||||
mapping_set_error(&inode->i_data, -EIO);
|
||||
}
|
||||
|
||||
spin_lock(&mdsc->cap_dirty_lock);
|
||||
|
||||
/* trash all of the cap flushes for this inode */
|
||||
while (!list_empty(&ci->i_cap_flush_list)) {
|
||||
cf = list_first_entry(&ci->i_cap_flush_list,
|
||||
struct ceph_cap_flush, i_list);
|
||||
list_del_init(&cf->g_list);
|
||||
list_del_init(&cf->i_list);
|
||||
if (!cf->is_capsnap)
|
||||
ceph_free_cap_flush(cf);
|
||||
}
|
||||
|
||||
if (!list_empty(&ci->i_dirty_item)) {
|
||||
pr_warn_ratelimited(
|
||||
" dropping dirty %s state for %p %lld\n",
|
||||
ceph_cap_string(ci->i_dirty_caps),
|
||||
inode, ceph_ino(inode));
|
||||
ci->i_dirty_caps = 0;
|
||||
list_del_init(&ci->i_dirty_item);
|
||||
dirty_dropped = true;
|
||||
}
|
||||
if (!list_empty(&ci->i_flushing_item)) {
|
||||
pr_warn_ratelimited(
|
||||
" dropping dirty+flushing %s state for %p %lld\n",
|
||||
ceph_cap_string(ci->i_flushing_caps),
|
||||
inode, ceph_ino(inode));
|
||||
ci->i_flushing_caps = 0;
|
||||
list_del_init(&ci->i_flushing_item);
|
||||
mdsc->num_cap_flushing--;
|
||||
dirty_dropped = true;
|
||||
}
|
||||
spin_unlock(&mdsc->cap_dirty_lock);
|
||||
|
||||
if (dirty_dropped) {
|
||||
mapping_set_error(inode->i_mapping, -EIO);
|
||||
|
||||
if (ci->i_wrbuffer_ref_head == 0 &&
|
||||
ci->i_wr_ref == 0 &&
|
||||
ci->i_dirty_caps == 0 &&
|
||||
ci->i_flushing_caps == 0) {
|
||||
ceph_put_snap_context(ci->i_head_snapc);
|
||||
ci->i_head_snapc = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (atomic_read(&ci->i_filelock_ref) > 0) {
|
||||
/* make further file lock syscall return -EIO */
|
||||
ci->i_ceph_flags |= CEPH_I_ERROR_FILELOCK;
|
||||
pr_warn_ratelimited(" dropping file locks for %p %lld\n",
|
||||
inode, ceph_ino(inode));
|
||||
}
|
||||
|
||||
if (!ci->i_dirty_caps && ci->i_prealloc_cap_flush) {
|
||||
cf = ci->i_prealloc_cap_flush;
|
||||
ci->i_prealloc_cap_flush = NULL;
|
||||
if (!cf->is_capsnap)
|
||||
ceph_free_cap_flush(cf);
|
||||
}
|
||||
|
||||
if (!list_empty(&ci->i_cap_snaps))
|
||||
capsnap_release = remove_capsnaps(mdsc, inode);
|
||||
}
|
||||
iputs = ceph_purge_inode_cap(inode, cap, &invalidate);
|
||||
spin_unlock(&ci->i_ceph_lock);
|
||||
|
||||
wake_up_all(&ci->i_cap_wq);
|
||||
if (invalidate)
|
||||
ceph_queue_invalidate(inode);
|
||||
if (dirty_dropped)
|
||||
iput(inode);
|
||||
while (capsnap_release--)
|
||||
while (iputs--)
|
||||
iput(inode);
|
||||
return 0;
|
||||
}
|
||||
|
@ -1199,6 +1199,7 @@ extern int ceph_mmap(struct file *file, struct vm_area_struct *vma);
|
||||
extern int ceph_uninline_data(struct file *filp, struct page *locked_page);
|
||||
extern int ceph_pool_perm_check(struct inode *inode, int need);
|
||||
extern void ceph_pool_perm_destroy(struct ceph_mds_client* mdsc);
|
||||
int ceph_purge_inode_cap(struct inode *inode, struct ceph_cap *cap, bool *invalidate);
|
||||
|
||||
/* file.c */
|
||||
extern const struct file_operations ceph_file_fops;
|
||||
|
Loading…
Reference in New Issue
Block a user