summaryrefslogtreecommitdiff
path: root/fs/overlayfs/readdir.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2020-04-09 07:40:30 +0300
committerLinus Torvalds <torvalds@linux-foundation.org>2020-04-09 07:40:30 +0300
commitc6b80eb89b55590b12db11103913088735205b5c (patch)
tree22182f07ee9ab31f5b8357531af91d90fad925d0 /fs/overlayfs/readdir.c
parent9744b923d50810bb489e49bfe89d0b4d5c84be31 (diff)
parent2eda9eaa6d7ec129150df4c7b7be65f27ac47346 (diff)
downloadlinux-c6b80eb89b55590b12db11103913088735205b5c.tar.xz
Merge tag 'ovl-update-5.7' of git://git.kernel.org/pub/scm/linux/kernel/git/mszeredi/vfs
Pull overlayfs update from Miklos Szeredi: - Fix failure to copy-up files from certain NFSv4 mounts - Sort out inconsistencies between st_ino and i_ino (used in /proc/locks) - Allow consistent (POSIX-y) inode numbering in more cases - Allow virtiofs to be used as upper layer - Miscellaneous cleanups and fixes * tag 'ovl-update-5.7' of git://git.kernel.org/pub/scm/linux/kernel/git/mszeredi/vfs: ovl: document xino expected behavior ovl: enable xino automatically in more cases ovl: avoid possible inode number collisions with xino=on ovl: use a private non-persistent ino pool ovl: fix WARN_ON nlink drop to zero ovl: fix a typo in comment ovl: replace zero-length array with flexible-array member ovl: ovl_obtain_alias(): don't call d_instantiate_anon() for old ovl: strict upper fs requirements for remote upper fs ovl: check if upper fs supports RENAME_WHITEOUT ovl: allow remote upper ovl: decide if revalidate needed on a per-dentry basis ovl: separate detection of remote upper layer from stacked overlay ovl: restructure dentry revalidation ovl: ignore failure to copy up unknown xattrs ovl: document permission model ovl: simplify i_ino initialization ovl: factor out helper ovl_get_root() ovl: fix out of date comment and unreachable code ovl: fix value of i_ino for lower hardlink corner case
Diffstat (limited to 'fs/overlayfs/readdir.c')
-rw-r--r--fs/overlayfs/readdir.c25
1 files changed, 18 insertions, 7 deletions
diff --git a/fs/overlayfs/readdir.c b/fs/overlayfs/readdir.c
index 40ac9ce2465a..e452ff7d583d 100644
--- a/fs/overlayfs/readdir.c
+++ b/fs/overlayfs/readdir.c
@@ -438,15 +438,23 @@ 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)
{
- if (ino >> (64 - xinobits)) {
- pr_warn_ratelimited("d_ino too big (%.*s, ino=%llu, xinobits=%d)\n",
- namelen, name, ino, xinobits);
+ unsigned int xinoshift = 64 - xinobits;
+
+ if (unlikely(ino >> xinoshift)) {
+ if (warn) {
+ pr_warn_ratelimited("d_ino too big (%.*s, ino=%llu, xinobits=%d)\n",
+ namelen, name, ino, xinobits);
+ }
return ino;
}
- return ino | ((u64)fsid) << (64 - xinobits);
+ /*
+ * The lowest xinobit is reserved for mapping the non-peresistent inode
+ * numbers range, but this range is only exposed via st_ino, not here.
+ */
+ return ino | ((u64)fsid) << (xinoshift + 1);
}
/*
@@ -515,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:
@@ -645,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,
@@ -665,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);
@@ -696,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)