@@ -1032,7 +1032,7 @@ static int afs_d_revalidate(struct dentry *dentry, unsigned int flags)
1032
1032
struct dentry * parent ;
1033
1033
struct inode * inode ;
1034
1034
struct key * key ;
1035
- afs_dataversion_t dir_version ;
1035
+ afs_dataversion_t dir_version , invalid_before ;
1036
1036
long de_version ;
1037
1037
int ret ;
1038
1038
@@ -1084,8 +1084,8 @@ static int afs_d_revalidate(struct dentry *dentry, unsigned int flags)
1084
1084
if (de_version == (long )dir_version )
1085
1085
goto out_valid_noupdate ;
1086
1086
1087
- dir_version = dir -> invalid_before ;
1088
- if (de_version - (long )dir_version >= 0 )
1087
+ invalid_before = dir -> invalid_before ;
1088
+ if (de_version - (long )invalid_before >= 0 )
1089
1089
goto out_valid ;
1090
1090
1091
1091
_debug ("dir modified" );
@@ -1275,6 +1275,7 @@ static int afs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
1275
1275
struct afs_fs_cursor fc ;
1276
1276
struct afs_vnode * dvnode = AFS_FS_I (dir );
1277
1277
struct key * key ;
1278
+ afs_dataversion_t data_version ;
1278
1279
int ret ;
1279
1280
1280
1281
mode |= S_IFDIR ;
@@ -1295,7 +1296,7 @@ static int afs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
1295
1296
1296
1297
ret = - ERESTARTSYS ;
1297
1298
if (afs_begin_vnode_operation (& fc , dvnode , key , true)) {
1298
- afs_dataversion_t data_version = dvnode -> status .data_version + 1 ;
1299
+ data_version = dvnode -> status .data_version + 1 ;
1299
1300
1300
1301
while (afs_select_fileserver (& fc )) {
1301
1302
fc .cb_break = afs_calc_vnode_cb_break (dvnode );
@@ -1316,10 +1317,14 @@ static int afs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
1316
1317
goto error_key ;
1317
1318
}
1318
1319
1319
- if (ret == 0 &&
1320
- test_bit (AFS_VNODE_DIR_VALID , & dvnode -> flags ))
1321
- afs_edit_dir_add (dvnode , & dentry -> d_name , & iget_data .fid ,
1322
- afs_edit_dir_for_create );
1320
+ if (ret == 0 ) {
1321
+ down_write (& dvnode -> validate_lock );
1322
+ if (test_bit (AFS_VNODE_DIR_VALID , & dvnode -> flags ) &&
1323
+ dvnode -> status .data_version == data_version )
1324
+ afs_edit_dir_add (dvnode , & dentry -> d_name , & iget_data .fid ,
1325
+ afs_edit_dir_for_create );
1326
+ up_write (& dvnode -> validate_lock );
1327
+ }
1323
1328
1324
1329
key_put (key );
1325
1330
kfree (scb );
@@ -1360,6 +1365,7 @@ static int afs_rmdir(struct inode *dir, struct dentry *dentry)
1360
1365
struct afs_fs_cursor fc ;
1361
1366
struct afs_vnode * dvnode = AFS_FS_I (dir ), * vnode = NULL ;
1362
1367
struct key * key ;
1368
+ afs_dataversion_t data_version ;
1363
1369
int ret ;
1364
1370
1365
1371
_enter ("{%llx:%llu},{%pd}" ,
@@ -1391,7 +1397,7 @@ static int afs_rmdir(struct inode *dir, struct dentry *dentry)
1391
1397
1392
1398
ret = - ERESTARTSYS ;
1393
1399
if (afs_begin_vnode_operation (& fc , dvnode , key , true)) {
1394
- afs_dataversion_t data_version = dvnode -> status .data_version + 1 ;
1400
+ data_version = dvnode -> status .data_version + 1 ;
1395
1401
1396
1402
while (afs_select_fileserver (& fc )) {
1397
1403
fc .cb_break = afs_calc_vnode_cb_break (dvnode );
@@ -1404,9 +1410,12 @@ static int afs_rmdir(struct inode *dir, struct dentry *dentry)
1404
1410
ret = afs_end_vnode_operation (& fc );
1405
1411
if (ret == 0 ) {
1406
1412
afs_dir_remove_subdir (dentry );
1407
- if (test_bit (AFS_VNODE_DIR_VALID , & dvnode -> flags ))
1413
+ down_write (& dvnode -> validate_lock );
1414
+ if (test_bit (AFS_VNODE_DIR_VALID , & dvnode -> flags ) &&
1415
+ dvnode -> status .data_version == data_version )
1408
1416
afs_edit_dir_remove (dvnode , & dentry -> d_name ,
1409
1417
afs_edit_dir_for_rmdir );
1418
+ up_write (& dvnode -> validate_lock );
1410
1419
}
1411
1420
}
1412
1421
@@ -1544,10 +1553,15 @@ static int afs_unlink(struct inode *dir, struct dentry *dentry)
1544
1553
ret = afs_end_vnode_operation (& fc );
1545
1554
if (ret == 0 && !(scb [1 ].have_status || scb [1 ].have_error ))
1546
1555
ret = afs_dir_remove_link (dvnode , dentry , key );
1547
- if (ret == 0 &&
1548
- test_bit (AFS_VNODE_DIR_VALID , & dvnode -> flags ))
1549
- afs_edit_dir_remove (dvnode , & dentry -> d_name ,
1550
- afs_edit_dir_for_unlink );
1556
+
1557
+ if (ret == 0 ) {
1558
+ down_write (& dvnode -> validate_lock );
1559
+ if (test_bit (AFS_VNODE_DIR_VALID , & dvnode -> flags ) &&
1560
+ dvnode -> status .data_version == data_version )
1561
+ afs_edit_dir_remove (dvnode , & dentry -> d_name ,
1562
+ afs_edit_dir_for_unlink );
1563
+ up_write (& dvnode -> validate_lock );
1564
+ }
1551
1565
}
1552
1566
1553
1567
if (need_rehash && ret < 0 && ret != - ENOENT )
@@ -1573,6 +1587,7 @@ static int afs_create(struct inode *dir, struct dentry *dentry, umode_t mode,
1573
1587
struct afs_status_cb * scb ;
1574
1588
struct afs_vnode * dvnode = AFS_FS_I (dir );
1575
1589
struct key * key ;
1590
+ afs_dataversion_t data_version ;
1576
1591
int ret ;
1577
1592
1578
1593
mode |= S_IFREG ;
@@ -1597,7 +1612,7 @@ static int afs_create(struct inode *dir, struct dentry *dentry, umode_t mode,
1597
1612
1598
1613
ret = - ERESTARTSYS ;
1599
1614
if (afs_begin_vnode_operation (& fc , dvnode , key , true)) {
1600
- afs_dataversion_t data_version = dvnode -> status .data_version + 1 ;
1615
+ data_version = dvnode -> status .data_version + 1 ;
1601
1616
1602
1617
while (afs_select_fileserver (& fc )) {
1603
1618
fc .cb_break = afs_calc_vnode_cb_break (dvnode );
@@ -1618,9 +1633,12 @@ static int afs_create(struct inode *dir, struct dentry *dentry, umode_t mode,
1618
1633
goto error_key ;
1619
1634
}
1620
1635
1621
- if (test_bit (AFS_VNODE_DIR_VALID , & dvnode -> flags ))
1636
+ down_write (& dvnode -> validate_lock );
1637
+ if (test_bit (AFS_VNODE_DIR_VALID , & dvnode -> flags ) &&
1638
+ dvnode -> status .data_version == data_version )
1622
1639
afs_edit_dir_add (dvnode , & dentry -> d_name , & iget_data .fid ,
1623
1640
afs_edit_dir_for_create );
1641
+ up_write (& dvnode -> validate_lock );
1624
1642
1625
1643
kfree (scb );
1626
1644
key_put (key );
@@ -1648,6 +1666,7 @@ static int afs_link(struct dentry *from, struct inode *dir,
1648
1666
struct afs_vnode * dvnode = AFS_FS_I (dir );
1649
1667
struct afs_vnode * vnode = AFS_FS_I (d_inode (from ));
1650
1668
struct key * key ;
1669
+ afs_dataversion_t data_version ;
1651
1670
int ret ;
1652
1671
1653
1672
_enter ("{%llx:%llu},{%llx:%llu},{%pd}" ,
@@ -1672,7 +1691,7 @@ static int afs_link(struct dentry *from, struct inode *dir,
1672
1691
1673
1692
ret = - ERESTARTSYS ;
1674
1693
if (afs_begin_vnode_operation (& fc , dvnode , key , true)) {
1675
- afs_dataversion_t data_version = dvnode -> status .data_version + 1 ;
1694
+ data_version = dvnode -> status .data_version + 1 ;
1676
1695
1677
1696
if (mutex_lock_interruptible_nested (& vnode -> io_lock , 1 ) < 0 ) {
1678
1697
afs_end_vnode_operation (& fc );
@@ -1702,9 +1721,12 @@ static int afs_link(struct dentry *from, struct inode *dir,
1702
1721
goto error_key ;
1703
1722
}
1704
1723
1705
- if (test_bit (AFS_VNODE_DIR_VALID , & dvnode -> flags ))
1724
+ down_write (& dvnode -> validate_lock );
1725
+ if (test_bit (AFS_VNODE_DIR_VALID , & dvnode -> flags ) &&
1726
+ dvnode -> status .data_version == data_version )
1706
1727
afs_edit_dir_add (dvnode , & dentry -> d_name , & vnode -> fid ,
1707
1728
afs_edit_dir_for_link );
1729
+ up_write (& dvnode -> validate_lock );
1708
1730
1709
1731
key_put (key );
1710
1732
kfree (scb );
@@ -1732,6 +1754,7 @@ static int afs_symlink(struct inode *dir, struct dentry *dentry,
1732
1754
struct afs_status_cb * scb ;
1733
1755
struct afs_vnode * dvnode = AFS_FS_I (dir );
1734
1756
struct key * key ;
1757
+ afs_dataversion_t data_version ;
1735
1758
int ret ;
1736
1759
1737
1760
_enter ("{%llx:%llu},{%pd},%s" ,
@@ -1759,7 +1782,7 @@ static int afs_symlink(struct inode *dir, struct dentry *dentry,
1759
1782
1760
1783
ret = - ERESTARTSYS ;
1761
1784
if (afs_begin_vnode_operation (& fc , dvnode , key , true)) {
1762
- afs_dataversion_t data_version = dvnode -> status .data_version + 1 ;
1785
+ data_version = dvnode -> status .data_version + 1 ;
1763
1786
1764
1787
while (afs_select_fileserver (& fc )) {
1765
1788
fc .cb_break = afs_calc_vnode_cb_break (dvnode );
@@ -1780,9 +1803,12 @@ static int afs_symlink(struct inode *dir, struct dentry *dentry,
1780
1803
goto error_key ;
1781
1804
}
1782
1805
1783
- if (test_bit (AFS_VNODE_DIR_VALID , & dvnode -> flags ))
1806
+ down_write (& dvnode -> validate_lock );
1807
+ if (test_bit (AFS_VNODE_DIR_VALID , & dvnode -> flags ) &&
1808
+ dvnode -> status .data_version == data_version )
1784
1809
afs_edit_dir_add (dvnode , & dentry -> d_name , & iget_data .fid ,
1785
1810
afs_edit_dir_for_symlink );
1811
+ up_write (& dvnode -> validate_lock );
1786
1812
1787
1813
key_put (key );
1788
1814
kfree (scb );
@@ -1812,6 +1838,8 @@ static int afs_rename(struct inode *old_dir, struct dentry *old_dentry,
1812
1838
struct dentry * tmp = NULL , * rehash = NULL ;
1813
1839
struct inode * new_inode ;
1814
1840
struct key * key ;
1841
+ afs_dataversion_t orig_data_version ;
1842
+ afs_dataversion_t new_data_version ;
1815
1843
bool new_negative = d_is_negative (new_dentry );
1816
1844
int ret ;
1817
1845
@@ -1890,10 +1918,6 @@ static int afs_rename(struct inode *old_dir, struct dentry *old_dentry,
1890
1918
1891
1919
ret = - ERESTARTSYS ;
1892
1920
if (afs_begin_vnode_operation (& fc , orig_dvnode , key , true)) {
1893
- afs_dataversion_t orig_data_version ;
1894
- afs_dataversion_t new_data_version ;
1895
- struct afs_status_cb * new_scb = & scb [1 ];
1896
-
1897
1921
orig_data_version = orig_dvnode -> status .data_version + 1 ;
1898
1922
1899
1923
if (orig_dvnode != new_dvnode ) {
@@ -1904,15 +1928,14 @@ static int afs_rename(struct inode *old_dir, struct dentry *old_dentry,
1904
1928
new_data_version = new_dvnode -> status .data_version + 1 ;
1905
1929
} else {
1906
1930
new_data_version = orig_data_version ;
1907
- new_scb = & scb [0 ];
1908
1931
}
1909
1932
1910
1933
while (afs_select_fileserver (& fc )) {
1911
1934
fc .cb_break = afs_calc_vnode_cb_break (orig_dvnode );
1912
1935
fc .cb_break_2 = afs_calc_vnode_cb_break (new_dvnode );
1913
1936
afs_fs_rename (& fc , old_dentry -> d_name .name ,
1914
1937
new_dvnode , new_dentry -> d_name .name ,
1915
- & scb [0 ], new_scb );
1938
+ & scb [0 ], & scb [ 1 ] );
1916
1939
}
1917
1940
1918
1941
afs_vnode_commit_status (& fc , orig_dvnode , fc .cb_break ,
@@ -1930,18 +1953,25 @@ static int afs_rename(struct inode *old_dir, struct dentry *old_dentry,
1930
1953
if (ret == 0 ) {
1931
1954
if (rehash )
1932
1955
d_rehash (rehash );
1933
- if (test_bit (AFS_VNODE_DIR_VALID , & orig_dvnode -> flags ))
1934
- afs_edit_dir_remove (orig_dvnode , & old_dentry -> d_name ,
1935
- afs_edit_dir_for_rename_0 );
1956
+ down_write (& orig_dvnode -> validate_lock );
1957
+ if (test_bit (AFS_VNODE_DIR_VALID , & orig_dvnode -> flags ) &&
1958
+ orig_dvnode -> status .data_version == orig_data_version )
1959
+ afs_edit_dir_remove (orig_dvnode , & old_dentry -> d_name ,
1960
+ afs_edit_dir_for_rename_0 );
1961
+ if (orig_dvnode != new_dvnode ) {
1962
+ up_write (& orig_dvnode -> validate_lock );
1936
1963
1937
- if (!new_negative &&
1938
- test_bit (AFS_VNODE_DIR_VALID , & new_dvnode -> flags ))
1939
- afs_edit_dir_remove (new_dvnode , & new_dentry -> d_name ,
1940
- afs_edit_dir_for_rename_1 );
1964
+ down_write (& new_dvnode -> validate_lock );
1965
+ }
1966
+ if (test_bit (AFS_VNODE_DIR_VALID , & new_dvnode -> flags ) &&
1967
+ orig_dvnode -> status .data_version == new_data_version ) {
1968
+ if (!new_negative )
1969
+ afs_edit_dir_remove (new_dvnode , & new_dentry -> d_name ,
1970
+ afs_edit_dir_for_rename_1 );
1941
1971
1942
- if (test_bit (AFS_VNODE_DIR_VALID , & new_dvnode -> flags ))
1943
1972
afs_edit_dir_add (new_dvnode , & new_dentry -> d_name ,
1944
1973
& vnode -> fid , afs_edit_dir_for_rename_2 );
1974
+ }
1945
1975
1946
1976
new_inode = d_inode (new_dentry );
1947
1977
if (new_inode ) {
@@ -1957,14 +1987,10 @@ static int afs_rename(struct inode *old_dir, struct dentry *old_dentry,
1957
1987
* Note that if we ever implement RENAME_EXCHANGE, we'll have
1958
1988
* to update both dentries with opposing dir versions.
1959
1989
*/
1960
- if (new_dvnode != orig_dvnode ) {
1961
- afs_update_dentry_version (& fc , old_dentry , & scb [1 ]);
1962
- afs_update_dentry_version (& fc , new_dentry , & scb [1 ]);
1963
- } else {
1964
- afs_update_dentry_version (& fc , old_dentry , & scb [0 ]);
1965
- afs_update_dentry_version (& fc , new_dentry , & scb [0 ]);
1966
- }
1990
+ afs_update_dentry_version (& fc , old_dentry , & scb [1 ]);
1991
+ afs_update_dentry_version (& fc , new_dentry , & scb [1 ]);
1967
1992
d_move (old_dentry , new_dentry );
1993
+ up_write (& new_dvnode -> validate_lock );
1968
1994
goto error_tmp ;
1969
1995
}
1970
1996
0 commit comments