From 6210f4ae96633b95fc62c8fddc7d9517b5bb7e5c Mon Sep 17 00:00:00 2001 From: James Simmons Date: Thu, 10 Apr 2025 10:41:12 -0400 Subject: [PATCH] LU-18783 llite: ensure dentry name within ll_namelen 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 Change-Id: I6bd872d69aca173d61ac55a2f8ffc505efb3f462 Reviewed-on: https://review.whamcloud.com/c/fs/lustre-release/+/58336 Tested-by: jenkins Tested-by: Maloo Reviewed-by: Oleg Drokin Reviewed-by: Andreas Dilger Reviewed-by: Shaun Tancheff Reviewed-by: Brian Behlendorf --- lustre/llite/llite_lib.c | 3 ++- lustre/llite/lproc_llite.c | 40 ++++++++++++++++++++++++++++++++++++++-- lustre/llite/namei.c | 9 ++++++++- 3 files changed, 48 insertions(+), 4 deletions(-) diff --git a/lustre/llite/llite_lib.c b/lustre/llite/llite_lib.c index 7b64959..57fef33 100644 --- a/lustre/llite/llite_lib.c +++ b/lustre/llite/llite_lib.c @@ -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)) diff --git a/lustre/llite/lproc_llite.c b/lustre/llite/lproc_llite.c index 17a41f7..81abd1a 100644 --- a/lustre/llite/lproc_llite.c +++ b/lustre/llite/lproc_llite.c @@ -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) diff --git a/lustre/llite/namei.c b/lustre/llite/namei.c index cd42c8a..ef245b2 100644 --- a/lustre/llite/namei.c +++ b/lustre/llite/namei.c @@ -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); -- 1.8.3.1