ovl: enable xino automatically in more cases
authorAmir Goldstein <amir73il@gmail.com>
Fri, 21 Feb 2020 14:34:45 +0000 (16:34 +0200)
committerMiklos Szeredi <mszeredi@redhat.com>
Fri, 27 Mar 2020 15:51:02 +0000 (16:51 +0100)
So far, with xino=auto, we only enable xino if we know that all
underlying filesystem use 32bit inode numbers.

When users configure overlay with xino=auto, they already declare that
they are ready to handle 64bit inode number from overlay.

It is a very common case, that underlying filesystem uses 64bit ino,
but rarely or never uses the high inode number bits (e.g. tmpfs, xfs).
Leaving it for the users to declare high ino bits are unused with
xino=on is not a recipe for many users to enjoy the benefits of xino.

There appears to be very little reason not to enable xino when users
declare xino=auto even if we do not know how many bits underlying
filesystem uses for inode numbers.

In the worst case of xino bits overflow by real inode number, we
already fall back to the non-xino behavior - real inode number with
unique pseudo dev or to non persistent inode number and overlay st_dev
(for directories).

The only annoyance from auto enabling xino is that xino bits overflow
emits a warning to kmsg. Suppress those warnings unless users explicitly
asked for xino=on, suggesting that they expected high ino bits to be
unused by underlying filesystem.

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/readdir.c
fs/overlayfs/super.c

index 2d6251a4caaff99537485aa1c0dcf51bb15871d5..b0d42ece4d7ccc470534576817278f8cdff0f08c 100644 (file)
@@ -99,13 +99,13 @@ static int ovl_map_dev_ino(struct dentry *dentry, struct kstat *stat, int fsid)
                 * This way all overlay inode numbers are unique and use the
                 * overlay st_dev.
                 */
-               if (unlikely(stat->ino >> xinoshift)) {
-                       pr_warn_ratelimited("inode number too big (%pd2, ino=%llu, xinobits=%d)\n",
-                                           dentry, stat->ino, xinobits);
-               } else {
+               if (likely(!(stat->ino >> xinoshift))) {
                        stat->ino |= ((u64)fsid) << (xinoshift + 1);
                        stat->dev = dentry->d_sb->s_dev;
                        return 0;
+               } else if (ovl_xino_warn(dentry->d_sb)) {
+                       pr_warn_ratelimited("inode number too big (%pd2, ino=%llu, xinobits=%d)\n",
+                                           dentry, stat->ino, xinobits);
                }
        }
 
index e81fea86139e6ea603252da61f9bf48179a4e9e7..e6f3670146ed1d1c4a64ef580f7818e1f14f6ba8 100644 (file)
@@ -48,6 +48,12 @@ enum ovl_entry_flag {
        OVL_E_CONNECTED,
 };
 
+enum {
+       OVL_XINO_OFF,
+       OVL_XINO_AUTO,
+       OVL_XINO_ON,
+};
+
 /*
  * The tuple (fh,uuid) is a universal unique identifier for a copy up origin,
  * where:
@@ -301,6 +307,16 @@ static inline bool ovl_is_impuredir(struct dentry *dentry)
        return ovl_check_dir_xattr(dentry, OVL_XATTR_IMPURE);
 }
 
+/*
+ * With xino=auto, we do best effort to keep all inodes on same st_dev and
+ * d_ino consistent with st_ino.
+ * With xino=on, we do the same effort but we warn if we failed.
+ */
+static inline bool ovl_xino_warn(struct super_block *sb)
+{
+       return OVL_FS(sb)->config.xino == OVL_XINO_ON;
+}
+
 /* All layers on same fs? */
 static inline bool ovl_same_fs(struct super_block *sb)
 {
index 6325dcc4c48bb996315936b933feed174dc4dbac..e452ff7d583d251143fa98feefe05d53eb921570 100644 (file)
@@ -438,13 +438,15 @@ static struct ovl_dir_cache *ovl_cache_get(struct dentry *dentry)
 
 /* Map inode number to lower fs unique range */
 static u64 ovl_remap_lower_ino(u64 ino, int xinobits, int fsid,
-                              const char *name, int namelen)
+                              const char *name, int namelen, bool warn)
 {
        unsigned int xinoshift = 64 - xinobits;
 
        if (unlikely(ino >> xinoshift)) {
-               pr_warn_ratelimited("d_ino too big (%.*s, ino=%llu, xinobits=%d)\n",
-                                   namelen, name, ino, xinobits);
+               if (warn) {
+                       pr_warn_ratelimited("d_ino too big (%.*s, ino=%llu, xinobits=%d)\n",
+                                           namelen, name, ino, xinobits);
+               }
                return ino;
        }
 
@@ -521,7 +523,8 @@ get:
        } else if (xinobits && !OVL_TYPE_UPPER(type)) {
                ino = ovl_remap_lower_ino(ino, xinobits,
                                          ovl_layer_lower(this)->fsid,
-                                         p->name, p->len);
+                                         p->name, p->len,
+                                         ovl_xino_warn(dir->d_sb));
        }
 
 out:
@@ -651,6 +654,7 @@ struct ovl_readdir_translate {
        u64 parent_ino;
        int fsid;
        int xinobits;
+       bool xinowarn;
 };
 
 static int ovl_fill_real(struct dir_context *ctx, const char *name,
@@ -671,7 +675,7 @@ static int ovl_fill_real(struct dir_context *ctx, const char *name,
                        ino = p->ino;
        } else if (rdt->xinobits) {
                ino = ovl_remap_lower_ino(ino, rdt->xinobits, rdt->fsid,
-                                         name, namelen);
+                                         name, namelen, rdt->xinowarn);
        }
 
        return orig_ctx->actor(orig_ctx, name, namelen, offset, ino, d_type);
@@ -702,6 +706,7 @@ static int ovl_iterate_real(struct file *file, struct dir_context *ctx)
                .ctx.actor = ovl_fill_real,
                .orig_ctx = ctx,
                .xinobits = ovl_xino_bits(dir->d_sb),
+               .xinowarn = ovl_xino_warn(dir->d_sb),
        };
 
        if (rdt.xinobits && lower_layer)
index 53dd094f970e801e0f68127aafefb03661a9dd01..732ad5495c9219c5ef43939bd92ce9a4cf65f251 100644 (file)
@@ -317,12 +317,6 @@ static const char *ovl_redirect_mode_def(void)
        return ovl_redirect_dir_def ? "on" : "off";
 }
 
-enum {
-       OVL_XINO_OFF,
-       OVL_XINO_AUTO,
-       OVL_XINO_ON,
-};
-
 static const char * const ovl_xino_str[] = {
        "off",
        "auto",
@@ -1479,8 +1473,8 @@ static int ovl_get_layers(struct super_block *sb, struct ovl_fs *ofs,
 
        /*
         * When all layers on same fs, overlay can use real inode numbers.
-        * With mount option "xino=on", mounter declares that there are enough
-        * free high bits in underlying fs to hold the unique fsid.
+        * With mount option "xino=<on|auto>", mounter declares that there are
+        * enough free high bits in underlying fs to hold the unique fsid.
         * If overlayfs does encounter underlying inodes using the high xino
         * bits reserved for fsid, it emits a warning and uses the original
         * inode number or a non persistent inode number allocated from a
@@ -1492,7 +1486,7 @@ static int ovl_get_layers(struct super_block *sb, struct ovl_fs *ofs,
                ofs->xino_mode = 0;
        } else if (ofs->config.xino == OVL_XINO_OFF) {
                ofs->xino_mode = -1;
-       } else if (ofs->config.xino == OVL_XINO_ON && ofs->xino_mode < 0) {
+       } else if (ofs->xino_mode < 0) {
                /*
                 * This is a roundup of number of bits needed for encoding
                 * fsid, where fsid 0 is reserved for upper fs (even with