mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git
synced 2025-01-16 21:35:07 +00:00
ceph: switch to use cap_delay_lock for the unlink delay list
The same list item will be used in both cap_delay_list and cap_unlink_delay_list, so it's buggy to use two different locks to protect them. Cc: stable@vger.kernel.org Fixes: dbc347ef7f0c ("ceph: add ceph_cap_unlink_work to fire check_caps() immediately") Link: https://lists.ceph.io/hyperkitty/list/ceph-users@ceph.io/thread/AODC76VXRAMXKLFDCTK4TKFDDPWUSCN5 Reported-by: Marc Ruhmann <ruhmann@luis.uni-hannover.de> Signed-off-by: Xiubo Li <xiubli@redhat.com> Reviewed-by: Ilya Dryomov <idryomov@gmail.com> Tested-by: Marc Ruhmann <ruhmann@luis.uni-hannover.de> Signed-off-by: Ilya Dryomov <idryomov@gmail.com>
This commit is contained in:
parent
b372e96bd0
commit
17f8dc2db5
@ -4783,13 +4783,13 @@ int ceph_drop_caps_for_unlink(struct inode *inode)
|
||||
|
||||
doutc(mdsc->fsc->client, "%p %llx.%llx\n", inode,
|
||||
ceph_vinop(inode));
|
||||
spin_lock(&mdsc->cap_unlink_delay_lock);
|
||||
spin_lock(&mdsc->cap_delay_lock);
|
||||
ci->i_ceph_flags |= CEPH_I_FLUSH;
|
||||
if (!list_empty(&ci->i_cap_delay_list))
|
||||
list_del_init(&ci->i_cap_delay_list);
|
||||
list_add_tail(&ci->i_cap_delay_list,
|
||||
&mdsc->cap_unlink_delay_list);
|
||||
spin_unlock(&mdsc->cap_unlink_delay_lock);
|
||||
spin_unlock(&mdsc->cap_delay_lock);
|
||||
|
||||
/*
|
||||
* Fire the work immediately, because the MDS maybe
|
||||
|
@ -2504,7 +2504,7 @@ static void ceph_cap_unlink_work(struct work_struct *work)
|
||||
struct ceph_client *cl = mdsc->fsc->client;
|
||||
|
||||
doutc(cl, "begin\n");
|
||||
spin_lock(&mdsc->cap_unlink_delay_lock);
|
||||
spin_lock(&mdsc->cap_delay_lock);
|
||||
while (!list_empty(&mdsc->cap_unlink_delay_list)) {
|
||||
struct ceph_inode_info *ci;
|
||||
struct inode *inode;
|
||||
@ -2516,15 +2516,15 @@ static void ceph_cap_unlink_work(struct work_struct *work)
|
||||
|
||||
inode = igrab(&ci->netfs.inode);
|
||||
if (inode) {
|
||||
spin_unlock(&mdsc->cap_unlink_delay_lock);
|
||||
spin_unlock(&mdsc->cap_delay_lock);
|
||||
doutc(cl, "on %p %llx.%llx\n", inode,
|
||||
ceph_vinop(inode));
|
||||
ceph_check_caps(ci, CHECK_CAPS_FLUSH);
|
||||
iput(inode);
|
||||
spin_lock(&mdsc->cap_unlink_delay_lock);
|
||||
spin_lock(&mdsc->cap_delay_lock);
|
||||
}
|
||||
}
|
||||
spin_unlock(&mdsc->cap_unlink_delay_lock);
|
||||
spin_unlock(&mdsc->cap_delay_lock);
|
||||
doutc(cl, "done\n");
|
||||
}
|
||||
|
||||
@ -5404,7 +5404,6 @@ int ceph_mdsc_init(struct ceph_fs_client *fsc)
|
||||
INIT_LIST_HEAD(&mdsc->cap_wait_list);
|
||||
spin_lock_init(&mdsc->cap_delay_lock);
|
||||
INIT_LIST_HEAD(&mdsc->cap_unlink_delay_list);
|
||||
spin_lock_init(&mdsc->cap_unlink_delay_lock);
|
||||
INIT_LIST_HEAD(&mdsc->snap_flush_list);
|
||||
spin_lock_init(&mdsc->snap_flush_lock);
|
||||
mdsc->last_cap_flush_tid = 1;
|
||||
|
@ -461,9 +461,8 @@ struct ceph_mds_client {
|
||||
struct delayed_work delayed_work; /* delayed work */
|
||||
unsigned long last_renew_caps; /* last time we renewed our caps */
|
||||
struct list_head cap_delay_list; /* caps with delayed release */
|
||||
spinlock_t cap_delay_lock; /* protects cap_delay_list */
|
||||
struct list_head cap_unlink_delay_list; /* caps with delayed release for unlink */
|
||||
spinlock_t cap_unlink_delay_lock; /* protects cap_unlink_delay_list */
|
||||
spinlock_t cap_delay_lock; /* protects cap_delay_list and cap_unlink_delay_list */
|
||||
struct list_head snap_flush_list; /* cap_snaps ready to flush */
|
||||
spinlock_t snap_flush_lock;
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user