Skip to content

Commit b835915

Browse files
committed
afs: Pass pre-fetch server and volume break counts into afs_iget5_set()
Pass the server and volume break counts from before the status fetch operation that queried the attributes of a file into afs_iget5_set() so that the new vnode's break counters can be initialised appropriately. This allows detection of a volume or server break that happened whilst we were fetching the status or setting up the vnode. Fixes: c435ee3 ("afs: Overhaul the callback handling") Signed-off-by: David Howells <[email protected]>
1 parent a38a755 commit b835915

File tree

4 files changed

+78
-49
lines changed

4 files changed

+78
-49
lines changed

fs/afs/dir.c

Lines changed: 38 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -641,7 +641,7 @@ static struct inode *afs_do_lookup(struct inode *dir, struct dentry *dentry,
641641
struct afs_cb_interest *dcbi, *cbi = NULL;
642642
struct afs_super_info *as = dir->i_sb->s_fs_info;
643643
struct afs_status_cb *scb;
644-
struct afs_iget_data data;
644+
struct afs_iget_data iget_data;
645645
struct afs_fs_cursor fc;
646646
struct afs_server *server;
647647
struct afs_vnode *dvnode = AFS_FS_I(dir);
@@ -684,9 +684,12 @@ static struct inode *afs_do_lookup(struct inode *dir, struct dentry *dentry,
684684
goto out;
685685

686686
/* Check to see if we already have an inode for the primary fid. */
687-
data.volume = dvnode->volume;
688-
data.fid = cookie->fids[0];
689-
inode = ilookup5(dir->i_sb, cookie->fids[0].vnode, afs_iget5_test, &data);
687+
iget_data.fid = cookie->fids[0];
688+
iget_data.volume = dvnode->volume;
689+
iget_data.cb_v_break = dvnode->volume->cb_v_break;
690+
iget_data.cb_s_break = 0;
691+
inode = ilookup5(dir->i_sb, cookie->fids[0].vnode,
692+
afs_iget5_test, &iget_data);
690693
if (inode)
691694
goto out;
692695

@@ -713,6 +716,8 @@ static struct inode *afs_do_lookup(struct inode *dir, struct dentry *dentry,
713716
fc.ac.error = -ECONNABORTED;
714717
break;
715718
}
719+
iget_data.cb_v_break = dvnode->volume->cb_v_break;
720+
iget_data.cb_s_break = fc.cbi->server->cb_s_break;
716721
afs_fs_inline_bulk_status(&fc,
717722
afs_v2net(dvnode),
718723
cookie->fids,
@@ -741,6 +746,8 @@ static struct inode *afs_do_lookup(struct inode *dir, struct dentry *dentry,
741746
inode = ERR_PTR(-ERESTARTSYS);
742747
if (afs_begin_vnode_operation(&fc, dvnode, key, true)) {
743748
while (afs_select_fileserver(&fc)) {
749+
iget_data.cb_v_break = dvnode->volume->cb_v_break;
750+
iget_data.cb_s_break = fc.cbi->server->cb_s_break;
744751
scb = &cookie->statuses[0];
745752
afs_fs_fetch_status(&fc,
746753
afs_v2net(dvnode),
@@ -775,8 +782,8 @@ static struct inode *afs_do_lookup(struct inode *dir, struct dentry *dentry,
775782
if (scb->status.abort_code != 0)
776783
continue;
777784

778-
ti = afs_iget(dir->i_sb, key, &cookie->fids[i],
779-
scb, cbi, dvnode);
785+
iget_data.fid = cookie->fids[i];
786+
ti = afs_iget(dir->i_sb, key, &iget_data, scb, cbi, dvnode);
780787
if (i == 0) {
781788
inode = ti;
782789
} else {
@@ -1112,7 +1119,7 @@ void afs_d_release(struct dentry *dentry)
11121119
*/
11131120
static void afs_vnode_new_inode(struct afs_fs_cursor *fc,
11141121
struct dentry *new_dentry,
1115-
struct afs_fid *newfid,
1122+
struct afs_iget_data *new_data,
11161123
struct afs_status_cb *new_scb)
11171124
{
11181125
struct afs_vnode *vnode;
@@ -1122,7 +1129,7 @@ static void afs_vnode_new_inode(struct afs_fs_cursor *fc,
11221129
return;
11231130

11241131
inode = afs_iget(fc->vnode->vfs_inode.i_sb, fc->key,
1125-
newfid, new_scb, fc->cbi, fc->vnode);
1132+
new_data, new_scb, fc->cbi, fc->vnode);
11261133
if (IS_ERR(inode)) {
11271134
/* ENOMEM or EINTR at a really inconvenient time - just abandon
11281135
* the new directory on the server.
@@ -1138,15 +1145,23 @@ static void afs_vnode_new_inode(struct afs_fs_cursor *fc,
11381145
d_instantiate(new_dentry, inode);
11391146
}
11401147

1148+
static void afs_prep_for_new_inode(struct afs_fs_cursor *fc,
1149+
struct afs_iget_data *iget_data)
1150+
{
1151+
iget_data->volume = fc->vnode->volume;
1152+
iget_data->cb_v_break = fc->vnode->volume->cb_v_break;
1153+
iget_data->cb_s_break = fc->cbi->server->cb_s_break;
1154+
}
1155+
11411156
/*
11421157
* create a directory on an AFS filesystem
11431158
*/
11441159
static int afs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
11451160
{
1161+
struct afs_iget_data iget_data;
11461162
struct afs_status_cb *scb;
11471163
struct afs_fs_cursor fc;
11481164
struct afs_vnode *dvnode = AFS_FS_I(dir);
1149-
struct afs_fid newfid;
11501165
struct key *key;
11511166
int ret;
11521167

@@ -1172,14 +1187,15 @@ static int afs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
11721187

11731188
while (afs_select_fileserver(&fc)) {
11741189
fc.cb_break = afs_calc_vnode_cb_break(dvnode);
1190+
afs_prep_for_new_inode(&fc, &iget_data);
11751191
afs_fs_create(&fc, dentry->d_name.name, mode,
1176-
&scb[0], &newfid, &scb[1]);
1192+
&scb[0], &iget_data.fid, &scb[1]);
11771193
}
11781194

11791195
afs_check_for_remote_deletion(&fc, dvnode);
11801196
afs_vnode_commit_status(&fc, dvnode, fc.cb_break,
11811197
&data_version, &scb[0]);
1182-
afs_vnode_new_inode(&fc, dentry, &newfid, &scb[1]);
1198+
afs_vnode_new_inode(&fc, dentry, &iget_data, &scb[1]);
11831199
ret = afs_end_vnode_operation(&fc);
11841200
if (ret < 0)
11851201
goto error_key;
@@ -1189,7 +1205,7 @@ static int afs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
11891205

11901206
if (ret == 0 &&
11911207
test_bit(AFS_VNODE_DIR_VALID, &dvnode->flags))
1192-
afs_edit_dir_add(dvnode, &dentry->d_name, &newfid,
1208+
afs_edit_dir_add(dvnode, &dentry->d_name, &iget_data.fid,
11931209
afs_edit_dir_for_create);
11941210

11951211
key_put(key);
@@ -1439,10 +1455,10 @@ static int afs_unlink(struct inode *dir, struct dentry *dentry)
14391455
static int afs_create(struct inode *dir, struct dentry *dentry, umode_t mode,
14401456
bool excl)
14411457
{
1458+
struct afs_iget_data iget_data;
14421459
struct afs_fs_cursor fc;
14431460
struct afs_status_cb *scb;
14441461
struct afs_vnode *dvnode = AFS_FS_I(dir);
1445-
struct afs_fid newfid;
14461462
struct key *key;
14471463
int ret;
14481464

@@ -1472,14 +1488,15 @@ static int afs_create(struct inode *dir, struct dentry *dentry, umode_t mode,
14721488

14731489
while (afs_select_fileserver(&fc)) {
14741490
fc.cb_break = afs_calc_vnode_cb_break(dvnode);
1491+
afs_prep_for_new_inode(&fc, &iget_data);
14751492
afs_fs_create(&fc, dentry->d_name.name, mode,
1476-
&scb[0], &newfid, &scb[1]);
1493+
&scb[0], &iget_data.fid, &scb[1]);
14771494
}
14781495

14791496
afs_check_for_remote_deletion(&fc, dvnode);
14801497
afs_vnode_commit_status(&fc, dvnode, fc.cb_break,
14811498
&data_version, &scb[0]);
1482-
afs_vnode_new_inode(&fc, dentry, &newfid, &scb[1]);
1499+
afs_vnode_new_inode(&fc, dentry, &iget_data, &scb[1]);
14831500
ret = afs_end_vnode_operation(&fc);
14841501
if (ret < 0)
14851502
goto error_key;
@@ -1488,7 +1505,7 @@ static int afs_create(struct inode *dir, struct dentry *dentry, umode_t mode,
14881505
}
14891506

14901507
if (test_bit(AFS_VNODE_DIR_VALID, &dvnode->flags))
1491-
afs_edit_dir_add(dvnode, &dentry->d_name, &newfid,
1508+
afs_edit_dir_add(dvnode, &dentry->d_name, &iget_data.fid,
14921509
afs_edit_dir_for_create);
14931510

14941511
kfree(scb);
@@ -1595,10 +1612,10 @@ static int afs_link(struct dentry *from, struct inode *dir,
15951612
static int afs_symlink(struct inode *dir, struct dentry *dentry,
15961613
const char *content)
15971614
{
1615+
struct afs_iget_data iget_data;
15981616
struct afs_fs_cursor fc;
15991617
struct afs_status_cb *scb;
16001618
struct afs_vnode *dvnode = AFS_FS_I(dir);
1601-
struct afs_fid newfid;
16021619
struct key *key;
16031620
int ret;
16041621

@@ -1631,14 +1648,15 @@ static int afs_symlink(struct inode *dir, struct dentry *dentry,
16311648

16321649
while (afs_select_fileserver(&fc)) {
16331650
fc.cb_break = afs_calc_vnode_cb_break(dvnode);
1651+
afs_prep_for_new_inode(&fc, &iget_data);
16341652
afs_fs_symlink(&fc, dentry->d_name.name, content,
1635-
&scb[0], &newfid, &scb[1]);
1653+
&scb[0], &iget_data.fid, &scb[1]);
16361654
}
16371655

16381656
afs_check_for_remote_deletion(&fc, dvnode);
16391657
afs_vnode_commit_status(&fc, dvnode, fc.cb_break,
16401658
&data_version, &scb[0]);
1641-
afs_vnode_new_inode(&fc, dentry, &newfid, &scb[1]);
1659+
afs_vnode_new_inode(&fc, dentry, &iget_data, &scb[1]);
16421660
ret = afs_end_vnode_operation(&fc);
16431661
if (ret < 0)
16441662
goto error_key;
@@ -1647,7 +1665,7 @@ static int afs_symlink(struct inode *dir, struct dentry *dentry,
16471665
}
16481666

16491667
if (test_bit(AFS_VNODE_DIR_VALID, &dvnode->flags))
1650-
afs_edit_dir_add(dvnode, &dentry->d_name, &newfid,
1668+
afs_edit_dir_add(dvnode, &dentry->d_name, &iget_data.fid,
16511669
afs_edit_dir_for_symlink);
16521670

16531671
key_put(key);

fs/afs/inode.c

Lines changed: 29 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -347,10 +347,10 @@ int afs_fetch_status(struct afs_vnode *vnode, struct key *key, bool is_new,
347347
*/
348348
int afs_iget5_test(struct inode *inode, void *opaque)
349349
{
350-
struct afs_iget_data *data = opaque;
350+
struct afs_iget_data *iget_data = opaque;
351351
struct afs_vnode *vnode = AFS_FS_I(inode);
352352

353-
return memcmp(&vnode->fid, &data->fid, sizeof(data->fid)) == 0;
353+
return memcmp(&vnode->fid, &iget_data->fid, sizeof(iget_data->fid)) == 0;
354354
}
355355

356356
/*
@@ -368,17 +368,19 @@ static int afs_iget5_pseudo_dir_test(struct inode *inode, void *opaque)
368368
*/
369369
static int afs_iget5_set(struct inode *inode, void *opaque)
370370
{
371-
struct afs_iget_data *data = opaque;
371+
struct afs_iget_data *iget_data = opaque;
372372
struct afs_vnode *vnode = AFS_FS_I(inode);
373373

374-
vnode->fid = data->fid;
375-
vnode->volume = data->volume;
374+
vnode->fid = iget_data->fid;
375+
vnode->volume = iget_data->volume;
376+
vnode->cb_v_break = iget_data->cb_v_break;
377+
vnode->cb_s_break = iget_data->cb_s_break;
376378

377379
/* YFS supports 96-bit vnode IDs, but Linux only supports
378380
* 64-bit inode numbers.
379381
*/
380-
inode->i_ino = data->fid.vnode;
381-
inode->i_generation = data->fid.unique;
382+
inode->i_ino = iget_data->fid.vnode;
383+
inode->i_generation = iget_data->fid.unique;
382384
return 0;
383385
}
384386

@@ -388,38 +390,42 @@ static int afs_iget5_set(struct inode *inode, void *opaque)
388390
*/
389391
struct inode *afs_iget_pseudo_dir(struct super_block *sb, bool root)
390392
{
391-
struct afs_iget_data data;
392393
struct afs_super_info *as;
393394
struct afs_vnode *vnode;
394395
struct inode *inode;
395396
static atomic_t afs_autocell_ino;
396397

398+
struct afs_iget_data iget_data = {
399+
.cb_v_break = 0,
400+
.cb_s_break = 0,
401+
};
402+
397403
_enter("");
398404

399405
as = sb->s_fs_info;
400406
if (as->volume) {
401-
data.volume = as->volume;
402-
data.fid.vid = as->volume->vid;
407+
iget_data.volume = as->volume;
408+
iget_data.fid.vid = as->volume->vid;
403409
}
404410
if (root) {
405-
data.fid.vnode = 1;
406-
data.fid.unique = 1;
411+
iget_data.fid.vnode = 1;
412+
iget_data.fid.unique = 1;
407413
} else {
408-
data.fid.vnode = atomic_inc_return(&afs_autocell_ino);
409-
data.fid.unique = 0;
414+
iget_data.fid.vnode = atomic_inc_return(&afs_autocell_ino);
415+
iget_data.fid.unique = 0;
410416
}
411417

412-
inode = iget5_locked(sb, data.fid.vnode,
418+
inode = iget5_locked(sb, iget_data.fid.vnode,
413419
afs_iget5_pseudo_dir_test, afs_iget5_set,
414-
&data);
420+
&iget_data);
415421
if (!inode) {
416422
_leave(" = -ENOMEM");
417423
return ERR_PTR(-ENOMEM);
418424
}
419425

420426
_debug("GOT INODE %p { ino=%lu, vl=%llx, vn=%llx, u=%x }",
421-
inode, inode->i_ino, data.fid.vid, data.fid.vnode,
422-
data.fid.unique);
427+
inode, inode->i_ino, iget_data.fid.vid, iget_data.fid.vnode,
428+
iget_data.fid.unique);
423429

424430
vnode = AFS_FS_I(inode);
425431

@@ -490,23 +496,24 @@ static void afs_get_inode_cache(struct afs_vnode *vnode)
490496
* inode retrieval
491497
*/
492498
struct inode *afs_iget(struct super_block *sb, struct key *key,
493-
struct afs_fid *fid, struct afs_status_cb *scb,
499+
struct afs_iget_data *iget_data,
500+
struct afs_status_cb *scb,
494501
struct afs_cb_interest *cbi,
495502
struct afs_vnode *parent_vnode)
496503
{
497-
struct afs_iget_data data = { .fid = *fid };
498504
struct afs_super_info *as;
499505
struct afs_vnode *vnode;
506+
struct afs_fid *fid = &iget_data->fid;
500507
struct inode *inode;
501508
int ret;
502509

503510
_enter(",{%llx:%llu.%u},,", fid->vid, fid->vnode, fid->unique);
504511

505512
as = sb->s_fs_info;
506-
data.volume = as->volume;
513+
iget_data->volume = as->volume;
507514

508515
inode = iget5_locked(sb, fid->vnode, afs_iget5_test, afs_iget5_set,
509-
&data);
516+
iget_data);
510517
if (!inode) {
511518
_leave(" = -ENOMEM");
512519
return ERR_PTR(-ENOMEM);

fs/afs/internal.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,8 @@ struct afs_fs_context {
6666
struct afs_iget_data {
6767
struct afs_fid fid;
6868
struct afs_volume *volume; /* volume on which resides */
69+
unsigned int cb_v_break; /* Pre-fetch volume break count */
70+
unsigned int cb_s_break; /* Pre-fetch server break count */
6971
};
7072

7173
enum afs_call_state {
@@ -1023,7 +1025,7 @@ extern int afs_fetch_status(struct afs_vnode *, struct key *, bool, afs_access_t
10231025
extern int afs_iget5_test(struct inode *, void *);
10241026
extern struct inode *afs_iget_pseudo_dir(struct super_block *, bool);
10251027
extern struct inode *afs_iget(struct super_block *, struct key *,
1026-
struct afs_fid *, struct afs_status_cb *,
1028+
struct afs_iget_data *, struct afs_status_cb *,
10271029
struct afs_cb_interest *,
10281030
struct afs_vnode *);
10291031
extern void afs_zap_data(struct afs_vnode *);

fs/afs/super.c

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -426,7 +426,7 @@ static int afs_set_super(struct super_block *sb, struct fs_context *fc)
426426
static int afs_fill_super(struct super_block *sb, struct afs_fs_context *ctx)
427427
{
428428
struct afs_super_info *as = AFS_FS_S(sb);
429-
struct afs_fid fid;
429+
struct afs_iget_data iget_data;
430430
struct inode *inode = NULL;
431431
int ret;
432432

@@ -451,11 +451,13 @@ static int afs_fill_super(struct super_block *sb, struct afs_fs_context *ctx)
451451
} else {
452452
sprintf(sb->s_id, "%llu", as->volume->vid);
453453
afs_activate_volume(as->volume);
454-
fid.vid = as->volume->vid;
455-
fid.vnode = 1;
456-
fid.vnode_hi = 0;
457-
fid.unique = 1;
458-
inode = afs_iget(sb, ctx->key, &fid, NULL, NULL, NULL);
454+
iget_data.fid.vid = as->volume->vid;
455+
iget_data.fid.vnode = 1;
456+
iget_data.fid.vnode_hi = 0;
457+
iget_data.fid.unique = 1;
458+
iget_data.cb_v_break = as->volume->cb_v_break;
459+
iget_data.cb_s_break = 0;
460+
inode = afs_iget(sb, ctx->key, &iget_data, NULL, NULL, NULL);
459461
}
460462

461463
if (IS_ERR(inode))

0 commit comments

Comments
 (0)