At this point, negative dentries are ignored for LOOKUP_CASEFOLD. This will be addressed later in the series. Signed-off-by: Gabriel Krisman Bertazi <krisman@xxxxxxxxxxxxxxx> --- fs/namei.c | 27 +++++++++++++++++++++++++-- fs/namespace.c | 11 ++++++++++- include/linux/fs.h | 2 ++ include/linux/mount.h | 1 + include/linux/namei.h | 1 + include/uapi/linux/fs.h | 1 + 6 files changed, 40 insertions(+), 3 deletions(-) diff --git a/fs/namei.c b/fs/namei.c index 921ae32dbc80..ddd5c9e9ab3c 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -761,8 +761,15 @@ static inline int d_revalidate(struct dentry *dentry, unsigned int flags) { if (unlikely(dentry->d_flags & DCACHE_OP_REVALIDATE)) return dentry->d_op->d_revalidate(dentry, flags); - else - return 1; + + /* Completely ignore negative dentries + for LOOKUP_CASEFOLD. */ + if (unlikely(flags & LOOKUP_CASEFOLD)) { + if (d_is_negative(dentry)) + return 0; + } + + return 1; } /** @@ -1159,6 +1166,15 @@ static int follow_automount(struct path *path, struct nameidata *nd, } +static void set_casefold_lookup(struct nameidata *nd, struct path *path) +{ + if (path && path->mnt && + path->mnt->mnt_flags & MNT_CASEFOLD) + nd->flags |= LOOKUP_CASEFOLD; + else + nd->flags &= ~LOOKUP_CASEFOLD; +} + /* * Handle a dentry that is managed in some way. * - Flagged for transit management (autofs) @@ -1202,6 +1218,7 @@ static int follow_managed(struct path *path, struct nameidata *nd) path->mnt = mounted; path->dentry = dget(mounted->mnt_root); need_mntput = true; + set_casefold_lookup(nd, path); continue; } @@ -1288,6 +1305,7 @@ static bool __follow_mount_rcu(struct nameidata *nd, struct path *path, path->mnt = &mounted->mnt; path->dentry = mounted->mnt.mnt_root; nd->flags |= LOOKUP_JUMPED; + set_casefold_lookup(nd, path); *seqp = read_seqcount_begin(&path->dentry->d_seq); /* * Update the inode too. We don't need to re-check the @@ -1336,6 +1354,7 @@ static int follow_dotdot_rcu(struct nameidata *nd) nd->path.mnt = &mparent->mnt; inode = inode2; nd->seq = seq; + set_casefold_lookup(nd, &nd->path); } } while (unlikely(d_mountpoint(nd->path.dentry))) { @@ -1350,6 +1369,7 @@ static int follow_dotdot_rcu(struct nameidata *nd) inode = nd->path.dentry->d_inode; nd->seq = read_seqcount_begin(&nd->path.dentry->d_seq); } + set_casefold_lookup(nd, &nd->path); nd->inode = inode; return 0; } @@ -2143,6 +2163,7 @@ static const char *path_init(struct nameidata *nd, unsigned flags) } else { path_get(&nd->path); } + set_casefold_lookup(nd, &nd->path); return s; } @@ -2177,6 +2198,7 @@ static const char *path_init(struct nameidata *nd, unsigned flags) get_fs_pwd(current->fs, &nd->path); nd->inode = nd->path.dentry->d_inode; } + set_casefold_lookup(nd, &nd->path); return s; } else { /* Caller must check execute permissions on the starting path component */ @@ -2205,6 +2227,7 @@ static const char *path_init(struct nameidata *nd, unsigned flags) nd->inode = nd->path.dentry->d_inode; } fdput(f); + set_casefold_lookup(nd, &nd->path); return s; } } diff --git a/fs/namespace.c b/fs/namespace.c index 9d1374ab6e06..0053e29b73cc 100644 --- a/fs/namespace.c +++ b/fs/namespace.c @@ -2509,6 +2509,12 @@ static int do_new_mount(struct path *path, const char *fstype, int sb_flags, if (!type) return -ENODEV; + if (mnt_flags & MNT_CASEFOLD && + !(type->fs_flags & FS_HAS_CASEFOLD)) { + put_filesystem(type); + return -EINVAL; + } + mnt = vfs_kern_mount(type, sb_flags, name, data); if (!IS_ERR(mnt) && (type->fs_flags & FS_HAS_SUBTYPE) && !mnt->mnt_sb->s_subtype) @@ -2809,6 +2815,8 @@ long do_mount(const char *dev_name, const char __user *dir_name, mnt_flags |= MNT_NODIRATIME; if (flags & MS_STRICTATIME) mnt_flags &= ~(MNT_RELATIME | MNT_NOATIME); + if (flags & MS_CASEFOLD) + mnt_flags |= MNT_CASEFOLD; if (flags & SB_RDONLY) mnt_flags |= MNT_READONLY; @@ -2827,7 +2835,8 @@ long do_mount(const char *dev_name, const char __user *dir_name, SB_SILENT | SB_POSIXACL | SB_LAZYTIME | - SB_I_VERSION); + SB_I_VERSION | + SB_CASEFOLD); if (flags & MS_REMOUNT) retval = do_remount(&path, flags, sb_flags, mnt_flags, diff --git a/include/linux/fs.h b/include/linux/fs.h index 2a815560fda0..743d38876a51 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -1287,6 +1287,7 @@ extern int send_sigurg(struct fown_struct *fown); #define SB_SYNCHRONOUS 16 /* Writes are synced at once */ #define SB_MANDLOCK 64 /* Allow mandatory locks on an FS */ #define SB_DIRSYNC 128 /* Directory modifications are synchronous */ +#define SB_CASEFOLD 256 /* Directory lookups are case-insensitive */ #define SB_NOATIME 1024 /* Do not update access times. */ #define SB_NODIRATIME 2048 /* Do not update directory access times */ #define SB_SILENT 32768 @@ -2069,6 +2070,7 @@ struct file_system_type { #define FS_BINARY_MOUNTDATA 2 #define FS_HAS_SUBTYPE 4 #define FS_USERNS_MOUNT 8 /* Can be mounted by userns root */ +#define FS_HAS_CASEFOLD 16 #define FS_RENAME_DOES_D_MOVE 32768 /* FS will handle d_move() during rename() internally. */ struct dentry *(*mount) (struct file_system_type *, int, const char *, void *); diff --git a/include/linux/mount.h b/include/linux/mount.h index 45b1f56c6c2f..05f5d6f71108 100644 --- a/include/linux/mount.h +++ b/include/linux/mount.h @@ -52,6 +52,7 @@ struct mnt_namespace; MNT_DOOMED | MNT_SYNC_UMOUNT | MNT_MARKED) #define MNT_INTERNAL 0x4000 +#define MNT_CASEFOLD 0x8000 #define MNT_LOCK_ATIME 0x040000 #define MNT_LOCK_NOEXEC 0x080000 diff --git a/include/linux/namei.h b/include/linux/namei.h index a982bb7cd480..fb74ab4c86f3 100644 --- a/include/linux/namei.h +++ b/include/linux/namei.h @@ -46,6 +46,7 @@ enum {LAST_NORM, LAST_ROOT, LAST_DOT, LAST_DOTDOT, LAST_BIND}; #define LOOKUP_ROOT 0x2000 #define LOOKUP_EMPTY 0x4000 #define LOOKUP_DOWN 0x8000 +#define LOOKUP_CASEFOLD 0x010000 extern int path_pts(struct path *path); diff --git a/include/uapi/linux/fs.h b/include/uapi/linux/fs.h index d2a8313fabd7..7fa23e5f49d6 100644 --- a/include/uapi/linux/fs.h +++ b/include/uapi/linux/fs.h @@ -113,6 +113,7 @@ struct inodes_stat_t { #define MS_REMOUNT 32 /* Alter flags of a mounted FS */ #define MS_MANDLOCK 64 /* Allow mandatory locks on an FS */ #define MS_DIRSYNC 128 /* Directory modifications are synchronous */ +#define MS_CASEFOLD 256 /* Directory lookups are case-insensitive */ #define MS_NOATIME 1024 /* Do not update access times. */ #define MS_NODIRATIME 2048 /* Do not update directory access times */ #define MS_BIND 4096 -- 2.17.0