Skip to content

Commit

Permalink
Support for longnames for files/directories (FreeBSD part/Doesn't work)
Browse files Browse the repository at this point in the history
Note, FreeBSD vfs layer imposes a limit of 255 name lengh, so even
though we add code to support it here, it won't actually work.

Signed-off-by: Chunwei Chen <[email protected]>
  • Loading branch information
davidchenntnx committed Oct 1, 2024
1 parent eba9acc commit 28cfb41
Show file tree
Hide file tree
Showing 4 changed files with 46 additions and 2 deletions.
1 change: 1 addition & 0 deletions include/os/freebsd/zfs/sys/zfs_vfsops_os.h
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ struct zfsvfs {
boolean_t z_use_sa; /* version allow system attributes */
boolean_t z_xattr_sa; /* allow xattrs to be stores as SA */
boolean_t z_use_namecache; /* make use of FreeBSD name cache */
boolean_t z_longname; /* Dataset supports long names */
uint8_t z_xattr; /* xattr type in use */
uint64_t z_version; /* ZPL version */
uint64_t z_shares_dir; /* hidden shares dir */
Expand Down
9 changes: 9 additions & 0 deletions module/os/freebsd/zfs/zfs_dir.c
Original file line number Diff line number Diff line change
Expand Up @@ -627,6 +627,15 @@ zfs_link_create(znode_t *dzp, const char *name, znode_t *zp, dmu_tx_t *tx,
return (error);
}

/*
* If we added a longname activate the SPA_FEATURE_LONGNAME.
*/
if (strlen(name) >= ZAP_MAXNAMELEN) {
dsl_dataset_t *ds = dmu_objset_ds(zfsvfs->z_os);
ds->ds_feature_activation[SPA_FEATURE_LONGNAME] =
(void *)B_TRUE;
}

SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_PARENT(zfsvfs), NULL,
&dzp->z_id, sizeof (dzp->z_id));
SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_FLAGS(zfsvfs), NULL,
Expand Down
13 changes: 12 additions & 1 deletion module/os/freebsd/zfs/zfs_vfsops.c
Original file line number Diff line number Diff line change
Expand Up @@ -614,6 +614,14 @@ acl_type_changed_cb(void *arg, uint64_t newval)
zfsvfs->z_acl_type = newval;
}

static void
longname_changed_cb(void *arg, uint64_t newval)
{
zfsvfs_t *zfsvfs = arg;

zfsvfs->z_longname = newval;
}

static int
zfs_register_callbacks(vfs_t *vfsp)
{
Expand Down Expand Up @@ -751,6 +759,8 @@ zfs_register_callbacks(vfs_t *vfsp)
error = error ? error : dsl_prop_register(ds,
zfs_prop_to_name(ZFS_PROP_ACLINHERIT), acl_inherit_changed_cb,
zfsvfs);
error = error ? error : dsl_prop_register(ds,
zfs_prop_to_name(ZFS_PROP_LONGNAME), longname_changed_cb, zfsvfs);
dsl_pool_config_exit(dmu_objset_pool(os), FTAG);
if (error)
goto unregister;
Expand Down Expand Up @@ -1489,7 +1499,8 @@ zfs_statfs(vfs_t *vfsp, struct statfs *statp)
strlcpy(statp->f_mntonname, vfsp->mnt_stat.f_mntonname,
sizeof (statp->f_mntonname));

statp->f_namemax = MAXNAMELEN - 1;
statp->f_namemax =
zfsvfs->z_longname ? (ZAP_MAXNAMELEN_NEW - 1) : (MAXNAMELEN - 1);

zfs_exit(zfsvfs, FTAG);
return (0);
Expand Down
25 changes: 24 additions & 1 deletion module/os/freebsd/zfs/zfs_vnops_os.c
Original file line number Diff line number Diff line change
Expand Up @@ -892,6 +892,14 @@ zfs_lookup(vnode_t *dvp, const char *nm, vnode_t **vpp,
return (error);
}

static inline bool
is_nametoolong(zfsvfs_t *zfsvfs, const char *name)
{
size_t dlen = strlen(name);
return ((!zfsvfs->z_longname && dlen >= ZAP_MAXNAMELEN) ||
dlen >= ZAP_MAXNAMELEN_NEW);
}

/*
* Attempt to create a new entry in a directory. If the entry
* already exists, truncate the file if permissible, else return
Expand Down Expand Up @@ -937,6 +945,9 @@ zfs_create(znode_t *dzp, const char *name, vattr_t *vap, int excl, int mode,
vnode_t *dvp = ZTOV(dzp);
#endif

if (is_nametoolong(zfsvfs, name))
return (SET_ERROR(ENAMETOOLONG));

/*
* If we have an ephemeral id, ACL, or XVATTR then
* make sure file system is at proper version
Expand Down Expand Up @@ -1301,6 +1312,9 @@ zfs_mkdir(znode_t *dzp, const char *dirname, vattr_t *vap, znode_t **zpp,

ASSERT3U(vap->va_type, ==, VDIR);

if (is_nametoolong(zfsvfs, dirname))
return (SET_ERROR(ENAMETOOLONG));

/*
* If we have an ephemeral id, ACL, or XVATTR then
* make sure file system is at proper version
Expand Down Expand Up @@ -1616,7 +1630,7 @@ zfs_readdir(vnode_t *vp, zfs_uio_t *uio, cred_t *cr, int *eofp,
os = zfsvfs->z_os;
offset = zfs_uio_offset(uio);
prefetch = zp->z_zn_prefetch;
zap = zap_attribute_alloc();
zap = zap_attribute_long_alloc();

/*
* Initialize the iterator cursor.
Expand Down Expand Up @@ -3294,6 +3308,9 @@ zfs_rename(znode_t *sdzp, const char *sname, znode_t *tdzp, const char *tname,
int error;
svp = tvp = NULL;

if (is_nametoolong(tdzp->z_zfsvfs, tname))
return (SET_ERROR(ENAMETOOLONG));

if (rflags != 0 || wo_vap != NULL)
return (SET_ERROR(EINVAL));

Expand Down Expand Up @@ -3358,6 +3375,9 @@ zfs_symlink(znode_t *dzp, const char *name, vattr_t *vap,

ASSERT3S(vap->va_type, ==, VLNK);

if (is_nametoolong(zfsvfs, name))
return (SET_ERROR(ENAMETOOLONG));

if ((error = zfs_enter_verify_zp(zfsvfs, dzp, FTAG)) != 0)
return (error);
zilog = zfsvfs->z_log;
Expand Down Expand Up @@ -3540,6 +3560,9 @@ zfs_link(znode_t *tdzp, znode_t *szp, const char *name, cred_t *cr,

ASSERT3S(ZTOV(tdzp)->v_type, ==, VDIR);

if (is_nametoolong(zfsvfs, name))
return (SET_ERROR(ENAMETOOLONG));

if ((error = zfs_enter_verify_zp(zfsvfs, tdzp, FTAG)) != 0)
return (error);
zilog = zfsvfs->z_log;
Expand Down

0 comments on commit 28cfb41

Please sign in to comment.