Skip to content

Commit 3eb9465

Browse files
committed
Support for longnames for files/directories (FreeBSD part)
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]>
1 parent ed82dc5 commit 3eb9465

File tree

4 files changed

+46
-2
lines changed

4 files changed

+46
-2
lines changed

include/os/freebsd/zfs/sys/zfs_vfsops_os.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@ struct zfsvfs {
8383
boolean_t z_use_sa; /* version allow system attributes */
8484
boolean_t z_xattr_sa; /* allow xattrs to be stores as SA */
8585
boolean_t z_use_namecache; /* make use of FreeBSD name cache */
86+
boolean_t z_longname; /* Dataset supports long names */
8687
uint8_t z_xattr; /* xattr type in use */
8788
uint64_t z_version; /* ZPL version */
8889
uint64_t z_shares_dir; /* hidden shares dir */

module/os/freebsd/zfs/zfs_dir.c

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -581,6 +581,7 @@ zfs_link_create(znode_t *dzp, const char *name, znode_t *zp, dmu_tx_t *tx,
581581
{
582582
zfsvfs_t *zfsvfs = zp->z_zfsvfs;
583583
vnode_t *vp = ZTOV(zp);
584+
dsl_dataset_t *ds = dmu_objset_ds(zfsvfs->z_os);
584585
uint64_t value;
585586
int zp_is_dir = (vp->v_type == VDIR);
586587
sa_bulk_attr_t bulk[5];
@@ -627,6 +628,14 @@ zfs_link_create(znode_t *dzp, const char *name, znode_t *zp, dmu_tx_t *tx,
627628
return (error);
628629
}
629630

631+
/*
632+
* If we added a longname activate the SPA_FEATURE_LONGNAME.
633+
*/
634+
if (strlen(name) >= ZAP_MAXNAMELEN) {
635+
ds->ds_feature_activation[SPA_FEATURE_LONGNAME] =
636+
(void *)B_TRUE;
637+
}
638+
630639
SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_PARENT(zfsvfs), NULL,
631640
&dzp->z_id, sizeof (dzp->z_id));
632641
SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_FLAGS(zfsvfs), NULL,

module/os/freebsd/zfs/zfs_vfsops.c

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -614,6 +614,14 @@ acl_type_changed_cb(void *arg, uint64_t newval)
614614
zfsvfs->z_acl_type = newval;
615615
}
616616

617+
static void
618+
longname_changed_cb(void *arg, uint64_t newval)
619+
{
620+
zfsvfs_t *zfsvfs = arg;
621+
622+
zfsvfs->z_longname = newval;
623+
}
624+
617625
static int
618626
zfs_register_callbacks(vfs_t *vfsp)
619627
{
@@ -751,6 +759,8 @@ zfs_register_callbacks(vfs_t *vfsp)
751759
error = error ? error : dsl_prop_register(ds,
752760
zfs_prop_to_name(ZFS_PROP_ACLINHERIT), acl_inherit_changed_cb,
753761
zfsvfs);
762+
error = error ? error : dsl_prop_register(ds,
763+
zfs_prop_to_name(ZFS_PROP_LONGNAME), longname_changed_cb, zfsvfs);
754764
dsl_pool_config_exit(dmu_objset_pool(os), FTAG);
755765
if (error)
756766
goto unregister;
@@ -1489,7 +1499,8 @@ zfs_statfs(vfs_t *vfsp, struct statfs *statp)
14891499
strlcpy(statp->f_mntonname, vfsp->mnt_stat.f_mntonname,
14901500
sizeof (statp->f_mntonname));
14911501

1492-
statp->f_namemax = MAXNAMELEN - 1;
1502+
statp->f_namemax =
1503+
zfsvfs->z_longname ? (ZAP_MAXNAMELEN_NEW - 1) : (MAXNAMELEN - 1);
14931504

14941505
zfs_exit(zfsvfs, FTAG);
14951506
return (0);

module/os/freebsd/zfs/zfs_vnops_os.c

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -892,6 +892,14 @@ zfs_lookup(vnode_t *dvp, const char *nm, vnode_t **vpp,
892892
return (error);
893893
}
894894

895+
static inline bool
896+
is_nametoolong(zfsvfs_t *zfsvfs, const char *name)
897+
{
898+
size_t dlen = strlen(name);
899+
return ((!zfsvfs->z_longname && dlen >= ZAP_MAXNAMELEN) ||
900+
dlen >= ZAP_MAXNAMELEN_NEW);
901+
}
902+
895903
/*
896904
* Attempt to create a new entry in a directory. If the entry
897905
* already exists, truncate the file if permissible, else return
@@ -937,6 +945,9 @@ zfs_create(znode_t *dzp, const char *name, vattr_t *vap, int excl, int mode,
937945
vnode_t *dvp = ZTOV(dzp);
938946
#endif
939947

948+
if (is_nametoolong(zfsvfs, name))
949+
return (SET_ERROR(ENAMETOOLONG));
950+
940951
/*
941952
* If we have an ephemeral id, ACL, or XVATTR then
942953
* make sure file system is at proper version
@@ -1301,6 +1312,9 @@ zfs_mkdir(znode_t *dzp, const char *dirname, vattr_t *vap, znode_t **zpp,
13011312

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

1315+
if (is_nametoolong(zfsvfs, dirname))
1316+
return (SET_ERROR(ENAMETOOLONG));
1317+
13041318
/*
13051319
* If we have an ephemeral id, ACL, or XVATTR then
13061320
* make sure file system is at proper version
@@ -1616,7 +1630,7 @@ zfs_readdir(vnode_t *vp, zfs_uio_t *uio, cred_t *cr, int *eofp,
16161630
os = zfsvfs->z_os;
16171631
offset = zfs_uio_offset(uio);
16181632
prefetch = zp->z_zn_prefetch;
1619-
zap = zap_attribute_alloc();
1633+
zap = zap_attribute_long_alloc();
16201634

16211635
/*
16221636
* Initialize the iterator cursor.
@@ -3294,6 +3308,9 @@ zfs_rename(znode_t *sdzp, const char *sname, znode_t *tdzp, const char *tname,
32943308
int error;
32953309
svp = tvp = NULL;
32963310

3311+
if (is_nametoolong(tdzp->z_zfsvfs, tname))
3312+
return (SET_ERROR(ENAMETOOLONG));
3313+
32973314
if (rflags != 0 || wo_vap != NULL)
32983315
return (SET_ERROR(EINVAL));
32993316

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

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

3378+
if (is_nametoolong(zfsvfs, name))
3379+
return (SET_ERROR(ENAMETOOLONG));
3380+
33613381
if ((error = zfs_enter_verify_zp(zfsvfs, dzp, FTAG)) != 0)
33623382
return (error);
33633383
zilog = zfsvfs->z_log;
@@ -3540,6 +3560,9 @@ zfs_link(znode_t *tdzp, znode_t *szp, const char *name, cred_t *cr,
35403560

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

3563+
if (is_nametoolong(zfsvfs, name))
3564+
return (SET_ERROR(ENAMETOOLONG));
3565+
35433566
if ((error = zfs_enter_verify_zp(zfsvfs, tdzp, FTAG)) != 0)
35443567
return (error);
35453568
zilog = zfsvfs->z_log;

0 commit comments

Comments
 (0)