Skip to content

Commit 39db981

Browse files
committed
afs: Fix application of the results of a inline bulk status fetch
Fix afs_do_lookup() such that when it does an inline bulk status fetch op, it will update inodes that are already extant (something that afs_iget() doesn't do) and to cache permits for each inode created (thereby avoiding a follow up FS.FetchStatus call to determine this). Extant inodes need looking up in advance so that their cb_break counters before and after the operation can be compared. To this end, the inode pointers are cached so that they don't need looking up again after the op. Fixes: 5cf9dd5 ("afs: Prospectively look up extra files when doing a single lookup") Signed-off-by: David Howells <[email protected]>
1 parent b835915 commit 39db981

File tree

2 files changed

+45
-7
lines changed

2 files changed

+45
-7
lines changed

fs/afs/afs.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,7 @@ struct afs_file_status {
150150
struct afs_status_cb {
151151
struct afs_file_status status;
152152
struct afs_callback callback;
153+
unsigned int cb_break; /* Pre-op callback break counter */
153154
bool have_status; /* True if status record was retrieved */
154155
bool have_cb; /* True if cb record was retrieved */
155156
bool have_error; /* True if status.abort_code indicates an error */

fs/afs/dir.c

Lines changed: 44 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,7 @@ struct afs_lookup_cookie {
103103
bool found;
104104
bool one_only;
105105
unsigned short nr_fids;
106+
struct inode **inodes;
106107
struct afs_status_cb *statuses;
107108
struct afs_fid fids[50];
108109
};
@@ -644,8 +645,8 @@ static struct inode *afs_do_lookup(struct inode *dir, struct dentry *dentry,
644645
struct afs_iget_data iget_data;
645646
struct afs_fs_cursor fc;
646647
struct afs_server *server;
647-
struct afs_vnode *dvnode = AFS_FS_I(dir);
648-
struct inode *inode = NULL;
648+
struct afs_vnode *dvnode = AFS_FS_I(dir), *vnode;
649+
struct inode *inode = NULL, *ti;
649650
int ret, i;
650651

651652
_enter("{%lu},%p{%pd},", dir->i_ino, dentry, dentry);
@@ -700,6 +701,27 @@ static struct inode *afs_do_lookup(struct inode *dir, struct dentry *dentry,
700701
if (!cookie->statuses)
701702
goto out;
702703

704+
cookie->inodes = kcalloc(cookie->nr_fids, sizeof(struct inode *),
705+
GFP_KERNEL);
706+
if (!cookie->inodes)
707+
goto out_s;
708+
709+
for (i = 1; i < cookie->nr_fids; i++) {
710+
scb = &cookie->statuses[i];
711+
712+
/* Find any inodes that already exist and get their
713+
* callback counters.
714+
*/
715+
iget_data.fid = cookie->fids[i];
716+
ti = ilookup5_nowait(dir->i_sb, iget_data.fid.vnode,
717+
afs_iget5_test, &iget_data);
718+
if (!IS_ERR_OR_NULL(ti)) {
719+
vnode = AFS_FS_I(ti);
720+
scb->cb_break = afs_calc_vnode_cb_break(vnode);
721+
cookie->inodes[i] = ti;
722+
}
723+
}
724+
703725
/* Try FS.InlineBulkStatus first. Abort codes for the individual
704726
* lookups contained therein are stored in the reply without aborting
705727
* the whole operation.
@@ -742,7 +764,6 @@ static struct inode *afs_do_lookup(struct inode *dir, struct dentry *dentry,
742764
* any of the lookups fails - so, for the moment, revert to
743765
* FS.FetchStatus for just the primary fid.
744766
*/
745-
cookie->nr_fids = 1;
746767
inode = ERR_PTR(-ERESTARTSYS);
747768
if (afs_begin_vnode_operation(&fc, dvnode, key, true)) {
748769
while (afs_select_fileserver(&fc)) {
@@ -764,9 +785,6 @@ static struct inode *afs_do_lookup(struct inode *dir, struct dentry *dentry,
764785
if (IS_ERR(inode))
765786
goto out_c;
766787

767-
for (i = 0; i < cookie->nr_fids; i++)
768-
cookie->statuses[i].status.abort_code = 0;
769-
770788
success:
771789
/* Turn all the files into inodes and save the first one - which is the
772790
* one we actually want.
@@ -777,13 +795,26 @@ static struct inode *afs_do_lookup(struct inode *dir, struct dentry *dentry,
777795

778796
for (i = 0; i < cookie->nr_fids; i++) {
779797
struct afs_status_cb *scb = &cookie->statuses[i];
780-
struct inode *ti;
798+
799+
if (!scb->have_status && !scb->have_error)
800+
continue;
801+
802+
if (cookie->inodes[i]) {
803+
afs_vnode_commit_status(&fc, AFS_FS_I(cookie->inodes[i]),
804+
scb->cb_break, NULL, scb);
805+
continue;
806+
}
781807

782808
if (scb->status.abort_code != 0)
783809
continue;
784810

785811
iget_data.fid = cookie->fids[i];
786812
ti = afs_iget(dir->i_sb, key, &iget_data, scb, cbi, dvnode);
813+
if (!IS_ERR(ti))
814+
afs_cache_permit(AFS_FS_I(ti), key,
815+
0 /* Assume vnode->cb_break is 0 */ +
816+
iget_data.cb_v_break,
817+
scb);
787818
if (i == 0) {
788819
inode = ti;
789820
} else {
@@ -794,6 +825,12 @@ static struct inode *afs_do_lookup(struct inode *dir, struct dentry *dentry,
794825

795826
out_c:
796827
afs_put_cb_interest(afs_v2net(dvnode), cbi);
828+
if (cookie->inodes) {
829+
for (i = 0; i < cookie->nr_fids; i++)
830+
iput(cookie->inodes[i]);
831+
kfree(cookie->inodes);
832+
}
833+
out_s:
797834
kvfree(cookie->statuses);
798835
out:
799836
kfree(cookie);

0 commit comments

Comments
 (0)