Whamcloud - gitweb
LU-18783 llite: ensure dentry name within ll_namelen 36/58336/13
authorJames Simmons <jsimmons@infradead.org>
Thu, 10 Apr 2025 14:41:12 +0000 (10:41 -0400)
committerOleg Drokin <green@whamcloud.com>
Fri, 25 Apr 2025 00:51:34 +0000 (00:51 +0000)
Some of the pjdfstest POSIX filename length tests are failing.
This is due to the test expecting a ENAMETOOLONG error to be
reported instead of the current ENOENT error.

Add a test for the dentry name len to ensure its not longer than
sbi->ll_namelen. pjdfstest is expecting the largest file name size
to be NAME_MAX but newer ZFS versions allow names up to 1024 chars.
Ensure client limits filenames to be within NAME_MAX and OSD limit.

Add a tunable parameter llite.*.namelen_max to set this if needed.

Fixes: 7d197837e0 ("LU-4219 mdd: limit os_namelen to the max of NAME_MAX")
Signed-off-by: James Simmons <jsimmons@infradead.org>
Change-Id: I6bd872d69aca173d61ac55a2f8ffc505efb3f462
Reviewed-on: https://review.whamcloud.com/c/fs/lustre-release/+/58336
Tested-by: jenkins <devops@whamcloud.com>
Tested-by: Maloo <maloo@whamcloud.com>
Reviewed-by: Oleg Drokin <green@whamcloud.com>
Reviewed-by: Andreas Dilger <adilger@whamcloud.com>
Reviewed-by: Shaun Tancheff <shaun.tancheff@hpe.com>
Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov>
lustre/llite/llite_lib.c
lustre/llite/lproc_llite.c
lustre/llite/namei.c

index 7b64959..57fef33 100644 (file)
@@ -487,7 +487,7 @@ retry_connect:
        sb->s_magic = LL_SUPER_MAGIC;
        sb->s_maxbytes = MAX_LFS_FILESIZE;
        sbi->ll_inode_cache_enabled = 1;
-       sbi->ll_namelen = osfs->os_namelen;
+       sbi->ll_namelen = min_t(u32, osfs->os_namelen, NAME_MAX);
        sbi->ll_mnt.mnt = current->fs->root.mnt;
        sbi->ll_mnt_ns = current->nsproxy->mnt_ns;
 
@@ -2703,6 +2703,7 @@ int ll_statfs(struct dentry *de, struct kstatfs *sfs)
        sfs->f_bavail = osfs.os_bavail;
        sfs->f_fsid.val[0] = (__u32)fsid;
        sfs->f_fsid.val[1] = (__u32)(fsid >> 32);
+       sfs->f_namelen = sbi->ll_namelen;
        if (ll_i2info(de->d_inode)->lli_projid &&
                test_bit(LL_SBI_STATFS_PROJECT, sbi->ll_flags) &&
            test_bit(LLIF_PROJECT_INHERIT, &ll_i2info(de->d_inode)->lli_flags))
index 17a41f7..81abd1a 100644 (file)
@@ -289,16 +289,52 @@ static ssize_t namelen_max_show(struct kobject *kobj, struct attribute *attr,
        struct ll_sb_info *sbi = container_of(kobj, struct ll_sb_info,
                                              ll_kset.kobj);
 
+       return scnprintf(buf, PAGE_SIZE, "%u\n", sbi->ll_namelen);
+}
+
+static ssize_t namelen_max_store(struct kobject *kobj, struct attribute *attr,
+                                const char *buffer, size_t count)
+{
+       struct ll_sb_info *sbi = container_of(kobj, struct ll_sb_info,
+                                             ll_kset.kobj);
        struct obd_statfs osfs;
+       int val;
        int rc;
 
+       rc = kstrtoint(buffer, 10, &val);
+       if (rc)
+               return rc;
+
        rc = ll_statfs_internal(sbi, &osfs, OBD_STATFS_NODELAY);
        if (rc)
                return rc;
 
-       return scnprintf(buf, PAGE_SIZE, "%u\n", osfs.os_namelen);
+       if (val < 12) { /* arbitrary sanity check, but 8.3 was OK for DOS :-) */
+               CERROR("%s: cannot set max filename length %u below 12 chars\n",
+                      sbi->ll_fsname, val);
+               return -ERANGE;
+       }
+
+       /* NAME_MAX is not strictly a VFS limit, but more of a convention.
+        * It would be possible to allow filenames over NAME_MAX, if the
+        * code in the client and server was fixed to allow this as well.
+        */
+       if (val > NAME_MAX) {
+               CERROR("%s: cannot set max filename length %u over VFS limit of %u chars\n",
+                      sbi->ll_fsname, val, NAME_MAX);
+               return -EOVERFLOW;
+       }
+       if (val > osfs.os_namelen) {
+               CERROR("%s: cannot set max filename length %u over MDT limit of %u chars\n",
+                      sbi->ll_fsname, val, osfs.os_namelen);
+               return -EOVERFLOW;
+       }
+
+       sbi->ll_namelen = val;
+
+       return count;
 }
-LUSTRE_RO_ATTR(namelen_max);
+LUSTRE_RW_ATTR(namelen_max);
 
 static ssize_t statfs_state_show(struct kobject *kobj, struct attribute *attr,
                                 char *buf)
index cd42c8a..ef245b2 100644 (file)
@@ -1252,8 +1252,12 @@ static struct dentry *ll_lookup_nd(struct inode *parent, struct dentry *dentry,
                                   unsigned int flags)
 {
        struct lookup_intent *itp, it = { .it_op = IT_GETATTR };
+       struct ll_sb_info *sbi = ll_i2sbi(parent);
        struct dentry *de = NULL;
 
+       if (dentry->d_name.len > sbi->ll_namelen)
+               return ERR_PTR(-ENAMETOOLONG);
+
        /* VFS has locked the inode before calling this */
        ll_set_inode_lock_owner(parent);
 
@@ -1326,12 +1330,15 @@ static int ll_atomic_open(struct inode *dir, struct dentry *dentry,
 {
        struct lookup_intent *it;
        struct dentry *de;
-       struct ll_sb_info *sbi = NULL;
+       struct ll_sb_info *sbi = ll_i2sbi(dir);
        struct pcc_create_attach pca = { NULL, NULL };
        int open_threshold;
        int rc = 0;
 
        ENTRY;
+       if (dentry->d_name.len > sbi->ll_namelen)
+               return -ENAMETOOLONG;
+
        /* VFS has locked the inode before calling this */
        ll_set_inode_lock_owner(dir);