ovl: simplify ovl_same_sb() helper
authorAmir Goldstein <amir73il@gmail.com>
Sat, 16 Nov 2019 16:14:41 +0000 (18:14 +0200)
committerMiklos Szeredi <mszeredi@redhat.com>
Fri, 24 Jan 2020 08:46:45 +0000 (09:46 +0100)
No code uses the sb returned from this helper, so make it retrun a boolean
and rename it to ovl_same_fs().

The xino mode is irrelevant when all layers are on same fs, so instead of
describing samefs with mode OVL_XINO_OFF, use a new xino_mode state, which
is 0 in the case of samefs, -1 in the case of xino=off and > 0 with xino
enabled.

Create a new helper ovl_same_dev(), to use instead of the common check for
(ovl_same_fs() || xinobits).

Signed-off-by: Amir Goldstein <amir73il@gmail.com>
Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
fs/overlayfs/inode.c
fs/overlayfs/overlayfs.h
fs/overlayfs/ovl_entry.h
fs/overlayfs/readdir.c
fs/overlayfs/super.c
fs/overlayfs/util.c

index 13981b0..cf51fa1 100644 (file)
@@ -78,7 +78,7 @@ out:
 static int ovl_map_dev_ino(struct dentry *dentry, struct kstat *stat,
                           struct ovl_layer *lower_layer)
 {
-       bool samefs = ovl_same_sb(dentry->d_sb);
+       bool samefs = ovl_same_fs(dentry->d_sb);
        unsigned int xinobits = ovl_xino_bits(dentry->d_sb);
 
        if (samefs) {
@@ -146,7 +146,7 @@ int ovl_getattr(const struct path *path, struct kstat *stat,
        struct path realpath;
        const struct cred *old_cred;
        bool is_dir = S_ISDIR(dentry->d_inode->i_mode);
-       bool samefs = ovl_same_sb(dentry->d_sb);
+       bool samefs = ovl_same_fs(dentry->d_sb);
        struct ovl_layer *lower_layer = NULL;
        int err;
        bool metacopy_blocks = false;
@@ -168,7 +168,7 @@ int ovl_getattr(const struct path *path, struct kstat *stat,
         * If lower filesystem supports NFS file handles, this also guaranties
         * persistent st_ino across mount cycle.
         */
-       if (!is_dir || samefs || ovl_xino_bits(dentry->d_sb)) {
+       if (!is_dir || ovl_same_dev(dentry->d_sb)) {
                if (!OVL_TYPE_UPPER(type)) {
                        lower_layer = ovl_layer_lower(dentry);
                } else if (OVL_TYPE_ORIGIN(type)) {
@@ -586,7 +586,7 @@ static void ovl_fill_inode(struct inode *inode, umode_t mode, dev_t rdev,
         * ovl_new_inode(), ino arg is 0, so i_ino will be updated to real
         * upper inode i_ino on ovl_inode_init() or ovl_inode_update().
         */
-       if (ovl_same_sb(inode->i_sb) || xinobits) {
+       if (ovl_same_dev(inode->i_sb)) {
                inode->i_ino = ino;
                if (xinobits && fsid && !(ino >> (64 - xinobits)))
                        inode->i_ino |= (unsigned long)fsid << (64 - xinobits);
index fea79f7..e4ae3a4 100644 (file)
@@ -224,7 +224,6 @@ int ovl_want_write(struct dentry *dentry);
 void ovl_drop_write(struct dentry *dentry);
 struct dentry *ovl_workdir(struct dentry *dentry);
 const struct cred *ovl_override_creds(struct super_block *sb);
-struct super_block *ovl_same_sb(struct super_block *sb);
 int ovl_can_decode_fh(struct super_block *sb);
 struct dentry *ovl_indexdir(struct super_block *sb);
 bool ovl_index_all(struct super_block *sb);
@@ -302,11 +301,21 @@ static inline bool ovl_is_impuredir(struct dentry *dentry)
        return ovl_check_dir_xattr(dentry, OVL_XATTR_IMPURE);
 }
 
-static inline unsigned int ovl_xino_bits(struct super_block *sb)
+/* All layers on same fs? */
+static inline bool ovl_same_fs(struct super_block *sb)
 {
-       struct ovl_fs *ofs = sb->s_fs_info;
+       return OVL_FS(sb)->xino_mode == 0;
+}
 
-       return ofs->xino_bits;
+/* All overlay inodes have same st_dev? */
+static inline bool ovl_same_dev(struct super_block *sb)
+{
+       return OVL_FS(sb)->xino_mode >= 0;
+}
+
+static inline unsigned int ovl_xino_bits(struct super_block *sb)
+{
+       return ovl_same_dev(sb) ? OVL_FS(sb)->xino_mode : 0;
 }
 
 static inline int ovl_inode_lock(struct inode *inode)
index 64baf04..9a78570 100644 (file)
@@ -71,10 +71,15 @@ struct ovl_fs {
        struct inode *workbasedir_trap;
        struct inode *workdir_trap;
        struct inode *indexdir_trap;
-       /* Inode numbers in all layers do not use the high xino_bits */
-       unsigned int xino_bits;
+       /* -1: disabled, 0: same fs, 1..32: number of unused ino bits */
+       int xino_mode;
 };
 
+static inline struct ovl_fs *OVL_FS(struct super_block *sb)
+{
+       return (struct ovl_fs *)sb->s_fs_info;
+}
+
 /* private information held for every overlayfs dentry */
 struct ovl_entry {
        union {
index a9816f2..c8e478f 100644 (file)
@@ -469,7 +469,7 @@ static int ovl_cache_update_ino(struct path *path, struct ovl_cache_entry *p)
        int xinobits = ovl_xino_bits(dir->d_sb);
        int err = 0;
 
-       if (!ovl_same_sb(dir->d_sb) && !xinobits)
+       if (!ovl_same_dev(dir->d_sb))
                goto out;
 
        if (p->name[0] == '.') {
@@ -744,7 +744,7 @@ static int ovl_iterate(struct file *file, struct dir_context *ctx)
                 * entries.
                 */
                if (ovl_xino_bits(dentry->d_sb) ||
-                   (ovl_same_sb(dentry->d_sb) &&
+                   (ovl_same_fs(dentry->d_sb) &&
                     (ovl_is_impure_dir(file) ||
                      OVL_TYPE_MERGE(ovl_path_type(dentry->d_parent))))) {
                        return ovl_iterate_real(file, ctx);
index 374a076..8f08313 100644 (file)
@@ -358,7 +358,7 @@ static int ovl_show_options(struct seq_file *m, struct dentry *dentry)
        if (ofs->config.nfs_export != ovl_nfs_export_def)
                seq_printf(m, ",nfs_export=%s", ofs->config.nfs_export ?
                                                "on" : "off");
-       if (ofs->config.xino != ovl_xino_def())
+       if (ofs->config.xino != ovl_xino_def() && !ovl_same_fs(sb))
                seq_printf(m, ",xino=%s", ovl_xino_str[ofs->config.xino]);
        if (ofs->config.metacopy != ovl_metacopy_def)
                seq_printf(m, ",metacopy=%s",
@@ -811,7 +811,7 @@ static int ovl_lower_dir(const char *name, struct path *path,
 
        /* Check if lower fs has 32bit inode numbers */
        if (fh_type != FILEID_INO32_GEN)
-               ofs->xino_bits = 0;
+               ofs->xino_mode = -1;
 
        return 0;
 
@@ -1142,7 +1142,7 @@ static int ovl_make_workdir(struct super_block *sb, struct ovl_fs *ofs,
 
        /* Check if upper fs has 32bit inode numbers */
        if (fh_type != FILEID_INO32_GEN)
-               ofs->xino_bits = 0;
+               ofs->xino_mode = -1;
 
        /* NFS export of r/w mount depends on index */
        if (ofs->config.nfs_export && !ofs->config.index) {
@@ -1395,21 +1395,22 @@ static int ovl_get_layers(struct super_block *sb, struct ovl_fs *ofs,
         * inode number.
         */
        if (!ofs->numlowerfs || (ofs->numlowerfs == 1 && !ofs->upper_mnt)) {
-               ofs->xino_bits = 0;
-               ofs->config.xino = OVL_XINO_OFF;
-       } else if (ofs->config.xino == OVL_XINO_ON && !ofs->xino_bits) {
+               if (ofs->config.xino == OVL_XINO_ON)
+                       pr_info("\"xino=on\" is useless with all layers on same fs, ignore.\n");
+               ofs->xino_mode = 0;
+       } else if (ofs->config.xino == OVL_XINO_ON && ofs->xino_mode < 0) {
                /*
                 * This is a roundup of number of bits needed for numlowerfs+1
                 * (i.e. ilog2(numlowerfs+1 - 1) + 1). fsid 0 is reserved for
                 * upper fs even with non upper overlay.
                 */
                BUILD_BUG_ON(ilog2(OVL_MAX_STACK) > 31);
-               ofs->xino_bits = ilog2(ofs->numlowerfs) + 1;
+               ofs->xino_mode = ilog2(ofs->numlowerfs) + 1;
        }
 
-       if (ofs->xino_bits) {
+       if (ofs->xino_mode > 0) {
                pr_info("\"xino\" feature enabled using %d upper inode bits.\n",
-                       ofs->xino_bits);
+                       ofs->xino_mode);
        }
 
        err = 0;
@@ -1610,7 +1611,7 @@ static int ovl_fill_super(struct super_block *sb, void *data, int silent)
        sb->s_maxbytes = MAX_LFS_FILESIZE;
        /* Assume underlaying fs uses 32bit inodes unless proven otherwise */
        if (ofs->config.xino != OVL_XINO_OFF)
-               ofs->xino_bits = BITS_PER_LONG - 32;
+               ofs->xino_mode = BITS_PER_LONG - 32;
 
        /* alloc/destroy_inode needed for setting up traps in inode cache */
        sb->s_op = &ovl_super_operations;
index cb4a5ea..df503a8 100644 (file)
@@ -40,18 +40,6 @@ const struct cred *ovl_override_creds(struct super_block *sb)
        return override_creds(ofs->creator_cred);
 }
 
-struct super_block *ovl_same_sb(struct super_block *sb)
-{
-       struct ovl_fs *ofs = sb->s_fs_info;
-
-       if (!ofs->numlowerfs)
-               return ofs->upper_mnt->mnt_sb;
-       else if (ofs->numlowerfs == 1 && !ofs->upper_mnt)
-               return ofs->lower_fs[0].sb;
-       else
-               return NULL;
-}
-
 /*
  * Check if underlying fs supports file handles and try to determine encoding
  * type, in order to deduce maximum inode number used by fs.