Commit 0ba83f09 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull overlayfs update from Amir Goldstein:
 "Relax the semantics of uuid=off to cater to a use case of overlayfs
  lower layers on btrfs clones, whose UUID are ephemeral and an upper
  layer on a different filesystem"

* tag 'ovl-update-7.0' of git://git.kernel.org/pub/scm/linux/kernel/git/overlayfs/vfs:
  ovl: relax requirement for uuid=off,index=on
parents 1d22968f 869056db
Loading
Loading
Loading
Loading
+3 −3
Original line number Diff line number Diff line
@@ -753,9 +753,9 @@ Note: the mount options index=off,nfs_export=on are conflicting for a
read-write mount and will result in an error.

Note: the mount option uuid=off can be used to replace UUID of the underlying
filesystem in file handles with null, and effectively disable UUID checks. This
filesystem in file handles with null, in order to relax the UUID checks. This
can be useful in case the underlying disk is copied and the UUID of this copy
is changed. This is only applicable if all lower/upper/work directories are on
is changed. This is only applicable if all lower directories are on
the same filesystem, otherwise it will fallback to normal behaviour.


@@ -769,7 +769,7 @@ controlled by the "uuid" mount option, which supports these values:
    UUID of overlayfs is null. fsid is taken from upper most filesystem.
- "off":
    UUID of overlayfs is null. fsid is taken from upper most filesystem.
    UUID of underlying layers is ignored.
    UUID of underlying layers is ignored and null used instead.
- "on":
    UUID of overlayfs is generated and used to report a unique fsid.
    UUID is stored in xattr "trusted.overlay.uuid", making overlayfs fsid
+13 −8
Original line number Diff line number Diff line
@@ -159,6 +159,18 @@ static struct ovl_fh *ovl_get_fh(struct ovl_fs *ofs, struct dentry *upperdentry,
	goto out;
}

bool ovl_uuid_match(struct ovl_fs *ofs, const struct super_block *sb,
		    const uuid_t *uuid)
{
	/*
	 * Make sure that the stored uuid matches the uuid of the lower
	 * layer where file handle will be decoded.
	 * In case of uuid=off option just make sure that stored uuid is null.
	 */
	return ovl_origin_uuid(ofs) ? uuid_equal(uuid, &sb->s_uuid) :
				      uuid_is_null(uuid);
}

struct dentry *ovl_decode_real_fh(struct ovl_fs *ofs, struct ovl_fh *fh,
				  struct vfsmount *mnt, bool connected)
{
@@ -168,14 +180,7 @@ struct dentry *ovl_decode_real_fh(struct ovl_fs *ofs, struct ovl_fh *fh,
	if (!capable(CAP_DAC_READ_SEARCH))
		return NULL;

	/*
	 * Make sure that the stored uuid matches the uuid of the lower
	 * layer where file handle will be decoded.
	 * In case of uuid=off option just make sure that stored uuid is null.
	 */
	if (ovl_origin_uuid(ofs) ?
	    !uuid_equal(&fh->fb.uuid, &mnt->mnt_sb->s_uuid) :
	    !uuid_is_null(&fh->fb.uuid))
	if (!ovl_uuid_match(ofs, mnt->mnt_sb, &fh->fb.uuid))
		return NULL;

	bytes = (fh->fb.len - offsetof(struct ovl_fb, fid));
+2 −0
Original line number Diff line number Diff line
@@ -710,6 +710,8 @@ static inline int ovl_check_fh_len(struct ovl_fh *fh, int fh_len)
	return ovl_check_fb_len(&fh->fb, fh_len - OVL_FH_WIRE_OFFSET);
}

bool ovl_uuid_match(struct ovl_fs *ofs, const struct super_block *sb,
		    const uuid_t *uuid);
struct dentry *ovl_decode_real_fh(struct ovl_fs *ofs, struct ovl_fh *fh,
				  struct vfsmount *mnt, bool connected);
int ovl_check_origin_fh(struct ovl_fs *ofs, struct ovl_fh *fh, bool connected,
+6 −9
Original line number Diff line number Diff line
@@ -940,7 +940,7 @@ static bool ovl_lower_uuid_ok(struct ovl_fs *ofs, const uuid_t *uuid)
		 * disable lower file handle decoding on all of them.
		 */
		if (ofs->fs[i].is_lower &&
		    uuid_equal(&ofs->fs[i].sb->s_uuid, uuid)) {
		    ovl_uuid_match(ofs, ofs->fs[i].sb, uuid)) {
			ofs->fs[i].bad_uuid = true;
			return false;
		}
@@ -952,6 +952,7 @@ static bool ovl_lower_uuid_ok(struct ovl_fs *ofs, const uuid_t *uuid)
static int ovl_get_fsid(struct ovl_fs *ofs, const struct path *path)
{
	struct super_block *sb = path->mnt->mnt_sb;
	const uuid_t *uuid = ovl_origin_uuid(ofs) ? &sb->s_uuid : &uuid_null;
	unsigned int i;
	dev_t dev;
	int err;
@@ -963,7 +964,7 @@ static int ovl_get_fsid(struct ovl_fs *ofs, const struct path *path)
			return i;
	}

	if (!ovl_lower_uuid_ok(ofs, &sb->s_uuid)) {
	if (!ovl_lower_uuid_ok(ofs, uuid)) {
		bad_uuid = true;
		if (ofs->config.xino == OVL_XINO_AUTO) {
			ofs->config.xino = OVL_XINO_OFF;
@@ -975,9 +976,8 @@ static int ovl_get_fsid(struct ovl_fs *ofs, const struct path *path)
			warn = true;
		}
		if (warn) {
			pr_warn("%s uuid detected in lower fs '%pd2', falling back to xino=%s,index=off,nfs_export=off.\n",
				uuid_is_null(&sb->s_uuid) ? "null" :
							    "conflicting",
			pr_warn("%s uuid in non-single lower fs '%pd2', falling back to xino=%s,index=off,nfs_export=off.\n",
				uuid_is_null(uuid) ? "null" : "conflicting",
				path->dentry, ovl_xino_mode(&ofs->config));
		}
	}
@@ -1469,10 +1469,7 @@ static int ovl_fill_super_creds(struct fs_context *fc, struct super_block *sb)
	if (!ovl_upper_mnt(ofs))
		sb->s_flags |= SB_RDONLY;

	if (!ovl_origin_uuid(ofs) && ofs->numfs > 1) {
		pr_warn("The uuid=off requires a single fs for lower and upper, falling back to uuid=null.\n");
		ofs->config.uuid = OVL_UUID_NULL;
	} else if (ovl_has_fsid(ofs) && ovl_upper_mnt(ofs)) {
	if (ovl_has_fsid(ofs) && ovl_upper_mnt(ofs)) {
		/* Use per instance persistent uuid/fsid */
		ovl_init_uuid_xattr(sb, ofs, &ctx->upper);
	}