aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Howells <dhowells@redhat.com>2019-05-14 07:33:10 -0400
committerDavid Howells <dhowells@redhat.com>2019-05-16 17:23:21 -0400
commit39db9815da489b47b50b8e6e4fc7566a77bd18bf (patch)
treefbdb5d1e2e32e4a3ec9c695f000d295b36138c2e
parentb8359153252d4465cb74f8de6c50e8c6295cbe2e (diff)
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: 5cf9dd55a0ec ("afs: Prospectively look up extra files when doing a single lookup") Signed-off-by: David Howells <dhowells@redhat.com>
-rw-r--r--fs/afs/afs.h1
-rw-r--r--fs/afs/dir.c51
2 files changed, 45 insertions, 7 deletions
diff --git a/fs/afs/afs.h b/fs/afs/afs.h
index a7d3f902a91c..3f4e460c6655 100644
--- a/fs/afs/afs.h
+++ b/fs/afs/afs.h
@@ -150,6 +150,7 @@ struct afs_file_status {
150struct afs_status_cb { 150struct afs_status_cb {
151 struct afs_file_status status; 151 struct afs_file_status status;
152 struct afs_callback callback; 152 struct afs_callback callback;
153 unsigned int cb_break; /* Pre-op callback break counter */
153 bool have_status; /* True if status record was retrieved */ 154 bool have_status; /* True if status record was retrieved */
154 bool have_cb; /* True if cb record was retrieved */ 155 bool have_cb; /* True if cb record was retrieved */
155 bool have_error; /* True if status.abort_code indicates an error */ 156 bool have_error; /* True if status.abort_code indicates an error */
diff --git a/fs/afs/dir.c b/fs/afs/dir.c
index 9e42f6c75747..79d93a26759a 100644
--- a/fs/afs/dir.c
+++ b/fs/afs/dir.c
@@ -103,6 +103,7 @@ struct afs_lookup_cookie {
103 bool found; 103 bool found;
104 bool one_only; 104 bool one_only;
105 unsigned short nr_fids; 105 unsigned short nr_fids;
106 struct inode **inodes;
106 struct afs_status_cb *statuses; 107 struct afs_status_cb *statuses;
107 struct afs_fid fids[50]; 108 struct afs_fid fids[50];
108}; 109};
@@ -644,8 +645,8 @@ static struct inode *afs_do_lookup(struct inode *dir, struct dentry *dentry,
644 struct afs_iget_data iget_data; 645 struct afs_iget_data iget_data;
645 struct afs_fs_cursor fc; 646 struct afs_fs_cursor fc;
646 struct afs_server *server; 647 struct afs_server *server;
647 struct afs_vnode *dvnode = AFS_FS_I(dir); 648 struct afs_vnode *dvnode = AFS_FS_I(dir), *vnode;
648 struct inode *inode = NULL; 649 struct inode *inode = NULL, *ti;
649 int ret, i; 650 int ret, i;
650 651
651 _enter("{%lu},%p{%pd},", dir->i_ino, dentry, dentry); 652 _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,
700 if (!cookie->statuses) 701 if (!cookie->statuses)
701 goto out; 702 goto out;
702 703
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
703 /* Try FS.InlineBulkStatus first. Abort codes for the individual 725 /* Try FS.InlineBulkStatus first. Abort codes for the individual
704 * lookups contained therein are stored in the reply without aborting 726 * lookups contained therein are stored in the reply without aborting
705 * the whole operation. 727 * the whole operation.
@@ -742,7 +764,6 @@ no_inline_bulk_status:
742 * any of the lookups fails - so, for the moment, revert to 764 * any of the lookups fails - so, for the moment, revert to
743 * FS.FetchStatus for just the primary fid. 765 * FS.FetchStatus for just the primary fid.
744 */ 766 */
745 cookie->nr_fids = 1;
746 inode = ERR_PTR(-ERESTARTSYS); 767 inode = ERR_PTR(-ERESTARTSYS);
747 if (afs_begin_vnode_operation(&fc, dvnode, key, true)) { 768 if (afs_begin_vnode_operation(&fc, dvnode, key, true)) {
748 while (afs_select_fileserver(&fc)) { 769 while (afs_select_fileserver(&fc)) {
@@ -764,9 +785,6 @@ no_inline_bulk_status:
764 if (IS_ERR(inode)) 785 if (IS_ERR(inode))
765 goto out_c; 786 goto out_c;
766 787
767 for (i = 0; i < cookie->nr_fids; i++)
768 cookie->statuses[i].status.abort_code = 0;
769
770success: 788success:
771 /* Turn all the files into inodes and save the first one - which is the 789 /* Turn all the files into inodes and save the first one - which is the
772 * one we actually want. 790 * one we actually want.
@@ -777,13 +795,26 @@ success:
777 795
778 for (i = 0; i < cookie->nr_fids; i++) { 796 for (i = 0; i < cookie->nr_fids; i++) {
779 struct afs_status_cb *scb = &cookie->statuses[i]; 797 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 }
781 807
782 if (scb->status.abort_code != 0) 808 if (scb->status.abort_code != 0)
783 continue; 809 continue;
784 810
785 iget_data.fid = cookie->fids[i]; 811 iget_data.fid = cookie->fids[i];
786 ti = afs_iget(dir->i_sb, key, &iget_data, scb, cbi, dvnode); 812 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);
787 if (i == 0) { 818 if (i == 0) {
788 inode = ti; 819 inode = ti;
789 } else { 820 } else {
@@ -794,6 +825,12 @@ success:
794 825
795out_c: 826out_c:
796 afs_put_cb_interest(afs_v2net(dvnode), cbi); 827 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 }
833out_s:
797 kvfree(cookie->statuses); 834 kvfree(cookie->statuses);
798out: 835out:
799 kfree(cookie); 836 kfree(cookie);