@@ -130,17 +130,26 @@ static bool afs_dir_check_page(struct afs_vnode *dvnode, struct page *page,
130
130
qty /= sizeof (union afs_xdr_dir_block );
131
131
132
132
/* check them */
133
- dbuf = page_address (page );
133
+ dbuf = kmap (page );
134
134
for (tmp = 0 ; tmp < qty ; tmp ++ ) {
135
135
if (dbuf -> blocks [tmp ].hdr .magic != AFS_DIR_MAGIC ) {
136
136
printk ("kAFS: %s(%lx): bad magic %d/%d is %04hx\n" ,
137
137
__func__ , dvnode -> vfs_inode .i_ino , tmp , qty ,
138
138
ntohs (dbuf -> blocks [tmp ].hdr .magic ));
139
139
trace_afs_dir_check_failed (dvnode , off , i_size );
140
+ kunmap (page );
140
141
goto error ;
141
142
}
143
+
144
+ /* Make sure each block is NUL terminated so we can reasonably
145
+ * use string functions on it. The filenames in the page
146
+ * *should* be NUL-terminated anyway.
147
+ */
148
+ ((u8 * )& dbuf -> blocks [tmp ])[AFS_DIR_BLOCK_SIZE - 1 ] = 0 ;
142
149
}
143
150
151
+ kunmap (page );
152
+
144
153
checked :
145
154
afs_stat_v (dvnode , n_read_dir );
146
155
return true;
@@ -1114,6 +1123,7 @@ static int afs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
1114
1123
struct afs_vnode * dvnode = AFS_FS_I (dir );
1115
1124
struct afs_fid newfid ;
1116
1125
struct key * key ;
1126
+ u64 data_version = dvnode -> status .data_version ;
1117
1127
int ret ;
1118
1128
1119
1129
mode |= S_IFDIR ;
@@ -1131,7 +1141,7 @@ static int afs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
1131
1141
if (afs_begin_vnode_operation (& fc , dvnode , key )) {
1132
1142
while (afs_select_fileserver (& fc )) {
1133
1143
fc .cb_break = dvnode -> cb_break + dvnode -> cb_s_break ;
1134
- afs_fs_create (& fc , dentry -> d_name .name , mode ,
1144
+ afs_fs_create (& fc , dentry -> d_name .name , mode , data_version ,
1135
1145
& newfid , & newstatus , & newcb );
1136
1146
}
1137
1147
@@ -1145,6 +1155,11 @@ static int afs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
1145
1155
goto error_key ;
1146
1156
}
1147
1157
1158
+ if (ret == 0 &&
1159
+ test_bit (AFS_VNODE_DIR_VALID , & dvnode -> flags ))
1160
+ afs_edit_dir_add (dvnode , & dentry -> d_name , & newfid ,
1161
+ afs_edit_dir_for_create );
1162
+
1148
1163
key_put (key );
1149
1164
_leave (" = 0" );
1150
1165
return 0 ;
@@ -1168,6 +1183,7 @@ static void afs_dir_remove_subdir(struct dentry *dentry)
1168
1183
clear_nlink (& vnode -> vfs_inode );
1169
1184
set_bit (AFS_VNODE_DELETED , & vnode -> flags );
1170
1185
clear_bit (AFS_VNODE_CB_PROMISED , & vnode -> flags );
1186
+ clear_bit (AFS_VNODE_DIR_VALID , & vnode -> flags );
1171
1187
}
1172
1188
}
1173
1189
@@ -1179,6 +1195,7 @@ static int afs_rmdir(struct inode *dir, struct dentry *dentry)
1179
1195
struct afs_fs_cursor fc ;
1180
1196
struct afs_vnode * dvnode = AFS_FS_I (dir );
1181
1197
struct key * key ;
1198
+ u64 data_version = dvnode -> status .data_version ;
1182
1199
int ret ;
1183
1200
1184
1201
_enter ("{%x:%u},{%pd}" ,
@@ -1194,13 +1211,18 @@ static int afs_rmdir(struct inode *dir, struct dentry *dentry)
1194
1211
if (afs_begin_vnode_operation (& fc , dvnode , key )) {
1195
1212
while (afs_select_fileserver (& fc )) {
1196
1213
fc .cb_break = dvnode -> cb_break + dvnode -> cb_s_break ;
1197
- afs_fs_remove (& fc , dentry -> d_name .name , true);
1214
+ afs_fs_remove (& fc , dentry -> d_name .name , true,
1215
+ data_version );
1198
1216
}
1199
1217
1200
1218
afs_vnode_commit_status (& fc , dvnode , fc .cb_break );
1201
1219
ret = afs_end_vnode_operation (& fc );
1202
- if (ret == 0 )
1220
+ if (ret == 0 ) {
1203
1221
afs_dir_remove_subdir (dentry );
1222
+ if (test_bit (AFS_VNODE_DIR_VALID , & dvnode -> flags ))
1223
+ afs_edit_dir_remove (dvnode , & dentry -> d_name ,
1224
+ afs_edit_dir_for_rmdir );
1225
+ }
1204
1226
}
1205
1227
1206
1228
key_put (key );
@@ -1265,6 +1287,7 @@ static int afs_unlink(struct inode *dir, struct dentry *dentry)
1265
1287
struct afs_vnode * dvnode = AFS_FS_I (dir ), * vnode ;
1266
1288
struct key * key ;
1267
1289
unsigned long d_version = (unsigned long )dentry -> d_fsdata ;
1290
+ u64 data_version = dvnode -> status .data_version ;
1268
1291
int ret ;
1269
1292
1270
1293
_enter ("{%x:%u},{%pd}" ,
@@ -1291,7 +1314,8 @@ static int afs_unlink(struct inode *dir, struct dentry *dentry)
1291
1314
if (afs_begin_vnode_operation (& fc , dvnode , key )) {
1292
1315
while (afs_select_fileserver (& fc )) {
1293
1316
fc .cb_break = dvnode -> cb_break + dvnode -> cb_s_break ;
1294
- afs_fs_remove (& fc , dentry -> d_name .name , false);
1317
+ afs_fs_remove (& fc , dentry -> d_name .name , false,
1318
+ data_version );
1295
1319
}
1296
1320
1297
1321
afs_vnode_commit_status (& fc , dvnode , fc .cb_break );
@@ -1300,6 +1324,10 @@ static int afs_unlink(struct inode *dir, struct dentry *dentry)
1300
1324
ret = afs_dir_remove_link (
1301
1325
dentry , key , d_version ,
1302
1326
(unsigned long )dvnode -> status .data_version );
1327
+ if (ret == 0 &&
1328
+ test_bit (AFS_VNODE_DIR_VALID , & dvnode -> flags ))
1329
+ afs_edit_dir_remove (dvnode , & dentry -> d_name ,
1330
+ afs_edit_dir_for_unlink );
1303
1331
}
1304
1332
1305
1333
error_key :
@@ -1321,6 +1349,7 @@ static int afs_create(struct inode *dir, struct dentry *dentry, umode_t mode,
1321
1349
struct afs_vnode * dvnode = AFS_FS_I (dir );
1322
1350
struct afs_fid newfid ;
1323
1351
struct key * key ;
1352
+ u64 data_version = dvnode -> status .data_version ;
1324
1353
int ret ;
1325
1354
1326
1355
mode |= S_IFREG ;
@@ -1342,7 +1371,7 @@ static int afs_create(struct inode *dir, struct dentry *dentry, umode_t mode,
1342
1371
if (afs_begin_vnode_operation (& fc , dvnode , key )) {
1343
1372
while (afs_select_fileserver (& fc )) {
1344
1373
fc .cb_break = dvnode -> cb_break + dvnode -> cb_s_break ;
1345
- afs_fs_create (& fc , dentry -> d_name .name , mode ,
1374
+ afs_fs_create (& fc , dentry -> d_name .name , mode , data_version ,
1346
1375
& newfid , & newstatus , & newcb );
1347
1376
}
1348
1377
@@ -1356,6 +1385,10 @@ static int afs_create(struct inode *dir, struct dentry *dentry, umode_t mode,
1356
1385
goto error_key ;
1357
1386
}
1358
1387
1388
+ if (test_bit (AFS_VNODE_DIR_VALID , & dvnode -> flags ))
1389
+ afs_edit_dir_add (dvnode , & dentry -> d_name , & newfid ,
1390
+ afs_edit_dir_for_create );
1391
+
1359
1392
key_put (key );
1360
1393
_leave (" = 0" );
1361
1394
return 0 ;
@@ -1377,10 +1410,12 @@ static int afs_link(struct dentry *from, struct inode *dir,
1377
1410
struct afs_fs_cursor fc ;
1378
1411
struct afs_vnode * dvnode , * vnode ;
1379
1412
struct key * key ;
1413
+ u64 data_version ;
1380
1414
int ret ;
1381
1415
1382
1416
vnode = AFS_FS_I (d_inode (from ));
1383
1417
dvnode = AFS_FS_I (dir );
1418
+ data_version = dvnode -> status .data_version ;
1384
1419
1385
1420
_enter ("{%x:%u},{%x:%u},{%pd}" ,
1386
1421
vnode -> fid .vid , vnode -> fid .vnode ,
@@ -1407,7 +1442,7 @@ static int afs_link(struct dentry *from, struct inode *dir,
1407
1442
while (afs_select_fileserver (& fc )) {
1408
1443
fc .cb_break = dvnode -> cb_break + dvnode -> cb_s_break ;
1409
1444
fc .cb_break_2 = vnode -> cb_break + vnode -> cb_s_break ;
1410
- afs_fs_link (& fc , vnode , dentry -> d_name .name );
1445
+ afs_fs_link (& fc , vnode , dentry -> d_name .name , data_version );
1411
1446
}
1412
1447
1413
1448
afs_vnode_commit_status (& fc , dvnode , fc .cb_break );
@@ -1423,6 +1458,10 @@ static int afs_link(struct dentry *from, struct inode *dir,
1423
1458
goto error_key ;
1424
1459
}
1425
1460
1461
+ if (test_bit (AFS_VNODE_DIR_VALID , & dvnode -> flags ))
1462
+ afs_edit_dir_add (dvnode , & dentry -> d_name , & vnode -> fid ,
1463
+ afs_edit_dir_for_link );
1464
+
1426
1465
key_put (key );
1427
1466
_leave (" = 0" );
1428
1467
return 0 ;
@@ -1446,6 +1485,7 @@ static int afs_symlink(struct inode *dir, struct dentry *dentry,
1446
1485
struct afs_vnode * dvnode = AFS_FS_I (dir );
1447
1486
struct afs_fid newfid ;
1448
1487
struct key * key ;
1488
+ u64 data_version = dvnode -> status .data_version ;
1449
1489
int ret ;
1450
1490
1451
1491
_enter ("{%x:%u},{%pd},%s" ,
@@ -1470,7 +1510,8 @@ static int afs_symlink(struct inode *dir, struct dentry *dentry,
1470
1510
if (afs_begin_vnode_operation (& fc , dvnode , key )) {
1471
1511
while (afs_select_fileserver (& fc )) {
1472
1512
fc .cb_break = dvnode -> cb_break + dvnode -> cb_s_break ;
1473
- afs_fs_symlink (& fc , dentry -> d_name .name , content ,
1513
+ afs_fs_symlink (& fc , dentry -> d_name .name ,
1514
+ content , data_version ,
1474
1515
& newfid , & newstatus );
1475
1516
}
1476
1517
@@ -1484,6 +1525,10 @@ static int afs_symlink(struct inode *dir, struct dentry *dentry,
1484
1525
goto error_key ;
1485
1526
}
1486
1527
1528
+ if (test_bit (AFS_VNODE_DIR_VALID , & dvnode -> flags ))
1529
+ afs_edit_dir_add (dvnode , & dentry -> d_name , & newfid ,
1530
+ afs_edit_dir_for_symlink );
1531
+
1487
1532
key_put (key );
1488
1533
_leave (" = 0" );
1489
1534
return 0 ;
@@ -1506,6 +1551,8 @@ static int afs_rename(struct inode *old_dir, struct dentry *old_dentry,
1506
1551
struct afs_fs_cursor fc ;
1507
1552
struct afs_vnode * orig_dvnode , * new_dvnode , * vnode ;
1508
1553
struct key * key ;
1554
+ u64 orig_data_version , new_data_version ;
1555
+ bool new_negative = d_is_negative (new_dentry );
1509
1556
int ret ;
1510
1557
1511
1558
if (flags )
@@ -1514,6 +1561,8 @@ static int afs_rename(struct inode *old_dir, struct dentry *old_dentry,
1514
1561
vnode = AFS_FS_I (d_inode (old_dentry ));
1515
1562
orig_dvnode = AFS_FS_I (old_dir );
1516
1563
new_dvnode = AFS_FS_I (new_dir );
1564
+ orig_data_version = orig_dvnode -> status .data_version ;
1565
+ new_data_version = new_dvnode -> status .data_version ;
1517
1566
1518
1567
_enter ("{%x:%u},{%x:%u},{%x:%u},{%pd}" ,
1519
1568
orig_dvnode -> fid .vid , orig_dvnode -> fid .vnode ,
@@ -1539,7 +1588,8 @@ static int afs_rename(struct inode *old_dir, struct dentry *old_dentry,
1539
1588
fc .cb_break = orig_dvnode -> cb_break + orig_dvnode -> cb_s_break ;
1540
1589
fc .cb_break_2 = new_dvnode -> cb_break + new_dvnode -> cb_s_break ;
1541
1590
afs_fs_rename (& fc , old_dentry -> d_name .name ,
1542
- new_dvnode , new_dentry -> d_name .name );
1591
+ new_dvnode , new_dentry -> d_name .name ,
1592
+ orig_data_version , new_data_version );
1543
1593
}
1544
1594
1545
1595
afs_vnode_commit_status (& fc , orig_dvnode , fc .cb_break );
@@ -1551,6 +1601,21 @@ static int afs_rename(struct inode *old_dir, struct dentry *old_dentry,
1551
1601
goto error_key ;
1552
1602
}
1553
1603
1604
+ if (ret == 0 ) {
1605
+ if (test_bit (AFS_VNODE_DIR_VALID , & orig_dvnode -> flags ))
1606
+ afs_edit_dir_remove (orig_dvnode , & old_dentry -> d_name ,
1607
+ afs_edit_dir_for_rename );
1608
+
1609
+ if (!new_negative &&
1610
+ test_bit (AFS_VNODE_DIR_VALID , & new_dvnode -> flags ))
1611
+ afs_edit_dir_remove (new_dvnode , & new_dentry -> d_name ,
1612
+ afs_edit_dir_for_rename );
1613
+
1614
+ if (test_bit (AFS_VNODE_DIR_VALID , & new_dvnode -> flags ))
1615
+ afs_edit_dir_add (new_dvnode , & new_dentry -> d_name ,
1616
+ & vnode -> fid , afs_edit_dir_for_rename );
1617
+ }
1618
+
1554
1619
error_key :
1555
1620
key_put (key );
1556
1621
error :
0 commit comments