Message ID | 20210810120807.456788-3-mszeredi@redhat.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | allow overlayfs to do RCU lookups | expand |
Hi Miklos, I love your patch! Yet something to improve: [auto build test ERROR on miklos-vfs/overlayfs-next] [also build test ERROR on kdave/for-next ceph-client/for-linus xiang-erofs/dev-test ext4/dev f2fs/dev-test fuse/for-next gfs2/for-next linus/master v5.14-rc5 next-20210810] [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] url: https://github.com/0day-ci/linux/commits/Miklos-Szeredi/allow-overlayfs-to-do-RCU-lookups/20210810-200939 base: https://git.kernel.org/pub/scm/linux/kernel/git/mszeredi/vfs.git overlayfs-next config: hexagon-randconfig-r032-20210810 (attached as .config) compiler: clang version 12.0.0 reproduce (this is a W=1 build): wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross chmod +x ~/bin/make.cross # https://github.com/0day-ci/linux/commit/7303859328569bbf653d8350215cd37b79486626 git remote add linux-review https://github.com/0day-ci/linux git fetch --no-tags linux-review Miklos-Szeredi/allow-overlayfs-to-do-RCU-lookups/20210810-200939 git checkout 7303859328569bbf653d8350215cd37b79486626 # save the attached .config to linux build tree COMPILER_INSTALL_PATH=$HOME/0day COMPILER=clang make.cross ARCH=hexagon If you fix the issue, kindly add following tag as appropriate Reported-by: kernel test robot <lkp@intel.com> All error/warnings (new ones prefixed by >>): >> fs/overlayfs/inode.c:460:10: error: implicit declaration of function 'get_cached_acl_rcu' [-Werror,-Wimplicit-function-declaration] return get_cached_acl_rcu(realinode, type); ^ >> fs/overlayfs/inode.c:460:10: warning: incompatible integer to pointer conversion returning 'int' from a function with result type 'struct posix_acl *' [-Wint-conversion] return get_cached_acl_rcu(realinode, type); ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1 warning and 1 error generated. vim +/get_cached_acl_rcu +460 fs/overlayfs/inode.c 449 450 struct posix_acl *ovl_get_acl(struct inode *inode, int type, int flags) 451 { 452 struct inode *realinode = ovl_inode_real(inode); 453 const struct cred *old_cred; 454 struct posix_acl *acl; 455 456 if (!IS_ENABLED(CONFIG_FS_POSIX_ACL) || !IS_POSIXACL(realinode)) 457 return NULL; 458 459 if (flags & LOOKUP_RCU) > 460 return get_cached_acl_rcu(realinode, type); 461 462 old_cred = ovl_override_creds(inode->i_sb); 463 acl = get_acl(realinode, type); 464 revert_creds(old_cred); 465 466 return acl; 467 } 468 --- 0-DAY CI Kernel Test Service, Intel Corporation https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org
diff --git a/fs/overlayfs/inode.c b/fs/overlayfs/inode.c index 727154a1d3ce..6a55231b262a 100644 --- a/fs/overlayfs/inode.c +++ b/fs/overlayfs/inode.c @@ -13,6 +13,7 @@ #include <linux/fiemap.h> #include <linux/fileattr.h> #include <linux/security.h> +#include <linux/namei.h> #include "overlayfs.h" @@ -454,12 +455,12 @@ struct posix_acl *ovl_get_acl(struct inode *inode, int type, int flags) const struct cred *old_cred; struct posix_acl *acl; - if (flags) - return ERR_PTR(-EINVAL); - if (!IS_ENABLED(CONFIG_FS_POSIX_ACL) || !IS_POSIXACL(realinode)) return NULL; + if (flags & LOOKUP_RCU) + return get_cached_acl_rcu(realinode, type); + old_cred = ovl_override_creds(inode->i_sb); acl = get_acl(realinode, type); revert_creds(old_cred); diff --git a/fs/posix_acl.c b/fs/posix_acl.c index 6b7f793e2b6f..4d1c6c266cf0 100644 --- a/fs/posix_acl.c +++ b/fs/posix_acl.c @@ -22,6 +22,7 @@ #include <linux/xattr.h> #include <linux/export.h> #include <linux/user_namespace.h> +#include <linux/namei.h> static struct posix_acl **acl_by_type(struct inode *inode, int type) { @@ -56,7 +57,12 @@ EXPORT_SYMBOL(get_cached_acl); struct posix_acl *get_cached_acl_rcu(struct inode *inode, int type) { - return rcu_dereference(*acl_by_type(inode, type)); + struct posix_acl *acl = rcu_dereference(*acl_by_type(inode, type)); + + if (acl == ACL_DONT_CACHE) + acl = inode->i_op->get_acl(inode, type, LOOKUP_RCU); + + return acl; } EXPORT_SYMBOL(get_cached_acl_rcu); diff --git a/include/linux/fs.h b/include/linux/fs.h index 1c56d4fc4efe..20b7db2d0a85 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -581,6 +581,11 @@ static inline void mapping_allow_writable(struct address_space *mapping) struct posix_acl; #define ACL_NOT_CACHED ((void *)(-1)) +/* + * ACL_DONT_CACHE is for stacked filesystems, that rely on underlying fs to + * cache the ACL. This also means that ->get_acl() can be called in RCU mode + * with the LOOKUP_RCU flag. + */ #define ACL_DONT_CACHE ((void *)(-3)) static inline struct posix_acl *
Overlayfs does not cache ACL's (to avoid double caching). Instead it just calls the underlying filesystem's i_op->get_acl(), which will return the cached value, if possible. In rcu path walk, however, get_cached_acl_rcu() is employed to get the value from the cache, which will fail on overlayfs resulting in dropping out of rcu walk mode. This can result in a big performance hit in certain situations. Fix by calling ->get_acl() with LOOKUP_RCU flag in case of ACL_DONT_CACHE (which indicates pass-through) Reported-by: garyhuang <zjh.20052005@163.com> Signed-off-by: Miklos Szeredi <mszeredi@redhat.com> --- fs/overlayfs/inode.c | 7 ++++--- fs/posix_acl.c | 8 +++++++- include/linux/fs.h | 5 +++++ 3 files changed, 16 insertions(+), 4 deletions(-)