diff options
Diffstat (limited to 'fs/ceph/inode.c')
-rw-r--r-- | fs/ceph/inode.c | 18 |
1 files changed, 14 insertions, 4 deletions
diff --git a/fs/ceph/inode.c b/fs/ceph/inode.c index 66edef12c6f2..8b136dc0bc13 100644 --- a/fs/ceph/inode.c +++ b/fs/ceph/inode.c | |||
@@ -1389,7 +1389,7 @@ int ceph_readdir_prepopulate(struct ceph_mds_request *req, | |||
1389 | struct qstr dname; | 1389 | struct qstr dname; |
1390 | struct dentry *dn; | 1390 | struct dentry *dn; |
1391 | struct inode *in; | 1391 | struct inode *in; |
1392 | int err = 0, ret, i; | 1392 | int err = 0, skipped = 0, ret, i; |
1393 | struct inode *snapdir = NULL; | 1393 | struct inode *snapdir = NULL; |
1394 | struct ceph_mds_request_head *rhead = req->r_request->front.iov_base; | 1394 | struct ceph_mds_request_head *rhead = req->r_request->front.iov_base; |
1395 | struct ceph_dentry_info *di; | 1395 | struct ceph_dentry_info *di; |
@@ -1501,7 +1501,17 @@ retry_lookup: | |||
1501 | } | 1501 | } |
1502 | 1502 | ||
1503 | if (d_really_is_negative(dn)) { | 1503 | if (d_really_is_negative(dn)) { |
1504 | struct dentry *realdn = splice_dentry(dn, in); | 1504 | struct dentry *realdn; |
1505 | |||
1506 | if (ceph_security_xattr_deadlock(in)) { | ||
1507 | dout(" skip splicing dn %p to inode %p" | ||
1508 | " (security xattr deadlock)\n", dn, in); | ||
1509 | iput(in); | ||
1510 | skipped++; | ||
1511 | goto next_item; | ||
1512 | } | ||
1513 | |||
1514 | realdn = splice_dentry(dn, in); | ||
1505 | if (IS_ERR(realdn)) { | 1515 | if (IS_ERR(realdn)) { |
1506 | err = PTR_ERR(realdn); | 1516 | err = PTR_ERR(realdn); |
1507 | d_drop(dn); | 1517 | d_drop(dn); |
@@ -1518,7 +1528,7 @@ retry_lookup: | |||
1518 | req->r_session, | 1528 | req->r_session, |
1519 | req->r_request_started); | 1529 | req->r_request_started); |
1520 | 1530 | ||
1521 | if (err == 0 && cache_ctl.index >= 0) { | 1531 | if (err == 0 && skipped == 0 && cache_ctl.index >= 0) { |
1522 | ret = fill_readdir_cache(d_inode(parent), dn, | 1532 | ret = fill_readdir_cache(d_inode(parent), dn, |
1523 | &cache_ctl, req); | 1533 | &cache_ctl, req); |
1524 | if (ret < 0) | 1534 | if (ret < 0) |
@@ -1529,7 +1539,7 @@ next_item: | |||
1529 | dput(dn); | 1539 | dput(dn); |
1530 | } | 1540 | } |
1531 | out: | 1541 | out: |
1532 | if (err == 0) { | 1542 | if (err == 0 && skipped == 0) { |
1533 | req->r_did_prepopulate = true; | 1543 | req->r_did_prepopulate = true; |
1534 | req->r_readdir_cache_idx = cache_ctl.index; | 1544 | req->r_readdir_cache_idx = cache_ctl.index; |
1535 | } | 1545 | } |