diff options
Diffstat (limited to 'fs/ceph/inode.c')
-rw-r--r-- | fs/ceph/inode.c | 53 |
1 files changed, 31 insertions, 22 deletions
diff --git a/fs/ceph/inode.c b/fs/ceph/inode.c index 5849b88bbed3..ed58b168904a 100644 --- a/fs/ceph/inode.c +++ b/fs/ceph/inode.c | |||
@@ -549,6 +549,10 @@ int ceph_fill_file_size(struct inode *inode, int issued, | |||
549 | if (ceph_seq_cmp(truncate_seq, ci->i_truncate_seq) > 0 || | 549 | if (ceph_seq_cmp(truncate_seq, ci->i_truncate_seq) > 0 || |
550 | (truncate_seq == ci->i_truncate_seq && size > inode->i_size)) { | 550 | (truncate_seq == ci->i_truncate_seq && size > inode->i_size)) { |
551 | dout("size %lld -> %llu\n", inode->i_size, size); | 551 | dout("size %lld -> %llu\n", inode->i_size, size); |
552 | if (size > 0 && S_ISDIR(inode->i_mode)) { | ||
553 | pr_err("fill_file_size non-zero size for directory\n"); | ||
554 | size = 0; | ||
555 | } | ||
552 | i_size_write(inode, size); | 556 | i_size_write(inode, size); |
553 | inode->i_blocks = (size + (1<<9) - 1) >> 9; | 557 | inode->i_blocks = (size + (1<<9) - 1) >> 9; |
554 | ci->i_reported_size = size; | 558 | ci->i_reported_size = size; |
@@ -977,13 +981,8 @@ out_unlock: | |||
977 | /* | 981 | /* |
978 | * splice a dentry to an inode. | 982 | * splice a dentry to an inode. |
979 | * caller must hold directory i_mutex for this to be safe. | 983 | * caller must hold directory i_mutex for this to be safe. |
980 | * | ||
981 | * we will only rehash the resulting dentry if @prehash is | ||
982 | * true; @prehash will be set to false (for the benefit of | ||
983 | * the caller) if we fail. | ||
984 | */ | 984 | */ |
985 | static struct dentry *splice_dentry(struct dentry *dn, struct inode *in, | 985 | static struct dentry *splice_dentry(struct dentry *dn, struct inode *in) |
986 | bool *prehash) | ||
987 | { | 986 | { |
988 | struct dentry *realdn; | 987 | struct dentry *realdn; |
989 | 988 | ||
@@ -996,8 +995,6 @@ static struct dentry *splice_dentry(struct dentry *dn, struct inode *in, | |||
996 | if (IS_ERR(realdn)) { | 995 | if (IS_ERR(realdn)) { |
997 | pr_err("splice_dentry error %ld %p inode %p ino %llx.%llx\n", | 996 | pr_err("splice_dentry error %ld %p inode %p ino %llx.%llx\n", |
998 | PTR_ERR(realdn), dn, in, ceph_vinop(in)); | 997 | PTR_ERR(realdn), dn, in, ceph_vinop(in)); |
999 | if (prehash) | ||
1000 | *prehash = false; /* don't rehash on error */ | ||
1001 | dn = realdn; /* note realdn contains the error */ | 998 | dn = realdn; /* note realdn contains the error */ |
1002 | goto out; | 999 | goto out; |
1003 | } else if (realdn) { | 1000 | } else if (realdn) { |
@@ -1013,8 +1010,6 @@ static struct dentry *splice_dentry(struct dentry *dn, struct inode *in, | |||
1013 | dout("dn %p attached to %p ino %llx.%llx\n", | 1010 | dout("dn %p attached to %p ino %llx.%llx\n", |
1014 | dn, d_inode(dn), ceph_vinop(d_inode(dn))); | 1011 | dn, d_inode(dn), ceph_vinop(d_inode(dn))); |
1015 | } | 1012 | } |
1016 | if ((!prehash || *prehash) && d_unhashed(dn)) | ||
1017 | d_rehash(dn); | ||
1018 | out: | 1013 | out: |
1019 | return dn; | 1014 | return dn; |
1020 | } | 1015 | } |
@@ -1247,10 +1242,8 @@ retry_lookup: | |||
1247 | dout("d_delete %p\n", dn); | 1242 | dout("d_delete %p\n", dn); |
1248 | d_delete(dn); | 1243 | d_delete(dn); |
1249 | } else { | 1244 | } else { |
1250 | dout("d_instantiate %p NULL\n", dn); | ||
1251 | d_instantiate(dn, NULL); | ||
1252 | if (have_lease && d_unhashed(dn)) | 1245 | if (have_lease && d_unhashed(dn)) |
1253 | d_rehash(dn); | 1246 | d_add(dn, NULL); |
1254 | update_dentry_lease(dn, rinfo->dlease, | 1247 | update_dentry_lease(dn, rinfo->dlease, |
1255 | session, | 1248 | session, |
1256 | req->r_request_started); | 1249 | req->r_request_started); |
@@ -1262,7 +1255,7 @@ retry_lookup: | |||
1262 | if (d_really_is_negative(dn)) { | 1255 | if (d_really_is_negative(dn)) { |
1263 | ceph_dir_clear_ordered(dir); | 1256 | ceph_dir_clear_ordered(dir); |
1264 | ihold(in); | 1257 | ihold(in); |
1265 | dn = splice_dentry(dn, in, &have_lease); | 1258 | dn = splice_dentry(dn, in); |
1266 | if (IS_ERR(dn)) { | 1259 | if (IS_ERR(dn)) { |
1267 | err = PTR_ERR(dn); | 1260 | err = PTR_ERR(dn); |
1268 | goto done; | 1261 | goto done; |
@@ -1272,6 +1265,7 @@ retry_lookup: | |||
1272 | dout(" %p links to %p %llx.%llx, not %llx.%llx\n", | 1265 | dout(" %p links to %p %llx.%llx, not %llx.%llx\n", |
1273 | dn, d_inode(dn), ceph_vinop(d_inode(dn)), | 1266 | dn, d_inode(dn), ceph_vinop(d_inode(dn)), |
1274 | ceph_vinop(in)); | 1267 | ceph_vinop(in)); |
1268 | d_invalidate(dn); | ||
1275 | have_lease = false; | 1269 | have_lease = false; |
1276 | } | 1270 | } |
1277 | 1271 | ||
@@ -1292,7 +1286,7 @@ retry_lookup: | |||
1292 | dout(" linking snapped dir %p to dn %p\n", in, dn); | 1286 | dout(" linking snapped dir %p to dn %p\n", in, dn); |
1293 | ceph_dir_clear_ordered(dir); | 1287 | ceph_dir_clear_ordered(dir); |
1294 | ihold(in); | 1288 | ihold(in); |
1295 | dn = splice_dentry(dn, in, NULL); | 1289 | dn = splice_dentry(dn, in); |
1296 | if (IS_ERR(dn)) { | 1290 | if (IS_ERR(dn)) { |
1297 | err = PTR_ERR(dn); | 1291 | err = PTR_ERR(dn); |
1298 | goto done; | 1292 | goto done; |
@@ -1360,15 +1354,20 @@ static int fill_readdir_cache(struct inode *dir, struct dentry *dn, | |||
1360 | 1354 | ||
1361 | if (!ctl->page || pgoff != page_index(ctl->page)) { | 1355 | if (!ctl->page || pgoff != page_index(ctl->page)) { |
1362 | ceph_readdir_cache_release(ctl); | 1356 | ceph_readdir_cache_release(ctl); |
1363 | ctl->page = grab_cache_page(&dir->i_data, pgoff); | 1357 | if (idx == 0) |
1358 | ctl->page = grab_cache_page(&dir->i_data, pgoff); | ||
1359 | else | ||
1360 | ctl->page = find_lock_page(&dir->i_data, pgoff); | ||
1364 | if (!ctl->page) { | 1361 | if (!ctl->page) { |
1365 | ctl->index = -1; | 1362 | ctl->index = -1; |
1366 | return -ENOMEM; | 1363 | return idx == 0 ? -ENOMEM : 0; |
1367 | } | 1364 | } |
1368 | /* reading/filling the cache are serialized by | 1365 | /* reading/filling the cache are serialized by |
1369 | * i_mutex, no need to use page lock */ | 1366 | * i_mutex, no need to use page lock */ |
1370 | unlock_page(ctl->page); | 1367 | unlock_page(ctl->page); |
1371 | ctl->dentries = kmap(ctl->page); | 1368 | ctl->dentries = kmap(ctl->page); |
1369 | if (idx == 0) | ||
1370 | memset(ctl->dentries, 0, PAGE_CACHE_SIZE); | ||
1372 | } | 1371 | } |
1373 | 1372 | ||
1374 | if (req->r_dir_release_cnt == atomic64_read(&ci->i_release_count) && | 1373 | if (req->r_dir_release_cnt == atomic64_read(&ci->i_release_count) && |
@@ -1391,7 +1390,7 @@ int ceph_readdir_prepopulate(struct ceph_mds_request *req, | |||
1391 | struct qstr dname; | 1390 | struct qstr dname; |
1392 | struct dentry *dn; | 1391 | struct dentry *dn; |
1393 | struct inode *in; | 1392 | struct inode *in; |
1394 | int err = 0, ret, i; | 1393 | int err = 0, skipped = 0, ret, i; |
1395 | struct inode *snapdir = NULL; | 1394 | struct inode *snapdir = NULL; |
1396 | struct ceph_mds_request_head *rhead = req->r_request->front.iov_base; | 1395 | struct ceph_mds_request_head *rhead = req->r_request->front.iov_base; |
1397 | struct ceph_dentry_info *di; | 1396 | struct ceph_dentry_info *di; |
@@ -1503,7 +1502,17 @@ retry_lookup: | |||
1503 | } | 1502 | } |
1504 | 1503 | ||
1505 | if (d_really_is_negative(dn)) { | 1504 | if (d_really_is_negative(dn)) { |
1506 | struct dentry *realdn = splice_dentry(dn, in, NULL); | 1505 | struct dentry *realdn; |
1506 | |||
1507 | if (ceph_security_xattr_deadlock(in)) { | ||
1508 | dout(" skip splicing dn %p to inode %p" | ||
1509 | " (security xattr deadlock)\n", dn, in); | ||
1510 | iput(in); | ||
1511 | skipped++; | ||
1512 | goto next_item; | ||
1513 | } | ||
1514 | |||
1515 | realdn = splice_dentry(dn, in); | ||
1507 | if (IS_ERR(realdn)) { | 1516 | if (IS_ERR(realdn)) { |
1508 | err = PTR_ERR(realdn); | 1517 | err = PTR_ERR(realdn); |
1509 | d_drop(dn); | 1518 | d_drop(dn); |
@@ -1520,7 +1529,7 @@ retry_lookup: | |||
1520 | req->r_session, | 1529 | req->r_session, |
1521 | req->r_request_started); | 1530 | req->r_request_started); |
1522 | 1531 | ||
1523 | if (err == 0 && cache_ctl.index >= 0) { | 1532 | if (err == 0 && skipped == 0 && cache_ctl.index >= 0) { |
1524 | ret = fill_readdir_cache(d_inode(parent), dn, | 1533 | ret = fill_readdir_cache(d_inode(parent), dn, |
1525 | &cache_ctl, req); | 1534 | &cache_ctl, req); |
1526 | if (ret < 0) | 1535 | if (ret < 0) |
@@ -1531,7 +1540,7 @@ next_item: | |||
1531 | dput(dn); | 1540 | dput(dn); |
1532 | } | 1541 | } |
1533 | out: | 1542 | out: |
1534 | if (err == 0) { | 1543 | if (err == 0 && skipped == 0) { |
1535 | req->r_did_prepopulate = true; | 1544 | req->r_did_prepopulate = true; |
1536 | req->r_readdir_cache_idx = cache_ctl.index; | 1545 | req->r_readdir_cache_idx = cache_ctl.index; |
1537 | } | 1546 | } |
@@ -1961,7 +1970,7 @@ int ceph_setattr(struct dentry *dentry, struct iattr *attr) | |||
1961 | if (dirtied) { | 1970 | if (dirtied) { |
1962 | inode_dirty_flags = __ceph_mark_dirty_caps(ci, dirtied, | 1971 | inode_dirty_flags = __ceph_mark_dirty_caps(ci, dirtied, |
1963 | &prealloc_cf); | 1972 | &prealloc_cf); |
1964 | inode->i_ctime = CURRENT_TIME; | 1973 | inode->i_ctime = current_fs_time(inode->i_sb); |
1965 | } | 1974 | } |
1966 | 1975 | ||
1967 | release &= issued; | 1976 | release &= issued; |