ceph: locking fixes for snaprealm handling
Subsystems (2)
cover ceph: locking fixes for snaprealm handling
The snaprealm handling code has a number of really old and misleading comments that claim that we need certain locks when holding certain functions. Some of them are wrong, and at least one caller is not holding the snap_rwsem when filling an inode.
The first patch in this series adds some lockdep annotations that mirror the comments. The second one relaxes the lockdep annotations for a couple of the functions to better conform with the real requirements of the code. The last patch then fixes a bug in async create code and ensures that we're holding the correct locks when filling a new inode.
Jeff Layton (3):
ceph: add some lockdep assertions around snaprealm handling
ceph: clean up locking annotation for ceph_get_snap_realm and
__lookup_snap_realm
ceph: must hold snap_rwsem when filling inode for async create
fs/ceph/file.c | 3 +++ fs/ceph/inode.c | 2 ++ fs/ceph/snap.c | 20 ++++++++++++++++++-- 3 files changed, 23 insertions(+), 2 deletions(-)
Signature · 1 line
2.31.1
PATCH 1/3 ceph: add some lockdep assertions around snaprealm handling
Turn some comments into lockdep asserts.
--- fs/ceph/snap.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+)
fs/ceph/snap.c +16 -0
@@ -65,6 +65,8 @@void ceph_get_snap_realm (struct ceph_mds_client *mdsc,struct ceph_snap_realm *realm) { +lockdep_assert_held_write (&mdsc->snap_rwsem); +dout ("get_realm %p %d -> %d\n" , realm,atomic_read (&realm->nref),atomic_read (&realm->nref)+1 );/*
@@ -113,6 +115,8 @@ static struct ceph_snap_realm *ceph_create_snap_realm( {struct ceph_snap_realm *realm; +lockdep_assert_held_write (&mdsc->snap_rwsem); + realm =kzalloc (sizeof (*realm),GFP_NOFS );if (!realm)return ERR_PTR (-ENOMEM );
@@ -143,6 +147,8 @@ static struct ceph_snap_realm *__lookup_snap_realm(struct ceph_mds_client *mdsc,struct rb_node *n = mdsc->snap_realms.rb_node;struct ceph_snap_realm *r; +lockdep_assert_held_write (&mdsc->snap_rwsem); +while (n) { r = rb_entry(n, struct ceph_snap_realm, node);if (ino < r->ino)
@@ -176,6 +182,8 @@ static void __put_snap_realm(struct ceph_mds_client *mdsc,static void __destroy_snap_realm (struct ceph_mds_client *mdsc,struct ceph_snap_realm *realm) { +lockdep_assert_held_write (&mdsc->snap_rwsem); +dout ("__destroy_snap_realm %p %llx\n" , realm, realm->ino);rb_erase (&realm->node, &mdsc->snap_realms);
@@ -198,6 +206,8 @@ static void __destroy_snap_realm(struct ceph_mds_client *mdsc,static void __put_snap_realm (struct ceph_mds_client *mdsc,struct ceph_snap_realm *realm) { +lockdep_assert_held_write (&mdsc->snap_rwsem); +dout ("__put_snap_realm %llx %p %d -> %d\n" , realm->ino, realm,atomic_read (&realm->nref),atomic_read (&realm->nref)-1 );if (atomic_dec_and_test (&realm->nref))
@@ -236,6 +246,8 @@ static void __cleanup_empty_realms(struct ceph_mds_client *mdsc) {struct ceph_snap_realm *realm; +lockdep_assert_held_write (&mdsc->snap_rwsem); +spin_lock (&mdsc->snap_empty_lock);while (!list_empty (&mdsc->snap_empty)) { realm = list_first_entry(&mdsc->snap_empty,
@@ -269,6 +281,8 @@ static int adjust_snap_realm_parent(struct ceph_mds_client *mdsc, {struct ceph_snap_realm *parent; +lockdep_assert_held_write (&mdsc->snap_rwsem); +if (realm->parent_ino == parentino)return 0 ;
@@ -696,6 +710,8 @@ int ceph_update_snap_trace(struct ceph_mds_client *mdsc,int err = -ENOMEM ;LIST_HEAD (dirty_realms); +lockdep_assert_held_write (&mdsc->snap_rwsem); +dout ("update_snap_trace deletion=%d\n" , deletion); more:ceph_decode_need (&p, e,sizeof (*ri), bad);
Signature · 1 line
2.31.1
Ilya Dryomov
maintainerRe: [PATCH 1/3] ceph: add some lockdep assertions around snaprealm handling
Quoted 49 lines · Jeff Layton
Turn some comments into lockdep asserts.
Signed-off-by Jeff Layton <[email protected]>--- fs/ceph/snap.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+)fs/ceph/snap.c +8
-0@@ -65,6 +65,8 @@void ceph_get_snap_realm (struct ceph_mds_client *mdsc,struct ceph_snap_realm *realm) { +lockdep_assert_held_write (&mdsc->snap_rwsem); +dout ("get_realm %p %d -> %d\n" , realm,atomic_read (&realm->nref),atomic_read (&realm->nref)+1 );/* @@ -113,6 +115,8 @@ static struct ceph_snap_realm *ceph_create_snap_realm( {struct ceph_snap_realm *realm; +lockdep_assert_held_write (&mdsc->snap_rwsem); + realm =kzalloc (sizeof (*realm),GFP_NOFS );if (!realm)return ERR_PTR (-ENOMEM );@@ -143,6 +147,8 @@ static struct ceph_snap_realm *__lookup_snap_realm(struct ceph_mds_client *mdsc,struct rb_node *n = mdsc->snap_realms.rb_node;struct ceph_snap_realm *r; +lockdep_assert_held_write (&mdsc->snap_rwsem); +while (n) { r = rb_entry(n, struct ceph_snap_realm, node);if (ino < r->ino)@@ -176,6 +182,8 @@ static void __put_snap_realm(struct ceph_mds_client *mdsc,static void __destroy_snap_realm (struct ceph_mds_client *mdsc,struct ceph_snap_realm *realm) { +lockdep_assert_held_write (&mdsc->snap_rwsem); +dout ("__destroy_snap_realm %p %llx\n" , realm, realm->ino);rb_erase (&realm->node, &mdsc->snap_realms);
fs/ceph/snap.c static void __destroy_snap_realm(struct ceph_mds_client *mdsc, · line 209
Quoted 4 lines
fs/ceph/snap.c +1
-0@@ -198,6 +206,8 @@ static void __destroy_snap_realm(struct ceph_mds_client *mdsc,static void __put_snap_realm (struct ceph_mds_client *mdsc,struct ceph_snap_realm *realm) { +lockdep_assert_held_write (&mdsc->snap_rwsem);
This one appears to be redundant since the only caller is __destroy_snap_realm().
fs/ceph/snap.c static void __cleanup_empty_realms(struct ceph_mds_client *mdsc) · line 249
Quoted 9 lines
fs/ceph/snap.c +2
-0+dout ("__put_snap_realm %llx %p %d -> %d\n" , realm->ino, realm,atomic_read (&realm->nref),atomic_read (&realm->nref)-1 );if (atomic_dec_and_test (&realm->nref))@@ -236,6 +246,8 @@ static void __cleanup_empty_realms(struct ceph_mds_client *mdsc) {struct ceph_snap_realm *realm; +lockdep_assert_held_write (&mdsc->snap_rwsem);
This too since it boils down to calling __destroy_snap_realm().
fs/ceph/snap.c static int adjust_snap_realm_parent(struct ceph_mds_client *mdsc, · line 284
Quoted 9 lines
fs/ceph/snap.c +2
-0+spin_lock (&mdsc->snap_empty_lock);while (!list_empty (&mdsc->snap_empty)) { realm = list_first_entry(&mdsc->snap_empty,@@ -269,6 +281,8 @@ static int adjust_snap_realm_parent(struct ceph_mds_client *mdsc, {struct ceph_snap_realm *parent; +lockdep_assert_held_write (&mdsc->snap_rwsem);
And this since ceph_lookup_snap_realm() is called right away.
fs/ceph/snap.c int ceph_update_snap_trace(struct ceph_mds_client *mdsc, · line 713
Quoted 9 lines
fs/ceph/snap.c +2
-0+if (realm->parent_ino == parentino)return 0 ;@@ -696,6 +710,8 @@ int ceph_update_snap_trace(struct ceph_mds_client *mdsc,int err = -ENOMEM ;LIST_HEAD (dirty_realms); +lockdep_assert_held_write (&mdsc->snap_rwsem);
Ditto.
Thanks,
Ilya
Re: [PATCH 1/3] ceph: add some lockdep assertions around snaprealm handling
Quoted 90 lines · Ilya Dryomov
Quoted 49 lines · Jeff Layton
Turn some comments into lockdep asserts.
Signed-off-by Jeff Layton <[email protected]>--- fs/ceph/snap.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+)fs/ceph/snap.c +8
-0@@ -65,6 +65,8 @@void ceph_get_snap_realm (struct ceph_mds_client *mdsc,struct ceph_snap_realm *realm) { +lockdep_assert_held_write (&mdsc->snap_rwsem); +dout ("get_realm %p %d -> %d\n" , realm,atomic_read (&realm->nref),atomic_read (&realm->nref)+1 );/* @@ -113,6 +115,8 @@ static struct ceph_snap_realm *ceph_create_snap_realm( {struct ceph_snap_realm *realm; +lockdep_assert_held_write (&mdsc->snap_rwsem); + realm =kzalloc (sizeof (*realm),GFP_NOFS );if (!realm)return ERR_PTR (-ENOMEM );@@ -143,6 +147,8 @@ static struct ceph_snap_realm *__lookup_snap_realm(struct ceph_mds_client *mdsc,struct rb_node *n = mdsc->snap_realms.rb_node;struct ceph_snap_realm *r; +lockdep_assert_held_write (&mdsc->snap_rwsem); +while (n) { r = rb_entry(n, struct ceph_snap_realm, node);if (ino < r->ino)@@ -176,6 +182,8 @@ static void __put_snap_realm(struct ceph_mds_client *mdsc,static void __destroy_snap_realm (struct ceph_mds_client *mdsc,struct ceph_snap_realm *realm) { +lockdep_assert_held_write (&mdsc->snap_rwsem); +dout ("__destroy_snap_realm %p %llx\n" , realm, realm->ino);rb_erase (&realm->node, &mdsc->snap_realms);fs/ceph/snap.c static void __destroy_snap_realm(struct ceph_mds_client *mdsc, · line 209
Quoted 4 lines
fs/ceph/snap.c +1
-0@@ -198,6 +206,8 @@ static void __destroy_snap_realm(struct ceph_mds_client *mdsc,static void __put_snap_realm (struct ceph_mds_client *mdsc,struct ceph_snap_realm *realm) { +lockdep_assert_held_write (&mdsc->snap_rwsem);This one appears to be redundant since the only caller is
__destroy_snap_realm().fs/ceph/snap.c static void __cleanup_empty_realms(struct ceph_mds_client *mdsc) · line 249
Quoted 9 lines
fs/ceph/snap.c +2
-0+dout ("__put_snap_realm %llx %p %d -> %d\n" , realm->ino, realm,atomic_read (&realm->nref),atomic_read (&realm->nref)-1 );if (atomic_dec_and_test (&realm->nref))@@ -236,6 +246,8 @@ static void __cleanup_empty_realms(struct ceph_mds_client *mdsc) {struct ceph_snap_realm *realm; +lockdep_assert_held_write (&mdsc->snap_rwsem);This too since it boils down to calling
__destroy_snap_realm().fs/ceph/snap.c static int adjust_snap_realm_parent(struct ceph_mds_client *mdsc, · line 284
Quoted 9 lines
fs/ceph/snap.c +2
-0+spin_lock (&mdsc->snap_empty_lock);while (!list_empty (&mdsc->snap_empty)) { realm = list_first_entry(&mdsc->snap_empty,@@ -269,6 +281,8 @@ static int adjust_snap_realm_parent(struct ceph_mds_client *mdsc, {struct ceph_snap_realm *parent; +lockdep_assert_held_write (&mdsc->snap_rwsem);And this since
ceph_lookup_snap_realm()is called right away.Quoted 8 lines
fs/ceph/snap.c +1
-0+if (realm->parent_ino == parentino)return 0 ;@@ -696,6 +710,8 @@ int ceph_update_snap_trace(struct ceph_mds_client *mdsc,int err = -ENOMEM ;LIST_HEAD (dirty_realms);
Quoted 7 lines
fs/ceph/snap.c int ceph_update_snap_trace(struct ceph_mds_client *mdsc, · line 713
Quoted 1 line
fs/ceph/snap.c +1
-0+lockdep_assert_held_write (&mdsc->snap_rwsem);Ditto.
Thanks,
Ilya
Some of these calls may be redundant, but I'd still like to keep them.
The locking in this code is a mess, and this is the most reliable way I've found to approach cleaning it up. These all compile out unless you're running with lockdep enabled anyway.
Signature · 1 line
Jeff Layton <[email protected]>
Re: [PATCH 1/3] ceph: add some lockdep assertions around snaprealm handling
Quoted 98 lines · Jeff Layton
Quoted 96 lines · Ilya Dryomov
Quoted 49 lines · Jeff Layton
Turn some comments into lockdep asserts.
Signed-off-by Jeff Layton <[email protected]>--- fs/ceph/snap.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+)fs/ceph/snap.c +8
-0@@ -65,6 +65,8 @@void ceph_get_snap_realm (struct ceph_mds_client *mdsc,struct ceph_snap_realm *realm) { +lockdep_assert_held_write (&mdsc->snap_rwsem); +dout ("get_realm %p %d -> %d\n" , realm,atomic_read (&realm->nref),atomic_read (&realm->nref)+1 );/* @@ -113,6 +115,8 @@ static struct ceph_snap_realm *ceph_create_snap_realm( {struct ceph_snap_realm *realm; +lockdep_assert_held_write (&mdsc->snap_rwsem); + realm =kzalloc (sizeof (*realm),GFP_NOFS );if (!realm)return ERR_PTR (-ENOMEM );@@ -143,6 +147,8 @@ static struct ceph_snap_realm *__lookup_snap_realm(struct ceph_mds_client *mdsc,struct rb_node *n = mdsc->snap_realms.rb_node;struct ceph_snap_realm *r; +lockdep_assert_held_write (&mdsc->snap_rwsem); +while (n) { r = rb_entry(n, struct ceph_snap_realm, node);if (ino < r->ino)@@ -176,6 +182,8 @@ static void __put_snap_realm(struct ceph_mds_client *mdsc,static void __destroy_snap_realm (struct ceph_mds_client *mdsc,struct ceph_snap_realm *realm) { +lockdep_assert_held_write (&mdsc->snap_rwsem); +dout ("__destroy_snap_realm %p %llx\n" , realm, realm->ino);rb_erase (&realm->node, &mdsc->snap_realms);fs/ceph/snap.c static void __destroy_snap_realm(struct ceph_mds_client *mdsc, · line 209
Quoted 4 lines
fs/ceph/snap.c +1
-0@@ -198,6 +206,8 @@ static void __destroy_snap_realm(struct ceph_mds_client *mdsc,static void __put_snap_realm (struct ceph_mds_client *mdsc,struct ceph_snap_realm *realm) { +lockdep_assert_held_write (&mdsc->snap_rwsem);This one appears to be redundant since the only caller is
__destroy_snap_realm().fs/ceph/snap.c static void __cleanup_empty_realms(struct ceph_mds_client *mdsc) · line 249
Quoted 9 lines
fs/ceph/snap.c +2
-0+dout ("__put_snap_realm %llx %p %d -> %d\n" , realm->ino, realm,atomic_read (&realm->nref),atomic_read (&realm->nref)-1 );if (atomic_dec_and_test (&realm->nref))@@ -236,6 +246,8 @@ static void __cleanup_empty_realms(struct ceph_mds_client *mdsc) {struct ceph_snap_realm *realm; +lockdep_assert_held_write (&mdsc->snap_rwsem);This too since it boils down to calling
__destroy_snap_realm().fs/ceph/snap.c static int adjust_snap_realm_parent(struct ceph_mds_client *mdsc, · line 284
Quoted 9 lines
fs/ceph/snap.c +2
-0+spin_lock (&mdsc->snap_empty_lock);while (!list_empty (&mdsc->snap_empty)) { realm = list_first_entry(&mdsc->snap_empty,@@ -269,6 +281,8 @@ static int adjust_snap_realm_parent(struct ceph_mds_client *mdsc, {struct ceph_snap_realm *parent; +lockdep_assert_held_write (&mdsc->snap_rwsem);And this since
ceph_lookup_snap_realm()is called right away.fs/ceph/snap.c int ceph_update_snap_trace(struct ceph_mds_client *mdsc, · line 713
Quoted 9 lines
fs/ceph/snap.c +2
-0+if (realm->parent_ino == parentino)return 0 ;@@ -696,6 +710,8 @@ int ceph_update_snap_trace(struct ceph_mds_client *mdsc,int err = -ENOMEM ;LIST_HEAD (dirty_realms); +lockdep_assert_held_write (&mdsc->snap_rwsem);Ditto.
Thanks,
Quoted 7 lines
Quoted 1 line
Ilya
Some of these calls may be redundant, but I'd still like to keep them.
The locking in this code is a mess, and this is the most reliable way I've found to approach cleaning it up. These all compile out unless you're running with lockdep enabled anyway.
Thanks,
Ilya
PATCH 2/3 ceph: clean up locking annotation for ceph_get_snap_realm and __lookup_snap_realm
In reply to Jeff LaytonThey both say that the snap_rwsem must be held for write, but I don't see any real reason for it, and it's not currently always called that way.
The lookup is just walking the rbtree, so holding it for read should be fine there. The "get" is bumping the refcount and (possibly) removing it from the empty list. I see no need to hold the snap_rwsem for write for that.
--- fs/ceph/snap.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-)
fs/ceph/snap.c +4 -4
@@ -60,12 +60,12 @@/* * increase ref count for the realm * -* caller must hold snap_rwsem for write. +* caller must hold snap_rwsem. */ void ceph_get_snap_realm (struct ceph_mds_client *mdsc,struct ceph_snap_realm *realm) { -lockdep_assert_held_write (&mdsc->snap_rwsem); +lockdep_assert_held (&mdsc->snap_rwsem);dout ("get_realm %p %d -> %d\n" , realm,atomic_read (&realm->nref),atomic_read (&realm->nref)+1 );
@@ -139,7 +139,7 @@ static struct ceph_snap_realm *ceph_create_snap_realm(/* * lookup the realm rooted at @ino. * -* caller must hold snap_rwsem for write. +* caller must hold snap_rwsem. */ static struct ceph_snap_realm *__lookup_snap_realm (struct ceph_mds_client *mdsc,u64 ino)
@@ -147,7 +147,7 @@ static struct ceph_snap_realm *__lookup_snap_realm(struct ceph_mds_client *mdsc,struct rb_node *n = mdsc->snap_realms.rb_node;struct ceph_snap_realm *r; -lockdep_assert_held_write (&mdsc->snap_rwsem); +lockdep_assert_held (&mdsc->snap_rwsem);while (n) { r = rb_entry(n, struct ceph_snap_realm, node);
Signature · 1 line
2.31.1
Re: [PATCH 2/3] ceph: clean up locking annotation for ceph_get_snap_realm and __lookup_snap_realm
Quoted 53 lines · Jeff Layton
They both say that the
snap_rwsemmust be held for write, but I don't see any real reason for it, and it's not currently always called that way.The lookup is just walking the rbtree, so holding it for read should be fine there. The "get" is bumping the refcount and (possibly) removing it from the empty list. I see no need to hold the
snap_rwsemfor write for that.Signed-off-by Jeff Layton <[email protected]>--- fs/ceph/snap.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-)fs/ceph/snap.c +4
-5@@ -60,12 +60,12 @@/* * increase ref count for the realm * -* caller must hold snap_rwsem for write. +* caller must hold snap_rwsem. */ void ceph_get_snap_realm (struct ceph_mds_client *mdsc,struct ceph_snap_realm *realm) { -lockdep_assert_held_write (&mdsc->snap_rwsem); +lockdep_assert_held (&mdsc->snap_rwsem);dout ("get_realm %p %d -> %d\n" , realm,atomic_read (&realm->nref),atomic_read (&realm->nref)+1 );@@ -139,7 +139,7 @@ static struct ceph_snap_realm *ceph_create_snap_realm(/* * lookup the realm rooted at @ino. * -* caller must hold snap_rwsem for write. +* caller must hold snap_rwsem. */ static struct ceph_snap_realm *__lookup_snap_realm (struct ceph_mds_client *mdsc,u64 ino)@@ -147,7 +147,7 @@ static struct ceph_snap_realm *__lookup_snap_realm(struct ceph_mds_client *mdsc,struct rb_node *n = mdsc->snap_realms.rb_node;struct ceph_snap_realm *r; -lockdep_assert_held_write (&mdsc->snap_rwsem); +lockdep_assert_held (&mdsc->snap_rwsem);while (n) { r = rb_entry(n, struct ceph_snap_realm, node); --
Quoted 2 lines
2.31.1
Ah, since you are relaxing the requirement some of those lockdep asserts from the previous patch aren't actually redundant. This seems fine to me: lookup definitely doesn't need the write lock and allowing concurrent gets should be OK. The write lock made some sense back when get was an atomic_read followed by atomic_inc but not now.
Thanks,
Ilya
PATCH 3/3 ceph: must hold snap_rwsem when filling inode for async create
In reply to Jeff Layton...and add a lockdep assertion for it to ceph_fill_inode().
--- fs/ceph/file.c | 3 +++ fs/ceph/inode.c | 2 ++ 2 files changed, 5 insertions(+)
fs/ceph/file.c +3 -0
@@ -578,6 +578,7 @@ static int ceph_finish_async_create(struct inode *dir, struct dentry *dentry,struct ceph_inode_info *ci =ceph_inode (dir);struct inode *inode;struct timespec64 now; +struct ceph_mds_client *mdsc =ceph_sb_to_mdsc (dir->i_sb);struct ceph_vino vino = { .ino = req->r_deleg_ino, .snap =CEPH_NOSNAP };
@@ -615,8 +616,10 @@ static int ceph_finish_async_create(struct inode *dir, struct dentry *dentry,ceph_file_layout_to_legacy (lo, &in.layout); +down_read (&mdsc->snap_rwsem); ret =ceph_fill_inode (inode,NULL , &iinfo,NULL , req->r_session, req->r_fmode,NULL ); +up_read (&mdsc->snap_rwsem);if (ret) {dout ("%s failed to fill inode: %d\n" , __func__, ret);ceph_dir_clear_complete (dir);
fs/ceph/inode.c +2 -0
@@ -777,6 +777,8 @@ int ceph_fill_inode(struct inode *inode, struct page *locked_page,umode_t mode =le32_to_cpu (info->mode);dev_t rdev =le32_to_cpu (info->rdev); +lockdep_assert_held (&mdsc->snap_rwsem); +dout ("%s %p ino %llx.%llx v %llu had %llu\n" , __func__, inode,ceph_vinop (inode),le64_to_cpu (info->version), ci->i_version);
Signature · 1 line
2.31.1
Re: [PATCH 3/3] ceph: must hold snap_rwsem when filling inode for async create
Quoted 48 lines · Jeff Layton
...and add a lockdep assertion for it to
ceph_fill_inode().Cc [email protected] # v5.7+Fixes 9a8d03ca2e2c3 ("ceph: attempt to do async create when possible")Signed-off-by Jeff Layton <[email protected]>--- fs/ceph/file.c | 3 +++ fs/ceph/inode.c | 2 ++ 2 files changed, 5 insertions(+)fs/ceph/file.c +3
-0@@ -578,6 +578,7 @@ static int ceph_finish_async_create(struct inode *dir, struct dentry *dentry,struct ceph_inode_info *ci =ceph_inode (dir);struct inode *inode;struct timespec64 now; +struct ceph_mds_client *mdsc =ceph_sb_to_mdsc (dir->i_sb);struct ceph_vino vino = { .ino = req->r_deleg_ino, .snap =CEPH_NOSNAP };@@ -615,8 +616,10 @@ static int ceph_finish_async_create(struct inode *dir, struct dentry *dentry,ceph_file_layout_to_legacy (lo, &in.layout); +down_read (&mdsc->snap_rwsem); ret =ceph_fill_inode (inode,NULL , &iinfo,NULL , req->r_session, req->r_fmode,NULL ); +up_read (&mdsc->snap_rwsem);if (ret) {dout ("%s failed to fill inode: %d\n" , __func__, ret);ceph_dir_clear_complete (dir);fs/ceph/inode.c +2
-1@@ -777,6 +777,8 @@ int ceph_fill_inode(struct inode *inode, struct page *locked_page,umode_t mode =le32_to_cpu (info->mode);dev_t rdev =le32_to_cpu (info->rdev); +lockdep_assert_held (&mdsc->snap_rwsem); +dout ("%s %p ino %llx.%llx v %llu had %llu\n" , __func__, inode,ceph_vinop (inode),le64_to_cpu (info->version), ci->i_version); --
Quoted 2 lines
2.31.1
Thanks,
Ilya