Message ID | 9a2b0c5b625cd88c561289bf7d4d7dfe305c10ed.1693440240.git.kjlx@templeofstupid.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | virtiofs submounts forgotten after client / guest memory pressure | expand |
Hi Krister, kernel test robot noticed the following build warnings: [auto build test WARNING on linus/master] [also build test WARNING on v6.6-rc1 next-20230911] [If your patch is applied to the wrong git tree, kindly drop us a note. And when submitting patch, we suggest to use '--base' as documented in https://git-scm.com/docs/git-format-patch#_base_tree_information] url: https://github.com/intel-lab-lkp/linux/commits/Krister-Johansen/fuse-revalidate-move-lookup-into-a-separate-function/20230912-051352 base: linus/master patch link: https://lore.kernel.org/r/9a2b0c5b625cd88c561289bf7d4d7dfe305c10ed.1693440240.git.kjlx%40templeofstupid.com patch subject: [PATCH 1/2] fuse: revalidate: move lookup into a separate function config: m68k-allyesconfig (https://download.01.org/0day-ci/archive/20230912/202309120853.QbAMM1to-lkp@intel.com/config) compiler: m68k-linux-gcc (GCC) 13.2.0 reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20230912/202309120853.QbAMM1to-lkp@intel.com/reproduce) If you fix the issue in a separate patch/commit (i.e. not just a new version of the same patch/commit), kindly add following tags | Reported-by: kernel test robot <lkp@intel.com> | Closes: https://lore.kernel.org/oe-kbuild-all/202309120853.QbAMM1to-lkp@intel.com/ All warnings (new ones prefixed by >>): fs/fuse/dir.c: In function 'fuse_dentry_revalidate_lookup': >> fs/fuse/dir.c:194:28: warning: variable 'fi' set but not used [-Wunused-but-set-variable] 194 | struct fuse_inode *fi; | ^~ vim +/fi +194 fs/fuse/dir.c 185 186 static int fuse_dentry_revalidate_lookup(struct fuse_mount *fm, 187 struct dentry *entry, 188 struct inode *inode, 189 struct fuse_entry_out *outarg, 190 bool *lookedup) 191 { 192 struct dentry *parent; 193 struct fuse_forget_link *forget; > 194 struct fuse_inode *fi; 195 FUSE_ARGS(args); 196 int ret; 197 198 forget = fuse_alloc_forget(); 199 ret = -ENOMEM; 200 if (!forget) 201 goto out; 202 203 parent = dget_parent(entry); 204 fuse_lookup_init(fm->fc, &args, get_node_id(d_inode(parent)), 205 &entry->d_name, outarg); 206 ret = fuse_simple_request(fm, &args); 207 dput(parent); 208 209 /* Zero nodeid is same as -ENOENT */ 210 if (!ret && !outarg->nodeid) 211 ret = -ENOENT; 212 if (!ret) { 213 fi = get_fuse_inode(inode); 214 if (outarg->nodeid != get_node_id(inode) || 215 (bool) IS_AUTOMOUNT(inode) != (bool) (outarg->attr.flags & FUSE_ATTR_SUBMOUNT)) { 216 fuse_queue_forget(fm->fc, forget, 217 outarg->nodeid, 1); 218 goto invalid; 219 } 220 *lookedup = true; 221 } 222 kfree(forget); 223 if (ret == -ENOMEM || ret == -EINTR) 224 goto out; 225 if (ret || fuse_invalid_attr(&outarg->attr) || 226 fuse_stale_inode(inode, outarg->generation, &outarg->attr)) { 227 goto invalid; 228 } 229 230 ret = 1; 231 out: 232 return ret; 233 234 invalid: 235 ret = 0; 236 goto out; 237 } 238
diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c index e190d09f220d..afbdd223b0f3 100644 --- a/fs/fuse/dir.c +++ b/fs/fuse/dir.c @@ -183,6 +183,59 @@ static void fuse_lookup_init(struct fuse_conn *fc, struct fuse_args *args, args->out_args[0].value = outarg; } +static int fuse_dentry_revalidate_lookup(struct fuse_mount *fm, + struct dentry *entry, + struct inode *inode, + struct fuse_entry_out *outarg, + bool *lookedup) +{ + struct dentry *parent; + struct fuse_forget_link *forget; + struct fuse_inode *fi; + FUSE_ARGS(args); + int ret; + + forget = fuse_alloc_forget(); + ret = -ENOMEM; + if (!forget) + goto out; + + parent = dget_parent(entry); + fuse_lookup_init(fm->fc, &args, get_node_id(d_inode(parent)), + &entry->d_name, outarg); + ret = fuse_simple_request(fm, &args); + dput(parent); + + /* Zero nodeid is same as -ENOENT */ + if (!ret && !outarg->nodeid) + ret = -ENOENT; + if (!ret) { + fi = get_fuse_inode(inode); + if (outarg->nodeid != get_node_id(inode) || + (bool) IS_AUTOMOUNT(inode) != (bool) (outarg->attr.flags & FUSE_ATTR_SUBMOUNT)) { + fuse_queue_forget(fm->fc, forget, + outarg->nodeid, 1); + goto invalid; + } + *lookedup = true; + } + kfree(forget); + if (ret == -ENOMEM || ret == -EINTR) + goto out; + if (ret || fuse_invalid_attr(&outarg->attr) || + fuse_stale_inode(inode, outarg->generation, &outarg->attr)) { + goto invalid; + } + + ret = 1; +out: + return ret; + +invalid: + ret = 0; + goto out; +} + /* * Check whether the dentry is still valid * @@ -206,9 +259,8 @@ static int fuse_dentry_revalidate(struct dentry *entry, unsigned int flags) else if (time_before64(fuse_dentry_time(entry), get_jiffies_64()) || (flags & (LOOKUP_EXCL | LOOKUP_REVAL | LOOKUP_RENAME_TARGET))) { struct fuse_entry_out outarg; - FUSE_ARGS(args); - struct fuse_forget_link *forget; u64 attr_version; + bool lookedup = false; /* For negative dentries, always do a fresh lookup */ if (!inode) @@ -220,38 +272,19 @@ static int fuse_dentry_revalidate(struct dentry *entry, unsigned int flags) fm = get_fuse_mount(inode); - forget = fuse_alloc_forget(); - ret = -ENOMEM; - if (!forget) - goto out; - attr_version = fuse_get_attr_version(fm->fc); - parent = dget_parent(entry); - fuse_lookup_init(fm->fc, &args, get_node_id(d_inode(parent)), - &entry->d_name, &outarg); - ret = fuse_simple_request(fm, &args); - dput(parent); - /* Zero nodeid is same as -ENOENT */ - if (!ret && !outarg.nodeid) - ret = -ENOENT; - if (!ret) { + ret = fuse_dentry_revalidate_lookup(fm, entry, inode, &outarg, + &lookedup); + if (ret == -ENOMEM || ret == -EINTR) + goto out; + if (lookedup) { fi = get_fuse_inode(inode); - if (outarg.nodeid != get_node_id(inode) || - (bool) IS_AUTOMOUNT(inode) != (bool) (outarg.attr.flags & FUSE_ATTR_SUBMOUNT)) { - fuse_queue_forget(fm->fc, forget, - outarg.nodeid, 1); - goto invalid; - } spin_lock(&fi->lock); fi->nlookup++; spin_unlock(&fi->lock); } - kfree(forget); - if (ret == -ENOMEM || ret == -EINTR) - goto out; - if (ret || fuse_invalid_attr(&outarg.attr) || - fuse_stale_inode(inode, outarg.generation, &outarg.attr)) + if (ret <= 0) goto invalid; forget_all_cached_acls(inode);
If this refactoring seems cumbersome, it's because the goal is to move the lookup parts of fuse_dentry_revalidate into a common function. This function will be used in a subsequent commit. In the meantime, the new function fuse_dentry_revalidate_lookup is responsible for just the lookup and validation portions of the revalidate dance. The fuse_dentry_revalidate function retains the responsibility for invalidating and mutating any state associated with the origial fuse_inode and dentry. Cc: stable@vger.kernel.org Fixes: 1866d779d5d2 ("fuse: Allow fuse_fill_super_common() for submounts") Signed-off-by: Krister Johansen <kjlx@templeofstupid.com> --- fs/fuse/dir.c | 87 +++++++++++++++++++++++++++++++++++---------------- 1 file changed, 60 insertions(+), 27 deletions(-)