summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Howells <dhowells@redhat.com>2019-07-30 09:38:52 -0400
committerDavid Howells <dhowells@redhat.com>2019-07-30 09:38:52 -0400
commit9dd0b82ef530cdfe805c9f7079c99e104be59a14 (patch)
tree9acb73a538d1c33df08eac0e4d3225673e1e2900
parent5dc84855b0fc7e1db182b55c5564fd539d6eff92 (diff)
afs: Fix missing dentry data version updating
In the in-kernel afs filesystem, the d_fsdata dentry field is used to hold the data version of the parent directory when it was created or when d_revalidate() last caused it to be updated. This is compared to the ->invalid_before field in the directory inode, rather than the actual data version number, thereby allowing changes due to local edits to be ignored. Only if the server data version gets bumped unexpectedly (eg. by a competing client), do we need to revalidate stuff. However, the d_fsdata field should also be updated if an rpc op is performed that modifies that particular dentry. Such ops return the revised data version of the directory(ies) involved, so we should use that. This is particularly problematic for rename, since a dentry from one directory may be moved directly into another directory (ie. mv a/x b/x). It would then be sporting the wrong data version - and if this is in the future, for the destination directory, revalidations would be missed, leading to foreign renames and hard-link deletion being missed. Fix this by the following means: (1) Return the data version number from operations that read the directory contents - if they issue the read. This starts in afs_dir_iterate() and is used, ignored or passed back by its callers. (2) In afs_lookup*(), set the dentry version to the version returned by (1) before d_splice_alias() is called and the dentry published. (3) In afs_d_revalidate(), set the dentry version to that returned from (1) if an rpc call was issued. This means that if a parallel procedure, such as mkdir(), modifies the directory, we won't accidentally use the data version from that. (4) In afs_{mkdir,create,link,symlink}(), set the new dentry's version to the directory data version before d_instantiate() is called. (5) In afs_{rmdir,unlink}, update the target dentry's version to the directory data version as soon as we've updated the directory inode. (6) In afs_rename(), we need to unhash the old dentry before we start so that we don't get afs_d_revalidate() reverting the version change in cross-directory renames. We then need to set both the old and the new dentry versions the data version of the new directory before we call d_move() as d_move() will rehash them. Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") Signed-off-by: David Howells <dhowells@redhat.com>
-rw-r--r--fs/afs/dir.c84
1 files changed, 70 insertions, 14 deletions
diff --git a/fs/afs/dir.c b/fs/afs/dir.c
index 618e26cea887..81207dc3c997 100644
--- a/fs/afs/dir.c
+++ b/fs/afs/dir.c
@@ -440,7 +440,7 @@ static int afs_dir_iterate_block(struct afs_vnode *dvnode,
440 * iterate through the data blob that lists the contents of an AFS directory 440 * iterate through the data blob that lists the contents of an AFS directory
441 */ 441 */
442static int afs_dir_iterate(struct inode *dir, struct dir_context *ctx, 442static int afs_dir_iterate(struct inode *dir, struct dir_context *ctx,
443 struct key *key) 443 struct key *key, afs_dataversion_t *_dir_version)
444{ 444{
445 struct afs_vnode *dvnode = AFS_FS_I(dir); 445 struct afs_vnode *dvnode = AFS_FS_I(dir);
446 struct afs_xdr_dir_page *dbuf; 446 struct afs_xdr_dir_page *dbuf;
@@ -460,6 +460,7 @@ static int afs_dir_iterate(struct inode *dir, struct dir_context *ctx,
460 req = afs_read_dir(dvnode, key); 460 req = afs_read_dir(dvnode, key);
461 if (IS_ERR(req)) 461 if (IS_ERR(req))
462 return PTR_ERR(req); 462 return PTR_ERR(req);
463 *_dir_version = req->data_version;
463 464
464 /* round the file position up to the next entry boundary */ 465 /* round the file position up to the next entry boundary */
465 ctx->pos += sizeof(union afs_xdr_dirent) - 1; 466 ctx->pos += sizeof(union afs_xdr_dirent) - 1;
@@ -514,7 +515,10 @@ out:
514 */ 515 */
515static int afs_readdir(struct file *file, struct dir_context *ctx) 516static int afs_readdir(struct file *file, struct dir_context *ctx)
516{ 517{
517 return afs_dir_iterate(file_inode(file), ctx, afs_file_key(file)); 518 afs_dataversion_t dir_version;
519
520 return afs_dir_iterate(file_inode(file), ctx, afs_file_key(file),
521 &dir_version);
518} 522}
519 523
520/* 524/*
@@ -555,7 +559,8 @@ static int afs_lookup_one_filldir(struct dir_context *ctx, const char *name,
555 * - just returns the FID the dentry name maps to if found 559 * - just returns the FID the dentry name maps to if found
556 */ 560 */
557static int afs_do_lookup_one(struct inode *dir, struct dentry *dentry, 561static int afs_do_lookup_one(struct inode *dir, struct dentry *dentry,
558 struct afs_fid *fid, struct key *key) 562 struct afs_fid *fid, struct key *key,
563 afs_dataversion_t *_dir_version)
559{ 564{
560 struct afs_super_info *as = dir->i_sb->s_fs_info; 565 struct afs_super_info *as = dir->i_sb->s_fs_info;
561 struct afs_lookup_one_cookie cookie = { 566 struct afs_lookup_one_cookie cookie = {
@@ -568,7 +573,7 @@ static int afs_do_lookup_one(struct inode *dir, struct dentry *dentry,
568 _enter("{%lu},%p{%pd},", dir->i_ino, dentry, dentry); 573 _enter("{%lu},%p{%pd},", dir->i_ino, dentry, dentry);
569 574
570 /* search the directory */ 575 /* search the directory */
571 ret = afs_dir_iterate(dir, &cookie.ctx, key); 576 ret = afs_dir_iterate(dir, &cookie.ctx, key, _dir_version);
572 if (ret < 0) { 577 if (ret < 0) {
573 _leave(" = %d [iter]", ret); 578 _leave(" = %d [iter]", ret);
574 return ret; 579 return ret;
@@ -642,6 +647,7 @@ static struct inode *afs_do_lookup(struct inode *dir, struct dentry *dentry,
642 struct afs_server *server; 647 struct afs_server *server;
643 struct afs_vnode *dvnode = AFS_FS_I(dir), *vnode; 648 struct afs_vnode *dvnode = AFS_FS_I(dir), *vnode;
644 struct inode *inode = NULL, *ti; 649 struct inode *inode = NULL, *ti;
650 afs_dataversion_t data_version = READ_ONCE(dvnode->status.data_version);
645 int ret, i; 651 int ret, i;
646 652
647 _enter("{%lu},%p{%pd},", dir->i_ino, dentry, dentry); 653 _enter("{%lu},%p{%pd},", dir->i_ino, dentry, dentry);
@@ -669,12 +675,14 @@ static struct inode *afs_do_lookup(struct inode *dir, struct dentry *dentry,
669 cookie->fids[i].vid = as->volume->vid; 675 cookie->fids[i].vid = as->volume->vid;
670 676
671 /* search the directory */ 677 /* search the directory */
672 ret = afs_dir_iterate(dir, &cookie->ctx, key); 678 ret = afs_dir_iterate(dir, &cookie->ctx, key, &data_version);
673 if (ret < 0) { 679 if (ret < 0) {
674 inode = ERR_PTR(ret); 680 inode = ERR_PTR(ret);
675 goto out; 681 goto out;
676 } 682 }
677 683
684 dentry->d_fsdata = (void *)(unsigned long)data_version;
685
678 inode = ERR_PTR(-ENOENT); 686 inode = ERR_PTR(-ENOENT);
679 if (!cookie->found) 687 if (!cookie->found)
680 goto out; 688 goto out;
@@ -968,7 +976,8 @@ static int afs_d_revalidate(struct dentry *dentry, unsigned int flags)
968 struct dentry *parent; 976 struct dentry *parent;
969 struct inode *inode; 977 struct inode *inode;
970 struct key *key; 978 struct key *key;
971 long dir_version, de_version; 979 afs_dataversion_t dir_version;
980 long de_version;
972 int ret; 981 int ret;
973 982
974 if (flags & LOOKUP_RCU) 983 if (flags & LOOKUP_RCU)
@@ -1014,20 +1023,20 @@ static int afs_d_revalidate(struct dentry *dentry, unsigned int flags)
1014 * on a 32-bit system, we only have 32 bits in the dentry to store the 1023 * on a 32-bit system, we only have 32 bits in the dentry to store the
1015 * version. 1024 * version.
1016 */ 1025 */
1017 dir_version = (long)dir->status.data_version; 1026 dir_version = dir->status.data_version;
1018 de_version = (long)dentry->d_fsdata; 1027 de_version = (long)dentry->d_fsdata;
1019 if (de_version == dir_version) 1028 if (de_version == (long)dir_version)
1020 goto out_valid_noupdate; 1029 goto out_valid_noupdate;
1021 1030
1022 dir_version = (long)dir->invalid_before; 1031 dir_version = dir->invalid_before;
1023 if (de_version - dir_version >= 0) 1032 if (de_version - (long)dir_version >= 0)
1024 goto out_valid; 1033 goto out_valid;
1025 1034
1026 _debug("dir modified"); 1035 _debug("dir modified");
1027 afs_stat_v(dir, n_reval); 1036 afs_stat_v(dir, n_reval);
1028 1037
1029 /* search the directory for this vnode */ 1038 /* search the directory for this vnode */
1030 ret = afs_do_lookup_one(&dir->vfs_inode, dentry, &fid, key); 1039 ret = afs_do_lookup_one(&dir->vfs_inode, dentry, &fid, key, &dir_version);
1031 switch (ret) { 1040 switch (ret) {
1032 case 0: 1041 case 0:
1033 /* the filename maps to something */ 1042 /* the filename maps to something */
@@ -1080,7 +1089,7 @@ static int afs_d_revalidate(struct dentry *dentry, unsigned int flags)
1080 } 1089 }
1081 1090
1082out_valid: 1091out_valid:
1083 dentry->d_fsdata = (void *)dir_version; 1092 dentry->d_fsdata = (void *)(unsigned long)dir_version;
1084out_valid_noupdate: 1093out_valid_noupdate:
1085 dput(parent); 1094 dput(parent);
1086 key_put(key); 1095 key_put(key);
@@ -1187,6 +1196,20 @@ static void afs_prep_for_new_inode(struct afs_fs_cursor *fc,
1187} 1196}
1188 1197
1189/* 1198/*
1199 * Note that a dentry got changed. We need to set d_fsdata to the data version
1200 * number derived from the result of the operation. It doesn't matter if
1201 * d_fsdata goes backwards as we'll just revalidate.
1202 */
1203static void afs_update_dentry_version(struct afs_fs_cursor *fc,
1204 struct dentry *dentry,
1205 struct afs_status_cb *scb)
1206{
1207 if (fc->ac.error == 0)
1208 dentry->d_fsdata =
1209 (void *)(unsigned long)scb->status.data_version;
1210}
1211
1212/*
1190 * create a directory on an AFS filesystem 1213 * create a directory on an AFS filesystem
1191 */ 1214 */
1192static int afs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode) 1215static int afs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
@@ -1228,6 +1251,7 @@ static int afs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
1228 afs_check_for_remote_deletion(&fc, dvnode); 1251 afs_check_for_remote_deletion(&fc, dvnode);
1229 afs_vnode_commit_status(&fc, dvnode, fc.cb_break, 1252 afs_vnode_commit_status(&fc, dvnode, fc.cb_break,
1230 &data_version, &scb[0]); 1253 &data_version, &scb[0]);
1254 afs_update_dentry_version(&fc, dentry, &scb[0]);
1231 afs_vnode_new_inode(&fc, dentry, &iget_data, &scb[1]); 1255 afs_vnode_new_inode(&fc, dentry, &iget_data, &scb[1]);
1232 ret = afs_end_vnode_operation(&fc); 1256 ret = afs_end_vnode_operation(&fc);
1233 if (ret < 0) 1257 if (ret < 0)
@@ -1320,6 +1344,7 @@ static int afs_rmdir(struct inode *dir, struct dentry *dentry)
1320 1344
1321 afs_vnode_commit_status(&fc, dvnode, fc.cb_break, 1345 afs_vnode_commit_status(&fc, dvnode, fc.cb_break,
1322 &data_version, scb); 1346 &data_version, scb);
1347 afs_update_dentry_version(&fc, dentry, scb);
1323 ret = afs_end_vnode_operation(&fc); 1348 ret = afs_end_vnode_operation(&fc);
1324 if (ret == 0) { 1349 if (ret == 0) {
1325 afs_dir_remove_subdir(dentry); 1350 afs_dir_remove_subdir(dentry);
@@ -1459,6 +1484,7 @@ static int afs_unlink(struct inode *dir, struct dentry *dentry)
1459 &data_version, &scb[0]); 1484 &data_version, &scb[0]);
1460 afs_vnode_commit_status(&fc, vnode, fc.cb_break_2, 1485 afs_vnode_commit_status(&fc, vnode, fc.cb_break_2,
1461 &data_version_2, &scb[1]); 1486 &data_version_2, &scb[1]);
1487 afs_update_dentry_version(&fc, dentry, &scb[0]);
1462 ret = afs_end_vnode_operation(&fc); 1488 ret = afs_end_vnode_operation(&fc);
1463 if (ret == 0 && !(scb[1].have_status || scb[1].have_error)) 1489 if (ret == 0 && !(scb[1].have_status || scb[1].have_error))
1464 ret = afs_dir_remove_link(dvnode, dentry, key); 1490 ret = afs_dir_remove_link(dvnode, dentry, key);
@@ -1527,6 +1553,7 @@ static int afs_create(struct inode *dir, struct dentry *dentry, umode_t mode,
1527 afs_check_for_remote_deletion(&fc, dvnode); 1553 afs_check_for_remote_deletion(&fc, dvnode);
1528 afs_vnode_commit_status(&fc, dvnode, fc.cb_break, 1554 afs_vnode_commit_status(&fc, dvnode, fc.cb_break,
1529 &data_version, &scb[0]); 1555 &data_version, &scb[0]);
1556 afs_update_dentry_version(&fc, dentry, &scb[0]);
1530 afs_vnode_new_inode(&fc, dentry, &iget_data, &scb[1]); 1557 afs_vnode_new_inode(&fc, dentry, &iget_data, &scb[1]);
1531 ret = afs_end_vnode_operation(&fc); 1558 ret = afs_end_vnode_operation(&fc);
1532 if (ret < 0) 1559 if (ret < 0)
@@ -1608,6 +1635,7 @@ static int afs_link(struct dentry *from, struct inode *dir,
1608 afs_vnode_commit_status(&fc, vnode, fc.cb_break_2, 1635 afs_vnode_commit_status(&fc, vnode, fc.cb_break_2,
1609 NULL, &scb[1]); 1636 NULL, &scb[1]);
1610 ihold(&vnode->vfs_inode); 1637 ihold(&vnode->vfs_inode);
1638 afs_update_dentry_version(&fc, dentry, &scb[0]);
1611 d_instantiate(dentry, &vnode->vfs_inode); 1639 d_instantiate(dentry, &vnode->vfs_inode);
1612 1640
1613 mutex_unlock(&vnode->io_lock); 1641 mutex_unlock(&vnode->io_lock);
@@ -1687,6 +1715,7 @@ static int afs_symlink(struct inode *dir, struct dentry *dentry,
1687 afs_check_for_remote_deletion(&fc, dvnode); 1715 afs_check_for_remote_deletion(&fc, dvnode);
1688 afs_vnode_commit_status(&fc, dvnode, fc.cb_break, 1716 afs_vnode_commit_status(&fc, dvnode, fc.cb_break,
1689 &data_version, &scb[0]); 1717 &data_version, &scb[0]);
1718 afs_update_dentry_version(&fc, dentry, &scb[0]);
1690 afs_vnode_new_inode(&fc, dentry, &iget_data, &scb[1]); 1719 afs_vnode_new_inode(&fc, dentry, &iget_data, &scb[1]);
1691 ret = afs_end_vnode_operation(&fc); 1720 ret = afs_end_vnode_operation(&fc);
1692 if (ret < 0) 1721 if (ret < 0)
@@ -1792,6 +1821,17 @@ static int afs_rename(struct inode *old_dir, struct dentry *old_dentry,
1792 } 1821 }
1793 } 1822 }
1794 1823
1824 /* This bit is potentially nasty as there's a potential race with
1825 * afs_d_revalidate{,_rcu}(). We have to change d_fsdata on the dentry
1826 * to reflect it's new parent's new data_version after the op, but
1827 * d_revalidate may see old_dentry between the op having taken place
1828 * and the version being updated.
1829 *
1830 * So drop the old_dentry for now to make other threads go through
1831 * lookup instead - which we hold a lock against.
1832 */
1833 d_drop(old_dentry);
1834
1795 ret = -ERESTARTSYS; 1835 ret = -ERESTARTSYS;
1796 if (afs_begin_vnode_operation(&fc, orig_dvnode, key, true)) { 1836 if (afs_begin_vnode_operation(&fc, orig_dvnode, key, true)) {
1797 afs_dataversion_t orig_data_version; 1837 afs_dataversion_t orig_data_version;
@@ -1803,7 +1843,7 @@ static int afs_rename(struct inode *old_dir, struct dentry *old_dentry,
1803 if (orig_dvnode != new_dvnode) { 1843 if (orig_dvnode != new_dvnode) {
1804 if (mutex_lock_interruptible_nested(&new_dvnode->io_lock, 1) < 0) { 1844 if (mutex_lock_interruptible_nested(&new_dvnode->io_lock, 1) < 0) {
1805 afs_end_vnode_operation(&fc); 1845 afs_end_vnode_operation(&fc);
1806 goto error_rehash; 1846 goto error_rehash_old;
1807 } 1847 }
1808 new_data_version = new_dvnode->status.data_version + 1; 1848 new_data_version = new_dvnode->status.data_version + 1;
1809 } else { 1849 } else {
@@ -1828,7 +1868,7 @@ static int afs_rename(struct inode *old_dir, struct dentry *old_dentry,
1828 } 1868 }
1829 ret = afs_end_vnode_operation(&fc); 1869 ret = afs_end_vnode_operation(&fc);
1830 if (ret < 0) 1870 if (ret < 0)
1831 goto error_rehash; 1871 goto error_rehash_old;
1832 } 1872 }
1833 1873
1834 if (ret == 0) { 1874 if (ret == 0) {
@@ -1854,10 +1894,26 @@ static int afs_rename(struct inode *old_dir, struct dentry *old_dentry,
1854 drop_nlink(new_inode); 1894 drop_nlink(new_inode);
1855 spin_unlock(&new_inode->i_lock); 1895 spin_unlock(&new_inode->i_lock);
1856 } 1896 }
1897
1898 /* Now we can update d_fsdata on the dentries to reflect their
1899 * new parent's data_version.
1900 *
1901 * Note that if we ever implement RENAME_EXCHANGE, we'll have
1902 * to update both dentries with opposing dir versions.
1903 */
1904 if (new_dvnode != orig_dvnode) {
1905 afs_update_dentry_version(&fc, old_dentry, &scb[1]);
1906 afs_update_dentry_version(&fc, new_dentry, &scb[1]);
1907 } else {
1908 afs_update_dentry_version(&fc, old_dentry, &scb[0]);
1909 afs_update_dentry_version(&fc, new_dentry, &scb[0]);
1910 }
1857 d_move(old_dentry, new_dentry); 1911 d_move(old_dentry, new_dentry);
1858 goto error_tmp; 1912 goto error_tmp;
1859 } 1913 }
1860 1914
1915error_rehash_old:
1916 d_rehash(new_dentry);
1861error_rehash: 1917error_rehash:
1862 if (rehash) 1918 if (rehash)
1863 d_rehash(rehash); 1919 d_rehash(rehash);