The concept of differentiating between "short" and "long" symlinks is
specific to ufs/, but the relevant variable is contained in struct
mount, which is used by all filesystems. I think it would be a worthwile
effort to clear this up by moving maxsymlinklen to struct ufsmount
instead. Filesystem code is already hard enough to understand without
such layering violations.
Note, that I replaced all references to mnt_maxsymlinklen in ufs/ext2fs
with EXT2_MAXSYMLINKLEN, which is the constant max short symlink len for
ext2fs. This allows to get rid of some (mnt_maxsymlinklen == 0) checks
there, which is always false for ext2fs.
Comments?
natano
Index: isofs/cd9660/cd9660_vfsops.c
===================================================================
RCS file: /cvs/src/sys/isofs/cd9660/cd9660_vfsops.c,v
retrieving revision 1.71
diff -u -p -r1.71 cd9660_vfsops.c
--- isofs/cd9660/cd9660_vfsops.c 9 Sep 2015 15:59:19 -0000 1.71
+++ isofs/cd9660/cd9660_vfsops.c 26 Feb 2016 21:30:15 -0000
@@ -383,7 +383,6 @@ iso_mountfs(devvp, mp, p, argp)
mp->mnt_data = (qaddr_t)isomp;
mp->mnt_stat.f_fsid.val[0] = (long)dev;
mp->mnt_stat.f_fsid.val[1] = mp->mnt_vfc->vfc_typenum;
- mp->mnt_maxsymlinklen = 0;
mp->mnt_flag |= MNT_LOCAL;
isomp->im_mountp = mp;
isomp->im_dev = dev;
Index: ntfs/ntfs_vfsops.c
===================================================================
RCS file: /cvs/src/sys/ntfs/ntfs_vfsops.c,v
retrieving revision 1.44
diff -u -p -r1.44 ntfs_vfsops.c
--- ntfs/ntfs_vfsops.c 14 Mar 2015 03:38:52 -0000 1.44
+++ ntfs/ntfs_vfsops.c 26 Feb 2016 21:30:16 -0000
@@ -436,7 +436,6 @@ ntfs_mountfs(struct vnode *devvp, struct
mp->mnt_stat.f_fsid.val[0] = dev;
mp->mnt_stat.f_fsid.val[1] = mp->mnt_vfc->vfc_typenum;
- mp->mnt_maxsymlinklen = 0;
mp->mnt_flag |= MNT_LOCAL;
devvp->v_specmountpoint = mp;
return (0);
Index: sys/mount.h
===================================================================
RCS file: /cvs/src/sys/sys/mount.h,v
retrieving revision 1.122
diff -u -p -r1.122 mount.h
--- sys/mount.h 26 Feb 2016 08:56:10 -0000 1.122
+++ sys/mount.h 26 Feb 2016 21:30:16 -0000
@@ -355,7 +355,6 @@ struct mount {
struct vnodelst mnt_vnodelist; /* list of vnodes this mount */
struct rwlock mnt_lock; /* mount structure lock */
int mnt_flag; /* flags */
- unsigned int mnt_maxsymlinklen; /* max size of short symlink */
struct statfs mnt_stat; /* cache of filesystem stats */
void *mnt_data; /* private data */
};
Index: ufs/ext2fs/ext2fs_inode.c
===================================================================
RCS file: /cvs/src/sys/ufs/ext2fs/ext2fs_inode.c,v
retrieving revision 1.56
diff -u -p -r1.56 ext2fs_inode.c
--- ufs/ext2fs/ext2fs_inode.c 14 Mar 2015 03:38:52 -0000 1.56
+++ ufs/ext2fs/ext2fs_inode.c 26 Feb 2016 21:30:16 -0000
@@ -227,10 +227,7 @@ ext2fs_truncate(struct inode *oip, off_t
ovp->v_type != VLNK)
return (0);
- if (ovp->v_type == VLNK &&
- (ext2fs_size(oip) < ovp->v_mount->mnt_maxsymlinklen ||
- (ovp->v_mount->mnt_maxsymlinklen == 0 &&
- oip->i_e2fs_nblock == 0))) {
+ if (ovp->v_type == VLNK && ext2fs_size(oip) < EXT2_MAXSYMLINKLEN) {
#ifdef DIAGNOSTIC
if (length != 0)
panic("ext2fs_truncate: partial truncate of symlink");
Index: ufs/ext2fs/ext2fs_readwrite.c
===================================================================
RCS file: /cvs/src/sys/ufs/ext2fs/ext2fs_readwrite.c,v
retrieving revision 1.38
diff -u -p -r1.38 ext2fs_readwrite.c
--- ufs/ext2fs/ext2fs_readwrite.c 26 Feb 2016 08:56:10 -0000 1.38
+++ ufs/ext2fs/ext2fs_readwrite.c 26 Feb 2016 21:30:16 -0000
@@ -95,9 +95,7 @@ ext2_ind_read(struct vnode *vp, struct i
panic("%s: mode", "ext2fs_read");
if (vp->v_type == VLNK) {
- if (ext2fs_size(ip) < vp->v_mount->mnt_maxsymlinklen ||
- (vp->v_mount->mnt_maxsymlinklen == 0 &&
- ip->i_e2fs_nblock == 0))
+ if (ext2fs_size(ip) < EXT2_MAXSYMLINKLEN)
panic("%s: short symlink", "ext2fs_read");
} else if (vp->v_type != VREG && vp->v_type != VDIR)
panic("%s: type %d", "ext2fs_read", vp->v_type);
Index: ufs/ext2fs/ext2fs_vfsops.c
===================================================================
RCS file: /cvs/src/sys/ufs/ext2fs/ext2fs_vfsops.c,v
retrieving revision 1.85
diff -u -p -r1.85 ext2fs_vfsops.c
--- ufs/ext2fs/ext2fs_vfsops.c 14 Mar 2015 03:38:52 -0000 1.85
+++ ufs/ext2fs/ext2fs_vfsops.c 26 Feb 2016 21:30:16 -0000
@@ -583,7 +583,6 @@ ext2fs_mountfs(struct vnode *devvp, stru
mp->mnt_data = (qaddr_t)ump;
mp->mnt_stat.f_fsid.val[0] = (long)dev;
mp->mnt_stat.f_fsid.val[1] = mp->mnt_vfc->vfc_typenum;
- mp->mnt_maxsymlinklen = EXT2_MAXSYMLINKLEN;
mp->mnt_flag |= MNT_LOCAL;
ump->um_mountp = mp;
ump->um_dev = dev;
@@ -591,6 +590,7 @@ ext2fs_mountfs(struct vnode *devvp, stru
ump->um_nindir = NINDIR(ump->um_e2fs);
ump->um_bptrtodb = ump->um_e2fs->e2fs_fsbtodb;
ump->um_seqinc = 1; /* no frags */
+ ump->um_maxsymlinklen = EXT2_MAXSYMLINKLEN;
devvp->v_specmountpoint = mp;
return (0);
out:
Index: ufs/ext2fs/ext2fs_vnops.c
===================================================================
RCS file: /cvs/src/sys/ufs/ext2fs/ext2fs_vnops.c,v
retrieving revision 1.75
diff -u -p -r1.75 ext2fs_vnops.c
--- ufs/ext2fs/ext2fs_vnops.c 26 Feb 2016 08:56:10 -0000 1.75
+++ ufs/ext2fs/ext2fs_vnops.c 26 Feb 2016 21:30:16 -0000
@@ -1091,7 +1091,7 @@ ext2fs_symlink(void *v)
return (error);
vp = *vpp;
len = strlen(ap->a_target);
- if (len < vp->v_mount->mnt_maxsymlinklen) {
+ if (len < EXT2_MAXSYMLINKLEN) {
ip = VTOI(vp);
memcpy(ip->i_e2din->e2di_shortlink, ap->a_target, len);
error = ext2fs_setsize(ip, len);
@@ -1119,8 +1119,7 @@ ext2fs_readlink(void *v)
u_int64_t isize;
isize = ext2fs_size(ip);
- if (isize < vp->v_mount->mnt_maxsymlinklen ||
- (vp->v_mount->mnt_maxsymlinklen == 0 && ip->i_e2fs_nblock == 0)) {
+ if (isize < EXT2_MAXSYMLINKLEN) {
return (uiomove((char *)ip->i_e2din->e2di_shortlink, isize,
ap->a_uio));
}
Index: ufs/ffs/ffs_inode.c
===================================================================
RCS file: /cvs/src/sys/ufs/ffs/ffs_inode.c,v
retrieving revision 1.75
diff -u -p -r1.75 ffs_inode.c
--- ufs/ffs/ffs_inode.c 28 Nov 2015 21:52:02 -0000 1.75
+++ ufs/ffs/ffs_inode.c 26 Feb 2016 21:30:16 -0000
@@ -152,8 +152,8 @@ ffs_truncate(struct inode *oip, off_t le
return (0);
if (ovp->v_type == VLNK &&
- (DIP(oip, size) < ovp->v_mount->mnt_maxsymlinklen ||
- (ovp->v_mount->mnt_maxsymlinklen == 0 &&
+ (DIP(oip, size) < oip->i_ump->um_maxsymlinklen ||
+ (oip->i_ump->um_maxsymlinklen == 0 &&
oip->i_din1->di_blocks == 0))) {
#ifdef DIAGNOSTIC
if (length != 0)
Index: ufs/ffs/ffs_vfsops.c
===================================================================
RCS file: /cvs/src/sys/ufs/ffs/ffs_vfsops.c,v
retrieving revision 1.151
diff -u -p -r1.151 ffs_vfsops.c
--- ufs/ffs/ffs_vfsops.c 26 Feb 2016 08:56:10 -0000 1.151
+++ ufs/ffs/ffs_vfsops.c 26 Feb 2016 21:30:16 -0000
@@ -573,7 +573,7 @@ ffs_reload(struct mount *mountp, struct
if (fs->fs_sbsize < SBSIZE)
bp->b_flags |= B_INVAL;
brelse(bp);
- mountp->mnt_maxsymlinklen = fs->fs_maxsymlinklen;
+ VFSTOUFS(mountp)->um_maxsymlinklen = fs->fs_maxsymlinklen;
ffs1_compat_read(fs, VFSTOUFS(mountp), fs->fs_sblockloc);
ffs_oldfscompat(fs);
(void)ffs_statfs(mountp, &mountp->mnt_stat, p);
@@ -834,7 +834,6 @@ ffs_mountfs(struct vnode *devvp, struct
else
mp->mnt_stat.f_fsid.val[1] = mp->mnt_vfc->vfc_typenum;
mp->mnt_stat.f_namemax = MAXNAMLEN;
- mp->mnt_maxsymlinklen = fs->fs_maxsymlinklen;
mp->mnt_flag |= MNT_LOCAL;
ump->um_mountp = mp;
ump->um_dev = dev;
@@ -842,6 +841,7 @@ ffs_mountfs(struct vnode *devvp, struct
ump->um_nindir = fs->fs_nindir;
ump->um_bptrtodb = fs->fs_fsbtodb;
ump->um_seqinc = fs->fs_frag;
+ ump->um_maxsymlinklen = fs->fs_maxsymlinklen;
for (i = 0; i < MAXQUOTAS; i++)
ump->um_quotas[i] = NULLVP;
Index: ufs/ffs/ffs_vnops.c
===================================================================
RCS file: /cvs/src/sys/ufs/ffs/ffs_vnops.c,v
retrieving revision 1.83
diff -u -p -r1.83 ffs_vnops.c
--- ufs/ffs/ffs_vnops.c 26 Feb 2016 08:56:10 -0000 1.83
+++ ufs/ffs/ffs_vnops.c 26 Feb 2016 21:30:16 -0000
@@ -207,9 +207,8 @@ ffs_read(void *v)
panic("ffs_read: mode");
if (vp->v_type == VLNK) {
- if (DIP(ip, size) < vp->v_mount->mnt_maxsymlinklen ||
- (vp->v_mount->mnt_maxsymlinklen == 0 &&
- DIP(ip, blocks) == 0))
+ if (DIP(ip, size) < ip->i_ump->um_maxsymlinklen ||
+ (ip->i_ump->um_maxsymlinklen == 0 && DIP(ip, blocks) == 0))
panic("ffs_read: short symlink");
} else if (vp->v_type != VREG && vp->v_type != VDIR)
panic("ffs_read: type %d", vp->v_type);
Index: ufs/ufs/ufs_dirhash.c
===================================================================
RCS file: /cvs/src/sys/ufs/ufs/ufs_dirhash.c,v
retrieving revision 1.33
diff -u -p -r1.33 ufs_dirhash.c
--- ufs/ufs/ufs_dirhash.c 14 Mar 2015 03:38:53 -0000 1.33
+++ ufs/ufs/ufs_dirhash.c 26 Feb 2016 21:30:16 -0000
@@ -54,7 +54,7 @@ __FBSDID("$FreeBSD: src/sys/ufs/ufs/ufs_
#define WRAPINCR(val, limit) (((val) + 1 == (limit)) ? 0 : ((val) + 1))
#define WRAPDECR(val, limit) (((val) == 0) ? ((limit) - 1) : ((val) - 1))
-#define OFSFMT(vp) ((vp)->v_mount->mnt_maxsymlinklen <= 0)
+#define OFSFMT(ip) ((ip)->i_ump->um_maxsymlinklen == 0)
#define BLKFREE2IDX(n) ((n) > DH_NFSTATS ? DH_NFSTATS : (n))
int ufs_mindirhashsize;
@@ -116,7 +116,7 @@ ufsdirhash_build(struct inode *ip)
/* Check if we can/should use dirhash. */
if (ip->i_dirhash == NULL) {
- if (DIP(ip, size) < ufs_mindirhashsize || OFSFMT(ip->i_vnode))
+ if (DIP(ip, size) < ufs_mindirhashsize || OFSFMT(ip))
return (-1);
} else {
/* Hash exists, but sysctls could have changed. */
Index: ufs/ufs/ufs_lookup.c
===================================================================
RCS file: /cvs/src/sys/ufs/ufs/ufs_lookup.c,v
retrieving revision 1.47
diff -u -p -r1.47 ufs_lookup.c
--- ufs/ufs/ufs_lookup.c 14 Mar 2015 03:38:53 -0000 1.47
+++ ufs/ufs/ufs_lookup.c 26 Feb 2016 21:30:16 -0000
@@ -64,7 +64,7 @@ int dirchk = 1;
int dirchk = 0;
#endif
-#define FSFMT(vp) ((vp)->v_mount->mnt_maxsymlinklen <= 0)
+#define OFSFMT(ip) ((ip)->i_ump->um_maxsymlinklen == 0)
/*
* Convert a component of a pathname into a pointer to a locked inode.
@@ -300,7 +300,7 @@ searchloop:
int size = ep->d_reclen;
if (ep->d_ino != 0)
- size -= DIRSIZ(FSFMT(vdp), ep);
+ size -= DIRSIZ(OFSFMT(dp), ep);
if (size > 0) {
if (size >= slotneeded) {
slotstatus = FOUND;
@@ -324,10 +324,10 @@ searchloop:
*/
if (ep->d_ino) {
# if (BYTE_ORDER == LITTLE_ENDIAN)
- if (vdp->v_mount->mnt_maxsymlinklen > 0)
- namlen = ep->d_namlen;
- else
+ if (OFSFMT(dp))
namlen = ep->d_type;
+ else
+ namlen = ep->d_namlen;
# else
namlen = ep->d_namlen;
# endif
@@ -441,9 +441,9 @@ found:
* Check that directory length properly reflects presence
* of this entry.
*/
- if (dp->i_offset + DIRSIZ(FSFMT(vdp), ep) > DIP(dp, size)) {
+ if (dp->i_offset + DIRSIZ(OFSFMT(dp), ep) > DIP(dp, size)) {
ufs_dirbad(dp, dp->i_offset, "i_ffs_size too small");
- DIP_ASSIGN(dp, size, dp->i_offset + DIRSIZ(FSFMT(vdp), ep));
+ DIP_ASSIGN(dp, size, dp->i_offset + DIRSIZ(OFSFMT(dp), ep));
dp->i_flag |= IN_CHANGE | IN_UPDATE;
}
brelse(bp);
@@ -618,22 +618,25 @@ ufs_dirbad(struct inode *ip, doff_t offs
* name must be as long as advertised, and null terminated
*/
int
-ufs_dirbadentry(struct vnode *dp, struct direct *ep, int entryoffsetinblock)
+ufs_dirbadentry(struct vnode *vdp, struct direct *ep, int entryoffsetinblock)
{
+ struct inode *dp;
int i;
int namlen;
+ dp = VTOI(vdp);
+
# if (BYTE_ORDER == LITTLE_ENDIAN)
- if (dp->v_mount->mnt_maxsymlinklen > 0)
- namlen = ep->d_namlen;
- else
+ if (OFSFMT(dp))
namlen = ep->d_type;
+ else
+ namlen = ep->d_namlen;
# else
namlen = ep->d_namlen;
# endif
if ((ep->d_reclen & 0x3) != 0 ||
ep->d_reclen > DIRBLKSIZ - (entryoffsetinblock & (DIRBLKSIZ - 1)) ||
- ep->d_reclen < DIRSIZ(FSFMT(dp), ep) || namlen > MAXNAMLEN) {
+ ep->d_reclen < DIRSIZ(OFSFMT(dp), ep) || namlen > MAXNAMLEN) {
/*return (1); */
printf("First bad\n");
goto bad;
@@ -669,16 +672,16 @@ ufs_makedirentry(struct inode *ip, struc
newdirp->d_ino = ip->i_number;
newdirp->d_namlen = cnp->cn_namelen;
memcpy(newdirp->d_name, cnp->cn_nameptr, cnp->cn_namelen + 1);
- if (ITOV(ip)->v_mount->mnt_maxsymlinklen > 0)
- newdirp->d_type = IFTODT(DIP(ip, mode));
- else {
+ if (OFSFMT(ip)) {
newdirp->d_type = 0;
# if (BYTE_ORDER == LITTLE_ENDIAN)
{ u_char tmp = newdirp->d_namlen;
newdirp->d_namlen = newdirp->d_type;
newdirp->d_type = tmp; }
# endif
- }
+ } else {
+ newdirp->d_type = IFTODT(DIP(ip, mode));
+ }
}
/*
@@ -708,7 +711,7 @@ ufs_direnter(struct vnode *dvp, struct v
cr = cnp->cn_cred;
p = cnp->cn_proc;
dp = VTOI(dvp);
- newentrysize = DIRSIZ(FSFMT(dvp), dirp);
+ newentrysize = DIRSIZ(OFSFMT(dp), dirp);
if (dp->i_count == 0) {
/*
@@ -823,7 +826,7 @@ ufs_direnter(struct vnode *dvp, struct v
* dp->i_offset + dp->i_count would yield the space.
*/
ep = (struct direct *)dirbuf;
- dsize = ep->d_ino ? DIRSIZ(FSFMT(dvp), ep) : 0;
+ dsize = ep->d_ino ? DIRSIZ(OFSFMT(dp), ep) : 0;
spacefree = ep->d_reclen - dsize;
for (loc = ep->d_reclen; loc < dp->i_count; ) {
nep = (struct direct *)(dirbuf + loc);
@@ -848,7 +851,7 @@ ufs_direnter(struct vnode *dvp, struct v
dsize = 0;
continue;
}
- dsize = DIRSIZ(FSFMT(dvp), nep);
+ dsize = DIRSIZ(OFSFMT(dp), nep);
spacefree += nep->d_reclen - dsize;
#ifdef UFS_DIRHASH
if (dp->i_dirhash != NULL)
@@ -1026,7 +1029,7 @@ ufs_dirrewrite(struct inode *dp, struct
if (error)
return (error);
ep->d_ino = newinum;
- if (vdp->v_mount->mnt_maxsymlinklen > 0)
+ if (!OFSFMT(dp))
ep->d_type = newtype;
oip->i_effnlink--;
if (DOINGSOFTDEP(vdp)) {
@@ -1084,10 +1087,10 @@ ufs_dirempty(struct inode *ip, ufsino_t
continue;
/* accept only "." and ".." */
# if (BYTE_ORDER == LITTLE_ENDIAN)
- if (ITOV(ip)->v_mount->mnt_maxsymlinklen > 0)
- namlen = dp->d_namlen;
- else
+ if (OFSFMT(ip))
namlen = dp->d_type;
+ else
+ namlen = dp->d_namlen;
# else
namlen = dp->d_namlen;
# endif
@@ -1142,10 +1145,10 @@ ufs_checkpath(struct inode *source, stru
if (error != 0)
break;
# if (BYTE_ORDER == LITTLE_ENDIAN)
- if (vp->v_mount->mnt_maxsymlinklen > 0)
- namlen = dirbuf.dotdot_namlen;
- else
+ if (OFSFMT(VTOI(vp)))
namlen = dirbuf.dotdot_type;
+ else
+ namlen = dirbuf.dotdot_namlen;
# else
namlen = dirbuf.dotdot_namlen;
# endif
Index: ufs/ufs/ufs_vnops.c
===================================================================
RCS file: /cvs/src/sys/ufs/ufs/ufs_vnops.c,v
retrieving revision 1.125
diff -u -p -r1.125 ufs_vnops.c
--- ufs/ufs/ufs_vnops.c 16 Feb 2016 17:56:12 -0000 1.125
+++ ufs/ufs/ufs_vnops.c 26 Feb 2016 21:30:16 -0000
@@ -1189,7 +1189,7 @@ ufs_mkdir(void *v)
/*
* Initialize directory with "." and ".." from static template.
*/
- if (dvp->v_mount->mnt_maxsymlinklen > 0)
+ if (dp->i_ump->um_maxsymlinklen > 0)
dtp = &mastertemplate;
else
dtp = (struct dirtemplate *)&omastertemplate;
@@ -1385,9 +1385,9 @@ ufs_symlink(void *v)
return (error);
VN_KNOTE(ap->a_dvp, NOTE_WRITE);
vp = *vpp;
+ ip = VTOI(vp);
len = strlen(ap->a_target);
- if (len < vp->v_mount->mnt_maxsymlinklen) {
- ip = VTOI(vp);
+ if (len < ip->i_ump->um_maxsymlinklen) {
memcpy(SHORTLINK(ip), ap->a_target, len);
DIP_ASSIGN(ip, size, len);
ip->i_flag |= IN_CHANGE | IN_UPDATE;
@@ -1422,7 +1422,7 @@ ufs_readdir(void *v)
size_t count, entries;
int readcnt, error;
#if (BYTE_ORDER == LITTLE_ENDIAN)
- int ofmt = ap->a_vp->v_mount->mnt_maxsymlinklen <= 0;
+ int ofmt = VTOI(ap->a_vp)->i_ump->um_maxsymlinklen == 0;
#endif
if (uio->uio_rw != UIO_READ)
@@ -1522,8 +1522,8 @@ ufs_readlink(void *v)
u_int64_t isize;
isize = DIP(ip, size);
- if (isize < vp->v_mount->mnt_maxsymlinklen ||
- (vp->v_mount->mnt_maxsymlinklen == 0 && DIP(ip, blocks) == 0)) {
+ if (isize < ip->i_ump->um_maxsymlinklen ||
+ (ip->i_ump->um_maxsymlinklen == 0 && DIP(ip, blocks) == 0)) {
return (uiomove((char *)SHORTLINK(ip), isize, ap->a_uio));
}
return (VOP_READ(vp, ap->a_uio, 0, ap->a_cred));
Index: ufs/ufs/ufsmount.h
===================================================================
RCS file: /cvs/src/sys/ufs/ufs/ufsmount.h,v
retrieving revision 1.12
diff -u -p -r1.12 ufsmount.h
--- ufs/ufs/ufsmount.h 29 Oct 2006 00:53:37 -0000 1.12
+++ ufs/ufs/ufsmount.h 26 Feb 2016 21:30:16 -0000
@@ -66,6 +66,7 @@ struct ufsmount {
char um_qflags[MAXQUOTAS]; /* quota specific flags */
struct netexport um_export; /* export information */
u_int64_t um_savedmaxfilesize; /* XXX - limit maxfilesize */
+ u_int um_maxsymlinklen; /* max size of short symlink */
};
/*