[Midnightbsd-cvs] src [10028] trunk/sys/fs: sync with freebsd
laffer1 at midnightbsd.org
laffer1 at midnightbsd.org
Sun May 27 18:19:26 EDT 2018
Revision: 10028
http://svnweb.midnightbsd.org/src/?rev=10028
Author: laffer1
Date: 2018-05-27 18:19:26 -0400 (Sun, 27 May 2018)
Log Message:
-----------
sync with freebsd
Modified Paths:
--------------
trunk/sys/fs/cd9660/TODO
trunk/sys/fs/cd9660/TODO.hibler
trunk/sys/fs/cd9660/cd9660_bmap.c
trunk/sys/fs/cd9660/cd9660_iconv.c
trunk/sys/fs/cd9660/cd9660_lookup.c
trunk/sys/fs/cd9660/cd9660_mount.h
trunk/sys/fs/cd9660/cd9660_node.c
trunk/sys/fs/cd9660/cd9660_node.h
trunk/sys/fs/cd9660/cd9660_rrip.c
trunk/sys/fs/cd9660/cd9660_rrip.h
trunk/sys/fs/cd9660/cd9660_util.c
trunk/sys/fs/cd9660/cd9660_vfsops.c
trunk/sys/fs/cd9660/cd9660_vnops.c
trunk/sys/fs/cd9660/iso.h
trunk/sys/fs/cd9660/iso_rrip.h
trunk/sys/fs/deadfs/dead_vnops.c
trunk/sys/fs/devfs/devfs.h
trunk/sys/fs/devfs/devfs_devs.c
trunk/sys/fs/devfs/devfs_dir.c
trunk/sys/fs/devfs/devfs_int.h
trunk/sys/fs/devfs/devfs_rule.c
trunk/sys/fs/devfs/devfs_vfsops.c
trunk/sys/fs/devfs/devfs_vnops.c
trunk/sys/fs/ext2fs/ext2_alloc.c
trunk/sys/fs/ext2fs/ext2_balloc.c
trunk/sys/fs/ext2fs/ext2_bmap.c
trunk/sys/fs/ext2fs/ext2_dinode.h
trunk/sys/fs/ext2fs/ext2_dir.h
trunk/sys/fs/ext2fs/ext2_extern.h
trunk/sys/fs/ext2fs/ext2_inode.c
trunk/sys/fs/ext2fs/ext2_inode_cnv.c
trunk/sys/fs/ext2fs/ext2_lookup.c
trunk/sys/fs/ext2fs/ext2_mount.h
trunk/sys/fs/ext2fs/ext2_subr.c
trunk/sys/fs/ext2fs/ext2_vfsops.c
trunk/sys/fs/ext2fs/ext2_vnops.c
trunk/sys/fs/ext2fs/ext2fs.h
trunk/sys/fs/ext2fs/fs.h
trunk/sys/fs/ext2fs/inode.h
trunk/sys/fs/fdescfs/fdesc.h
trunk/sys/fs/fdescfs/fdesc_vfsops.c
trunk/sys/fs/fdescfs/fdesc_vnops.c
trunk/sys/fs/fifofs/fifo_vnops.c
trunk/sys/fs/msdosfs/bootsect.h
trunk/sys/fs/msdosfs/bpb.h
trunk/sys/fs/msdosfs/denode.h
trunk/sys/fs/msdosfs/direntry.h
trunk/sys/fs/msdosfs/fat.h
trunk/sys/fs/msdosfs/msdosfs_conv.c
trunk/sys/fs/msdosfs/msdosfs_denode.c
trunk/sys/fs/msdosfs/msdosfs_fat.c
trunk/sys/fs/msdosfs/msdosfs_fileno.c
trunk/sys/fs/msdosfs/msdosfs_iconv.c
trunk/sys/fs/msdosfs/msdosfs_lookup.c
trunk/sys/fs/msdosfs/msdosfs_vfsops.c
trunk/sys/fs/msdosfs/msdosfs_vnops.c
trunk/sys/fs/msdosfs/msdosfsmount.h
Added Paths:
-----------
trunk/sys/fs/ext2fs/ext2_extents.c
trunk/sys/fs/ext2fs/ext2_extents.h
trunk/sys/fs/ext2fs/ext2_hash.c
trunk/sys/fs/ext2fs/ext2_htree.c
trunk/sys/fs/ext2fs/htree.h
Property Changed:
----------------
trunk/sys/fs/cd9660/TODO
trunk/sys/fs/cd9660/TODO.hibler
Modified: trunk/sys/fs/cd9660/TODO
===================================================================
--- trunk/sys/fs/cd9660/TODO 2018-05-27 22:18:36 UTC (rev 10027)
+++ trunk/sys/fs/cd9660/TODO 2018-05-27 22:19:26 UTC (rev 10028)
@@ -1,4 +1,4 @@
-# $MidnightBSD$
+# $FreeBSD: stable/10/sys/fs/cd9660/TODO 166639 2007-02-11 13:54:25Z rodrigc $
2) should understand Rock Ridge
Property changes on: trunk/sys/fs/cd9660/TODO
___________________________________________________________________
Added: mnbsd:nokeywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Modified: trunk/sys/fs/cd9660/TODO.hibler
===================================================================
--- trunk/sys/fs/cd9660/TODO.hibler 2018-05-27 22:18:36 UTC (rev 10027)
+++ trunk/sys/fs/cd9660/TODO.hibler 2018-05-27 22:19:26 UTC (rev 10028)
@@ -1,4 +1,4 @@
-$MidnightBSD$
+$FreeBSD: stable/10/sys/fs/cd9660/TODO.hibler 166639 2007-02-11 13:54:25Z rodrigc $
1. Investiate making ISOFS another UFS shared filesystem (ala FFS/MFS/LFS).
Since it was modelled after the inode code, we might be able to merge
Property changes on: trunk/sys/fs/cd9660/TODO.hibler
___________________________________________________________________
Added: mnbsd:nokeywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Modified: trunk/sys/fs/cd9660/cd9660_bmap.c
===================================================================
--- trunk/sys/fs/cd9660/cd9660_bmap.c 2018-05-27 22:18:36 UTC (rev 10027)
+++ trunk/sys/fs/cd9660/cd9660_bmap.c 2018-05-27 22:19:26 UTC (rev 10028)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*-
* Copyright (c) 1994
* The Regents of the University of California. All rights reserved.
@@ -35,7 +36,7 @@
*/
#include <sys/cdefs.h>
-__MBSDID("$MidnightBSD$");
+__FBSDID("$FreeBSD: stable/10/sys/fs/cd9660/cd9660_bmap.c 185071 2008-11-18 23:19:43Z jhb $");
#include <sys/param.h>
#include <sys/systm.h>
Modified: trunk/sys/fs/cd9660/cd9660_iconv.c
===================================================================
--- trunk/sys/fs/cd9660/cd9660_iconv.c 2018-05-27 22:18:36 UTC (rev 10027)
+++ trunk/sys/fs/cd9660/cd9660_iconv.c 2018-05-27 22:19:26 UTC (rev 10028)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*-
* Copyright (c) 2003 Ryuichiro Imura
* All rights reserved.
@@ -25,7 +26,7 @@
*/
#include <sys/cdefs.h>
-__MBSDID("$MidnightBSD$");
+__FBSDID("$FreeBSD: stable/10/sys/fs/cd9660/cd9660_iconv.c 166639 2007-02-11 13:54:25Z rodrigc $");
#include <sys/param.h>
#include <sys/kernel.h>
Modified: trunk/sys/fs/cd9660/cd9660_lookup.c
===================================================================
--- trunk/sys/fs/cd9660/cd9660_lookup.c 2018-05-27 22:18:36 UTC (rev 10027)
+++ trunk/sys/fs/cd9660/cd9660_lookup.c 2018-05-27 22:19:26 UTC (rev 10028)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*-
* Copyright (c) 1989, 1993, 1994
* The Regents of the University of California. All rights reserved.
@@ -36,7 +37,7 @@
*/
#include <sys/cdefs.h>
-__MBSDID("$MidnightBSD$");
+__FBSDID("$FreeBSD: stable/10/sys/fs/cd9660/cd9660_lookup.c 269165 2014-07-28 00:53:26Z kib $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -50,6 +51,23 @@
#include <fs/cd9660/cd9660_node.h>
#include <fs/cd9660/iso_rrip.h>
+struct cd9660_ino_alloc_arg {
+ ino_t ino;
+ ino_t i_ino;
+ struct iso_directory_record *ep;
+};
+
+static int
+cd9660_ino_alloc(struct mount *mp, void *arg, int lkflags,
+ struct vnode **vpp)
+{
+ struct cd9660_ino_alloc_arg *dd_arg;
+
+ dd_arg = arg;
+ return (cd9660_vget_internal(mp, dd_arg->i_ino, lkflags, vpp,
+ dd_arg->i_ino != dd_arg->ino, dd_arg->ep));
+}
+
/*
* Convert a component of a pathname into a pointer to a locked inode.
* This is a very central and rather complicated routine.
@@ -104,6 +122,7 @@
doff_t endsearch; /* offset to end directory search */
struct vnode *pdp; /* saved dp during symlink work */
struct vnode *tdp; /* returned by cd9660_vget_internal */
+ struct cd9660_ino_alloc_arg dd_arg;
u_long bmask; /* block offset mask */
int error;
ino_t ino, i_ino;
@@ -114,7 +133,6 @@
int res;
int assoc, len;
char *name;
- struct mount *mp;
struct vnode **vpp = ap->a_vpp;
struct componentname *cnp = ap->a_cnp;
int flags = cnp->cn_flags;
@@ -368,39 +386,13 @@
* it's a relocated directory.
*/
if (flags & ISDOTDOT) {
- /*
- * Expanded copy of vn_vget_ino() so that we can use
- * cd9660_vget_internal().
- */
- mp = pdp->v_mount;
- ltype = VOP_ISLOCKED(pdp);
- error = vfs_busy(mp, MBF_NOWAIT);
- if (error != 0) {
- vfs_ref(mp);
- VOP_UNLOCK(pdp, 0);
- error = vfs_busy(mp, 0);
- vn_lock(pdp, ltype | LK_RETRY);
- vfs_rel(mp);
- if (error)
- return (ENOENT);
- if (pdp->v_iflag & VI_DOOMED) {
- vfs_unbusy(mp);
- return (ENOENT);
- }
- }
- VOP_UNLOCK(pdp, 0);
- error = cd9660_vget_internal(vdp->v_mount, i_ino,
- cnp->cn_lkflags, &tdp,
- i_ino != ino, ep);
+ dd_arg.ino = ino;
+ dd_arg.i_ino = i_ino;
+ dd_arg.ep = ep;
+ error = vn_vget_ino_gen(pdp, cd9660_ino_alloc, &dd_arg,
+ cnp->cn_lkflags, &tdp);
free(ep2, M_TEMP);
- vfs_unbusy(mp);
- vn_lock(pdp, ltype | LK_RETRY);
- if (pdp->v_iflag & VI_DOOMED) {
- if (error == 0)
- vput(tdp);
- error = ENOENT;
- }
- if (error)
+ if (error != 0)
return (error);
*vpp = tdp;
} else if (dp->i_number == i_ino) {
Modified: trunk/sys/fs/cd9660/cd9660_mount.h
===================================================================
--- trunk/sys/fs/cd9660/cd9660_mount.h 2018-05-27 22:18:36 UTC (rev 10027)
+++ trunk/sys/fs/cd9660/cd9660_mount.h 2018-05-27 22:19:26 UTC (rev 10028)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*-
* Copyright (c) 1995
* The Regents of the University of California. All rights reserved.
@@ -32,7 +33,7 @@
* SUCH DAMAGE.
*
* @(#)cd9660_mount.h 8.1 (Berkeley) 5/24/95
- * $MidnightBSD$
+ * $FreeBSD: stable/10/sys/fs/cd9660/cd9660_mount.h 213664 2010-10-10 07:05:47Z kib $
*/
/*
Modified: trunk/sys/fs/cd9660/cd9660_node.c
===================================================================
--- trunk/sys/fs/cd9660/cd9660_node.c 2018-05-27 22:18:36 UTC (rev 10027)
+++ trunk/sys/fs/cd9660/cd9660_node.c 2018-05-27 22:19:26 UTC (rev 10028)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*-
* Copyright (c) 1982, 1986, 1989, 1994, 1995
* The Regents of the University of California. All rights reserved.
@@ -35,7 +36,7 @@
*/
#include <sys/cdefs.h>
-__MBSDID("$MidnightBSD$");
+__FBSDID("$FreeBSD: stable/10/sys/fs/cd9660/cd9660_node.c 234607 2012-04-23 14:10:34Z trasz $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -65,7 +66,6 @@
} */ *ap;
{
struct vnode *vp = ap->a_vp;
- struct thread *td = ap->a_td;
struct iso_node *ip = VTOI(vp);
int error = 0;
@@ -74,7 +74,7 @@
* so that it can be reused immediately.
*/
if (ip->inode.iso_mode == 0)
- vrecycle(vp, td);
+ vrecycle(vp);
return error;
}
Modified: trunk/sys/fs/cd9660/cd9660_node.h
===================================================================
--- trunk/sys/fs/cd9660/cd9660_node.h 2018-05-27 22:18:36 UTC (rev 10027)
+++ trunk/sys/fs/cd9660/cd9660_node.h 2018-05-27 22:19:26 UTC (rev 10028)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*-
* Copyright (c) 1994
* The Regents of the University of California. All rights reserved.
@@ -32,7 +33,7 @@
* SUCH DAMAGE.
*
* @(#)cd9660_node.h 8.6 (Berkeley) 5/14/95
- * $MidnightBSD$
+ * $FreeBSD: stable/10/sys/fs/cd9660/cd9660_node.h 187838 2009-01-28 18:54:56Z jhb $
*/
/*
Modified: trunk/sys/fs/cd9660/cd9660_rrip.c
===================================================================
--- trunk/sys/fs/cd9660/cd9660_rrip.c 2018-05-27 22:18:36 UTC (rev 10027)
+++ trunk/sys/fs/cd9660/cd9660_rrip.c 2018-05-27 22:19:26 UTC (rev 10028)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*-
* Copyright (c) 1993, 1994
* The Regents of the University of California. All rights reserved.
@@ -35,7 +36,7 @@
*/
#include <sys/cdefs.h>
-__MBSDID("$MidnightBSD$");
+__FBSDID("$FreeBSD: stable/10/sys/fs/cd9660/cd9660_rrip.c 193066 2009-05-29 21:27:12Z jamie $");
#include <sys/param.h>
#include <sys/systm.h>
Modified: trunk/sys/fs/cd9660/cd9660_rrip.h
===================================================================
--- trunk/sys/fs/cd9660/cd9660_rrip.h 2018-05-27 22:18:36 UTC (rev 10027)
+++ trunk/sys/fs/cd9660/cd9660_rrip.h 2018-05-27 22:19:26 UTC (rev 10028)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*-
* Copyright (c) 1993, 1994
* The Regents of the University of California. All rights reserved.
@@ -32,7 +33,7 @@
* SUCH DAMAGE.
*
* @(#)cd9660_rrip.h 8.2 (Berkeley) 12/5/94
- * $MidnightBSD$
+ * $FreeBSD: stable/10/sys/fs/cd9660/cd9660_rrip.h 166639 2007-02-11 13:54:25Z rodrigc $
*/
typedef struct {
Modified: trunk/sys/fs/cd9660/cd9660_util.c
===================================================================
--- trunk/sys/fs/cd9660/cd9660_util.c 2018-05-27 22:18:36 UTC (rev 10027)
+++ trunk/sys/fs/cd9660/cd9660_util.c 2018-05-27 22:19:26 UTC (rev 10028)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*-
* Copyright (c) 1994
* The Regents of the University of California. All rights reserved.
@@ -36,7 +37,7 @@
*/
#include <sys/cdefs.h>
-__MBSDID("$MidnightBSD$");
+__FBSDID("$FreeBSD: stable/10/sys/fs/cd9660/cd9660_util.c 278060 2015-02-02 07:42:03Z dim $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -80,7 +81,8 @@
inbuf[2]='\0';
inp = inbuf;
outp = outbuf;
- cd9660_iconv->convchr(handle, (const char **)&inp, &i, &outp, &j);
+ cd9660_iconv->convchr(handle, __DECONST(const char **, &inp), &i,
+ &outp, &j);
len -= j;
if (clen) *clen = len;
*c = '\0';
@@ -121,7 +123,8 @@
u_char *fnend = fn + fnlen, *isoend = isofn + isolen;
for (; fn < fnend; ) {
- d = sgetrune(fn, fnend - fn, (char const **)&fn, flags, lhandle);
+ d = sgetrune(fn, fnend - fn, __DECONST(const char **, &fn),
+ flags, lhandle);
if (isofn == isoend)
return d;
isofn += isochar(isofn, isoend, joliet_level, &c, NULL, flags, handle);
Modified: trunk/sys/fs/cd9660/cd9660_vfsops.c
===================================================================
--- trunk/sys/fs/cd9660/cd9660_vfsops.c 2018-05-27 22:18:36 UTC (rev 10027)
+++ trunk/sys/fs/cd9660/cd9660_vfsops.c 2018-05-27 22:19:26 UTC (rev 10028)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*-
* Copyright (c) 1994
* The Regents of the University of California. All rights reserved.
@@ -35,7 +36,7 @@
*/
#include <sys/cdefs.h>
-__MBSDID("$MidnightBSD$");
+__FBSDID("$FreeBSD: stable/10/sys/fs/cd9660/cd9660_vfsops.c 255867 2013-09-25 02:49:18Z jmg $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -133,7 +134,7 @@
int error;
accmode_t accmode;
struct nameidata ndp;
- struct iso_mnt *imp = 0;
+ struct iso_mnt *imp = NULL;
td = curthread;
@@ -205,7 +206,7 @@
struct vnode *devvp;
struct mount *mp;
{
- struct iso_mnt *isomp = (struct iso_mnt *)0;
+ struct iso_mnt *isomp = NULL;
struct buf *bp = NULL;
struct buf *pribp = NULL, *supbp = NULL;
struct cdev *dev;
@@ -214,7 +215,7 @@
int iso_bsize;
int iso_blknum;
int joliet_level;
- struct iso_volume_descriptor *vdp = 0;
+ struct iso_volume_descriptor *vdp = NULL;
struct iso_primary_descriptor *pri = NULL;
struct iso_sierra_primary_descriptor *pri_sierra = NULL;
struct iso_supplementary_descriptor *sup = NULL;
@@ -369,6 +370,9 @@
pribp->b_flags |= B_AGE;
brelse(pribp);
pribp = NULL;
+ rootp = NULL;
+ pri = NULL;
+ pri_sierra = NULL;
mp->mnt_data = isomp;
mp->mnt_stat.f_fsid.val[0] = dev2udev(dev);
@@ -376,8 +380,7 @@
mp->mnt_maxsymlinklen = 0;
MNT_ILOCK(mp);
mp->mnt_flag |= MNT_LOCAL;
- mp->mnt_kern_flag |= MNTK_MPSAFE | MNTK_LOOKUP_SHARED |
- MNTK_EXTENDED_SHARED;
+ mp->mnt_kern_flag |= MNTK_LOOKUP_SHARED | MNTK_EXTENDED_SHARED;
MNT_IUNLOCK(mp);
isomp->im_mountp = mp;
isomp->im_dev = dev;
@@ -391,11 +394,11 @@
/* Check the Rock Ridge Extension support */
if (!(isomp->im_flags & ISOFSMNT_NORRIP)) {
- if ((error = bread(isomp->im_devvp,
- (isomp->root_extent + isonum_711(rootp->ext_attr_length)) <<
- (isomp->im_bshift - DEV_BSHIFT),
- isomp->logical_block_size, NOCRED, &bp)) != 0)
- goto out;
+ if ((error = bread(isomp->im_devvp, (isomp->root_extent +
+ isonum_711(((struct iso_directory_record *)isomp->root)->
+ ext_attr_length)) << (isomp->im_bshift - DEV_BSHIFT),
+ isomp->logical_block_size, NOCRED, &bp)) != 0)
+ goto out;
rootp = (struct iso_directory_record *)bp->b_data;
@@ -412,6 +415,7 @@
bp->b_flags |= B_AGE;
brelse(bp);
bp = NULL;
+ rootp = NULL;
}
if (isomp->im_flags & ISOFSMNT_KICONV && cd9660_iconv) {
@@ -466,6 +470,7 @@
if (supbp) {
brelse(supbp);
supbp = NULL;
+ sup = NULL;
}
return 0;
@@ -484,7 +489,7 @@
PICKUP_GIANT();
}
if (isomp) {
- free((caddr_t)isomp, M_ISOFSMNT);
+ free(isomp, M_ISOFSMNT);
mp->mnt_data = NULL;
}
dev_rel(dev);
@@ -522,7 +527,7 @@
PICKUP_GIANT();
vrele(isomp->im_devvp);
dev_rel(isomp->im_dev);
- free((caddr_t)isomp, M_ISOFSMNT);
+ free(isomp, M_ISOFSMNT);
mp->mnt_data = NULL;
MNT_ILOCK(mp);
mp->mnt_flag &= ~MNT_LOCAL;
Modified: trunk/sys/fs/cd9660/cd9660_vnops.c
===================================================================
--- trunk/sys/fs/cd9660/cd9660_vnops.c 2018-05-27 22:18:36 UTC (rev 10027)
+++ trunk/sys/fs/cd9660/cd9660_vnops.c 2018-05-27 22:19:26 UTC (rev 10028)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*-
* Copyright (c) 1994
* The Regents of the University of California. All rights reserved.
@@ -35,7 +36,7 @@
*/
#include <sys/cdefs.h>
-__MBSDID("$MidnightBSD$");
+__FBSDID("$FreeBSD: stable/10/sys/fs/cd9660/cd9660_vnops.c 248282 2013-03-14 20:28:26Z kib $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -47,7 +48,6 @@
#include <sys/buf.h>
#include <sys/mount.h>
#include <sys/vnode.h>
-#include <fs/fifofs/fifo.h>
#include <sys/malloc.h>
#include <sys/dirent.h>
#include <sys/unistd.h>
@@ -330,7 +330,7 @@
if (lblktosize(imp, rablock) < ip->i_size)
error = cluster_read(vp, (off_t)ip->i_size,
lbn, size, NOCRED, uio->uio_resid,
- (ap->a_ioflag >> 16), &bp);
+ (ap->a_ioflag >> 16), 0, &bp);
else
error = bread(vp, lbn, size, NOCRED, &bp);
} else {
Modified: trunk/sys/fs/cd9660/iso.h
===================================================================
--- trunk/sys/fs/cd9660/iso.h 2018-05-27 22:18:36 UTC (rev 10027)
+++ trunk/sys/fs/cd9660/iso.h 2018-05-27 22:19:26 UTC (rev 10028)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*-
* Copyright (c) 1994
* The Regents of the University of California. All rights reserved.
@@ -32,7 +33,7 @@
* SUCH DAMAGE.
*
* @(#)iso.h 8.6 (Berkeley) 5/10/95
- * $MidnightBSD$
+ * $FreeBSD: stable/10/sys/fs/cd9660/iso.h 253742 2013-07-28 12:29:10Z marius $
*/
#define ISODCL(from, to) (to - from + 1)
@@ -291,56 +292,65 @@
*/
static __inline uint8_t
-isonum_711(unsigned char *p)
+isonum_711(const unsigned char *p)
{
- return p[0];
+
+ return (p[0]);
}
-static __inline uint8_t
-isonum_712(unsigned char *p)
+static __inline int8_t
+isonum_712(const unsigned char *p)
{
- return p[0];
+
+ return ((signed char)p[0]);
}
static __inline uint8_t
-isonum_713(unsigned char *p)
+isonum_713(const unsigned char *p)
{
- return p[0];
+
+ return (p[0]);
}
static __inline uint16_t
-isonum_721(unsigned char *p)
+isonum_721(const unsigned char *p)
{
+
return (p[0] | p[1] << 8);
}
static __inline uint16_t
-isonum_722(unsigned char *p)
+isonum_722(const unsigned char *p)
{
+
return (p[1] | p[0] << 8);
}
static __inline uint16_t
-isonum_723(unsigned char *p)
+isonum_723(const unsigned char *p)
{
+
return (p[0] | p[1] << 8);
}
static __inline uint32_t
-isonum_731(unsigned char *p)
+isonum_731(const unsigned char *p)
{
+
return (p[0] | p[1] << 8 | p[2] << 16 | p[3] << 24);
}
static __inline uint32_t
-isonum_732(unsigned char *p)
+isonum_732(const unsigned char *p)
{
+
return (p[3] | p[2] << 8 | p[1] << 16 | p[0] << 24);
}
static __inline uint32_t
-isonum_733(unsigned char *p)
+isonum_733(const unsigned char *p)
{
+
return (p[0] | p[1] << 8 | p[2] << 16 | p[3] << 24);
}
Modified: trunk/sys/fs/cd9660/iso_rrip.h
===================================================================
--- trunk/sys/fs/cd9660/iso_rrip.h 2018-05-27 22:18:36 UTC (rev 10027)
+++ trunk/sys/fs/cd9660/iso_rrip.h 2018-05-27 22:19:26 UTC (rev 10028)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*-
* Copyright (c) 1993, 1994
* The Regents of the University of California. All rights reserved.
@@ -32,7 +33,7 @@
* SUCH DAMAGE.
*
* @(#)iso_rrip.h 8.2 (Berkeley) 1/23/94
- * $MidnightBSD$
+ * $FreeBSD: stable/10/sys/fs/cd9660/iso_rrip.h 166639 2007-02-11 13:54:25Z rodrigc $
*/
Modified: trunk/sys/fs/deadfs/dead_vnops.c
===================================================================
--- trunk/sys/fs/deadfs/dead_vnops.c 2018-05-27 22:18:36 UTC (rev 10027)
+++ trunk/sys/fs/deadfs/dead_vnops.c 2018-05-27 22:19:26 UTC (rev 10028)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*-
* Copyright (c) 1989, 1993
* The Regents of the University of California. All rights reserved.
@@ -27,7 +28,7 @@
* SUCH DAMAGE.
*
* @(#)dead_vnops.c 8.1 (Berkeley) 6/10/93
- * $MidnightBSD$
+ * $FreeBSD: stable/10/sys/fs/deadfs/dead_vnops.c 273463 2014-10-22 09:12:20Z kib $
*/
#include <sys/param.h>
@@ -43,9 +44,6 @@
*/
static vop_lookup_t dead_lookup;
static vop_open_t dead_open;
-static vop_poll_t dead_poll;
-static vop_read_t dead_read;
-static vop_write_t dead_write;
static vop_getwritemount_t dead_getwritemount;
static vop_rename_t dead_rename;
@@ -80,14 +78,10 @@
.vop_write = dead_write,
};
-/* ARGSUSED */
static int
-dead_getwritemount(ap)
- struct vop_getwritemount_args /* {
- struct vnode *a_vp;
- struct mount **a_mpp;
- } */ *ap;
+dead_getwritemount(struct vop_getwritemount_args *ap)
{
+
*(ap->a_mpp) = NULL;
return (0);
}
@@ -95,14 +89,8 @@
/*
* Trivial lookup routine that always fails.
*/
-/* ARGSUSED */
static int
-dead_lookup(ap)
- struct vop_lookup_args /* {
- struct vnode * a_dvp;
- struct vnode ** a_vpp;
- struct componentname * a_cnp;
- } */ *ap;
+dead_lookup(struct vop_lookup_args *ap)
{
*ap->a_vpp = NULL;
@@ -112,33 +100,17 @@
/*
* Open always fails as if device did not exist.
*/
-/* ARGSUSED */
static int
-dead_open(ap)
- struct vop_open_args /* {
- struct vnode *a_vp;
- int a_mode;
- struct ucred *a_cred;
- struct proc *a_p;
- } */ *ap;
+dead_open(struct vop_open_args *ap)
{
return (ENXIO);
}
-/*
- * Vnode op for read
- */
-/* ARGSUSED */
-static int
-dead_read(ap)
- struct vop_read_args /* {
- struct vnode *a_vp;
- struct uio *a_uio;
- int a_ioflag;
- struct ucred *a_cred;
- } */ *ap;
+int
+dead_read(struct vop_read_args *ap)
{
+
/*
* Return EOF for tty devices, EIO for others
*/
@@ -147,44 +119,29 @@
return (0);
}
-/*
- * Vnode op for write
- */
-/* ARGSUSED */
-static int
-dead_write(ap)
- struct vop_write_args /* {
- struct vnode *a_vp;
- struct uio *a_uio;
- int a_ioflag;
- struct ucred *a_cred;
- } */ *ap;
+int
+dead_write(struct vop_write_args *ap)
{
+
return (EIO);
}
-/*
- * Trivial poll routine that always returns POLLHUP.
- * This is necessary so that a process which is polling a file
- * gets notified when that file is revoke()d.
- */
-static int
-dead_poll(ap)
- struct vop_poll_args *ap;
+int
+dead_poll(struct vop_poll_args *ap)
{
- return (POLLHUP);
+
+ if (ap->a_events & ~POLLSTANDARD)
+ return (POLLNVAL);
+
+ /*
+ * Let the user find out that the descriptor is gone.
+ */
+ return (POLLHUP | ((POLLIN | POLLRDNORM) & ap->a_events));
+
}
static int
-dead_rename(ap)
- struct vop_rename_args /* {
- struct vnode *a_fdvp;
- struct vnode *a_fvp;
- struct componentname *a_fcnp;
- struct vnode *a_tdvp;
- struct vnode *a_tvp;
- struct componentname *a_tcnp;
- } */ *ap;
+dead_rename(struct vop_rename_args *ap)
{
vop_rename_fail(ap);
Modified: trunk/sys/fs/devfs/devfs.h
===================================================================
--- trunk/sys/fs/devfs/devfs.h 2018-05-27 22:18:36 UTC (rev 10027)
+++ trunk/sys/fs/devfs/devfs.h 2018-05-27 22:19:26 UTC (rev 10028)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*-
* Copyright (c) 1992, 1993
* The Regents of the University of California. All rights reserved.
@@ -33,7 +34,7 @@
* @(#)kernfs.h 8.6 (Berkeley) 3/29/95
* From: FreeBSD: src/sys/miscfs/kernfs/kernfs.h 1.14
*
- * $MidnightBSD$
+ * $FreeBSD: stable/10/sys/fs/devfs/devfs.h 231265 2012-02-09 10:09:12Z mm $
*/
#ifndef _FS_DEVFS_DEVFS_H_
Modified: trunk/sys/fs/devfs/devfs_devs.c
===================================================================
--- trunk/sys/fs/devfs/devfs_devs.c 2018-05-27 22:18:36 UTC (rev 10027)
+++ trunk/sys/fs/devfs/devfs_devs.c 2018-05-27 22:19:26 UTC (rev 10028)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*-
* Copyright (c) 2000,2004
* Poul-Henning Kamp. All rights reserved.
@@ -25,7 +26,7 @@
*
* From: FreeBSD: src/sys/miscfs/kernfs/kernfs_vfsops.c 1.36
*
- * $MidnightBSD$
+ * $FreeBSD: stable/10/sys/fs/devfs/devfs_devs.c 313932 2017-02-19 03:17:11Z kib $
*/
#include <sys/param.h>
@@ -61,7 +62,7 @@
static MALLOC_DEFINE(M_DEVFS3, "DEVFS3", "DEVFS data 3");
static MALLOC_DEFINE(M_CDEVP, "DEVFS1", "DEVFS cdev_priv storage");
-static SYSCTL_NODE(_vfs, OID_AUTO, devfs, CTLFLAG_RW, 0, "DEVFS filesystem");
+SYSCTL_NODE(_vfs, OID_AUTO, devfs, CTLFLAG_RW, 0, "DEVFS filesystem");
static unsigned devfs_generation;
SYSCTL_UINT(_vfs_devfs, OID_AUTO, generation, CTLFLAG_RD,
@@ -109,10 +110,10 @@
NULL, 0, sysctl_devname, "", "devname(3) handler");
SYSCTL_INT(_debug_sizeof, OID_AUTO, cdev, CTLFLAG_RD,
- 0, sizeof(struct cdev), "sizeof(struct cdev)");
+ SYSCTL_NULL_INT_PTR, sizeof(struct cdev), "sizeof(struct cdev)");
SYSCTL_INT(_debug_sizeof, OID_AUTO, cdev_priv, CTLFLAG_RD,
- 0, sizeof(struct cdev_priv), "sizeof(struct cdev_priv)");
+ SYSCTL_NULL_INT_PTR, sizeof(struct cdev_priv), "sizeof(struct cdev_priv)");
struct cdev *
devfs_alloc(int flags)
@@ -121,23 +122,17 @@
struct cdev *cdev;
struct timespec ts;
- cdp = malloc(sizeof *cdp, M_CDEVP, M_USE_RESERVE | M_ZERO |
+ cdp = malloc(sizeof *cdp, M_CDEVP, M_ZERO |
((flags & MAKEDEV_NOWAIT) ? M_NOWAIT : M_WAITOK));
if (cdp == NULL)
return (NULL);
cdp->cdp_dirents = &cdp->cdp_dirent0;
- cdp->cdp_dirent0 = NULL;
- cdp->cdp_maxdirent = 0;
- cdp->cdp_inode = 0;
cdev = &cdp->cdp_c;
-
- cdev->si_name = cdev->__si_namebuf;
LIST_INIT(&cdev->si_children);
vfs_timestamp(&ts);
cdev->si_atime = cdev->si_mtime = cdev->si_ctime = ts;
- cdev->si_cred = NULL;
return (cdev);
}
@@ -187,6 +182,16 @@
continue;
if (type != 0 && type != de->de_dirent->d_type)
continue;
+
+ /*
+ * The race with finding non-active name is not
+ * completely closed by the check, but it is similar
+ * to the devfs_allocv() in making it unlikely enough.
+ */
+ if (de->de_dirent->d_type == DT_CHR &&
+ (de->de_cdp->cdp_flags & CDP_ACTIVE) == 0)
+ continue;
+
if (bcmp(name, de->de_dirent->d_name, namelen) != 0)
continue;
break;
@@ -204,7 +209,7 @@
struct dirent d;
d.d_namlen = namelen;
- i = sizeof (*de) + GENERIC_DIRSIZ(&d);
+ i = sizeof(*de) + GENERIC_DIRSIZ(&d);
de = malloc(i, M_DEVFS3, M_WAITOK | M_ZERO);
de->de_dirent = (struct dirent *)(de + 1);
de->de_dirent->d_namlen = namelen;
@@ -242,7 +247,8 @@
}
struct devfs_dirent *
-devfs_vmkdir(struct devfs_mount *dmp, char *name, int namelen, struct devfs_dirent *dotdot, u_int inode)
+devfs_vmkdir(struct devfs_mount *dmp, char *name, int namelen,
+ struct devfs_dirent *dotdot, u_int inode)
{
struct devfs_dirent *dd;
struct devfs_dirent *de;
@@ -295,6 +301,13 @@
void
devfs_dirent_free(struct devfs_dirent *de)
{
+ struct vnode *vp;
+
+ vp = de->de_vnode;
+ mtx_lock(&devfs_de_interlock);
+ if (vp != NULL && vp->v_data == de)
+ vp->v_data = NULL;
+ mtx_unlock(&devfs_de_interlock);
free(de, M_DEVFS3);
}
@@ -656,7 +669,7 @@
/*
* devfs_create() and devfs_destroy() are called from kern_conf.c and
* in both cases the devlock() mutex is held, so no further locking
- * is necesary and no sleeping allowed.
+ * is necessary and no sleeping allowed.
*/
void
Modified: trunk/sys/fs/devfs/devfs_dir.c
===================================================================
--- trunk/sys/fs/devfs/devfs_dir.c 2018-05-27 22:18:36 UTC (rev 10027)
+++ trunk/sys/fs/devfs/devfs_dir.c 2018-05-27 22:19:26 UTC (rev 10028)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*-
* Copyright (c) 2010 Jaakko Heinonen <jh at FreeBSD.org>
* All rights reserved.
@@ -23,7 +24,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $MidnightBSD$
+ * $FreeBSD: stable/10/sys/fs/devfs/devfs_dir.c 213215 2010-09-27 17:47:09Z jh $
*/
#include <sys/param.h>
Modified: trunk/sys/fs/devfs/devfs_int.h
===================================================================
--- trunk/sys/fs/devfs/devfs_int.h 2018-05-27 22:18:36 UTC (rev 10027)
+++ trunk/sys/fs/devfs/devfs_int.h 2018-05-27 22:19:26 UTC (rev 10028)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*-
* Copyright (c) 2005 Poul-Henning Kamp. All rights reserved.
*
@@ -22,7 +23,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $MidnightBSD$
+ * $FreeBSD: stable/10/sys/fs/devfs/devfs_int.h 278283 2015-02-05 20:49:13Z hselasky $
*/
/*
@@ -70,7 +71,7 @@
LIST_HEAD(, cdev_privdata) cdp_fdpriv;
};
-#define cdev2priv(c) member2struct(cdev_priv, cdp_c, c)
+#define cdev2priv(c) __containerof(c, struct cdev_priv, cdp_c)
struct cdev *devfs_alloc(int);
int devfs_dev_exists(const char *);
Modified: trunk/sys/fs/devfs/devfs_rule.c
===================================================================
--- trunk/sys/fs/devfs/devfs_rule.c 2018-05-27 22:18:36 UTC (rev 10027)
+++ trunk/sys/fs/devfs/devfs_rule.c 2018-05-27 22:19:26 UTC (rev 10028)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*-
* Copyright (c) 2002 Dima Dorfman.
* All rights reserved.
@@ -23,7 +24,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $MidnightBSD$
+ * $FreeBSD: stable/10/sys/fs/devfs/devfs_rule.c 253677 2013-07-26 14:25:58Z avg $
*/
/*
@@ -101,7 +102,7 @@
static devfs_rid devfs_rid_input(devfs_rid rid, struct devfs_mount *dm);
static void devfs_rule_applyde_recursive(struct devfs_krule *dk,
- struct devfs_dirent *de);
+ struct devfs_mount *dm, struct devfs_dirent *de);
static void devfs_rule_applydm(struct devfs_krule *dk, struct devfs_mount *dm);
static int devfs_rule_autonumber(struct devfs_ruleset *ds, devfs_rnum *rnp);
static struct devfs_krule *devfs_rule_byid(devfs_rid rid);
@@ -109,13 +110,16 @@
static struct cdev *devfs_rule_getdev(struct devfs_dirent *de);
static int devfs_rule_input(struct devfs_rule *dr, struct devfs_mount *dm);
static int devfs_rule_insert(struct devfs_rule *dr);
-static int devfs_rule_match(struct devfs_krule *dk, struct devfs_dirent *de);
-static int devfs_rule_matchpath(struct devfs_krule *dk,
+static int devfs_rule_match(struct devfs_krule *dk, struct devfs_mount *dm,
struct devfs_dirent *de);
-static void devfs_rule_run(struct devfs_krule *dk, struct devfs_dirent *de, unsigned depth);
+static int devfs_rule_matchpath(struct devfs_krule *dk, struct devfs_mount *dm,
+ struct devfs_dirent *de);
+static void devfs_rule_run(struct devfs_krule *dk, struct devfs_mount *dm,
+ struct devfs_dirent *de, unsigned depth);
static void devfs_ruleset_applyde(struct devfs_ruleset *ds,
- struct devfs_dirent *de, unsigned depth);
+ struct devfs_mount *dm, struct devfs_dirent *de,
+ unsigned depth);
static void devfs_ruleset_applydm(struct devfs_ruleset *ds,
struct devfs_mount *dm);
static struct devfs_ruleset *devfs_ruleset_bynum(devfs_rsnum rsnum);
@@ -146,7 +150,7 @@
sx_slock(&sx_rules);
ds = devfs_ruleset_bynum(dm->dm_ruleset);
KASSERT(ds != NULL, ("mount-point has NULL ruleset"));
- devfs_ruleset_applyde(ds, de, devfs_rule_depth);
+ devfs_ruleset_applyde(ds, dm, de, devfs_rule_depth);
sx_sunlock(&sx_rules);
}
@@ -337,13 +341,14 @@
* XXX: a linear search could be done through the cdev list instead.
*/
static void
-devfs_rule_applyde_recursive(struct devfs_krule *dk, struct devfs_dirent *de)
+devfs_rule_applyde_recursive(struct devfs_krule *dk, struct devfs_mount *dm,
+ struct devfs_dirent *de)
{
struct devfs_dirent *de2;
TAILQ_FOREACH(de2, &de->de_dlist, de_list)
- devfs_rule_applyde_recursive(dk, de2);
- devfs_rule_run(dk, de, devfs_rule_depth);
+ devfs_rule_applyde_recursive(dk, dm, de2);
+ devfs_rule_run(dk, dm, de, devfs_rule_depth);
}
/*
@@ -353,7 +358,7 @@
devfs_rule_applydm(struct devfs_krule *dk, struct devfs_mount *dm)
{
- devfs_rule_applyde_recursive(dk, dm->dm_rootdir);
+ devfs_rule_applyde_recursive(dk, dm, dm->dm_rootdir);
}
/*
@@ -525,7 +530,8 @@
* de; 0, otherwise.
*/
static int
-devfs_rule_match(struct devfs_krule *dk, struct devfs_dirent *de)
+devfs_rule_match(struct devfs_krule *dk, struct devfs_mount *dm,
+ struct devfs_dirent *de)
{
struct devfs_rule *dr = &dk->dk_rule;
struct cdev *dev;
@@ -558,7 +564,7 @@
dev_relthread(dev, ref);
}
if (dr->dr_icond & DRC_PATHPTRN)
- if (!devfs_rule_matchpath(dk, de))
+ if (!devfs_rule_matchpath(dk, dm, de))
return (0);
return (1);
@@ -568,23 +574,30 @@
* Determine whether dk matches de on account of dr_pathptrn.
*/
static int
-devfs_rule_matchpath(struct devfs_krule *dk, struct devfs_dirent *de)
+devfs_rule_matchpath(struct devfs_krule *dk, struct devfs_mount *dm,
+ struct devfs_dirent *de)
{
struct devfs_rule *dr = &dk->dk_rule;
- char *pname;
struct cdev *dev;
+ int match;
+ char *pname, *specname;
+ specname = NULL;
dev = devfs_rule_getdev(de);
if (dev != NULL)
pname = dev->si_name;
else if (de->de_dirent->d_type == DT_LNK ||
- de->de_dirent->d_type == DT_DIR)
- pname = de->de_dirent->d_name;
- else
+ (de->de_dirent->d_type == DT_DIR && de != dm->dm_rootdir &&
+ (de->de_flags & (DE_DOT | DE_DOTDOT)) == 0)) {
+ specname = malloc(SPECNAMELEN + 1, M_TEMP, M_WAITOK);
+ pname = devfs_fqpn(specname, dm, de, NULL);
+ } else
return (0);
+
KASSERT(pname != NULL, ("devfs_rule_matchpath: NULL pname"));
-
- return (fnmatch(dr->dr_pathptrn, pname, 0) == 0);
+ match = fnmatch(dr->dr_pathptrn, pname, FNM_PATHNAME) == 0;
+ free(specname, M_TEMP);
+ return (match);
}
/*
@@ -591,12 +604,13 @@
* Run dk on de.
*/
static void
-devfs_rule_run(struct devfs_krule *dk, struct devfs_dirent *de, unsigned depth)
+devfs_rule_run(struct devfs_krule *dk, struct devfs_mount *dm,
+ struct devfs_dirent *de, unsigned depth)
{
struct devfs_rule *dr = &dk->dk_rule;
struct devfs_ruleset *ds;
- if (!devfs_rule_match(dk, de))
+ if (!devfs_rule_match(dk, dm, de))
return;
if (dr->dr_iacts & DRA_BACTS) {
if (dr->dr_bacts & DRB_HIDE)
@@ -623,7 +637,7 @@
if (depth > 0) {
ds = devfs_ruleset_bynum(dk->dk_rule.dr_incset);
KASSERT(ds != NULL, ("DRA_INCSET but bad dr_incset"));
- devfs_ruleset_applyde(ds, de, depth - 1);
+ devfs_ruleset_applyde(ds, dm, de, depth - 1);
}
}
}
@@ -632,12 +646,13 @@
* Apply all the rules in ds to de.
*/
static void
-devfs_ruleset_applyde(struct devfs_ruleset *ds, struct devfs_dirent *de, unsigned depth)
+devfs_ruleset_applyde(struct devfs_ruleset *ds, struct devfs_mount *dm,
+ struct devfs_dirent *de, unsigned depth)
{
struct devfs_krule *dk;
TAILQ_FOREACH(dk, &ds->ds_rules, dk_list)
- devfs_rule_run(dk, de, depth);
+ devfs_rule_run(dk, dm, de, depth);
}
/*
Modified: trunk/sys/fs/devfs/devfs_vfsops.c
===================================================================
--- trunk/sys/fs/devfs/devfs_vfsops.c 2018-05-27 22:18:36 UTC (rev 10027)
+++ trunk/sys/fs/devfs/devfs_vfsops.c 2018-05-27 22:19:26 UTC (rev 10028)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*-
* Copyright (c) 1992, 1993, 1995
* The Regents of the University of California. All rights reserved.
@@ -31,7 +32,7 @@
* @(#)kernfs_vfsops.c 8.10 (Berkeley) 5/14/95
* From: FreeBSD: src/sys/miscfs/kernfs/kernfs_vfsops.c 1.36
*
- * $MidnightBSD$
+ * $FreeBSD: stable/10/sys/fs/devfs/devfs_vfsops.c 297523 2016-04-03 14:38:02Z mav $
*/
#include <sys/param.h>
@@ -131,8 +132,7 @@
MNT_ILOCK(mp);
mp->mnt_flag |= MNT_LOCAL;
- mp->mnt_kern_flag |= MNTK_MPSAFE | MNTK_LOOKUP_SHARED |
- MNTK_EXTENDED_SHARED;
+ mp->mnt_kern_flag |= MNTK_LOOKUP_SHARED | MNTK_EXTENDED_SHARED;
#ifdef MAC
mp->mnt_flag |= MNT_MULTILABEL;
#endif
@@ -183,6 +183,8 @@
fmp = VFSTODEVFS(mp);
KASSERT(fmp->dm_mount != NULL,
("devfs_unmount unmounted devfs_mount"));
+ if (mntflags & MNT_FORCE)
+ flags |= FORCECLOSE;
/* There is 1 extra root vnode reference from devfs_mount(). */
error = vflush(mp, 1, flags, curthread);
if (error)
Modified: trunk/sys/fs/devfs/devfs_vnops.c
===================================================================
--- trunk/sys/fs/devfs/devfs_vnops.c 2018-05-27 22:18:36 UTC (rev 10027)
+++ trunk/sys/fs/devfs/devfs_vnops.c 2018-05-27 22:19:26 UTC (rev 10028)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*-
* Copyright (c) 2000-2004
* Poul-Henning Kamp. All rights reserved.
@@ -31,7 +32,7 @@
* @(#)kernfs_vnops.c 8.15 (Berkeley) 5/21/95
* From: FreeBSD: src/sys/miscfs/kernfs/kernfs_vnops.c 1.43
*
- * $MidnightBSD$
+ * $FreeBSD: stable/10/sys/fs/devfs/devfs_vnops.c 327060 2017-12-21 13:32:49Z kib $
*/
/*
@@ -57,6 +58,7 @@
#include <sys/proc.h>
#include <sys/stat.h>
#include <sys/sx.h>
+#include <sys/sysctl.h>
#include <sys/time.h>
#include <sys/ttycom.h>
#include <sys/unistd.h>
@@ -80,6 +82,32 @@
struct mtx cdevpriv_mtx;
MTX_SYSINIT(cdevpriv_mtx, &cdevpriv_mtx, "cdevpriv lock", MTX_DEF);
+SYSCTL_DECL(_vfs_devfs);
+
+static int devfs_dotimes;
+SYSCTL_INT(_vfs_devfs, OID_AUTO, dotimes, CTLFLAG_RW,
+ &devfs_dotimes, 0, "Update timestamps on DEVFS with default precision");
+
+/*
+ * Update devfs node timestamp. Note that updates are unlocked and
+ * stat(2) could see partially updated times.
+ */
+static void
+devfs_timestamp(struct timespec *tsp)
+{
+ time_t ts;
+
+ if (devfs_dotimes) {
+ vfs_timestamp(tsp);
+ } else {
+ ts = time_second;
+ if (tsp->tv_sec != ts) {
+ tsp->tv_sec = ts;
+ tsp->tv_nsec = 0;
+ }
+ }
+}
+
static int
devfs_fp_check(struct file *fp, struct cdev **devp, struct cdevsw **dswp,
int *ref)
@@ -119,7 +147,7 @@
}
int
-devfs_set_cdevpriv(void *priv, cdevpriv_dtr_t priv_dtr)
+devfs_set_cdevpriv(void *priv, d_priv_dtor_t *priv_dtr)
{
struct file *fp;
struct cdev_priv *cdp;
@@ -212,11 +240,11 @@
if (DEVFS_DMP_DROP(dmp)) {
sx_xunlock(&dmp->dm_lock);
devfs_unmount_final(dmp);
- return (EBADF);
+ return (ERESTART);
}
if ((vp->v_iflag & VI_DOOMED) != 0) {
sx_xunlock(&dmp->dm_lock);
- return (EBADF);
+ return (ERESTART);
}
de = vp->v_data;
KASSERT(de != NULL,
@@ -223,7 +251,7 @@
("devfs_populate_vp: vp->v_data == NULL but vnode not doomed"));
if ((de->de_flags & DE_DOOMED) != 0) {
sx_xunlock(&dmp->dm_lock);
- return (EBADF);
+ return (ERESTART);
}
return (0);
@@ -734,8 +762,10 @@
fpop = td->td_fpop;
error = devfs_fp_check(fp, &dev, &dsw, &ref);
- if (error)
+ if (error != 0) {
+ error = vnops.fo_ioctl(fp, com, data, cred, td);
return (error);
+ }
if (com == FIODTYPE) {
*(int *)data = dsw->d_flags & D_TYPEMASK;
@@ -840,6 +870,7 @@
struct devfs_dirent *de, *dd;
struct devfs_dirent **dde;
struct devfs_mount *dmp;
+ struct mount *mp;
struct cdev *cdev;
int error, flags, nameiop, dvplocked;
char specname[SPECNAMELEN + 1], *pname;
@@ -851,7 +882,8 @@
td = cnp->cn_thread;
flags = cnp->cn_flags;
nameiop = cnp->cn_nameiop;
- dmp = VFSTODEVFS(dvp->v_mount);
+ mp = dvp->v_mount;
+ dmp = VFSTODEVFS(mp);
dd = dvp->v_data;
*vpp = NULLVP;
@@ -884,8 +916,8 @@
return (ENOENT);
dvplocked = VOP_ISLOCKED(dvp);
VOP_UNLOCK(dvp, 0);
- error = devfs_allocv(de, dvp->v_mount,
- cnp->cn_lkflags & LK_TYPE_MASK, vpp);
+ error = devfs_allocv(de, mp, cnp->cn_lkflags & LK_TYPE_MASK,
+ vpp);
*dm_unlock = 0;
vn_lock(dvp, dvplocked | LK_RETRY);
return (error);
@@ -970,8 +1002,7 @@
return (0);
}
}
- error = devfs_allocv(de, dvp->v_mount, cnp->cn_lkflags & LK_TYPE_MASK,
- vpp);
+ error = devfs_allocv(de, mp, cnp->cn_lkflags & LK_TYPE_MASK, vpp);
*dm_unlock = 0;
return (error);
}
@@ -1021,6 +1052,9 @@
TAILQ_FOREACH(de, &dd->de_dlist, de_list) {
if (cnp->cn_namelen != de->de_dirent->d_namlen)
continue;
+ if (de->de_dirent->d_type == DT_CHR &&
+ (de->de_cdp->cdp_flags & CDP_ACTIVE) == 0)
+ continue;
if (bcmp(cnp->cn_nameptr, de->de_dirent->d_name,
de->de_dirent->d_namlen) != 0)
continue;
@@ -1082,7 +1116,7 @@
error = dsw->d_fdopen(dev, ap->a_mode, td, fp);
else
error = dsw->d_open(dev, ap->a_mode, S_IFCHR, td);
- /* cleanup any cdevpriv upon error */
+ /* Clean up any cdevpriv upon error. */
if (error != 0)
devfs_clear_cdevpriv();
td->td_fpop = fpop;
@@ -1149,8 +1183,10 @@
fpop = td->td_fpop;
error = devfs_fp_check(fp, &dev, &dsw, &ref);
- if (error)
- return (poll_no_poll(events));
+ if (error != 0) {
+ error = vnops.fo_poll(fp, events, cred, td);
+ return (error);
+ }
error = dsw->d_poll(dev, events, td);
td->td_fpop = fpop;
dev_relthread(dev, ref);
@@ -1168,9 +1204,9 @@
return (0);
}
-/* ARGSUSED */
static int
-devfs_read_f(struct file *fp, struct uio *uio, struct ucred *cred, int flags, struct thread *td)
+devfs_read_f(struct file *fp, struct uio *uio, struct ucred *cred,
+ int flags, struct thread *td)
{
struct cdev *dev;
int ioflag, error, ref;
@@ -1178,10 +1214,14 @@
struct cdevsw *dsw;
struct file *fpop;
+ if (uio->uio_resid > DEVFS_IOSIZE_MAX)
+ return (EINVAL);
fpop = td->td_fpop;
error = devfs_fp_check(fp, &dev, &dsw, &ref);
- if (error)
+ if (error != 0) {
+ error = vnops.fo_read(fp, uio, cred, flags, td);
return (error);
+ }
resid = uio->uio_resid;
ioflag = fp->f_flag & (O_NONBLOCK | O_DIRECT);
if (ioflag & O_DIRECT)
@@ -1190,7 +1230,7 @@
foffset_lock_uio(fp, uio, flags | FOF_NOLOCK);
error = dsw->d_read(dev, uio, ioflag);
if (uio->uio_resid != resid || (error == 0 && resid != 0))
- vfs_timestamp(&dev->si_atime);
+ devfs_timestamp(&dev->si_atime);
td->td_fpop = fpop;
dev_relthread(dev, ref);
@@ -1287,10 +1327,10 @@
static int
devfs_reclaim(struct vop_reclaim_args *ap)
{
- struct vnode *vp = ap->a_vp;
+ struct vnode *vp;
struct devfs_dirent *de;
- struct cdev *dev;
+ vp = ap->a_vp;
mtx_lock(&devfs_de_interlock);
de = vp->v_data;
if (de != NULL) {
@@ -1298,24 +1338,31 @@
vp->v_data = NULL;
}
mtx_unlock(&devfs_de_interlock);
-
vnode_destroy_vobject(vp);
+ return (0);
+}
+static int
+devfs_reclaim_vchr(struct vop_reclaim_args *ap)
+{
+ struct vnode *vp;
+ struct cdev *dev;
+
+ vp = ap->a_vp;
+ MPASS(vp->v_type == VCHR);
+
+ devfs_reclaim(ap);
+
VI_LOCK(vp);
dev_lock();
dev = vp->v_rdev;
vp->v_rdev = NULL;
-
- if (dev == NULL) {
- dev_unlock();
- VI_UNLOCK(vp);
- return (0);
- }
-
- dev->si_usecount -= vp->v_usecount;
+ if (dev != NULL)
+ dev->si_usecount -= vp->v_usecount;
dev_unlock();
VI_UNLOCK(vp);
- dev_rel(dev);
+ if (dev != NULL)
+ dev_rel(dev);
return (0);
}
@@ -1371,7 +1418,7 @@
struct cdev *dev;
struct cdev_priv *cdp;
struct devfs_dirent *de;
- int i;
+ u_int i;
KASSERT((ap->a_flags & REVOKEALL) != 0, ("devfs_revoke !REVOKEALL"));
@@ -1495,11 +1542,15 @@
return (EINVAL);
}
+ error = devfs_populate_vp(vp);
+ if (error != 0)
+ return (error);
+
de = vp->v_data;
if (vp->v_type == VDIR)
de = de->de_dir;
- error = c = 0;
+ c = 0;
if (vap->va_uid == (uid_t)VNOVAL)
uid = de->de_uid;
else
@@ -1512,8 +1563,8 @@
if ((ap->a_cred->cr_uid != de->de_uid) || uid != de->de_uid ||
(gid != de->de_gid && !groupmember(gid, ap->a_cred))) {
error = priv_check(td, PRIV_VFS_CHOWN);
- if (error)
- return (error);
+ if (error != 0)
+ goto ret;
}
de->de_uid = uid;
de->de_gid = gid;
@@ -1523,8 +1574,8 @@
if (vap->va_mode != (mode_t)VNOVAL) {
if (ap->a_cred->cr_uid != de->de_uid) {
error = priv_check(td, PRIV_VFS_ADMIN);
- if (error)
- return (error);
+ if (error != 0)
+ goto ret;
}
de->de_mode = vap->va_mode;
c = 1;
@@ -1531,11 +1582,9 @@
}
if (vap->va_atime.tv_sec != VNOVAL || vap->va_mtime.tv_sec != VNOVAL) {
- /* See the comment in ufs_vnops::ufs_setattr(). */
- if ((error = VOP_ACCESS(vp, VADMIN, ap->a_cred, td)) &&
- ((vap->va_vaflags & VA_UTIMES_NULL) == 0 ||
- (error = VOP_ACCESS(vp, VWRITE, ap->a_cred, td))))
- return (error);
+ error = vn_utimes_perm(vp, vap, ap->a_cred, td);
+ if (error != 0)
+ goto ret;
if (vap->va_atime.tv_sec != VNOVAL) {
if (vp->v_type == VCHR)
vp->v_rdev->si_atime = vap->va_atime;
@@ -1557,7 +1606,10 @@
else
vfs_timestamp(&de->de_mtime);
}
- return (0);
+
+ret:
+ sx_xunlock(&VFSTODEVFS(vp->v_mount)->dm_lock);
+ return (error);
}
#ifdef MAC
@@ -1643,9 +1695,9 @@
return (vnops.fo_truncate(fp, length, cred, td));
}
-/* ARGSUSED */
static int
-devfs_write_f(struct file *fp, struct uio *uio, struct ucred *cred, int flags, struct thread *td)
+devfs_write_f(struct file *fp, struct uio *uio, struct ucred *cred,
+ int flags, struct thread *td)
{
struct cdev *dev;
int error, ioflag, ref;
@@ -1653,10 +1705,14 @@
struct cdevsw *dsw;
struct file *fpop;
+ if (uio->uio_resid > DEVFS_IOSIZE_MAX)
+ return (EINVAL);
fpop = td->td_fpop;
error = devfs_fp_check(fp, &dev, &dsw, &ref);
- if (error)
+ if (error != 0) {
+ error = vnops.fo_write(fp, uio, cred, flags, td);
return (error);
+ }
KASSERT(uio->uio_td == td, ("uio_td %p is not td %p", uio->uio_td, td));
ioflag = fp->f_flag & (O_NONBLOCK | O_DIRECT | O_FSYNC);
if (ioflag & O_DIRECT)
@@ -1667,7 +1723,7 @@
error = dsw->d_write(dev, uio, ioflag);
if (uio->uio_resid != resid || (error == 0 && resid != 0)) {
- vfs_timestamp(&dev->si_ctime);
+ devfs_timestamp(&dev->si_ctime);
dev->si_mtime = dev->si_ctime;
}
td->td_fpop = fpop;
@@ -1696,6 +1752,8 @@
.fo_close = devfs_close_f,
.fo_chmod = vn_chmod,
.fo_chown = vn_chown,
+ .fo_sendfile = vn_sendfile,
+ .fo_seek = vn_seek,
.fo_flags = DFLAG_PASSABLE | DFLAG_SEEKABLE
};
@@ -1736,12 +1794,13 @@
.vop_mknod = VOP_PANIC,
.vop_open = devfs_open,
.vop_pathconf = devfs_pathconf,
+ .vop_poll = dead_poll,
.vop_print = devfs_print,
- .vop_read = VOP_PANIC,
+ .vop_read = dead_read,
.vop_readdir = VOP_PANIC,
.vop_readlink = VOP_PANIC,
.vop_reallocblks = VOP_PANIC,
- .vop_reclaim = devfs_reclaim,
+ .vop_reclaim = devfs_reclaim_vchr,
.vop_remove = devfs_remove,
.vop_rename = VOP_PANIC,
.vop_revoke = devfs_revoke,
@@ -1753,7 +1812,7 @@
.vop_strategy = VOP_PANIC,
.vop_symlink = VOP_PANIC,
.vop_vptocnp = devfs_vptocnp,
- .vop_write = VOP_PANIC,
+ .vop_write = dead_write,
};
/*
Modified: trunk/sys/fs/ext2fs/ext2_alloc.c
===================================================================
--- trunk/sys/fs/ext2fs/ext2_alloc.c 2018-05-27 22:18:36 UTC (rev 10027)
+++ trunk/sys/fs/ext2fs/ext2_alloc.c 2018-05-27 22:19:26 UTC (rev 10028)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*-
* modified for Lites 1.1
*
@@ -33,7 +34,7 @@
* SUCH DAMAGE.
*
* @(#)ffs_alloc.c 8.8 (Berkeley) 2/21/94
- * $MidnightBSD$
+ * $FreeBSD: stable/10/sys/fs/ext2fs/ext2_alloc.c 325750 2017-11-13 02:31:25Z pfg $
*/
#include <sys/param.h>
@@ -46,10 +47,10 @@
#include <sys/syslog.h>
#include <sys/buf.h>
+#include <fs/ext2fs/fs.h>
#include <fs/ext2fs/inode.h>
#include <fs/ext2fs/ext2_mount.h>
#include <fs/ext2fs/ext2fs.h>
-#include <fs/ext2fs/fs.h>
#include <fs/ext2fs/ext2_extern.h>
static daddr_t ext2_alloccg(struct inode *, int, daddr_t, int);
@@ -63,7 +64,7 @@
static daddr_t ext2_mapsearch(struct m_ext2fs *, char *, daddr_t);
/*
- * Allocate a block in the file system.
+ * Allocate a block in the filesystem.
*
* A preference may be optionally specified. If a preference is given
* the following hierarchy is used to allocate a block:
@@ -80,18 +81,19 @@
* available block is located.
*/
int
-ext2_alloc(struct inode *ip, int32_t lbn, int32_t bpref, int size,
- struct ucred *cred, int32_t *bnp)
+ext2_alloc(struct inode *ip, daddr_t lbn, e4fs_daddr_t bpref, int size,
+ struct ucred *cred, e4fs_daddr_t *bnp)
{
struct m_ext2fs *fs;
struct ext2mount *ump;
int32_t bno;
- int cg;
+ int cg;
+
*bnp = 0;
fs = ip->i_e2fs;
ump = ip->i_ump;
mtx_assert(EXT2_MTX(ump), MA_OWNED);
-#ifdef DIAGNOSTIC
+#ifdef INVARIANTS
if ((u_int)size > fs->e2fs_bsize || blkoff(fs, size) != 0) {
vn_printf(ip->i_devvp, "bsize = %lu, size = %d, fs = %s\n",
(long unsigned int)fs->e2fs_bsize, size, fs->e2fs_fsmnt);
@@ -99,11 +101,11 @@
}
if (cred == NOCRED)
panic("ext2_alloc: missing credential");
-#endif /* DIAGNOSTIC */
+#endif /* INVARIANTS */
if (size == fs->e2fs_bsize && fs->e2fs->e2fs_fbcount == 0)
goto nospace;
- if (cred->cr_uid != 0 &&
- fs->e2fs->e2fs_fbcount < fs->e2fs->e2fs_rbcount)
+ if (cred->cr_uid != 0 &&
+ fs->e2fs->e2fs_fbcount < fs->e2fs->e2fs_rbcount)
goto nospace;
if (bpref >= fs->e2fs->e2fs_bcount)
bpref = 0;
@@ -112,7 +114,7 @@
else
cg = dtog(fs, bpref);
bno = (daddr_t)ext2_hashalloc(ip, cg, bpref, fs->e2fs_bsize,
- ext2_alloccg);
+ ext2_alloccg);
if (bno > 0) {
/* set next_alloc fields as done in block_getblk */
ip->i_next_alloc_block = lbn;
@@ -122,11 +124,11 @@
ip->i_flag |= IN_CHANGE | IN_UPDATE;
*bnp = bno;
return (0);
- }
+ }
nospace:
EXT2_UNLOCK(ump);
- ext2_fserr(fs, cred->cr_uid, "file system full");
- uprintf("\n%s: write failed, file system is full\n", fs->e2fs_fsmnt);
+ ext2_fserr(fs, cred->cr_uid, "filesystem full");
+ uprintf("\n%s: write failed, filesystem is full\n", fs->e2fs_fsmnt);
return (ENOSPC);
}
@@ -147,11 +149,13 @@
static SYSCTL_NODE(_vfs, OID_AUTO, ext2fs, CTLFLAG_RW, 0, "EXT2FS filesystem");
-static int doasyncfree = 0;
+static int doasyncfree = 1;
+
SYSCTL_INT(_vfs_ext2fs, OID_AUTO, doasyncfree, CTLFLAG_RW, &doasyncfree, 0,
"Use asychronous writes to update block pointers when freeing blocks");
static int doreallocblks = 0;
+
SYSCTL_INT(_vfs_ext2fs, OID_AUTO, doreallocblks, CTLFLAG_RW, &doreallocblks, 0, "");
int
@@ -161,15 +165,17 @@
struct inode *ip;
struct vnode *vp;
struct buf *sbp, *ebp;
- uint32_t *bap, *sbap, *ebap = 0;
+ uint32_t *bap, *sbap, *ebap;
struct ext2mount *ump;
struct cluster_save *buflist;
struct indir start_ap[NIADDR + 1], end_ap[NIADDR + 1], *idp;
- int32_t start_lbn, end_lbn, soff, newblk, blkno;
+ e2fs_lbn_t start_lbn, end_lbn;
+ int soff;
+ e2fs_daddr_t newblk, blkno;
int i, len, start_lvl, end_lvl, pref, ssize;
if (doreallocblks == 0)
- return (ENOSPC);
+ return (ENOSPC);
vp = ap->a_vp;
ip = VTOI(vp);
@@ -183,7 +189,7 @@
len = buflist->bs_nchildren;
start_lbn = buflist->bs_children[0]->b_lblkno;
end_lbn = start_lbn + len - 1;
-#ifdef DIAGNOSTIC
+#ifdef INVARIANTS
for (i = 1; i < len; i++)
if (buflist->bs_children[i]->b_lblkno != start_lbn + i)
panic("ext2_reallocblks: non-cluster");
@@ -223,23 +229,24 @@
brelse(sbp);
return (ENOSPC);
}
- sbap = (int32_t *)sbp->b_data;
+ sbap = (u_int *)sbp->b_data;
soff = idp->in_off;
}
/*
* If the block range spans two block maps, get the second map.
*/
+ ebap = NULL;
if (end_lvl == 0 || (idp = &end_ap[end_lvl - 1])->in_off + 1 >= len) {
ssize = len;
} else {
-#ifdef DIAGNOSTIC
- if (start_ap[start_lvl-1].in_lbn == idp->in_lbn)
+#ifdef INVARIANTS
+ if (start_ap[start_lvl - 1].in_lbn == idp->in_lbn)
panic("ext2_reallocblks: start == end");
#endif
ssize = len - (idp->in_off + 1);
if (bread(vp, idp->in_lbn, (int)fs->e2fs_bsize, NOCRED, &ebp))
goto fail;
- ebap = (int32_t *)ebp->b_data;
+ ebap = (u_int *)ebp->b_data;
}
/*
* Find the preferred location for the cluster.
@@ -249,11 +256,11 @@
/*
* Search the block map looking for an allocation of the desired size.
*/
- if ((newblk = (int32_t)ext2_hashalloc(ip, dtog(fs, pref), pref,
- len, ext2_clusteralloc)) == 0){
+ if ((newblk = (e2fs_daddr_t)ext2_hashalloc(ip, dtog(fs, pref), pref,
+ len, ext2_clusteralloc)) == 0) {
EXT2_UNLOCK(ump);
goto fail;
- }
+ }
/*
* We have found a new contiguous block.
*
@@ -264,7 +271,7 @@
#ifdef DEBUG
printf("realloc: ino %d, lbns %jd-%jd\n\told:", ip->i_number,
(intmax_t)start_lbn, (intmax_t)end_lbn);
-#endif /* DEBUG */
+#endif /* DEBUG */
blkno = newblk;
for (bap = &sbap[soff], i = 0; i < len; i++, blkno += fs->e2fs_fpb) {
if (i == ssize) {
@@ -271,13 +278,13 @@
bap = ebap;
soff = -i;
}
-#ifdef DIAGNOSTIC
+#ifdef INVARIANTS
if (buflist->bs_children[i]->b_blkno != fsbtodb(fs, *bap))
panic("ext2_reallocblks: alloc mismatch");
#endif
#ifdef DEBUG
- printf(" %d,", *bap);
-#endif /* DEBUG */
+ printf(" %d,", *bap);
+#endif /* DEBUG */
*bap++ = blkno;
}
/*
@@ -284,7 +291,7 @@
* Next we must write out the modified inode and indirect blocks.
* For strict correctness, the writes should be synchronous since
* the old block values may have been written to disk. In practise
- * they are almost never written, but if we are concerned about
+ * they are almost never written, but if we are concerned about
* strict correctness, the `doasyncfree' flag should be set to zero.
*
* The test on `doasyncfree' should be changed to test a flag
@@ -315,7 +322,7 @@
*/
#ifdef DEBUG
printf("\n\tnew:");
-#endif /* DEBUG */
+#endif /* DEBUG */
for (blkno = newblk, i = 0; i < len; i++, blkno += fs->e2fs_fpb) {
ext2_blkfree(ip, dbtofsb(fs, buflist->bs_children[i]->b_blkno),
fs->e2fs_bsize);
@@ -322,11 +329,11 @@
buflist->bs_children[i]->b_blkno = fsbtodb(fs, blkno);
#ifdef DEBUG
printf(" %d,", blkno);
-#endif /* DEBUG */
+#endif /* DEBUG */
}
#ifdef DEBUG
printf("\n");
-#endif /* DEBUG */
+#endif /* DEBUG */
return (0);
fail:
@@ -338,8 +345,8 @@
}
/*
- * Allocate an inode in the file system.
- *
+ * Allocate an inode in the filesystem.
+ *
*/
int
ext2_valloc(struct vnode *pvp, int mode, struct ucred *cred, struct vnode **vpp)
@@ -351,7 +358,7 @@
struct ext2mount *ump;
ino_t ino, ipref;
int i, error, cg;
-
+
*vpp = NULL;
pip = VTOI(pvp);
fs = pip->i_e2fs;
@@ -377,7 +384,7 @@
ipref = cg * fs->e2fs->e2fs_ipg + 1;
ino = (ino_t)ext2_hashalloc(pip, cg, (long)ipref, mode, ext2_nodealloccg);
- if (ino == 0)
+ if (ino == 0)
goto noinodes;
error = VFS_VGET(pvp->v_mount, ino, LK_EXCLUSIVE, vpp);
if (error) {
@@ -391,22 +398,21 @@
* Linux doesn't read the old inode in when it is allocating a
* new one. I will set at least i_size and i_blocks to zero.
*/
+ ip->i_flag = 0;
ip->i_size = 0;
ip->i_blocks = 0;
ip->i_mode = 0;
ip->i_flags = 0;
- /* now we want to make sure that the block pointers are zeroed out */
- for (i = 0; i < NDADDR; i++)
- ip->i_db[i] = 0;
- for (i = 0; i < NIADDR; i++)
- ip->i_ib[i] = 0;
+ /* now we want to make sure that the block pointers are zeroed out */
+ for (i = 0; i < NDADDR; i++)
+ ip->i_db[i] = 0;
+ for (i = 0; i < NIADDR; i++)
+ ip->i_ib[i] = 0;
/*
* Set up a new generation number for this inode.
- * XXX check if this makes sense in ext2
*/
- if (ip->i_gen == 0 || ++ip->i_gen == 0)
- ip->i_gen = random() / 2 + 1;
+ ip->i_gen = arc4random();
vfs_timestamp(&ts);
ip->i_birthtime = ts.tv_sec;
@@ -441,18 +447,18 @@
ext2_dirpref(struct inode *pip)
{
struct m_ext2fs *fs;
- int cg, prefcg, dirsize, cgsize;
- int avgifree, avgbfree, avgndir, curdirsize;
- int minifree, minbfree, maxndir;
- int mincg, minndir;
- int maxcontigdirs;
+ int cg, prefcg, cgsize;
+ u_int avgifree, avgbfree, avgndir, curdirsize;
+ u_int minifree, minbfree, maxndir;
+ u_int mincg, minndir;
+ u_int dirsize, maxcontigdirs;
mtx_assert(EXT2_MTX(pip->i_ump), MA_OWNED);
fs = pip->i_e2fs;
- avgifree = fs->e2fs->e2fs_ficount / fs->e2fs_gcount;
+ avgifree = fs->e2fs->e2fs_ficount / fs->e2fs_gcount;
avgbfree = fs->e2fs->e2fs_fbcount / fs->e2fs_gcount;
- avgndir = fs->e2fs_total_dir / fs->e2fs_gcount;
+ avgndir = fs->e2fs_total_dir / fs->e2fs_gcount;
/*
* Force allocation in another cg if creating a first level dir.
@@ -471,15 +477,13 @@
}
for (cg = 0; cg < prefcg; cg++)
if (fs->e2fs_gd[cg].ext2bgd_ndirs < minndir &&
- fs->e2fs_gd[cg].ext2bgd_nifree >= avgifree &&
- fs->e2fs_gd[cg].ext2bgd_nbfree >= avgbfree) {
- mincg = cg;
- minndir = fs->e2fs_gd[cg].ext2bgd_ndirs;
- }
-
+ fs->e2fs_gd[cg].ext2bgd_nifree >= avgifree &&
+ fs->e2fs_gd[cg].ext2bgd_nbfree >= avgbfree) {
+ mincg = cg;
+ minndir = fs->e2fs_gd[cg].ext2bgd_ndirs;
+ }
return (mincg);
}
-
/*
* Count various limits which used for
* optimal allocation of a directory inode.
@@ -496,16 +500,13 @@
curdirsize = avgndir ? (cgsize - avgbfree * fs->e2fs_bsize) / avgndir : 0;
if (dirsize < curdirsize)
dirsize = curdirsize;
- if (dirsize <= 0)
- maxcontigdirs = 0; /* dirsize overflowed */
- else
- maxcontigdirs = min((avgbfree * fs->e2fs_bsize) / dirsize, 255);
+ maxcontigdirs = min((avgbfree * fs->e2fs_bsize) / dirsize, 255);
maxcontigdirs = min(maxcontigdirs, fs->e2fs_ipg / AFPDIR);
if (maxcontigdirs == 0)
maxcontigdirs = 1;
/*
- * Limit number of dirs in one cg and reserve space for
+ * Limit number of dirs in one cg and reserve space for
* regular files, but only if we have no deficit in
* inodes or space.
*/
@@ -513,7 +514,7 @@
for (cg = prefcg; cg < fs->e2fs_gcount; cg++)
if (fs->e2fs_gd[cg].ext2bgd_ndirs < maxndir &&
fs->e2fs_gd[cg].ext2bgd_nifree >= minifree &&
- fs->e2fs_gd[cg].ext2bgd_nbfree >= minbfree) {
+ fs->e2fs_gd[cg].ext2bgd_nbfree >= minbfree) {
if (fs->e2fs_contigdirs[cg] < maxcontigdirs)
return (cg);
}
@@ -520,7 +521,7 @@
for (cg = 0; cg < prefcg; cg++)
if (fs->e2fs_gd[cg].ext2bgd_ndirs < maxndir &&
fs->e2fs_gd[cg].ext2bgd_nifree >= minifree &&
- fs->e2fs_gd[cg].ext2bgd_nbfree >= minbfree) {
+ fs->e2fs_gd[cg].ext2bgd_nbfree >= minbfree) {
if (fs->e2fs_contigdirs[cg] < maxcontigdirs)
return (cg);
}
@@ -537,7 +538,7 @@
}
/*
- * Select the desired position for the next block in a file.
+ * Select the desired position for the next block in a file.
*
* we try to mimic what Remy does in inode_getblk/block_getblk
*
@@ -549,34 +550,38 @@
* of the above. Then, blocknr tells us the number of the block
* that will hold the pointer
*/
-int32_t
-ext2_blkpref(struct inode *ip, int32_t lbn, int indx, int32_t *bap,
- int32_t blocknr)
+e4fs_daddr_t
+ext2_blkpref(struct inode *ip, e2fs_lbn_t lbn, int indx, e2fs_daddr_t *bap,
+ e2fs_daddr_t blocknr)
{
- int tmp;
+ int tmp;
+
mtx_assert(EXT2_MTX(ip->i_ump), MA_OWNED);
- /* if the next block is actually what we thought it is,
- then set the goal to what we thought it should be
- */
+ /*
+ * If the next block is actually what we thought it is, then set the
+ * goal to what we thought it should be.
+ */
if (ip->i_next_alloc_block == lbn && ip->i_next_alloc_goal != 0)
return ip->i_next_alloc_goal;
- /* now check whether we were provided with an array that basically
- tells us previous blocks to which we want to stay closeby
- */
- if (bap)
- for (tmp = indx - 1; tmp >= 0; tmp--)
- if (bap[tmp])
+ /*
+ * Now check whether we were provided with an array that basically
+ * tells us previous blocks to which we want to stay close.
+ */
+ if (bap)
+ for (tmp = indx - 1; tmp >= 0; tmp--)
+ if (bap[tmp])
return bap[tmp];
- /* else let's fall back to the blocknr, or, if there is none,
- follow the rule that a block should be allocated near its inode
- */
+ /*
+ * Else lets fall back to the blocknr or, if there is none, follow
+ * the rule that a block should be allocated near its inode.
+ */
return blocknr ? blocknr :
- (int32_t)(ip->i_block_group *
- EXT2_BLOCKS_PER_GROUP(ip->i_e2fs)) +
- ip->i_e2fs->e2fs->e2fs_first_dblock;
+ (e2fs_daddr_t)(ip->i_block_group *
+ EXT2_BLOCKS_PER_GROUP(ip->i_e2fs)) +
+ ip->i_e2fs->e2fs->e2fs_first_dblock;
}
/*
@@ -589,7 +594,7 @@
*/
static u_long
ext2_hashalloc(struct inode *ip, int cg, long pref, int size,
- daddr_t (*allocator)(struct inode *, int, daddr_t, int))
+ daddr_t (*allocator) (struct inode *, int, daddr_t, int))
{
struct m_ext2fs *fs;
ino_t result;
@@ -653,8 +658,8 @@
return (0);
EXT2_UNLOCK(ump);
error = bread(ip->i_devvp, fsbtodb(fs,
- fs->e2fs_gd[cg].ext2bgd_b_bitmap),
- (int)fs->e2fs_bsize, NOCRED, &bp);
+ fs->e2fs_gd[cg].ext2bgd_b_bitmap),
+ (int)fs->e2fs_bsize, NOCRED, &bp);
if (error) {
brelse(bp);
EXT2_LOCK(ump);
@@ -740,18 +745,17 @@
start = 0;
goto retry;
}
-
bno = ext2_mapsearch(fs, bbp, bpref);
- if (bno < 0){
+ if (bno < 0) {
brelse(bp);
EXT2_LOCK(ump);
return (0);
}
gotit:
-#ifdef DIAGNOSTIC
+#ifdef INVARIANTS
if (isset(bbp, bno)) {
printf("ext2fs_alloccgblk: cg=%d bno=%jd fs=%s\n",
- cg, (intmax_t)bno, fs->e2fs_fsmnt);
+ cg, (intmax_t)bno, fs->e2fs_fsmnt);
panic("ext2fs_alloccg: dup alloc");
}
#endif
@@ -794,8 +798,6 @@
goto fail_lock;
bbp = (char *)bp->b_data;
- bp->b_xflags |= BX_BKGRDWRITE;
-
EXT2_LOCK(ump);
/*
* Check to see if a cluster of the needed size (or bigger) is
@@ -813,9 +815,9 @@
* to find no cluster.
*/
lp = &fs->e2fs_clustersum[cg].cs_sum[len - 1];
- for (i = len - 1; i > 0; i--)
- if (*lp-- > 0)
- break;
+ for (i = len - 1; i > 0; i--)
+ if (*lp-- > 0)
+ break;
fs->e2fs_maxcluster[cg] = i;
goto fail;
}
@@ -888,9 +890,10 @@
struct m_ext2fs *fs;
struct buf *bp;
struct ext2mount *ump;
- int error, start, len, loc, map, i;
- char *ibp;
- ipref--; /* to avoid a lot of (ipref -1) */
+ int error, start, len;
+ char *ibp, *loc;
+
+ ipref--; /* to avoid a lot of (ipref -1) */
if (ipref == -1)
ipref = 0;
fs = ip->i_e2fs;
@@ -897,10 +900,10 @@
ump = ip->i_ump;
if (fs->e2fs_gd[cg].ext2bgd_nifree == 0)
return (0);
- EXT2_UNLOCK(ump);
+ EXT2_UNLOCK(ump);
error = bread(ip->i_devvp, fsbtodb(fs,
- fs->e2fs_gd[cg].ext2bgd_i_bitmap),
- (int)fs->e2fs_bsize, NOCRED, &bp);
+ fs->e2fs_gd[cg].ext2bgd_i_bitmap),
+ (int)fs->e2fs_bsize, NOCRED, &bp);
if (error) {
brelse(bp);
EXT2_LOCK(ump);
@@ -923,25 +926,19 @@
}
start = ipref / NBBY;
len = howmany(fs->e2fs->e2fs_ipg - ipref, NBBY);
- loc = skpc(0xff, len, &ibp[start]);
- if (loc == 0) {
+ loc = memcchr(&ibp[start], 0xff, len);
+ if (loc == NULL) {
len = start + 1;
start = 0;
- loc = skpc(0xff, len, &ibp[0]);
- if (loc == 0) {
+ loc = memcchr(&ibp[start], 0xff, len);
+ if (loc == NULL) {
printf("cg = %d, ipref = %lld, fs = %s\n",
- cg, (long long)ipref, fs->e2fs_fsmnt);
+ cg, (long long)ipref, fs->e2fs_fsmnt);
panic("ext2fs_nodealloccg: map corrupted");
/* NOTREACHED */
}
- }
- i = start + len - loc;
- map = ibp[i] ^ 0xff;
- if (map == 0) {
- printf("fs = %s\n", fs->e2fs_fsmnt);
- panic("ext2fs_nodealloccg: block not in map");
}
- ipref = i * NBBY + ffs(map) - 1;
+ ipref = (loc - ibp) * NBBY + ffs(~*loc) - 1;
gotit:
setbit(ibp, ipref);
EXT2_LOCK(ump);
@@ -954,7 +951,7 @@
}
EXT2_UNLOCK(ump);
bdwrite(bp);
- return (cg * fs->e2fs->e2fs_ipg + ipref +1);
+ return (cg * fs->e2fs->e2fs_ipg + ipref + 1);
}
/*
@@ -962,7 +959,7 @@
*
*/
void
-ext2_blkfree(struct inode *ip, int32_t bno, long size)
+ext2_blkfree(struct inode *ip, e4fs_daddr_t bno, long size)
{
struct m_ext2fs *fs;
struct buf *bp;
@@ -974,33 +971,33 @@
ump = ip->i_ump;
cg = dtog(fs, bno);
if ((u_int)bno >= fs->e2fs->e2fs_bcount) {
- printf("bad block %lld, ino %llu\n", (long long)bno,
- (unsigned long long)ip->i_number);
- ext2_fserr(fs, ip->i_uid, "bad block");
- return;
- }
- error = bread(ip->i_devvp,
- fsbtodb(fs, fs->e2fs_gd[cg].ext2bgd_b_bitmap),
- (int)fs->e2fs_bsize, NOCRED, &bp);
- if (error) {
- brelse(bp);
- return;
- }
- bbp = (char *)bp->b_data;
- bno = dtogd(fs, bno);
- if (isclr(bbp, bno)) {
- printf("block = %lld, fs = %s\n",
- (long long)bno, fs->e2fs_fsmnt);
- panic("ext2_blkfree: freeing free block");
- }
- clrbit(bbp, bno);
+ printf("bad block %lld, ino %llu\n", (long long)bno,
+ (unsigned long long)ip->i_number);
+ ext2_fserr(fs, ip->i_uid, "bad block");
+ return;
+ }
+ error = bread(ip->i_devvp,
+ fsbtodb(fs, fs->e2fs_gd[cg].ext2bgd_b_bitmap),
+ (int)fs->e2fs_bsize, NOCRED, &bp);
+ if (error) {
+ brelse(bp);
+ return;
+ }
+ bbp = (char *)bp->b_data;
+ bno = dtogd(fs, bno);
+ if (isclr(bbp, bno)) {
+ printf("block = %lld, fs = %s\n",
+ (long long)bno, fs->e2fs_fsmnt);
+ panic("ext2_blkfree: freeing free block");
+ }
+ clrbit(bbp, bno);
EXT2_LOCK(ump);
ext2_clusteracct(fs, bbp, cg, bno, 1);
- fs->e2fs->e2fs_fbcount++;
- fs->e2fs_gd[cg].ext2bgd_nbfree++;
- fs->e2fs_fmod = 1;
+ fs->e2fs->e2fs_fbcount++;
+ fs->e2fs_gd[cg].ext2bgd_nbfree++;
+ fs->e2fs_fmod = 1;
EXT2_UNLOCK(ump);
- bdwrite(bp);
+ bdwrite(bp);
}
/*
@@ -1015,19 +1012,19 @@
struct buf *bp;
struct ext2mount *ump;
int error, cg;
- char * ibp;
+ char *ibp;
pip = VTOI(pvp);
fs = pip->i_e2fs;
ump = pip->i_ump;
if ((u_int)ino > fs->e2fs_ipg * fs->e2fs_gcount)
- panic("ext2_vfree: range: devvp = %p, ino = %d, fs = %s",
- pip->i_devvp, ino, fs->e2fs_fsmnt);
+ panic("ext2_vfree: range: devvp = %p, ino = %ju, fs = %s",
+ pip->i_devvp, (uintmax_t)ino, fs->e2fs_fsmnt);
cg = ino_to_cg(fs, ino);
error = bread(pip->i_devvp,
- fsbtodb(fs, fs->e2fs_gd[cg].ext2bgd_i_bitmap),
- (int)fs->e2fs_bsize, NOCRED, &bp);
+ fsbtodb(fs, fs->e2fs_gd[cg].ext2bgd_i_bitmap),
+ (int)fs->e2fs_bsize, NOCRED, &bp);
if (error) {
brelse(bp);
return (0);
@@ -1036,7 +1033,7 @@
ino = (ino - 1) % fs->e2fs->e2fs_ipg;
if (isclr(ibp, ino)) {
printf("ino = %llu, fs = %s\n",
- (unsigned long long)ino, fs->e2fs_fsmnt);
+ (unsigned long long)ino, fs->e2fs_fsmnt);
if (fs->e2fs_ronly == 0)
panic("ext2_vfree: freeing free inode");
}
@@ -1063,7 +1060,8 @@
static daddr_t
ext2_mapsearch(struct m_ext2fs *fs, char *bbp, daddr_t bpref)
{
- int start, len, loc, i, map;
+ char *loc;
+ int start, len;
/*
* find the fragment by searching through the free block
@@ -1074,30 +1072,24 @@
else
start = 0;
len = howmany(fs->e2fs->e2fs_fpg, NBBY) - start;
- loc = skpc(0xff, len, &bbp[start]);
- if (loc == 0) {
+ loc = memcchr(&bbp[start], 0xff, len);
+ if (loc == NULL) {
len = start + 1;
start = 0;
- loc = skpc(0xff, len, &bbp[start]);
- if (loc == 0) {
+ loc = memcchr(&bbp[start], 0xff, len);
+ if (loc == NULL) {
printf("start = %d, len = %d, fs = %s\n",
- start, len, fs->e2fs_fsmnt);
+ start, len, fs->e2fs_fsmnt);
panic("ext2_mapsearch: map corrupted");
/* NOTREACHED */
}
}
- i = start + len - loc;
- map = bbp[i] ^ 0xff;
- if (map == 0) {
- printf("fs = %s\n", fs->e2fs_fsmnt);
- panic("ext2fs_mapsearch: block not in map");
- }
- return (i * NBBY + ffs(map) - 1);
+ return ((loc - bbp) * NBBY + ffs(~*loc) - 1);
}
/*
- * Fserr prints the name of a file system with an error diagnostic.
- *
+ * Fserr prints the name of a filesystem with an error diagnostic.
+ *
* The form of the error message is:
* fs: error message
*/
@@ -1111,14 +1103,14 @@
int
cg_has_sb(int i)
{
- int a3, a5, a7;
+ int a3, a5, a7;
- if (i == 0 || i == 1)
- return 1;
- for (a3 = 3, a5 = 5, a7 = 7;
- a3 <= i || a5 <= i || a7 <= i;
- a3 *= 3, a5 *= 5, a7 *= 7)
- if (i == a3 || i == a5 || i == a7)
- return 1;
- return 0;
+ if (i == 0 || i == 1)
+ return 1;
+ for (a3 = 3, a5 = 5, a7 = 7;
+ a3 <= i || a5 <= i || a7 <= i;
+ a3 *= 3, a5 *= 5, a7 *= 7)
+ if (i == a3 || i == a5 || i == a7)
+ return 1;
+ return 0;
}
Modified: trunk/sys/fs/ext2fs/ext2_balloc.c
===================================================================
--- trunk/sys/fs/ext2fs/ext2_balloc.c 2018-05-27 22:18:36 UTC (rev 10027)
+++ trunk/sys/fs/ext2fs/ext2_balloc.c 2018-05-27 22:19:26 UTC (rev 10028)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*-
* modified for Lites 1.1
*
@@ -33,7 +34,7 @@
* SUCH DAMAGE.
*
* @(#)ffs_balloc.c 8.4 (Berkeley) 9/23/93
- * $MidnightBSD$
+ * $FreeBSD: stable/10/sys/fs/ext2fs/ext2_balloc.c 311232 2017-01-04 02:43:33Z pfg $
*/
#include <sys/param.h>
@@ -44,27 +45,29 @@
#include <sys/mount.h>
#include <sys/vnode.h>
+#include <fs/ext2fs/fs.h>
#include <fs/ext2fs/inode.h>
#include <fs/ext2fs/ext2fs.h>
-#include <fs/ext2fs/fs.h>
+#include <fs/ext2fs/ext2_dinode.h>
#include <fs/ext2fs/ext2_extern.h>
#include <fs/ext2fs/ext2_mount.h>
+
/*
- * Balloc defines the structure of file system storage
+ * Balloc defines the structure of filesystem storage
* by allocating the physical blocks on a device given
* the inode and the logical block number in a file.
*/
int
-ext2_balloc(struct inode *ip, int32_t lbn, int size, struct ucred *cred,
+ext2_balloc(struct inode *ip, e2fs_lbn_t lbn, int size, struct ucred *cred,
struct buf **bpp, int flags)
{
struct m_ext2fs *fs;
struct ext2mount *ump;
- int32_t nb;
struct buf *bp, *nbp;
struct vnode *vp = ITOV(ip);
struct indir indirs[NIADDR + 2];
- uint32_t newb, *bap, pref;
+ e4fs_daddr_t nb, newb;
+ e2fs_daddr_t *bap, pref;
int osize, nsize, num, i, error;
*bpp = NULL;
@@ -74,22 +77,23 @@
ump = ip->i_ump;
/*
- * check if this is a sequential block allocation.
- * If so, increment next_alloc fields to allow ext2_blkpref
+ * check if this is a sequential block allocation.
+ * If so, increment next_alloc fields to allow ext2_blkpref
* to make a good guess
*/
- if (lbn == ip->i_next_alloc_block + 1) {
+ if (lbn == ip->i_next_alloc_block + 1) {
ip->i_next_alloc_block++;
ip->i_next_alloc_goal++;
}
-
/*
* The first NDADDR blocks are direct blocks
*/
if (lbn < NDADDR) {
nb = ip->i_db[lbn];
- /* no new block is to be allocated, and no need to expand
- the file */
+ /*
+ * no new block is to be allocated, and no need to expand
+ * the file
+ */
if (nb != 0 && ip->i_size >= (lbn + 1) * fs->e2fs_bsize) {
error = bread(vp, lbn, fs->e2fs_bsize, NOCRED, &bp);
if (error) {
@@ -114,10 +118,13 @@
}
bp->b_blkno = fsbtodb(fs, nb);
} else {
- /* Godmar thinks: this shouldn't happen w/o fragments */
- printf("nsize %d(%d) > osize %d(%d) nb %d\n",
- (int)nsize, (int)size, (int)osize,
- (int)ip->i_size, (int)nb);
+ /*
+ * Godmar thinks: this shouldn't happen w/o
+ * fragments
+ */
+ printf("nsize %d(%d) > osize %d(%d) nb %d\n",
+ (int)nsize, (int)size, (int)osize,
+ (int)ip->i_size, (int)nb);
panic(
"ext2_balloc: Something is terribly wrong");
/*
@@ -152,9 +159,9 @@
pref = 0;
if ((error = ext2_getlbns(vp, lbn, indirs, &num)) != 0)
return (error);
-#ifdef DIAGNOSTIC
+#ifdef INVARIANTS
if (num < 1)
- panic ("ext2_balloc: ext2_getlbns returned indirect block");
+ panic("ext2_balloc: ext2_getlbns returned indirect block");
#endif
/*
* Fetch the first indirect block allocating if necessary.
@@ -163,10 +170,10 @@
nb = ip->i_ib[indirs[0].in_off];
if (nb == 0) {
EXT2_LOCK(ump);
- pref = ext2_blkpref(ip, lbn, indirs[0].in_off +
- EXT2_NDIR_BLOCKS, &ip->i_db[0], 0);
- if ((error = ext2_alloc(ip, lbn, pref,
- (int)fs->e2fs_bsize, cred, &newb)))
+ pref = ext2_blkpref(ip, lbn, indirs[0].in_off +
+ EXT2_NDIR_BLOCKS, &ip->i_db[0], 0);
+ if ((error = ext2_alloc(ip, lbn, pref, fs->e2fs_bsize, cred,
+ &newb)))
return (error);
nb = newb;
bp = getblk(vp, indirs[1].in_lbn, fs->e2fs_bsize, 0, 0, 0);
@@ -193,7 +200,7 @@
brelse(bp);
return (error);
}
- bap = (int32_t *)bp->b_data;
+ bap = (e2fs_daddr_t *)bp->b_data;
nb = bap[indirs[i].in_off];
if (i == num)
break;
@@ -205,8 +212,8 @@
EXT2_LOCK(ump);
if (pref == 0)
pref = ext2_blkpref(ip, lbn, indirs[i].in_off, bap,
- bp->b_lblkno);
- error = ext2_alloc(ip, lbn, pref, (int)fs->e2fs_bsize, cred, &newb);
+ bp->b_lblkno);
+ error = ext2_alloc(ip, lbn, pref, (int)fs->e2fs_bsize, cred, &newb);
if (error) {
brelse(bp);
return (error);
@@ -243,8 +250,8 @@
*/
if (nb == 0) {
EXT2_LOCK(ump);
- pref = ext2_blkpref(ip, lbn, indirs[i].in_off, &bap[0],
- bp->b_lblkno);
+ pref = ext2_blkpref(ip, lbn, indirs[i].in_off, &bap[0],
+ bp->b_lblkno);
if ((error = ext2_alloc(ip,
lbn, pref, (int)fs->e2fs_bsize, cred, &newb)) != 0) {
brelse(bp);
@@ -263,7 +270,7 @@
if (flags & IO_SYNC) {
bwrite(bp);
} else {
- if (bp->b_bufsize == fs->e2fs_bsize)
+ if (bp->b_bufsize == fs->e2fs_bsize)
bp->b_flags |= B_CLUSTEROK;
bdwrite(bp);
}
@@ -273,10 +280,11 @@
brelse(bp);
if (flags & BA_CLRBUF) {
int seqcount = (flags & BA_SEQMASK) >> BA_SEQSHIFT;
+
if (seqcount && (vp->v_mount->mnt_flag & MNT_NOCLUSTERR) == 0) {
error = cluster_read(vp, ip->i_size, lbn,
(int)fs->e2fs_bsize, NOCRED,
- MAXBSIZE, seqcount, &nbp);
+ MAXBSIZE, seqcount, 0, &nbp);
} else {
error = bread(vp, lbn, (int)fs->e2fs_bsize, NOCRED, &nbp);
}
@@ -291,4 +299,3 @@
*bpp = nbp;
return (0);
}
-
Modified: trunk/sys/fs/ext2fs/ext2_bmap.c
===================================================================
--- trunk/sys/fs/ext2fs/ext2_bmap.c 2018-05-27 22:18:36 UTC (rev 10027)
+++ trunk/sys/fs/ext2fs/ext2_bmap.c 2018-05-27 22:19:26 UTC (rev 10028)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*-
* Copyright (c) 1989, 1991, 1993
* The Regents of the University of California. All rights reserved.
@@ -32,7 +33,7 @@
* SUCH DAMAGE.
*
* @(#)ufs_bmap.c 8.7 (Berkeley) 3/21/95
- * $MidnightBSD$
+ * $FreeBSD: stable/10/sys/fs/ext2fs/ext2_bmap.c 311232 2017-01-04 02:43:33Z pfg $
*/
#include <sys/param.h>
@@ -46,10 +47,14 @@
#include <sys/stat.h>
#include <fs/ext2fs/inode.h>
+#include <fs/ext2fs/fs.h>
#include <fs/ext2fs/ext2fs.h>
+#include <fs/ext2fs/ext2_dinode.h>
#include <fs/ext2fs/ext2_extern.h>
#include <fs/ext2fs/ext2_mount.h>
+static int ext4_bmapext(struct vnode *, int32_t, int64_t *, int *, int *);
+
/*
* Bmap converts the logical block number of a file to its physical block
* number on the disk. The conversion is done by using the logical block
@@ -58,7 +63,7 @@
int
ext2_bmap(struct vop_bmap_args *ap)
{
- int32_t blkno;
+ daddr_t blkno;
int error;
/*
@@ -70,13 +75,64 @@
if (ap->a_bnp == NULL)
return (0);
- error = ext2_bmaparray(ap->a_vp, ap->a_bn, &blkno,
- ap->a_runp, ap->a_runb);
+ if (VTOI(ap->a_vp)->i_flag & IN_E4EXTENTS)
+ error = ext4_bmapext(ap->a_vp, ap->a_bn, &blkno,
+ ap->a_runp, ap->a_runb);
+ else
+ error = ext2_bmaparray(ap->a_vp, ap->a_bn, &blkno,
+ ap->a_runp, ap->a_runb);
*ap->a_bnp = blkno;
return (error);
}
/*
+ * This function converts the logical block number of a file to
+ * its physical block number on the disk within ext4 extents.
+ */
+static int
+ext4_bmapext(struct vnode *vp, int32_t bn, int64_t *bnp, int *runp, int *runb)
+{
+ struct inode *ip;
+ struct m_ext2fs *fs;
+ struct ext4_extent *ep;
+ struct ext4_extent_path path = {.ep_bp = NULL};
+ daddr_t lbn;
+ int ret = 0;
+
+ ip = VTOI(vp);
+ fs = ip->i_e2fs;
+ lbn = bn;
+
+ /*
+ * TODO: need to implement read ahead to improve the performance.
+ */
+ if (runp != NULL)
+ *runp = 0;
+
+ if (runb != NULL)
+ *runb = 0;
+
+ ext4_ext_find_extent(fs, ip, lbn, &path);
+ ep = path.ep_ext;
+ if (ep == NULL)
+ ret = EIO;
+ else {
+ *bnp = fsbtodb(fs, lbn - ep->e_blk +
+ (ep->e_start_lo | (daddr_t)ep->e_start_hi << 32));
+
+ if (*bnp == 0)
+ *bnp = -1;
+ }
+
+ if (path.ep_bp != NULL) {
+ brelse(path.ep_bp);
+ path.ep_bp = NULL;
+ }
+
+ return (ret);
+}
+
+/*
* Indirect blocks are now on the vnode for the file. They are given negative
* logical block numbers. Indirect blocks are addressed by the negative
* address of the first data block to which they point. Double indirect blocks
@@ -91,16 +147,15 @@
*/
int
-ext2_bmaparray(struct vnode *vp, int32_t bn, int32_t *bnp, int *runp, int *runb)
+ext2_bmaparray(struct vnode *vp, daddr_t bn, daddr_t *bnp, int *runp, int *runb)
{
struct inode *ip;
struct buf *bp;
struct ext2mount *ump;
struct mount *mp;
- struct vnode *devvp;
- struct indir a[NIADDR+1], *ap;
- int32_t daddr;
- long metalbn;
+ struct indir a[NIADDR + 1], *ap;
+ daddr_t daddr;
+ e2fs_lbn_t metalbn;
int error, num, maxrun = 0, bsize;
int *nump;
@@ -108,7 +163,6 @@
ip = VTOI(vp);
mp = vp->v_mount;
ump = VFSTOEXT2(mp);
- devvp = ump->um_devvp;
bsize = EXT2_BLOCK_SIZE(ump->um_e2fs);
@@ -116,10 +170,8 @@
maxrun = mp->mnt_iosize_max / bsize - 1;
*runp = 0;
}
-
- if (runb) {
+ if (runb)
*runb = 0;
- }
ap = a;
@@ -134,7 +186,8 @@
if (*bnp == 0) {
*bnp = -1;
} else if (runp) {
- int32_t bnb = bn;
+ daddr_t bnb = bn;
+
for (++bn; bn < NDADDR && *runp < maxrun &&
is_sequential(ump, ip->i_db[bn - 1], ip->i_db[bn]);
++bn, ++*runp);
@@ -142,7 +195,7 @@
if (runb && (bn > 0)) {
for (--bn; (bn >= 0) && (*runb < maxrun) &&
is_sequential(ump, ip->i_db[bn],
- ip->i_db[bn+1]);
+ ip->i_db[bn + 1]);
--bn, ++*runb);
}
}
@@ -149,7 +202,6 @@
return (0);
}
-
/* Get disk address out of indirect block array */
daddr = ip->i_ib[ap->in_off];
@@ -172,7 +224,7 @@
bp = getblk(vp, metalbn, bsize, 0, 0, 0);
if ((bp->b_flags & B_CACHE) == 0) {
-#ifdef DIAGNOSTIC
+#ifdef INVARIANTS
if (!daddr)
panic("ext2_bmaparray: indirect block not in cache");
#endif
@@ -191,20 +243,21 @@
}
}
- daddr = ((int32_t *)bp->b_data)[ap->in_off];
+ daddr = ((e2fs_daddr_t *)bp->b_data)[ap->in_off];
if (num == 1 && daddr && runp) {
for (bn = ap->in_off + 1;
bn < MNINDIR(ump) && *runp < maxrun &&
is_sequential(ump,
- ((int32_t *)bp->b_data)[bn - 1],
- ((int32_t *)bp->b_data)[bn]);
+ ((e2fs_daddr_t *)bp->b_data)[bn - 1],
+ ((e2fs_daddr_t *)bp->b_data)[bn]);
++bn, ++*runp);
bn = ap->in_off;
if (runb && bn) {
for (--bn; bn >= 0 && *runb < maxrun &&
- is_sequential(ump, ((int32_t *)bp->b_data)[bn],
- ((int32_t *)bp->b_data)[bn+1]);
- --bn, ++*runb);
+ is_sequential(ump,
+ ((e2fs_daddr_t *)bp->b_data)[bn],
+ ((e2fs_daddr_t *)bp->b_data)[bn + 1]);
+ --bn, ++*runb);
}
}
}
@@ -218,7 +271,7 @@
* return a request for a zeroed out buffer if attempts are made
* to read a BLK_NOCOPY or BLK_SNAP block.
*/
- if ((ip->i_flags & SF_SNAPSHOT) && daddr > 0 && daddr < ump->um_seqinc){
+ if ((ip->i_flags & SF_SNAPSHOT) && daddr > 0 && daddr < ump->um_seqinc) {
*bnp = -1;
return (0);
}
@@ -239,9 +292,10 @@
* once with the offset into the page itself.
*/
int
-ext2_getlbns(struct vnode *vp, int32_t bn, struct indir *ap, int *nump)
+ext2_getlbns(struct vnode *vp, daddr_t bn, struct indir *ap, int *nump)
{
- long blockcnt, metalbn, realbn;
+ long blockcnt;
+ e2fs_lbn_t metalbn, realbn;
struct ext2mount *ump;
int i, numlevels, off;
int64_t qblockcnt;
Modified: trunk/sys/fs/ext2fs/ext2_dinode.h
===================================================================
--- trunk/sys/fs/ext2fs/ext2_dinode.h 2018-05-27 22:18:36 UTC (rev 10027)
+++ trunk/sys/fs/ext2fs/ext2_dinode.h 2018-05-27 22:19:26 UTC (rev 10028)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*-
* Copyright (c) 2009 Aditya Sarawgi
* All rights reserved.
@@ -23,11 +24,11 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $MidnightBSD$
+ * $FreeBSD: stable/10/sys/fs/ext2fs/ext2_dinode.h 305494 2016-09-06 19:53:05Z pfg $
*/
#ifndef _FS_EXT2FS_EXT2_DINODE_H_
-#define _FS_EXT2FS_EXT2_DINODE_H_
+#define _FS_EXT2FS_EXT2_DINODE_H_
/*
* Special inode numbers
@@ -44,43 +45,62 @@
#define EXT2_UNDELDIRINO ((ino_t)6)
#define EXT2_RESIZEINO ((ino_t)7)
#define EXT2_JOURNALINO ((ino_t)8)
+#define EXT2_EXCLUDEINO ((ino_t)9)
+#define EXT2_REPLICAINO ((ino_t)10)
#define EXT2_FIRSTINO ((ino_t)11)
/*
* Inode flags
- * The current implementation uses only EXT2_IMMUTABLE and EXT2_APPEND flags
+ * The system supports EXT2_IMMUTABLE, EXT2_APPEND and EXT2_NODUMP flags.
+ * The current implementation also uses EXT3_INDEX, EXT4_EXTENTS and
+ * EXT4_HUGE_FILE with some restrictions, imposed the lack of write
+ * support.
*/
-#define EXT2_SECRM 0x00000001 /* Secure deletion */
-#define EXT2_UNRM 0x00000002 /* Undelete */
-#define EXT2_COMPR 0x00000004 /* Compress file */
-#define EXT2_SYNC 0x00000008 /* Synchronous updates */
-#define EXT2_IMMUTABLE 0x00000010 /* Immutable file */
-#define EXT2_APPEND 0x00000020 /* writes to file may only append */
-#define EXT2_NODUMP 0x00000040 /* do not dump file */
-#define EXT2_NOATIME 0x00000080 /* do not update atime */
+#define EXT2_SECRM 0x00000001 /* Secure deletion */
+#define EXT2_UNRM 0x00000002 /* Undelete */
+#define EXT2_COMPR 0x00000004 /* Compress file */
+#define EXT2_SYNC 0x00000008 /* Synchronous updates */
+#define EXT2_IMMUTABLE 0x00000010 /* Immutable file */
+#define EXT2_APPEND 0x00000020 /* Writes to file may only append */
+#define EXT2_NODUMP 0x00000040 /* Do not dump file */
+#define EXT2_NOATIME 0x00000080 /* Do not update atime */
+#define EXT3_INDEX 0x00001000 /* Hash-indexed directory */
+#define EXT4_IMAGIC 0x00002000 /* AFS directory */
+#define EXT4_JOURNAL_DATA 0x00004000 /* File data should be journaled */
+#define EXT4_NOTAIL 0x00008000 /* File tail should not be merged */
+#define EXT4_DIRSYNC 0x00010000 /* Dirsync behaviour */
+#define EXT4_TOPDIR 0x00020000 /* Top of directory hierarchies*/
+#define EXT4_HUGE_FILE 0x00040000 /* Set to each huge file */
+#define EXT4_EXTENTS 0x00080000 /* Inode uses extents */
+#define EXT4_EA_INODE 0x00200000 /* Inode used for large EA */
+#define EXT4_EOFBLOCKS 0x00400000 /* Blocks allocated beyond EOF */
+#define EXT4_INLINE_DATA 0x10000000 /* Inode has inline data */
+#define EXT4_PROJINHERIT 0x20000000 /* Children inherit project ID */
-#define EXT4_INDEX 0x00001000 /* hash-indexed directory */
-#define EXT4_IMAGIC 0x00002000 /* AFS directory */
-#define EXT4_JOURNAL_DATA 0x00004000 /* file data should be journaled */
-#define EXT4_NOTAIL 0x00008000 /* file tail should not be merged */
-#define EXT4_DIRSYNC 0x00010000 /* dirsync behaviour */
-#define EXT4_TOPDIR 0x00020000 /* Top of directory hierarchies*/
-#define EXT4_HUGE_FILE 0x00040000 /* Set to each huge file */
-#define EXT4_EXTENTS 0x00080000 /* Inode uses extents */
-#define EXT4_EOFBLOCKS 0x00400000 /* Blocks allocated beyond EOF */
-
/*
* Definitions for nanosecond timestamps.
* Ext3 inode versioning, 2006-12-13.
*/
-#define EXT3_EPOCH_BITS 2
-#define EXT3_EPOCH_MASK ((1 << EXT3_EPOCH_BITS) - 1)
-#define EXT3_NSEC_MASK (~0UL << EXT3_EPOCH_BITS)
+#define EXT3_EPOCH_BITS 2
+#define EXT3_EPOCH_MASK ((1 << EXT3_EPOCH_BITS) - 1)
+#define EXT3_NSEC_MASK (~0UL << EXT3_EPOCH_BITS)
-#define E2DI_HAS_XTIME(ip) (EXT2_HAS_RO_COMPAT_FEATURE(ip->i_e2fs, \
+#define E2DI_HAS_XTIME(ip) (EXT2_HAS_RO_COMPAT_FEATURE(ip->i_e2fs, \
EXT2F_ROCOMPAT_EXTRA_ISIZE))
+#define E2DI_HAS_HUGE_FILE(ip) (EXT2_HAS_RO_COMPAT_FEATURE(ip->i_e2fs, \
+ EXT2F_ROCOMPAT_HUGE_FILE))
/*
+ * Constants relative to the data blocks
+ */
+#define EXT2_NDIR_BLOCKS 12
+#define EXT2_IND_BLOCK EXT2_NDIR_BLOCKS
+#define EXT2_DIND_BLOCK (EXT2_IND_BLOCK + 1)
+#define EXT2_TIND_BLOCK (EXT2_DIND_BLOCK + 1)
+#define EXT2_N_BLOCKS (EXT2_TIND_BLOCK + 1)
+#define EXT2_MAXSYMLINKLEN (EXT2_N_BLOCKS * sizeof(uint32_t))
+
+/*
* Structure of an inode on the disk
*/
struct ext2fs_dinode {
@@ -105,16 +125,17 @@
uint16_t e2di_facl_high; /* 118: File EA bits 47:32 */
uint16_t e2di_uid_high; /* 120: Owner UID top 16 bits */
uint16_t e2di_gid_high; /* 122: Owner GID top 16 bits */
- uint16_t e2di_chksum_lo; /* 124: Lower inode checksum */
+ uint16_t e2di_chksum_lo; /* 124: Lower inode checksum */
uint16_t e2di_lx_reserved; /* 126: Unused */
uint16_t e2di_extra_isize; /* 128: Size of this inode */
uint16_t e2di_chksum_hi; /* 130: High inode checksum */
- uint32_t e2di_ctime_extra; /* 132: Extra change time */
- uint32_t e2di_mtime_extra; /* 136: Extra modification time */
- uint32_t e2di_atime_extra; /* 140: Extra access time */
- uint32_t e2di_crtime; /* 144: Creation (birth)time */
- uint32_t e2di_crtime_extra; /* 148: Extra creation (birth)time */
- uint32_t e2di_version_hi; /* 152: High bits of inode version */
+ uint32_t e2di_ctime_extra; /* 132: Extra change time */
+ uint32_t e2di_mtime_extra; /* 136: Extra modification time */
+ uint32_t e2di_atime_extra; /* 140: Extra access time */
+ uint32_t e2di_crtime; /* 144: Creation (birth)time */
+ uint32_t e2di_crtime_extra; /* 148: Extra creation (birth)time */
+ uint32_t e2di_version_hi; /* 152: High bits of inode version */
+ uint32_t e2di_projid; /* 156: Project ID */
};
#endif /* !_FS_EXT2FS_EXT2_DINODE_H_ */
Modified: trunk/sys/fs/ext2fs/ext2_dir.h
===================================================================
--- trunk/sys/fs/ext2fs/ext2_dir.h 2018-05-27 22:18:36 UTC (rev 10027)
+++ trunk/sys/fs/ext2fs/ext2_dir.h 2018-05-27 22:19:26 UTC (rev 10028)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*-
* Copyright (c) 2009 Aditya Sarawgi
* All rights reserved.
@@ -23,23 +24,38 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $MidnightBSD$
+ * $FreeBSD: stable/10/sys/fs/ext2fs/ext2_dir.h 311232 2017-01-04 02:43:33Z pfg $
*/
#ifndef _FS_EXT2FS_EXT2_DIR_H_
-#define _FS_EXT2FS_EXT2_DIR_H_
+#define _FS_EXT2FS_EXT2_DIR_H_
/*
* Structure of a directory entry
*/
-#define EXT2FS_MAXNAMLEN 255
+#define EXT2FS_MAXNAMLEN 255
-struct ext2fs_direct {
+struct ext2fs_direct {
uint32_t e2d_ino; /* inode number of entry */
uint16_t e2d_reclen; /* length of this record */
uint16_t e2d_namlen; /* length of string in e2d_name */
char e2d_name[EXT2FS_MAXNAMLEN];/* name with length<=EXT2FS_MAXNAMLEN */
};
+
+enum slotstatus {
+ NONE,
+ COMPACT,
+ FOUND
+};
+
+struct ext2fs_searchslot {
+ enum slotstatus slotstatus;
+ doff_t slotoffset; /* offset of area with free space */
+ int slotsize; /* size of area at slotoffset */
+ int slotfreespace; /* amount of space free in slot */
+ int slotneeded; /* sizeof the entry we are seeking */
+};
+
/*
* The new version of the directory entry. Since EXT2 structures are
* stored in intel byte order, and the name_len field could never be
@@ -46,36 +62,41 @@
* bigger than 255 chars, it's safe to reclaim the extra byte for the
* file_type field.
*/
-struct ext2fs_direct_2 {
+struct ext2fs_direct_2 {
uint32_t e2d_ino; /* inode number of entry */
uint16_t e2d_reclen; /* length of this record */
- uint8_t e2d_namlen; /* length of string in e2d_name */
- uint8_t e2d_type; /* file type */
- char e2d_name[EXT2FS_MAXNAMLEN];/* name with length<=EXT2FS_MAXNAMLEN */
+ uint8_t e2d_namlen; /* length of string in e2d_name */
+ uint8_t e2d_type; /* file type */
+ char e2d_name[EXT2FS_MAXNAMLEN]; /* name with
+ * length<=EXT2FS_MAXNAMLEN */
};
+
/*
+ * Maximal count of links to a file
+ */
+#define EXT2_LINK_MAX 32000
+
+/*
* Ext2 directory file types. Only the low 3 bits are used. The
* other bits are reserved for now.
*/
-#define EXT2_FT_UNKNOWN 0
-#define EXT2_FT_REG_FILE 1
-#define EXT2_FT_DIR 2
-#define EXT2_FT_CHRDEV 3
-#define EXT2_FT_BLKDEV 4
-#define EXT2_FT_FIFO 5
-#define EXT2_FT_SOCK 6
-#define EXT2_FT_SYMLINK 7
+#define EXT2_FT_UNKNOWN 0
+#define EXT2_FT_REG_FILE 1
+#define EXT2_FT_DIR 2
+#define EXT2_FT_CHRDEV 3
+#define EXT2_FT_BLKDEV 4
+#define EXT2_FT_FIFO 5
+#define EXT2_FT_SOCK 6
+#define EXT2_FT_SYMLINK 7
+#define EXT2_FT_MAX 8
-#define EXT2_FT_MAX 8
-
/*
* EXT2_DIR_PAD defines the directory entries boundaries
*
* NOTE: It must be a multiple of 4
*/
-#define EXT2_DIR_PAD 4
-#define EXT2_DIR_ROUND (EXT2_DIR_PAD - 1)
-#define EXT2_DIR_REC_LEN(name_len) (((name_len) + 8 + EXT2_DIR_ROUND) & \
+#define EXT2_DIR_PAD 4
+#define EXT2_DIR_ROUND (EXT2_DIR_PAD - 1)
+#define EXT2_DIR_REC_LEN(name_len) (((name_len) + 8 + EXT2_DIR_ROUND) & \
~EXT2_DIR_ROUND)
-#endif /* !_FS_EXT2FS_EXT2_DIR_H_ */
-
+#endif /* !_FS_EXT2FS_EXT2_DIR_H_ */
Added: trunk/sys/fs/ext2fs/ext2_extents.c
===================================================================
--- trunk/sys/fs/ext2fs/ext2_extents.c (rev 0)
+++ trunk/sys/fs/ext2fs/ext2_extents.c 2018-05-27 22:19:26 UTC (rev 10028)
@@ -0,0 +1,176 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2010 Zheng Liu <lz at freebsd.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: stable/10/sys/fs/ext2fs/ext2_extents.c 311232 2017-01-04 02:43:33Z pfg $
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/types.h>
+#include <sys/kernel.h>
+#include <sys/malloc.h>
+#include <sys/vnode.h>
+#include <sys/bio.h>
+#include <sys/buf.h>
+#include <sys/conf.h>
+
+#include <fs/ext2fs/ext2_mount.h>
+#include <fs/ext2fs/fs.h>
+#include <fs/ext2fs/inode.h>
+#include <fs/ext2fs/ext2fs.h>
+#include <fs/ext2fs/ext2_extents.h>
+#include <fs/ext2fs/ext2_extern.h>
+
+static void ext4_ext_binsearch_index(struct inode *ip, struct ext4_extent_path
+ *path, daddr_t lbn)
+{
+ struct ext4_extent_header *ehp = path->ep_header;
+ struct ext4_extent_index *l, *r, *m;
+
+ l = (struct ext4_extent_index *)(char *)(ehp + 1);
+ r = (struct ext4_extent_index *)(char *)(ehp + 1) + ehp->eh_ecount - 1;
+ while (l <= r) {
+ m = l + (r - l) / 2;
+ if (lbn < m->ei_blk)
+ r = m - 1;
+ else
+ l = m + 1;
+ }
+
+ path->ep_index = l - 1;
+}
+
+static void
+ext4_ext_binsearch(struct inode *ip, struct ext4_extent_path *path, daddr_t lbn)
+{
+ struct ext4_extent_header *ehp = path->ep_header;
+ struct ext4_extent *l, *r, *m;
+
+ if (ehp->eh_ecount == 0)
+ return;
+
+ l = (struct ext4_extent *)(char *)(ehp + 1);
+ r = (struct ext4_extent *)(char *)(ehp + 1) + ehp->eh_ecount - 1;
+ while (l <= r) {
+ m = l + (r - l) / 2;
+ if (lbn < m->e_blk)
+ r = m - 1;
+ else
+ l = m + 1;
+ }
+
+ path->ep_ext = l - 1;
+}
+
+/*
+ * Find a block in ext4 extent cache.
+ */
+int
+ext4_ext_in_cache(struct inode *ip, daddr_t lbn, struct ext4_extent *ep)
+{
+ struct ext4_extent_cache *ecp;
+ int ret = EXT4_EXT_CACHE_NO;
+
+ ecp = &ip->i_ext_cache;
+
+ /* cache is invalid */
+ if (ecp->ec_type == EXT4_EXT_CACHE_NO)
+ return (ret);
+
+ if (lbn >= ecp->ec_blk && lbn < ecp->ec_blk + ecp->ec_len) {
+ ep->e_blk = ecp->ec_blk;
+ ep->e_start_lo = ecp->ec_start & 0xffffffff;
+ ep->e_start_hi = ecp->ec_start >> 32 & 0xffff;
+ ep->e_len = ecp->ec_len;
+ ret = ecp->ec_type;
+ }
+ return (ret);
+}
+
+/*
+ * Put an ext4_extent structure in ext4 cache.
+ */
+void
+ext4_ext_put_cache(struct inode *ip, struct ext4_extent *ep, int type)
+{
+ struct ext4_extent_cache *ecp;
+
+ ecp = &ip->i_ext_cache;
+ ecp->ec_type = type;
+ ecp->ec_blk = ep->e_blk;
+ ecp->ec_len = ep->e_len;
+ ecp->ec_start = (daddr_t)ep->e_start_hi << 32 | ep->e_start_lo;
+}
+
+/*
+ * Find an extent.
+ */
+struct ext4_extent_path *
+ext4_ext_find_extent(struct m_ext2fs *fs, struct inode *ip,
+ daddr_t lbn, struct ext4_extent_path *path)
+{
+ struct ext4_extent_header *ehp;
+ uint16_t i;
+ int error, size;
+ daddr_t nblk;
+
+ ehp = (struct ext4_extent_header *)(char *)ip->i_db;
+
+ if (ehp->eh_magic != EXT4_EXT_MAGIC)
+ return (NULL);
+
+ path->ep_header = ehp;
+
+ for (i = ehp->eh_depth; i != 0; --i) {
+ ext4_ext_binsearch_index(ip, path, lbn);
+ path->ep_depth = 0;
+ path->ep_ext = NULL;
+
+ nblk = (daddr_t)path->ep_index->ei_leaf_hi << 32 |
+ path->ep_index->ei_leaf_lo;
+ size = blksize(fs, ip, nblk);
+ if (path->ep_bp != NULL) {
+ brelse(path->ep_bp);
+ path->ep_bp = NULL;
+ }
+ error = bread(ip->i_devvp, fsbtodb(fs, nblk), size, NOCRED,
+ &path->ep_bp);
+ if (error) {
+ brelse(path->ep_bp);
+ path->ep_bp = NULL;
+ return (NULL);
+ }
+ ehp = (struct ext4_extent_header *)path->ep_bp->b_data;
+ path->ep_header = ehp;
+ }
+
+ path->ep_depth = i;
+ path->ep_ext = NULL;
+ path->ep_index = NULL;
+
+ ext4_ext_binsearch(ip, path, lbn);
+ return (path);
+}
Property changes on: trunk/sys/fs/ext2fs/ext2_extents.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/fs/ext2fs/ext2_extents.h
===================================================================
--- trunk/sys/fs/ext2fs/ext2_extents.h (rev 0)
+++ trunk/sys/fs/ext2fs/ext2_extents.h 2018-05-27 22:19:26 UTC (rev 10028)
@@ -0,0 +1,101 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2012, 2010 Zheng Liu <lz at freebsd.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: stable/10/sys/fs/ext2fs/ext2_extents.h 311232 2017-01-04 02:43:33Z pfg $
+ */
+#ifndef _FS_EXT2FS_EXT2_EXTENTS_H_
+#define _FS_EXT2FS_EXT2_EXTENTS_H_
+
+#include <sys/types.h>
+
+#define EXT4_EXT_MAGIC 0xf30a
+
+#define EXT4_EXT_CACHE_NO 0
+#define EXT4_EXT_CACHE_GAP 1
+#define EXT4_EXT_CACHE_IN 2
+
+/*
+ * Ext4 file system extent on disk.
+ */
+struct ext4_extent {
+ uint32_t e_blk; /* first logical block */
+ uint16_t e_len; /* number of blocks */
+ uint16_t e_start_hi; /* high 16 bits of physical block */
+ uint32_t e_start_lo; /* low 32 bits of physical block */
+};
+
+/*
+ * Extent index on disk.
+ */
+struct ext4_extent_index {
+ uint32_t ei_blk; /* indexes logical blocks */
+ uint32_t ei_leaf_lo; /* points to physical block of the
+ * next level */
+ uint16_t ei_leaf_hi; /* high 16 bits of physical block */
+ uint16_t ei_unused;
+};
+
+/*
+ * Extent tree header.
+ */
+struct ext4_extent_header {
+ uint16_t eh_magic; /* magic number: 0xf30a */
+ uint16_t eh_ecount; /* number of valid entries */
+ uint16_t eh_max; /* capacity of store in entries */
+ uint16_t eh_depth; /* the depth of extent tree */
+ uint32_t eh_gen; /* generation of extent tree */
+};
+
+/*
+ * Save cached extent.
+ */
+struct ext4_extent_cache {
+ daddr_t ec_start; /* extent start */
+ uint32_t ec_blk; /* logical block */
+ uint32_t ec_len;
+ uint32_t ec_type;
+};
+
+/*
+ * Save path to some extent.
+ */
+struct ext4_extent_path {
+ uint16_t ep_depth;
+ struct buf *ep_bp;
+ struct ext4_extent *ep_ext;
+ struct ext4_extent_index *ep_index;
+ struct ext4_extent_header *ep_header;
+};
+
+struct inode;
+struct m_ext2fs;
+int ext4_ext_in_cache(struct inode *, daddr_t, struct ext4_extent *);
+void ext4_ext_put_cache(struct inode *, struct ext4_extent *, int);
+struct ext4_extent_path *
+ext4_ext_find_extent(struct m_ext2fs *fs,
+ struct inode *, daddr_t, struct ext4_extent_path *);
+
+#endif /* !_FS_EXT2FS_EXT2_EXTENTS_H_ */
Property changes on: trunk/sys/fs/ext2fs/ext2_extents.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Modified: trunk/sys/fs/ext2fs/ext2_extern.h
===================================================================
--- trunk/sys/fs/ext2fs/ext2_extern.h 2018-05-27 22:18:36 UTC (rev 10027)
+++ trunk/sys/fs/ext2fs/ext2_extern.h 2018-05-27 22:19:26 UTC (rev 10028)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*-
* modified for EXT2FS support in Lites 1.1
*
@@ -33,7 +34,7 @@
* SUCH DAMAGE.
*
* @(#)ffs_extern.h 8.3 (Berkeley) 4/16/94
- * $MidnightBSD$
+ * $FreeBSD: stable/10/sys/fs/ext2fs/ext2_extern.h 311232 2017-01-04 02:43:33Z pfg $
*/
#ifndef _FS_EXT2FS_EXT2_EXTERN_H_
@@ -40,6 +41,8 @@
#define _FS_EXT2FS_EXT2_EXTERN_H_
struct ext2fs_dinode;
+struct ext2fs_direct_2;
+struct ext2fs_searchslot;
struct indir;
struct inode;
struct mount;
@@ -46,32 +49,35 @@
struct vfsconf;
struct vnode;
-int ext2_alloc(struct inode *,
- int32_t, int32_t, int, struct ucred *, int32_t *);
+int ext2_add_entry(struct vnode *, struct ext2fs_direct_2 *);
+int ext2_alloc(struct inode *, daddr_t, e4fs_daddr_t, int,
+ struct ucred *, e4fs_daddr_t *);
int ext2_balloc(struct inode *,
- int32_t, int, struct ucred *, struct buf **, int);
+ e2fs_lbn_t, int, struct ucred *, struct buf **, int);
int ext2_blkatoff(struct vnode *, off_t, char **, struct buf **);
-void ext2_blkfree(struct inode *, int32_t, long);
-int32_t ext2_blkpref(struct inode *, int32_t, int, int32_t *, int32_t);
+void ext2_blkfree(struct inode *, e4fs_daddr_t, long);
+e4fs_daddr_t ext2_blkpref(struct inode *, e2fs_lbn_t, int, e2fs_daddr_t *,
+ e2fs_daddr_t);
int ext2_bmap(struct vop_bmap_args *);
-int ext2_bmaparray(struct vnode *, int32_t, int32_t *, int *, int *);
+int ext2_bmaparray(struct vnode *, daddr_t, daddr_t *, int *, int *);
void ext2_clusteracct(struct m_ext2fs *, char *, int, daddr_t, int);
void ext2_dirbad(struct inode *ip, doff_t offset, char *how);
void ext2_ei2i(struct ext2fs_dinode *, struct inode *);
-int ext2_getlbns(struct vnode *, int32_t, struct indir *, int *);
+int ext2_getlbns(struct vnode *, daddr_t, struct indir *, int *);
void ext2_i2ei(struct inode *, struct ext2fs_dinode *);
-int ext2_reallocblks(struct vop_reallocblks_args *);
void ext2_itimes(struct vnode *vp);
+int ext2_reallocblks(struct vop_reallocblks_args *);
int ext2_reclaim(struct vop_reclaim_args *);
-void ext2_setblock(struct m_ext2fs *, u_char *, int32_t);
int ext2_truncate(struct vnode *, off_t, int, struct ucred *, struct thread *);
int ext2_update(struct vnode *, int);
int ext2_valloc(struct vnode *, int, struct ucred *, struct vnode **);
int ext2_vfree(struct vnode *, ino_t, int);
int ext2_vinit(struct mount *, struct vop_vector *, struct vnode **vpp);
-int ext2_lookup(struct vop_cachedlookup_args *);
-int ext2_readdir(struct vop_readdir_args *);
+int ext2_lookup(struct vop_cachedlookup_args *);
+int ext2_readdir(struct vop_readdir_args *);
+#ifdef EXT2FS_DEBUG
void ext2_print_inode(struct inode *);
+#endif
int ext2_direnter(struct inode *,
struct vnode *, struct componentname *);
int ext2_dirremove(struct vnode *, struct componentname *);
@@ -81,7 +87,19 @@
int ext2_checkpath(struct inode *, struct inode *, struct ucred *);
int cg_has_sb(int i);
int ext2_inactive(struct vop_inactive_args *);
+int ext2_htree_add_entry(struct vnode *, struct ext2fs_direct_2 *,
+ struct componentname *);
+int ext2_htree_create_index(struct vnode *, struct componentname *,
+ struct ext2fs_direct_2 *);
+int ext2_htree_has_idx(struct inode *);
+int ext2_htree_hash(const char *, int, uint32_t *, int, uint32_t *,
+ uint32_t *);
+int ext2_htree_lookup(struct inode *, const char *, int, struct buf **,
+ int *, doff_t *, doff_t *, doff_t *, struct ext2fs_searchslot *);
+int ext2_search_dirblock(struct inode *, void *, int *, const char *, int,
+ int *, doff_t *, doff_t *, doff_t *, struct ext2fs_searchslot *);
+
/* Flags to low-level allocation routines.
* The low 16-bits are reserved for IO_ flags from vnode.h.
*/
@@ -93,4 +111,4 @@
extern struct vop_vector ext2_vnodeops;
extern struct vop_vector ext2_fifoops;
-#endif /* !_FS_EXT2FS_EXT2_EXTERN_H_ */
+#endif /* !_FS_EXT2FS_EXT2_EXTERN_H_ */
Added: trunk/sys/fs/ext2fs/ext2_hash.c
===================================================================
--- trunk/sys/fs/ext2fs/ext2_hash.c (rev 0)
+++ trunk/sys/fs/ext2fs/ext2_hash.c 2018-05-27 22:19:26 UTC (rev 10028)
@@ -0,0 +1,317 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2010, 2013 Zheng Liu <lz at freebsd.org>
+ * Copyright (c) 2012, Vyacheslav Matyushin
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: stable/10/sys/fs/ext2fs/ext2_hash.c 311232 2017-01-04 02:43:33Z pfg $
+ */
+
+/*
+ * The following notice applies to the code in ext2_half_md4():
+ *
+ * Copyright (C) 1990-2, RSA Data Security, Inc. All rights reserved.
+ *
+ * License to copy and use this software is granted provided that it
+ * is identified as the "RSA Data Security, Inc. MD4 Message-Digest
+ * Algorithm" in all material mentioning or referencing this software
+ * or this function.
+ *
+ * License is also granted to make and use derivative works provided
+ * that such works are identified as "derived from the RSA Data
+ * Security, Inc. MD4 Message-Digest Algorithm" in all material
+ * mentioning or referencing the derived work.
+ *
+ * RSA Data Security, Inc. makes no representations concerning either
+ * the merchantability of this software or the suitability of this
+ * software for any particular purpose. It is provided "as is"
+ * without express or implied warranty of any kind.
+ *
+ * These notices must be retained in any copies of any part of this
+ * documentation and/or software.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/conf.h>
+#include <sys/vnode.h>
+#include <sys/stat.h>
+#include <sys/mount.h>
+
+#include <fs/ext2fs/htree.h>
+#include <fs/ext2fs/inode.h>
+#include <fs/ext2fs/ext2_mount.h>
+#include <fs/ext2fs/ext2_extern.h>
+
+/* F, G, and H are MD4 functions */
+#define F(x, y, z) (((x) & (y)) | ((~x) & (z)))
+#define G(x, y, z) (((x) & (y)) | ((x) & (z)) | ((y) & (z)))
+#define H(x, y, z) ((x) ^ (y) ^ (z))
+
+/* ROTATE_LEFT rotates x left n bits */
+#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32 - (n))))
+
+/*
+ * FF, GG, and HH are transformations for rounds 1, 2, and 3.
+ * Rotation is separated from addition to prevent recomputation.
+ */
+#define FF(a, b, c, d, x, s) { \
+ (a) += F ((b), (c), (d)) + (x); \
+ (a) = ROTATE_LEFT ((a), (s)); \
+}
+
+#define GG(a, b, c, d, x, s) { \
+ (a) += G ((b), (c), (d)) + (x) + (uint32_t)0x5A827999; \
+ (a) = ROTATE_LEFT ((a), (s)); \
+}
+
+#define HH(a, b, c, d, x, s) { \
+ (a) += H ((b), (c), (d)) + (x) + (uint32_t)0x6ED9EBA1; \
+ (a) = ROTATE_LEFT ((a), (s)); \
+}
+
+/*
+ * MD4 basic transformation. It transforms state based on block.
+ *
+ * This is a half md4 algorithm since Linux uses this algorithm for dir
+ * index. This function is derived from the RSA Data Security, Inc. MD4
+ * Message-Digest Algorithm and was modified as necessary.
+ *
+ * The return value of this function is uint32_t in Linux, but actually we don't
+ * need to check this value, so in our version this function doesn't return any
+ * value.
+ */
+static void
+ext2_half_md4(uint32_t hash[4], uint32_t data[8])
+{
+ uint32_t a = hash[0], b = hash[1], c = hash[2], d = hash[3];
+
+ /* Round 1 */
+ FF(a, b, c, d, data[0], 3);
+ FF(d, a, b, c, data[1], 7);
+ FF(c, d, a, b, data[2], 11);
+ FF(b, c, d, a, data[3], 19);
+ FF(a, b, c, d, data[4], 3);
+ FF(d, a, b, c, data[5], 7);
+ FF(c, d, a, b, data[6], 11);
+ FF(b, c, d, a, data[7], 19);
+
+ /* Round 2 */
+ GG(a, b, c, d, data[1], 3);
+ GG(d, a, b, c, data[3], 5);
+ GG(c, d, a, b, data[5], 9);
+ GG(b, c, d, a, data[7], 13);
+ GG(a, b, c, d, data[0], 3);
+ GG(d, a, b, c, data[2], 5);
+ GG(c, d, a, b, data[4], 9);
+ GG(b, c, d, a, data[6], 13);
+
+ /* Round 3 */
+ HH(a, b, c, d, data[3], 3);
+ HH(d, a, b, c, data[7], 9);
+ HH(c, d, a, b, data[2], 11);
+ HH(b, c, d, a, data[6], 15);
+ HH(a, b, c, d, data[1], 3);
+ HH(d, a, b, c, data[5], 9);
+ HH(c, d, a, b, data[0], 11);
+ HH(b, c, d, a, data[4], 15);
+
+ hash[0] += a;
+ hash[1] += b;
+ hash[2] += c;
+ hash[3] += d;
+}
+
+/*
+ * Tiny Encryption Algorithm.
+ */
+static void
+ext2_tea(uint32_t hash[4], uint32_t data[8])
+{
+ uint32_t tea_delta = 0x9E3779B9;
+ uint32_t sum;
+ uint32_t x = hash[0], y = hash[1];
+ int n = 16;
+ int i = 1;
+
+ while (n-- > 0) {
+ sum = i * tea_delta;
+ x += ((y << 4) + data[0]) ^ (y + sum) ^ ((y >> 5) + data[1]);
+ y += ((x << 4) + data[2]) ^ (x + sum) ^ ((x >> 5) + data[3]);
+ i++;
+ }
+
+ hash[0] += x;
+ hash[1] += y;
+}
+
+static uint32_t
+ext2_legacy_hash(const char *name, int len, int unsigned_char)
+{
+ uint32_t h0, h1 = 0x12A3FE2D, h2 = 0x37ABE8F9;
+ uint32_t multi = 0x6D22F5;
+ const unsigned char *uname = (const unsigned char *)name;
+ const signed char *sname = (const signed char *)name;
+ int val, i;
+
+ for (i = 0; i < len; i++) {
+ if (unsigned_char)
+ val = (u_int)*uname++;
+ else
+ val = (int)*sname++;
+
+ h0 = h2 + (h1 ^ (val * multi));
+ if (h0 & 0x80000000)
+ h0 -= 0x7FFFFFFF;
+ h2 = h1;
+ h1 = h0;
+ }
+
+ return (h1 << 1);
+}
+
+static void
+ext2_prep_hashbuf(const char *src, int slen, uint32_t *dst, int dlen,
+ int unsigned_char)
+{
+ uint32_t padding = slen | (slen << 8) | (slen << 16) | (slen << 24);
+ uint32_t buf_val;
+ const unsigned char *ubuf = (const unsigned char *)src;
+ const signed char *sbuf = (const signed char *)src;
+ int len, i;
+ int buf_byte;
+
+ if (slen > dlen)
+ len = dlen;
+ else
+ len = slen;
+
+ buf_val = padding;
+
+ for (i = 0; i < len; i++) {
+ if (unsigned_char)
+ buf_byte = (u_int)ubuf[i];
+ else
+ buf_byte = (int)sbuf[i];
+
+ if ((i % 4) == 0)
+ buf_val = padding;
+
+ buf_val <<= 8;
+ buf_val += buf_byte;
+
+ if ((i % 4) == 3) {
+ *dst++ = buf_val;
+ dlen -= sizeof(uint32_t);
+ buf_val = padding;
+ }
+ }
+
+ dlen -= sizeof(uint32_t);
+ if (dlen >= 0)
+ *dst++ = buf_val;
+
+ dlen -= sizeof(uint32_t);
+ while (dlen >= 0) {
+ *dst++ = padding;
+ dlen -= sizeof(uint32_t);
+ }
+}
+
+int
+ext2_htree_hash(const char *name, int len,
+ uint32_t *hash_seed, int hash_version,
+ uint32_t *hash_major, uint32_t *hash_minor)
+{
+ uint32_t hash[4];
+ uint32_t data[8];
+ uint32_t major = 0, minor = 0;
+ int unsigned_char = 0;
+
+ if (!name || !hash_major)
+ return (-1);
+
+ if (len < 1 || len > 255)
+ goto error;
+
+ hash[0] = 0x67452301;
+ hash[1] = 0xEFCDAB89;
+ hash[2] = 0x98BADCFE;
+ hash[3] = 0x10325476;
+
+ if (hash_seed)
+ memcpy(hash, hash_seed, sizeof(hash));
+
+ switch (hash_version) {
+ case EXT2_HTREE_TEA_UNSIGNED:
+ unsigned_char = 1;
+ /* FALLTHROUGH */
+ case EXT2_HTREE_TEA:
+ while (len > 0) {
+ ext2_prep_hashbuf(name, len, data, 16, unsigned_char);
+ ext2_tea(hash, data);
+ len -= 16;
+ name += 16;
+ }
+ major = hash[0];
+ minor = hash[1];
+ break;
+ case EXT2_HTREE_LEGACY_UNSIGNED:
+ unsigned_char = 1;
+ /* FALLTHROUGH */
+ case EXT2_HTREE_LEGACY:
+ major = ext2_legacy_hash(name, len, unsigned_char);
+ break;
+ case EXT2_HTREE_HALF_MD4_UNSIGNED:
+ unsigned_char = 1;
+ /* FALLTHROUGH */
+ case EXT2_HTREE_HALF_MD4:
+ while (len > 0) {
+ ext2_prep_hashbuf(name, len, data, 32, unsigned_char);
+ ext2_half_md4(hash, data);
+ len -= 32;
+ name += 32;
+ }
+ major = hash[1];
+ minor = hash[2];
+ break;
+ default:
+ goto error;
+ }
+
+ major &= ~1;
+ if (major == (EXT2_HTREE_EOF << 1))
+ major = (EXT2_HTREE_EOF - 1) << 1;
+ *hash_major = major;
+ if (hash_minor)
+ *hash_minor = minor;
+
+ return (0);
+
+error:
+ *hash_major = 0;
+ if (hash_minor)
+ *hash_minor = 0;
+ return (-1);
+}
Property changes on: trunk/sys/fs/ext2fs/ext2_hash.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/fs/ext2fs/ext2_htree.c
===================================================================
--- trunk/sys/fs/ext2fs/ext2_htree.c (rev 0)
+++ trunk/sys/fs/ext2fs/ext2_htree.c 2018-05-27 22:19:26 UTC (rev 10028)
@@ -0,0 +1,902 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2010, 2012 Zheng Liu <lz at freebsd.org>
+ * Copyright (c) 2012, Vyacheslav Matyushin
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: stable/10/sys/fs/ext2fs/ext2_htree.c 314227 2017-02-24 21:38:41Z pfg $
+ */
+
+#include <sys/param.h>
+#include <sys/endian.h>
+#include <sys/systm.h>
+#include <sys/namei.h>
+#include <sys/bio.h>
+#include <sys/buf.h>
+#include <sys/endian.h>
+#include <sys/mount.h>
+#include <sys/vnode.h>
+#include <sys/malloc.h>
+#include <sys/dirent.h>
+#include <sys/sysctl.h>
+
+#include <ufs/ufs/dir.h>
+
+#include <fs/ext2fs/inode.h>
+#include <fs/ext2fs/ext2_mount.h>
+#include <fs/ext2fs/ext2fs.h>
+#include <fs/ext2fs/fs.h>
+#include <fs/ext2fs/ext2_extern.h>
+#include <fs/ext2fs/ext2_dinode.h>
+#include <fs/ext2fs/ext2_dir.h>
+#include <fs/ext2fs/htree.h>
+
+static void ext2_append_entry(char *block, uint32_t blksize,
+ struct ext2fs_direct_2 *last_entry,
+ struct ext2fs_direct_2 *new_entry);
+static int ext2_htree_append_block(struct vnode *vp, char *data,
+ struct componentname *cnp, uint32_t blksize);
+static int ext2_htree_check_next(struct inode *ip, uint32_t hash,
+ const char *name, struct ext2fs_htree_lookup_info *info);
+static int ext2_htree_cmp_sort_entry(const void *e1, const void *e2);
+static int ext2_htree_find_leaf(struct inode *ip, const char *name,
+ int namelen, uint32_t *hash, uint8_t *hash_version,
+ struct ext2fs_htree_lookup_info *info);
+static uint32_t ext2_htree_get_block(struct ext2fs_htree_entry *ep);
+static uint16_t ext2_htree_get_count(struct ext2fs_htree_entry *ep);
+static uint32_t ext2_htree_get_hash(struct ext2fs_htree_entry *ep);
+static uint16_t ext2_htree_get_limit(struct ext2fs_htree_entry *ep);
+static void ext2_htree_insert_entry_to_level(struct ext2fs_htree_lookup_level *level,
+ uint32_t hash, uint32_t blk);
+static void ext2_htree_insert_entry(struct ext2fs_htree_lookup_info *info,
+ uint32_t hash, uint32_t blk);
+static uint32_t ext2_htree_node_limit(struct inode *ip);
+static void ext2_htree_set_block(struct ext2fs_htree_entry *ep,
+ uint32_t blk);
+static void ext2_htree_set_count(struct ext2fs_htree_entry *ep,
+ uint16_t cnt);
+static void ext2_htree_set_hash(struct ext2fs_htree_entry *ep,
+ uint32_t hash);
+static void ext2_htree_set_limit(struct ext2fs_htree_entry *ep,
+ uint16_t limit);
+static int ext2_htree_split_dirblock(char *block1, char *block2,
+ uint32_t blksize, uint32_t *hash_seed, uint8_t hash_version,
+ uint32_t *split_hash, struct ext2fs_direct_2 *entry);
+static void ext2_htree_release(struct ext2fs_htree_lookup_info *info);
+static uint32_t ext2_htree_root_limit(struct inode *ip, int len);
+static int ext2_htree_writebuf(struct ext2fs_htree_lookup_info *info);
+
+int
+ext2_htree_has_idx(struct inode *ip)
+{
+ if (EXT2_HAS_COMPAT_FEATURE(ip->i_e2fs, EXT2F_COMPAT_DIRHASHINDEX) &&
+ ip->i_flag & IN_E3INDEX)
+ return (1);
+ else
+ return (0);
+}
+
+static int
+ext2_htree_check_next(struct inode *ip, uint32_t hash, const char *name,
+ struct ext2fs_htree_lookup_info *info)
+{
+ struct vnode *vp = ITOV(ip);
+ struct ext2fs_htree_lookup_level *level;
+ struct buf *bp;
+ uint32_t next_hash;
+ int idx = info->h_levels_num - 1;
+ int levels = 0;
+
+ do {
+ level = &info->h_levels[idx];
+ level->h_entry++;
+ if (level->h_entry < level->h_entries +
+ ext2_htree_get_count(level->h_entries))
+ break;
+ if (idx == 0)
+ return (0);
+ idx--;
+ levels++;
+ } while (1);
+
+ next_hash = ext2_htree_get_hash(level->h_entry);
+ if ((hash & 1) == 0) {
+ if (hash != (next_hash & ~1))
+ return (0);
+ }
+
+ while (levels > 0) {
+ levels--;
+ if (ext2_blkatoff(vp, ext2_htree_get_block(level->h_entry) *
+ ip->i_e2fs->e2fs_bsize, NULL, &bp) != 0)
+ return (0);
+ level = &info->h_levels[idx + 1];
+ brelse(level->h_bp);
+ level->h_bp = bp;
+ level->h_entry = level->h_entries =
+ ((struct ext2fs_htree_node *)bp->b_data)->h_entries;
+ }
+
+ return (1);
+}
+
+static uint32_t
+ext2_htree_get_block(struct ext2fs_htree_entry *ep)
+{
+ return (ep->h_blk & 0x00FFFFFF);
+}
+
+static void
+ext2_htree_set_block(struct ext2fs_htree_entry *ep, uint32_t blk)
+{
+ ep->h_blk = blk;
+}
+
+static uint16_t
+ext2_htree_get_count(struct ext2fs_htree_entry *ep)
+{
+ return (((struct ext2fs_htree_count *)(ep))->h_entries_num);
+}
+
+static void
+ext2_htree_set_count(struct ext2fs_htree_entry *ep, uint16_t cnt)
+{
+ ((struct ext2fs_htree_count *)(ep))->h_entries_num = cnt;
+}
+
+static uint32_t
+ext2_htree_get_hash(struct ext2fs_htree_entry *ep)
+{
+ return (ep->h_hash);
+}
+
+static uint16_t
+ext2_htree_get_limit(struct ext2fs_htree_entry *ep)
+{
+ return (((struct ext2fs_htree_count *)(ep))->h_entries_max);
+}
+
+static void
+ext2_htree_set_hash(struct ext2fs_htree_entry *ep, uint32_t hash)
+{
+ ep->h_hash = hash;
+}
+
+static void
+ext2_htree_set_limit(struct ext2fs_htree_entry *ep, uint16_t limit)
+{
+ ((struct ext2fs_htree_count *)(ep))->h_entries_max = limit;
+}
+
+static void
+ext2_htree_release(struct ext2fs_htree_lookup_info *info)
+{
+ u_int i;
+
+ for (i = 0; i < info->h_levels_num; i++) {
+ struct buf *bp = info->h_levels[i].h_bp;
+
+ if (bp != NULL)
+ brelse(bp);
+ }
+}
+
+static uint32_t
+ext2_htree_root_limit(struct inode *ip, int len)
+{
+ uint32_t space;
+
+ space = ip->i_e2fs->e2fs_bsize - EXT2_DIR_REC_LEN(1) -
+ EXT2_DIR_REC_LEN(2) - len;
+ return (space / sizeof(struct ext2fs_htree_entry));
+}
+
+static uint32_t
+ext2_htree_node_limit(struct inode *ip)
+{
+ struct m_ext2fs *fs;
+ uint32_t space;
+
+ fs = ip->i_e2fs;
+ space = fs->e2fs_bsize - EXT2_DIR_REC_LEN(0);
+
+ return (space / sizeof(struct ext2fs_htree_entry));
+}
+
+static int
+ext2_htree_find_leaf(struct inode *ip, const char *name, int namelen,
+ uint32_t *hash, uint8_t *hash_ver,
+ struct ext2fs_htree_lookup_info *info)
+{
+ struct vnode *vp;
+ struct ext2fs *fs;
+ struct m_ext2fs *m_fs;
+ struct buf *bp = NULL;
+ struct ext2fs_htree_root *rootp;
+ struct ext2fs_htree_entry *entp, *start, *end, *middle, *found;
+ struct ext2fs_htree_lookup_level *level_info;
+ uint32_t hash_major = 0, hash_minor = 0;
+ uint32_t levels, cnt;
+ uint8_t hash_version;
+
+ if (name == NULL || info == NULL)
+ return (-1);
+
+ vp = ITOV(ip);
+ fs = ip->i_e2fs->e2fs;
+ m_fs = ip->i_e2fs;
+
+ if (ext2_blkatoff(vp, 0, NULL, &bp) != 0)
+ return (-1);
+
+ info->h_levels_num = 1;
+ info->h_levels[0].h_bp = bp;
+ rootp = (struct ext2fs_htree_root *)bp->b_data;
+ if (rootp->h_info.h_hash_version != EXT2_HTREE_LEGACY &&
+ rootp->h_info.h_hash_version != EXT2_HTREE_HALF_MD4 &&
+ rootp->h_info.h_hash_version != EXT2_HTREE_TEA)
+ goto error;
+
+ hash_version = rootp->h_info.h_hash_version;
+ if (hash_version <= EXT2_HTREE_TEA)
+ hash_version += m_fs->e2fs_uhash;
+ *hash_ver = hash_version;
+
+ ext2_htree_hash(name, namelen, fs->e3fs_hash_seed,
+ hash_version, &hash_major, &hash_minor);
+ *hash = hash_major;
+
+ if ((levels = rootp->h_info.h_ind_levels) > 1)
+ goto error;
+
+ entp = (struct ext2fs_htree_entry *)(((char *)&rootp->h_info) +
+ rootp->h_info.h_info_len);
+
+ if (ext2_htree_get_limit(entp) !=
+ ext2_htree_root_limit(ip, rootp->h_info.h_info_len))
+ goto error;
+
+ while (1) {
+ cnt = ext2_htree_get_count(entp);
+ if (cnt == 0 || cnt > ext2_htree_get_limit(entp))
+ goto error;
+
+ start = entp + 1;
+ end = entp + cnt - 1;
+ while (start <= end) {
+ middle = start + (end - start) / 2;
+ if (ext2_htree_get_hash(middle) > hash_major)
+ end = middle - 1;
+ else
+ start = middle + 1;
+ }
+ found = start - 1;
+
+ level_info = &(info->h_levels[info->h_levels_num - 1]);
+ level_info->h_bp = bp;
+ level_info->h_entries = entp;
+ level_info->h_entry = found;
+ if (levels == 0)
+ return (0);
+ levels--;
+ if (ext2_blkatoff(vp,
+ ext2_htree_get_block(found) * m_fs->e2fs_bsize,
+ NULL, &bp) != 0)
+ goto error;
+ entp = ((struct ext2fs_htree_node *)bp->b_data)->h_entries;
+ info->h_levels_num++;
+ info->h_levels[info->h_levels_num - 1].h_bp = bp;
+ }
+
+error:
+ ext2_htree_release(info);
+ return (-1);
+}
+
+/*
+ * Try to lookup a directory entry in HTree index
+ */
+int
+ext2_htree_lookup(struct inode *ip, const char *name, int namelen,
+ struct buf **bpp, int *entryoffp, doff_t *offp,
+ doff_t *prevoffp, doff_t *endusefulp,
+ struct ext2fs_searchslot *ss)
+{
+ struct vnode *vp;
+ struct ext2fs_htree_lookup_info info;
+ struct ext2fs_htree_entry *leaf_node;
+ struct m_ext2fs *m_fs;
+ struct buf *bp;
+ uint32_t blk;
+ uint32_t dirhash;
+ uint32_t bsize;
+ uint8_t hash_version;
+ int search_next;
+ int found = 0;
+
+ m_fs = ip->i_e2fs;
+ bsize = m_fs->e2fs_bsize;
+ vp = ITOV(ip);
+
+ /* TODO: print error msg because we don't lookup '.' and '..' */
+
+ memset(&info, 0, sizeof(info));
+ if (ext2_htree_find_leaf(ip, name, namelen, &dirhash,
+ &hash_version, &info))
+ return (-1);
+
+ do {
+ leaf_node = info.h_levels[info.h_levels_num - 1].h_entry;
+ blk = ext2_htree_get_block(leaf_node);
+ if (ext2_blkatoff(vp, blk * bsize, NULL, &bp) != 0) {
+ ext2_htree_release(&info);
+ return (-1);
+ }
+
+ *offp = blk * bsize;
+ *entryoffp = 0;
+ *prevoffp = blk * bsize;
+ *endusefulp = blk * bsize;
+
+ if (ss->slotstatus == NONE) {
+ ss->slotoffset = -1;
+ ss->slotfreespace = 0;
+ }
+
+ if (ext2_search_dirblock(ip, bp->b_data, &found,
+ name, namelen, entryoffp, offp, prevoffp,
+ endusefulp, ss) != 0) {
+ brelse(bp);
+ ext2_htree_release(&info);
+ return (-1);
+ }
+
+ if (found) {
+ *bpp = bp;
+ ext2_htree_release(&info);
+ return (0);
+ }
+
+ brelse(bp);
+ search_next = ext2_htree_check_next(ip, dirhash, name, &info);
+ } while (search_next);
+
+ ext2_htree_release(&info);
+ return (ENOENT);
+}
+
+static int
+ext2_htree_append_block(struct vnode *vp, char *data,
+ struct componentname *cnp, uint32_t blksize)
+{
+ struct iovec aiov;
+ struct uio auio;
+ struct inode *dp = VTOI(vp);
+ uint64_t cursize, newsize;
+ int error;
+
+ cursize = roundup(dp->i_size, blksize);
+ newsize = cursize + blksize;
+
+ auio.uio_offset = cursize;
+ auio.uio_resid = blksize;
+ aiov.iov_len = blksize;
+ aiov.iov_base = data;
+ auio.uio_iov = &aiov;
+ auio.uio_iovcnt = 1;
+ auio.uio_rw = UIO_WRITE;
+ auio.uio_segflg = UIO_SYSSPACE;
+ error = VOP_WRITE(vp, &auio, IO_SYNC, cnp->cn_cred);
+ if (!error)
+ dp->i_size = newsize;
+
+ return (error);
+}
+
+static int
+ext2_htree_writebuf(struct ext2fs_htree_lookup_info *info)
+{
+ int i, error;
+
+ for (i = 0; i < info->h_levels_num; i++) {
+ struct buf *bp = info->h_levels[i].h_bp;
+
+ error = bwrite(bp);
+ if (error)
+ return (error);
+ }
+
+ return (0);
+}
+
+static void
+ext2_htree_insert_entry_to_level(struct ext2fs_htree_lookup_level *level,
+ uint32_t hash, uint32_t blk)
+{
+ struct ext2fs_htree_entry *target;
+ int entries_num;
+
+ target = level->h_entry + 1;
+ entries_num = ext2_htree_get_count(level->h_entries);
+
+ memmove(target + 1, target, (char *)(level->h_entries + entries_num) -
+ (char *)target);
+ ext2_htree_set_block(target, blk);
+ ext2_htree_set_hash(target, hash);
+ ext2_htree_set_count(level->h_entries, entries_num + 1);
+}
+
+/*
+ * Insert an index entry to the index node.
+ */
+static void
+ext2_htree_insert_entry(struct ext2fs_htree_lookup_info *info,
+ uint32_t hash, uint32_t blk)
+{
+ struct ext2fs_htree_lookup_level *level;
+
+ level = &info->h_levels[info->h_levels_num - 1];
+ ext2_htree_insert_entry_to_level(level, hash, blk);
+}
+
+/*
+ * Compare two entry sort descriptors by name hash value.
+ * This is used together with qsort.
+ */
+static int
+ext2_htree_cmp_sort_entry(const void *e1, const void *e2)
+{
+ const struct ext2fs_htree_sort_entry *entry1, *entry2;
+
+ entry1 = (const struct ext2fs_htree_sort_entry *)e1;
+ entry2 = (const struct ext2fs_htree_sort_entry *)e2;
+
+ if (entry1->h_hash < entry2->h_hash)
+ return (-1);
+ if (entry1->h_hash > entry2->h_hash)
+ return (1);
+ return (0);
+}
+
+/*
+ * Append an entry to the end of the directory block.
+ */
+static void
+ext2_append_entry(char *block, uint32_t blksize,
+ struct ext2fs_direct_2 *last_entry,
+ struct ext2fs_direct_2 *new_entry)
+{
+ uint16_t entry_len;
+
+ entry_len = EXT2_DIR_REC_LEN(last_entry->e2d_namlen);
+ last_entry->e2d_reclen = entry_len;
+ last_entry = (struct ext2fs_direct_2 *)((char *)last_entry + entry_len);
+ new_entry->e2d_reclen = block + blksize - (char *)last_entry;
+ memcpy(last_entry, new_entry, EXT2_DIR_REC_LEN(new_entry->e2d_namlen));
+}
+
+/*
+ * Move half of entries from the old directory block to the new one.
+ */
+static int
+ext2_htree_split_dirblock(char *block1, char *block2, uint32_t blksize,
+ uint32_t *hash_seed, uint8_t hash_version,
+ uint32_t *split_hash, struct ext2fs_direct_2 *entry)
+{
+ int entry_cnt = 0;
+ int size = 0;
+ int i, k;
+ uint32_t offset;
+ uint16_t entry_len = 0;
+ uint32_t entry_hash;
+ struct ext2fs_direct_2 *ep, *last;
+ char *dest;
+ struct ext2fs_htree_sort_entry *sort_info;
+
+ ep = (struct ext2fs_direct_2 *)block1;
+ dest = block2;
+ sort_info = (struct ext2fs_htree_sort_entry *)
+ ((char *)block2 + blksize);
+
+ /*
+ * Calculate name hash value for the entry which is to be added.
+ */
+ ext2_htree_hash(entry->e2d_name, entry->e2d_namlen, hash_seed,
+ hash_version, &entry_hash, NULL);
+
+ /*
+ * Fill in directory entry sort descriptors.
+ */
+ while ((char *)ep < block1 + blksize) {
+ if (ep->e2d_ino && ep->e2d_namlen) {
+ entry_cnt++;
+ sort_info--;
+ sort_info->h_size = ep->e2d_reclen;
+ sort_info->h_offset = (char *)ep - block1;
+ ext2_htree_hash(ep->e2d_name, ep->e2d_namlen,
+ hash_seed, hash_version,
+ &sort_info->h_hash, NULL);
+ }
+ ep = (struct ext2fs_direct_2 *)
+ ((char *)ep + ep->e2d_reclen);
+ }
+
+ /*
+ * Sort directory entry descriptors by name hash value.
+ */
+ qsort(sort_info, entry_cnt, sizeof(struct ext2fs_htree_sort_entry),
+ ext2_htree_cmp_sort_entry);
+
+ /*
+ * Count the number of entries to move to directory block 2.
+ */
+ for (i = entry_cnt - 1; i >= 0; i--) {
+ if (sort_info[i].h_size + size > blksize / 2)
+ break;
+ size += sort_info[i].h_size;
+ }
+
+ *split_hash = sort_info[i + 1].h_hash;
+
+ /*
+ * Set collision bit.
+ */
+ if (*split_hash == sort_info[i].h_hash)
+ *split_hash += 1;
+
+ /*
+ * Move half of directory entries from block 1 to block 2.
+ */
+ for (k = i + 1; k < entry_cnt; k++) {
+ ep = (struct ext2fs_direct_2 *)((char *)block1 +
+ sort_info[k].h_offset);
+ entry_len = EXT2_DIR_REC_LEN(ep->e2d_namlen);
+ memcpy(dest, ep, entry_len);
+ ((struct ext2fs_direct_2 *)dest)->e2d_reclen = entry_len;
+ /* Mark directory entry as unused. */
+ ep->e2d_ino = 0;
+ dest += entry_len;
+ }
+ dest -= entry_len;
+
+ /* Shrink directory entries in block 1. */
+ last = (struct ext2fs_direct_2 *)block1;
+ entry_len = 0;
+ for (offset = 0; offset < blksize; ) {
+ ep = (struct ext2fs_direct_2 *)(block1 + offset);
+ offset += ep->e2d_reclen;
+ if (ep->e2d_ino) {
+ last = (struct ext2fs_direct_2 *)
+ ((char *)last + entry_len);
+ entry_len = EXT2_DIR_REC_LEN(ep->e2d_namlen);
+ memcpy((void *)last, (void *)ep, entry_len);
+ last->e2d_reclen = entry_len;
+ }
+ }
+
+ if (entry_hash >= *split_hash) {
+ /* Add entry to block 2. */
+ ext2_append_entry(block2, blksize,
+ (struct ext2fs_direct_2 *)dest, entry);
+
+ /* Adjust length field of last entry of block 1. */
+ last->e2d_reclen = block1 + blksize - (char *)last;
+ } else {
+ /* Add entry to block 1. */
+ ext2_append_entry(block1, blksize, last, entry);
+
+ /* Adjust length field of last entry of block 2. */
+ ((struct ext2fs_direct_2 *)dest)->e2d_reclen =
+ block2 + blksize - dest;
+ }
+
+ return (0);
+}
+
+/*
+ * Create an HTree index for a directory
+ */
+int
+ext2_htree_create_index(struct vnode *vp, struct componentname *cnp,
+ struct ext2fs_direct_2 *new_entry)
+{
+ struct buf *bp = NULL;
+ struct inode *dp;
+ struct ext2fs *fs;
+ struct m_ext2fs *m_fs;
+ struct ext2fs_direct_2 *ep, *dotdot;
+ struct ext2fs_htree_root *root;
+ struct ext2fs_htree_lookup_info info;
+ uint32_t blksize, dirlen, split_hash;
+ uint8_t hash_version;
+ char *buf1 = NULL;
+ char *buf2 = NULL;
+ int error = 0;
+
+ dp = VTOI(vp);
+ fs = dp->i_e2fs->e2fs;
+ m_fs = dp->i_e2fs;
+ blksize = m_fs->e2fs_bsize;
+
+ buf1 = malloc(blksize, M_TEMP, M_WAITOK | M_ZERO);
+ buf2 = malloc(blksize, M_TEMP, M_WAITOK | M_ZERO);
+
+ if ((error = ext2_blkatoff(vp, 0, NULL, &bp)) != 0)
+ goto out;
+
+ root = (struct ext2fs_htree_root *)bp->b_data;
+ dotdot = (struct ext2fs_direct_2 *)((char *)&(root->h_dotdot));
+ ep = (struct ext2fs_direct_2 *)((char *)dotdot + dotdot->e2d_reclen);
+ dirlen = (char *)root + blksize - (char *)ep;
+ memcpy(buf1, ep, dirlen);
+ ep = (struct ext2fs_direct_2 *)buf1;
+ while ((char *)ep < buf1 + dirlen)
+ ep = (struct ext2fs_direct_2 *)
+ ((char *)ep + ep->e2d_reclen);
+ ep->e2d_reclen = buf1 + blksize - (char *)ep;
+
+ dp->i_flag |= IN_E3INDEX;
+
+ /*
+ * Initialize index root.
+ */
+ dotdot->e2d_reclen = blksize - EXT2_DIR_REC_LEN(1);
+ memset(&root->h_info, 0, sizeof(root->h_info));
+ root->h_info.h_hash_version = fs->e3fs_def_hash_version;
+ root->h_info.h_info_len = sizeof(root->h_info);
+ ext2_htree_set_block(root->h_entries, 1);
+ ext2_htree_set_count(root->h_entries, 1);
+ ext2_htree_set_limit(root->h_entries,
+ ext2_htree_root_limit(dp, sizeof(root->h_info)));
+
+ memset(&info, 0, sizeof(info));
+ info.h_levels_num = 1;
+ info.h_levels[0].h_entries = root->h_entries;
+ info.h_levels[0].h_entry = root->h_entries;
+
+ hash_version = root->h_info.h_hash_version;
+ if (hash_version <= EXT2_HTREE_TEA)
+ hash_version += m_fs->e2fs_uhash;
+ ext2_htree_split_dirblock(buf1, buf2, blksize, fs->e3fs_hash_seed,
+ hash_version, &split_hash, new_entry);
+ ext2_htree_insert_entry(&info, split_hash, 2);
+
+ /*
+ * Write directory block 0.
+ */
+ if (DOINGASYNC(vp)) {
+ bdwrite(bp);
+ error = 0;
+ } else {
+ error = bwrite(bp);
+ }
+ dp->i_flag |= IN_CHANGE | IN_UPDATE;
+ if (error)
+ goto out;
+
+ /*
+ * Write directory block 1.
+ */
+ error = ext2_htree_append_block(vp, buf1, cnp, blksize);
+ if (error)
+ goto out1;
+
+ /*
+ * Write directory block 2.
+ */
+ error = ext2_htree_append_block(vp, buf2, cnp, blksize);
+
+ free(buf1, M_TEMP);
+ free(buf2, M_TEMP);
+ return (error);
+out:
+ if (bp != NULL)
+ brelse(bp);
+out1:
+ free(buf1, M_TEMP);
+ free(buf2, M_TEMP);
+ return (error);
+}
+
+/*
+ * Add an entry to the directory using htree index.
+ */
+int
+ext2_htree_add_entry(struct vnode *dvp, struct ext2fs_direct_2 *entry,
+ struct componentname *cnp)
+{
+ struct ext2fs_htree_entry *entries, *leaf_node;
+ struct ext2fs_htree_lookup_info info;
+ struct buf *bp = NULL;
+ struct ext2fs *fs;
+ struct m_ext2fs *m_fs;
+ struct inode *ip;
+ uint16_t ent_num;
+ uint32_t dirhash, split_hash;
+ uint32_t blksize, blknum;
+ uint64_t cursize, dirsize;
+ uint8_t hash_version;
+ char *newdirblock = NULL;
+ char *newidxblock = NULL;
+ struct ext2fs_htree_node *dst_node;
+ struct ext2fs_htree_entry *dst_entries;
+ struct ext2fs_htree_entry *root_entires;
+ struct buf *dst_bp = NULL;
+ int error, write_bp = 0, write_dst_bp = 0, write_info = 0;
+
+ ip = VTOI(dvp);
+ m_fs = ip->i_e2fs;
+ fs = m_fs->e2fs;
+ blksize = m_fs->e2fs_bsize;
+
+ if (ip->i_count != 0)
+ return ext2_add_entry(dvp, entry);
+
+ /* Target directory block is full, split it */
+ memset(&info, 0, sizeof(info));
+ error = ext2_htree_find_leaf(ip, entry->e2d_name, entry->e2d_namlen,
+ &dirhash, &hash_version, &info);
+ if (error)
+ return (error);
+
+ entries = info.h_levels[info.h_levels_num - 1].h_entries;
+ ent_num = ext2_htree_get_count(entries);
+ if (ent_num == ext2_htree_get_limit(entries)) {
+ /* Split the index node. */
+ root_entires = info.h_levels[0].h_entries;
+ newidxblock = malloc(blksize, M_TEMP, M_WAITOK | M_ZERO);
+ dst_node = (struct ext2fs_htree_node *)newidxblock;
+ memset(&dst_node->h_fake_dirent, 0,
+ sizeof(dst_node->h_fake_dirent));
+ dst_node->h_fake_dirent.e2d_reclen = blksize;
+
+ cursize = roundup(ip->i_size, blksize);
+ dirsize = cursize + blksize;
+ blknum = dirsize / blksize - 1;
+
+ error = ext2_htree_append_block(dvp, newidxblock,
+ cnp, blksize);
+ if (error)
+ goto finish;
+ error = ext2_blkatoff(dvp, cursize, NULL, &dst_bp);
+ if (error)
+ goto finish;
+ dst_node = (struct ext2fs_htree_node *)dst_bp->b_data;
+ dst_entries = dst_node->h_entries;
+
+ if (info.h_levels_num == 2) {
+ uint16_t src_ent_num, dst_ent_num;
+
+ if (ext2_htree_get_count(root_entires) ==
+ ext2_htree_get_limit(root_entires)) {
+ /* Directory index is full */
+ error = EIO;
+ goto finish;
+ }
+
+ src_ent_num = ent_num / 2;
+ dst_ent_num = ent_num - src_ent_num;
+ split_hash = ext2_htree_get_hash(entries + src_ent_num);
+
+ /* Move half of index entries to the new index node */
+ memcpy(dst_entries, entries + src_ent_num,
+ dst_ent_num * sizeof(struct ext2fs_htree_entry));
+ ext2_htree_set_count(entries, src_ent_num);
+ ext2_htree_set_count(dst_entries, dst_ent_num);
+ ext2_htree_set_limit(dst_entries,
+ ext2_htree_node_limit(ip));
+
+ if (info.h_levels[1].h_entry >= entries + src_ent_num) {
+ struct buf *tmp = info.h_levels[1].h_bp;
+
+ info.h_levels[1].h_bp = dst_bp;
+ dst_bp = tmp;
+
+ info.h_levels[1].h_entry =
+ info.h_levels[1].h_entry -
+ (entries + src_ent_num) +
+ dst_entries;
+ info.h_levels[1].h_entries = dst_entries;
+ }
+ ext2_htree_insert_entry_to_level(&info.h_levels[0],
+ split_hash, blknum);
+
+ /* Write new index node to disk */
+ error = bwrite(dst_bp);
+ ip->i_flag |= IN_CHANGE | IN_UPDATE;
+ if (error)
+ goto finish;
+ write_dst_bp = 1;
+ } else {
+ /* Create second level for htree index */
+ struct ext2fs_htree_root *idx_root;
+
+ memcpy(dst_entries, entries,
+ ent_num * sizeof(struct ext2fs_htree_entry));
+ ext2_htree_set_limit(dst_entries,
+ ext2_htree_node_limit(ip));
+
+ idx_root = (struct ext2fs_htree_root *)
+ info.h_levels[0].h_bp->b_data;
+ idx_root->h_info.h_ind_levels = 1;
+
+ ext2_htree_set_count(entries, 1);
+ ext2_htree_set_block(entries, blknum);
+
+ info.h_levels_num = 2;
+ info.h_levels[1].h_entries = dst_entries;
+ info.h_levels[1].h_entry = info.h_levels[0].h_entry -
+ info.h_levels[0].h_entries + dst_entries;
+ info.h_levels[1].h_bp = dst_bp;
+ dst_bp = NULL;
+ }
+ }
+
+ leaf_node = info.h_levels[info.h_levels_num - 1].h_entry;
+ blknum = ext2_htree_get_block(leaf_node);
+ error = ext2_blkatoff(dvp, blknum * blksize, NULL, &bp);
+ if (error)
+ goto finish;
+
+ /* Split target directory block */
+ newdirblock = malloc(blksize, M_TEMP, M_WAITOK | M_ZERO);
+ ext2_htree_split_dirblock((char *)bp->b_data, newdirblock, blksize,
+ fs->e3fs_hash_seed, hash_version, &split_hash, entry);
+ cursize = roundup(ip->i_size, blksize);
+ dirsize = cursize + blksize;
+ blknum = dirsize / blksize - 1;
+
+ /* Add index entry for the new directory block */
+ ext2_htree_insert_entry(&info, split_hash, blknum);
+
+ /* Write the new directory block to the end of the directory */
+ error = ext2_htree_append_block(dvp, newdirblock, cnp, blksize);
+ if (error)
+ goto finish;
+
+ /* Write the target directory block */
+ error = bwrite(bp);
+ ip->i_flag |= IN_CHANGE | IN_UPDATE;
+ if (error)
+ goto finish;
+ write_bp = 1;
+
+ /* Write the index block */
+ error = ext2_htree_writebuf(&info);
+ if (!error)
+ write_info = 1;
+
+finish:
+ if (dst_bp != NULL && !write_dst_bp)
+ brelse(dst_bp);
+ if (bp != NULL && !write_bp)
+ brelse(bp);
+ if (newdirblock != NULL)
+ free(newdirblock, M_TEMP);
+ if (newidxblock != NULL)
+ free(newidxblock, M_TEMP);
+ if (!write_info)
+ ext2_htree_release(&info);
+ return (error);
+}
Property changes on: trunk/sys/fs/ext2fs/ext2_htree.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Modified: trunk/sys/fs/ext2fs/ext2_inode.c
===================================================================
--- trunk/sys/fs/ext2fs/ext2_inode.c 2018-05-27 22:18:36 UTC (rev 10027)
+++ trunk/sys/fs/ext2fs/ext2_inode.c 2018-05-27 22:19:26 UTC (rev 10028)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*-
* modified for Lites 1.1
*
@@ -33,7 +34,7 @@
* SUCH DAMAGE.
*
* @(#)ffs_inode.c 8.5 (Berkeley) 12/30/93
- * $MidnightBSD$
+ * $FreeBSD: stable/10/sys/fs/ext2fs/ext2_inode.c 311232 2017-01-04 02:43:33Z pfg $
*/
#include <sys/param.h>
@@ -43,6 +44,7 @@
#include <sys/buf.h>
#include <sys/vnode.h>
#include <sys/malloc.h>
+#include <sys/rwlock.h>
#include <vm/vm.h>
#include <vm/vm_extern.h>
@@ -53,8 +55,8 @@
#include <fs/ext2fs/fs.h>
#include <fs/ext2fs/ext2_extern.h>
-static int ext2_indirtrunc(struct inode *, int32_t, int32_t, int32_t, int,
- long *);
+static int ext2_indirtrunc(struct inode *, daddr_t, daddr_t,
+ daddr_t, int, e4fs_daddr_t *);
/*
* Update the access, modified, and inode change times as specified by the
@@ -80,11 +82,11 @@
return (0);
ip->i_flag &= ~(IN_LAZYACCESS | IN_LAZYMOD | IN_MODIFIED);
fs = ip->i_e2fs;
- if(fs->e2fs_ronly)
+ if (fs->e2fs_ronly)
return (0);
if ((error = bread(ip->i_devvp,
fsbtodb(fs, ino_to_fsba(fs, ip->i_number)),
- (int)fs->e2fs_bsize, NOCRED, &bp)) != 0) {
+ (int)fs->e2fs_bsize, NOCRED, &bp)) != 0) {
brelse(bp);
return (error);
}
@@ -114,25 +116,29 @@
struct inode *oip;
int32_t bn, lbn, lastiblock[NIADDR], indir_lbn[NIADDR];
uint32_t oldblks[NDADDR + NIADDR], newblks[NDADDR + NIADDR];
- struct bufobj *bo;
struct m_ext2fs *fs;
struct buf *bp;
int offset, size, level;
- long count, nblocks, blocksreleased = 0;
+ e4fs_daddr_t count, nblocks, blocksreleased = 0;
int error, i, allerror;
off_t osize;
+#ifdef INVARIANTS
+ struct bufobj *bo;
+#endif
oip = VTOI(ovp);
+#ifdef INVARIANTS
bo = &ovp->v_bufobj;
+#endif
- ASSERT_VOP_LOCKED(vp, "ext2_truncate");
+ ASSERT_VOP_LOCKED(vp, "ext2_truncate");
if (length < 0)
- return (EINVAL);
+ return (EINVAL);
if (ovp->v_type == VLNK &&
oip->i_size < ovp->v_mount->mnt_maxsymlinklen) {
-#ifdef DIAGNOSTIC
+#ifdef INVARIANTS
if (length != 0)
panic("ext2_truncate: partial truncate of symlink");
#endif
@@ -223,14 +229,18 @@
* will be returned to the free list. lastiblock values are also
* normalized to -1 for calls to ext2_indirtrunc below.
*/
- bcopy((caddr_t)&oip->i_db[0], (caddr_t)oldblks, sizeof(oldblks));
- for (level = TRIPLE; level >= SINGLE; level--)
+ for (level = TRIPLE; level >= SINGLE; level--) {
+ oldblks[NDADDR + level] = oip->i_ib[level];
if (lastiblock[level] < 0) {
oip->i_ib[level] = 0;
lastiblock[level] = -1;
}
- for (i = NDADDR - 1; i > lastblock; i--)
- oip->i_db[i] = 0;
+ }
+ for (i = 0; i < NDADDR; i++) {
+ oldblks[i] = oip->i_db[i];
+ if (i > lastblock)
+ oip->i_db[i] = 0;
+ }
oip->i_flag |= IN_CHANGE | IN_UPDATE;
allerror = ext2_update(ovp, !DOINGASYNC(ovp));
@@ -240,14 +250,20 @@
* Note that we save the new block configuration so we can check it
* when we are done.
*/
- bcopy((caddr_t)&oip->i_db[0], (caddr_t)newblks, sizeof(newblks));
- bcopy((caddr_t)oldblks, (caddr_t)&oip->i_db[0], sizeof(oldblks));
+ for (i = 0; i < NDADDR; i++) {
+ newblks[i] = oip->i_db[i];
+ oip->i_db[i] = oldblks[i];
+ }
+ for (i = 0; i < NIADDR; i++) {
+ newblks[NDADDR + i] = oip->i_ib[i];
+ oip->i_ib[i] = oldblks[NDADDR + i];
+ }
oip->i_size = osize;
- error = vtruncbuf(ovp, cred, td, length, (int)fs->e2fs_bsize);
+ error = vtruncbuf(ovp, cred, length, (int)fs->e2fs_bsize);
if (error && (allerror == 0))
allerror = error;
vnode_pager_setsize(ovp, length);
-
+
/*
* Indirect blocks first.
*/
@@ -318,7 +334,7 @@
}
}
done:
-#ifdef DIAGNOSTIC
+#ifdef INVARIANTS
for (level = SINGLE; level <= TRIPLE; level++)
if (newblks[NDADDR + level] != oip->i_ib[level])
panic("itrunc1");
@@ -330,7 +346,7 @@
bo->bo_clean.bv_cnt != 0))
panic("itrunc3");
BO_UNLOCK(bo);
-#endif /* DIAGNOSTIC */
+#endif /* INVARIANTS */
/*
* Put back the real size.
*/
@@ -355,16 +371,16 @@
*/
static int
-ext2_indirtrunc(struct inode *ip, int32_t lbn, int32_t dbn, int32_t lastbn,
- int level, long *countp)
+ext2_indirtrunc(struct inode *ip, daddr_t lbn, daddr_t dbn,
+ daddr_t lastbn, int level, e4fs_daddr_t *countp)
{
struct buf *bp;
struct m_ext2fs *fs = ip->i_e2fs;
struct vnode *vp;
- int32_t *bap, *copy, nb, nlbn, last;
- long blkcount, factor;
- int i, nblocks, blocksreleased = 0;
- int error = 0, allerror = 0;
+ e2fs_daddr_t *bap, *copy;
+ int i, nblocks, error = 0, allerror = 0;
+ e2fs_lbn_t nb, nlbn, last;
+ e4fs_daddr_t blkcount, factor, blocksreleased = 0;
/*
* Calculate index in current block of last
@@ -403,12 +419,11 @@
*countp = 0;
return (error);
}
-
- bap = (int32_t *)bp->b_data;
+ bap = (e2fs_daddr_t *)bp->b_data;
copy = malloc(fs->e2fs_bsize, M_TEMP, M_WAITOK);
bcopy((caddr_t)bap, (caddr_t)copy, (u_int)fs->e2fs_bsize);
bzero((caddr_t)&bap[last + 1],
- (u_int)(NINDIR(fs) - (last + 1)) * sizeof(int32_t));
+ (NINDIR(fs) - (last + 1)) * sizeof(e2fs_daddr_t));
if (last == -1)
bp->b_flags |= B_INVAL;
if (DOINGASYNC(vp)) {
@@ -488,7 +503,7 @@
* so that it can be reused immediately.
*/
if (ip->i_mode == 0)
- vrecycle(vp, td);
+ vrecycle(vp);
return (error);
}
Modified: trunk/sys/fs/ext2fs/ext2_inode_cnv.c
===================================================================
--- trunk/sys/fs/ext2fs/ext2_inode_cnv.c 2018-05-27 22:18:36 UTC (rev 10027)
+++ trunk/sys/fs/ext2fs/ext2_inode_cnv.c 2018-05-27 22:19:26 UTC (rev 10028)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*-
* Copyright (c) 1995 The University of Utah and
* the Computer Systems Laboratory at the University of Utah (CSL).
@@ -19,7 +20,7 @@
* improvements that they make and grant CSL redistribution rights.
*
* Utah $Hdr$
- * $MidnightBSD$
+ * $FreeBSD: stable/10/sys/fs/ext2fs/ext2_inode_cnv.c 320841 2017-07-09 15:14:22Z pfg $
*/
/*
@@ -32,6 +33,7 @@
#include <sys/stat.h>
#include <sys/vnode.h>
+#include <fs/ext2fs/fs.h>
#include <fs/ext2fs/inode.h>
#include <fs/ext2fs/ext2fs.h>
#include <fs/ext2fs/ext2_dinode.h>
@@ -40,28 +42,42 @@
#define XTIME_TO_NSEC(x) ((x & EXT3_NSEC_MASK) >> 2)
#define NSEC_TO_XTIME(t) (le32toh(t << 2) & EXT3_NSEC_MASK)
+#ifdef EXT2FS_DEBUG
void
ext2_print_inode(struct inode *in)
{
int i;
+ struct ext4_extent_header *ehp;
+ struct ext4_extent *ep;
- printf( "Inode: %5d", in->i_number);
- printf( /* "Inode: %5d" */
- " Type: %10s Mode: 0x%o Flags: 0x%x Version: %d\n",
- "n/a", in->i_mode, in->i_flags, in->i_gen);
- printf( "User: %5lu Group: %5lu Size: %lu\n",
- (unsigned long)in->i_uid, (unsigned long)in->i_gid,
- (unsigned long)in->i_size);
- printf( "Links: %3d Blockcount: %d\n",
- in->i_nlink, in->i_blocks);
- printf( "ctime: 0x%x", in->i_ctime);
- printf( "atime: 0x%x", in->i_atime);
- printf( "mtime: 0x%x", in->i_mtime);
- printf( "BLOCKS: ");
- for(i=0; i < (in->i_blocks <= 24 ? ((in->i_blocks+1)/2): 12); i++)
- printf("%d ", in->i_db[i]);
+ printf("Inode: %5ju", (uintmax_t)in->i_number);
+ printf( /* "Inode: %5d" */
+ " Type: %10s Mode: 0x%o Flags: 0x%x Version: %d\n",
+ "n/a", in->i_mode, in->i_flags, in->i_gen);
+ printf("User: %5u Group: %5u Size: %ju\n",
+ in->i_uid, in->i_gid, (uintmax_t)in->i_size);
+ printf("Links: %3d Blockcount: %ju\n",
+ in->i_nlink, (uintmax_t)in->i_blocks);
+ printf("ctime: 0x%x", in->i_ctime);
+ printf("atime: 0x%x", in->i_atime);
+ printf("mtime: 0x%x", in->i_mtime);
+ if (E2DI_HAS_XTIME(in))
+ printf("crtime %#x ", in->i_birthtime);
+ printf("BLOCKS:");
+ for (i = 0; i < (in->i_blocks <= 24 ? (in->i_blocks + 1) / 2 : 12); i++)
+ printf(" %d", in->i_db[i]);
printf("\n");
+ printf("Extents:\n");
+ ehp = (struct ext4_extent_header *)in->i_db;
+ printf("Header (magic 0x%x entries %d max %d depth %d gen %d)\n",
+ ehp->eh_magic, ehp->eh_ecount, ehp->eh_max, ehp->eh_depth,
+ ehp->eh_gen);
+ ep = (struct ext4_extent *)(char *)(ehp + 1);
+ printf("Index (blk %d len %d start_lo %d start_hi %d)\n", ep->e_blk,
+ ep->e_len, ep->e_start_lo, ep->e_start_hi);
+ printf("\n");
}
+#endif /* EXT2FS_DEBUG */
/*
* raw ext2 inode to inode
@@ -69,14 +85,15 @@
void
ext2_ei2i(struct ext2fs_dinode *ei, struct inode *ip)
{
- int i;
+ int i;
ip->i_nlink = ei->e2di_nlink;
- /* Godmar thinks - if the link count is zero, then the inode is
- unused - according to ext2 standards. Ufs marks this fact
- by setting i_mode to zero - why ?
- I can see that this might lead to problems in an undelete.
- */
+ /*
+ * Godmar thinks - if the link count is zero, then the inode is
+ * unused - according to ext2 standards. Ufs marks this fact by
+ * setting i_mode to zero - why ? I can see that this might lead to
+ * problems in an undelete.
+ */
ip->i_mode = ei->e2di_nlink ? ei->e2di_mode : 0;
ip->i_size = ei->e2di_size;
if (S_ISREG(ip->i_mode))
@@ -95,14 +112,23 @@
ip->i_flags |= (ei->e2di_flags & EXT2_APPEND) ? SF_APPEND : 0;
ip->i_flags |= (ei->e2di_flags & EXT2_IMMUTABLE) ? SF_IMMUTABLE : 0;
ip->i_flags |= (ei->e2di_flags & EXT2_NODUMP) ? UF_NODUMP : 0;
+ ip->i_flag |= (ei->e2di_flags & EXT3_INDEX) ? IN_E3INDEX : 0;
+ ip->i_flag |= (ei->e2di_flags & EXT4_EXTENTS) ? IN_E4EXTENTS : 0;
ip->i_blocks = ei->e2di_nblock;
+ if (E2DI_HAS_HUGE_FILE(ip)) {
+ ip->i_blocks |= (uint64_t)ei->e2di_nblock_high << 32;
+ if (ei->e2di_flags & EXT4_HUGE_FILE)
+ ip->i_blocks = fsbtodb(ip->i_e2fs, ip->i_blocks);
+ }
ip->i_gen = ei->e2di_gen;
ip->i_uid = ei->e2di_uid;
ip->i_gid = ei->e2di_gid;
+ ip->i_uid |= (uint32_t)ei->e2di_uid_high << 16;
+ ip->i_gid |= (uint32_t)ei->e2di_gid_high << 16;
/* XXX use memcpy */
- for(i = 0; i < NDADDR; i++)
+ for (i = 0; i < NDADDR; i++)
ip->i_db[i] = ei->e2di_blocks[i];
- for(i = 0; i < NIADDR; i++)
+ for (i = 0; i < NIADDR; i++)
ip->i_ib[i] = ei->e2di_blocks[EXT2_NDIR_BLOCKS + i];
}
@@ -116,9 +142,9 @@
ei->e2di_mode = ip->i_mode;
ei->e2di_nlink = ip->i_nlink;
- /*
- Godmar thinks: if dtime is nonzero, ext2 says this inode
- has been deleted, this would correspond to a zero link count
+ /*
+ * Godmar thinks: if dtime is nonzero, ext2 says this inode has been
+ * deleted, this would correspond to a zero link count
*/
ei->e2di_dtime = ei->e2di_nlink ? 0 : ip->i_mtime;
ei->e2di_size = ip->i_size;
@@ -134,18 +160,22 @@
ei->e2di_crtime = ip->i_birthtime;
ei->e2di_crtime_extra = NSEC_TO_XTIME(ip->i_birthnsec);
}
- ei->e2di_flags = ip->i_flags;
ei->e2di_flags = 0;
- ei->e2di_flags |= (ip->i_flags & SF_APPEND) ? EXT2_APPEND: 0;
- ei->e2di_flags |= (ip->i_flags & SF_IMMUTABLE) ? EXT2_IMMUTABLE: 0;
- ei->e2di_flags |= (ip->i_flags & UF_NODUMP) ? EXT2_NODUMP: 0;
- ei->e2di_nblock = ip->i_blocks;
+ ei->e2di_flags |= (ip->i_flags & SF_APPEND) ? EXT2_APPEND : 0;
+ ei->e2di_flags |= (ip->i_flags & SF_IMMUTABLE) ? EXT2_IMMUTABLE : 0;
+ ei->e2di_flags |= (ip->i_flags & UF_NODUMP) ? EXT2_NODUMP : 0;
+ ei->e2di_flags |= (ip->i_flag & IN_E3INDEX) ? EXT3_INDEX : 0;
+ ei->e2di_flags |= (ip->i_flag & IN_E4EXTENTS) ? EXT4_EXTENTS : 0;
+ ei->e2di_nblock = ip->i_blocks & 0xffffffff;
+ ei->e2di_nblock_high = ip->i_blocks >> 32 & 0xffff;
ei->e2di_gen = ip->i_gen;
- ei->e2di_uid = ip->i_uid;
- ei->e2di_gid = ip->i_gid;
+ ei->e2di_uid = ip->i_uid & 0xffff;
+ ei->e2di_uid_high = ip->i_uid >> 16 & 0xffff;
+ ei->e2di_gid = ip->i_gid & 0xffff;
+ ei->e2di_gid_high = ip->i_gid >> 16 & 0xffff;
/* XXX use memcpy */
- for(i = 0; i < NDADDR; i++)
+ for (i = 0; i < NDADDR; i++)
ei->e2di_blocks[i] = ip->i_db[i];
- for(i = 0; i < NIADDR; i++)
+ for (i = 0; i < NIADDR; i++)
ei->e2di_blocks[EXT2_NDIR_BLOCKS + i] = ip->i_ib[i];
}
Modified: trunk/sys/fs/ext2fs/ext2_lookup.c
===================================================================
--- trunk/sys/fs/ext2fs/ext2_lookup.c 2018-05-27 22:18:36 UTC (rev 10027)
+++ trunk/sys/fs/ext2fs/ext2_lookup.c 2018-05-27 22:19:26 UTC (rev 10028)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*-
* modified for Lites 1.1
*
@@ -38,7 +39,7 @@
* SUCH DAMAGE.
*
* @(#)ufs_lookup.c 8.6 (Berkeley) 4/1/94
- * $MidnightBSD$
+ * $FreeBSD: stable/10/sys/fs/ext2fs/ext2_lookup.c 332750 2018-04-19 02:50:15Z pfg $
*/
#include <sys/param.h>
@@ -62,7 +63,7 @@
#include <fs/ext2fs/ext2_dir.h>
#include <fs/ext2fs/ext2_extern.h>
-#ifdef DIAGNOSTIC
+#ifdef INVARIANTS
static int dirchk = 1;
#else
static int dirchk = 0;
@@ -113,65 +114,84 @@
static int ext2_dirbadentry(struct vnode *dp, struct ext2fs_direct_2 *de,
int entryoffsetinblock);
+static int ext2_is_dot_entry(struct componentname *cnp);
static int ext2_lookup_ino(struct vnode *vdp, struct vnode **vpp,
struct componentname *cnp, ino_t *dd_ino);
+static int
+ext2_is_dot_entry(struct componentname *cnp)
+{
+ if (cnp->cn_namelen <= 2 && cnp->cn_nameptr[0] == '.' &&
+ (cnp->cn_nameptr[1] == '.' || cnp->cn_nameptr[1] == '\0'))
+ return (1);
+ return (0);
+}
+
/*
* Vnode op for reading directories.
- *
- * This function has to convert directory entries from the on-disk
- * format to the format defined by <sys/dirent.h>. Unfortunately, the
- * conversion will blow up some entries by four bytes, so it can't be
- * done in place. Instead, the conversion is done entry by entry and
- * the converted entry is sent via uiomove.
- *
- * XXX allocate a buffer, convert as many entries as possible, then send
- * the whole buffer to uiomove
*/
int
ext2_readdir(struct vop_readdir_args *ap)
{
+ struct vnode *vp = ap->a_vp;
struct uio *uio = ap->a_uio;
- int count, error;
-
- struct ext2fs_direct_2 *edp, *dp;
+ struct buf *bp;
+ struct inode *ip;
+ struct ext2fs_direct_2 *dp, *edp;
+ u_long *cookies;
+ struct dirent dstdp;
+ off_t offset, startoffset;
+ size_t readcnt, skipcnt;
+ ssize_t startresid;
int ncookies;
- struct dirent dstdp;
- struct uio auio;
- struct iovec aiov;
- caddr_t dirbuf;
int DIRBLKSIZ = VTOI(ap->a_vp)->i_e2fs->e2fs_bsize;
- int readcnt;
- off_t startoffset = uio->uio_offset;
+ int error;
- count = uio->uio_resid;
- /*
- * Avoid complications for partial directory entries by adjusting
- * the i/o to end at a block boundary. Don't give up (like ufs
- * does) if the initial adjustment gives a negative count, since
- * many callers don't supply a large enough buffer. The correct
- * size is a little larger than DIRBLKSIZ to allow for expansion
- * of directory entries, but some callers just use 512.
- */
- count -= (uio->uio_offset + count) & (DIRBLKSIZ -1);
- if (count <= 0)
- count += DIRBLKSIZ;
- auio = *uio;
- auio.uio_iov = &aiov;
- auio.uio_iovcnt = 1;
- auio.uio_resid = count;
- auio.uio_segflg = UIO_SYSSPACE;
- aiov.iov_len = count;
- dirbuf = malloc(count, M_TEMP, M_WAITOK);
- aiov.iov_base = dirbuf;
- error = VOP_READ(ap->a_vp, &auio, 0, ap->a_cred);
- if (error == 0) {
- readcnt = count - auio.uio_resid;
- edp = (struct ext2fs_direct_2 *)&dirbuf[readcnt];
+ if (uio->uio_offset < 0)
+ return (EINVAL);
+ ip = VTOI(vp);
+ if (ap->a_ncookies != NULL) {
+ if (uio->uio_resid < 0)
+ ncookies = 0;
+ else
+ ncookies = uio->uio_resid;
+ if (uio->uio_offset >= ip->i_size)
+ ncookies = 0;
+ else if (ip->i_size - uio->uio_offset < ncookies)
+ ncookies = ip->i_size - uio->uio_offset;
+ ncookies = ncookies / (offsetof(struct ext2fs_direct_2,
+ e2d_namlen) + 4) + 1;
+ cookies = malloc(ncookies * sizeof(*cookies), M_TEMP, M_WAITOK);
+ *ap->a_ncookies = ncookies;
+ *ap->a_cookies = cookies;
+ } else {
ncookies = 0;
- bzero(&dstdp, offsetof(struct dirent, d_name));
- for (dp = (struct ext2fs_direct_2 *)dirbuf;
- !error && uio->uio_resid > 0 && dp < edp; ) {
+ cookies = NULL;
+ }
+ offset = startoffset = uio->uio_offset;
+ startresid = uio->uio_resid;
+ error = 0;
+ while (error == 0 && uio->uio_resid > 0 &&
+ uio->uio_offset < ip->i_size) {
+ error = ext2_blkatoff(vp, uio->uio_offset, NULL, &bp);
+ if (error)
+ break;
+ if (bp->b_offset + bp->b_bcount > ip->i_size)
+ readcnt = ip->i_size - bp->b_offset;
+ else
+ readcnt = bp->b_bcount;
+ skipcnt = (size_t)(uio->uio_offset - bp->b_offset) &
+ ~(size_t)(DIRBLKSIZ - 1);
+ offset = bp->b_offset + skipcnt;
+ dp = (struct ext2fs_direct_2 *)&bp->b_data[skipcnt];
+ edp = (struct ext2fs_direct_2 *)&bp->b_data[readcnt];
+ while (error == 0 && uio->uio_resid > 0 && dp < edp) {
+ if (dp->e2d_reclen <= offsetof(struct ext2fs_direct_2,
+ e2d_namlen) || (caddr_t)dp + dp->e2d_reclen >
+ (caddr_t)edp) {
+ error = EIO;
+ break;
+ }
/*-
* "New" ext2fs directory entries differ in 3 ways
* from ufs on-disk ones:
@@ -188,57 +208,60 @@
* because ext2fs uses a machine-independent disk
* layout.
*/
+ dstdp.d_namlen = dp->e2d_namlen;
+ dstdp.d_type = FTTODT(dp->e2d_type);
+ if (offsetof(struct ext2fs_direct_2, e2d_namlen) +
+ dstdp.d_namlen > dp->e2d_reclen) {
+ error = EIO;
+ break;
+ }
+ if (offset < startoffset || dp->e2d_ino == 0)
+ goto nextentry;
dstdp.d_fileno = dp->e2d_ino;
- dstdp.d_type = FTTODT(dp->e2d_type);
- dstdp.d_namlen = dp->e2d_namlen;
dstdp.d_reclen = GENERIC_DIRSIZ(&dstdp);
bcopy(dp->e2d_name, dstdp.d_name, dstdp.d_namlen);
- bzero(dstdp.d_name + dstdp.d_namlen,
- dstdp.d_reclen - offsetof(struct dirent, d_name) -
- dstdp.d_namlen);
-
- if (dp->e2d_reclen > 0) {
- if(dstdp.d_reclen <= uio->uio_resid) {
- /* advance dp */
- dp = (struct ext2fs_direct_2 *)
- ((char *)dp + dp->e2d_reclen);
- error =
- uiomove(&dstdp, dstdp.d_reclen, uio);
- if (!error)
- ncookies++;
- } else
- break;
- } else {
- error = EIO;
+ dstdp.d_name[dstdp.d_namlen] = '\0';
+ if (dstdp.d_reclen > uio->uio_resid) {
+ if (uio->uio_resid == startresid)
+ error = EINVAL;
+ else
+ error = EJUSTRETURN;
break;
}
- }
- /* we need to correct uio_offset */
- uio->uio_offset = startoffset + (caddr_t)dp - dirbuf;
-
- if (!error && ap->a_ncookies != NULL) {
- u_long *cookiep, *cookies, *ecookies;
- off_t off;
-
- if (uio->uio_segflg != UIO_SYSSPACE || uio->uio_iovcnt != 1)
- panic("ext2_readdir: unexpected uio from NFS server");
- cookies = malloc(ncookies * sizeof(u_long), M_TEMP,
- M_WAITOK);
- off = startoffset;
- for (dp = (struct ext2fs_direct_2 *)dirbuf,
- cookiep = cookies, ecookies = cookies + ncookies;
- cookiep < ecookies;
- dp = (struct ext2fs_direct_2 *)((caddr_t) dp + dp->e2d_reclen)) {
- off += dp->e2d_reclen;
- *cookiep++ = (u_long) off;
+ /* Advance dp. */
+ error = uiomove((caddr_t)&dstdp, dstdp.d_reclen, uio);
+ if (error)
+ break;
+ if (cookies != NULL) {
+ KASSERT(ncookies > 0,
+ ("ext2_readdir: cookies buffer too small"));
+ *cookies = offset + dp->e2d_reclen;
+ cookies++;
+ ncookies--;
}
- *ap->a_ncookies = ncookies;
- *ap->a_cookies = cookies;
+nextentry:
+ offset += dp->e2d_reclen;
+ dp = (struct ext2fs_direct_2 *)((caddr_t)dp +
+ dp->e2d_reclen);
}
+ bqrelse(bp);
+ uio->uio_offset = offset;
}
- free(dirbuf, M_TEMP);
- if (ap->a_eofflag)
- *ap->a_eofflag = VTOI(ap->a_vp)->i_size <= uio->uio_offset;
+ /* We need to correct uio_offset. */
+ uio->uio_offset = offset;
+ if (error == EJUSTRETURN)
+ error = 0;
+ if (ap->a_ncookies != NULL) {
+ if (error == 0) {
+ ap->a_ncookies -= ncookies;
+ } else {
+ free(*ap->a_cookies, M_TEMP);
+ *ap->a_ncookies = 0;
+ *ap->a_cookies = NULL;
+ }
+ }
+ if (error == 0 && ap->a_eofflag)
+ *ap->a_eofflag = ip->i_size <= uio->uio_offset;
return (error);
}
@@ -287,13 +310,9 @@
struct buf *bp; /* a buffer of directory entries */
struct ext2fs_direct_2 *ep; /* the current directory entry */
int entryoffsetinblock; /* offset of ep in bp's buffer */
- enum {NONE, COMPACT, FOUND} slotstatus;
- doff_t slotoffset; /* offset of area with free space */
- int slotsize; /* size of area at slotoffset */
+ struct ext2fs_searchslot ss;
doff_t i_diroff; /* cached i_diroff value */
doff_t i_offset; /* cached i_offset value */
- int slotfreespace; /* amount of space free in slot */
- int slotneeded; /* size of the entry we're seeking */
int numdirpasses; /* strategy for directory search */
doff_t endsearch; /* offset to end directory search */
doff_t prevoff; /* prev entry dp->i_offset */
@@ -301,14 +320,15 @@
struct vnode *tdp; /* returned by VFS_VGET */
doff_t enduseful; /* pointer past last used dir slot */
u_long bmask; /* block offset mask */
- int namlen, error;
+ int error;
struct ucred *cred = cnp->cn_cred;
int flags = cnp->cn_flags;
int nameiop = cnp->cn_nameiop;
ino_t ino, ino1;
int ltype;
+ int entry_found = 0;
- int DIRBLKSIZ = VTOI(vdp)->i_e2fs->e2fs_bsize;
+ int DIRBLKSIZ = VTOI(vdp)->i_e2fs->e2fs_bsize;
if (vpp != NULL)
*vpp = NULL;
@@ -317,30 +337,55 @@
bmask = VFSTOEXT2(vdp->v_mount)->um_mountp->mnt_stat.f_iosize - 1;
restart:
bp = NULL;
- slotoffset = -1;
+ ss.slotoffset = -1;
/*
* We now have a segment name to search for, and a directory to search.
- */
-
- /*
+ *
* Suppress search for slots unless creating
* file and at end of pathname, in which case
* we watch for a place to put the new file in
* case it doesn't already exist.
*/
- ino = 0;
i_diroff = dp->i_diroff;
- slotstatus = FOUND;
- slotfreespace = slotsize = slotneeded = 0;
+ ss.slotstatus = FOUND;
+ ss.slotfreespace = ss.slotsize = ss.slotneeded = 0;
if ((nameiop == CREATE || nameiop == RENAME) &&
(flags & ISLASTCN)) {
- slotstatus = NONE;
- slotneeded = EXT2_DIR_REC_LEN(cnp->cn_namelen);
- /* was
- slotneeded = (sizeof(struct direct) - MAXNAMLEN +
- cnp->cn_namelen + 3) &~ 3; */
+ ss.slotstatus = NONE;
+ ss.slotneeded = EXT2_DIR_REC_LEN(cnp->cn_namelen);
+ /*
+ * was ss.slotneeded = (sizeof(struct direct) - MAXNAMLEN +
+ * cnp->cn_namelen + 3) &~ 3;
+ */
}
+ /*
+ * Try to lookup dir entry using htree directory index.
+ *
+ * If we got an error or we want to find '.' or '..' entry,
+ * we will fall back to linear search.
+ */
+ if (!ext2_is_dot_entry(cnp) && ext2_htree_has_idx(dp)) {
+ numdirpasses = 1;
+ entryoffsetinblock = 0;
+ switch (ext2_htree_lookup(dp, cnp->cn_nameptr, cnp->cn_namelen,
+ &bp, &entryoffsetinblock, &i_offset, &prevoff,
+ &enduseful, &ss)) {
+ case 0:
+ ep = (struct ext2fs_direct_2 *)((char *)bp->b_data +
+ (i_offset & bmask));
+ goto foundentry;
+ case ENOENT:
+ i_offset = roundup2(dp->i_size, DIRBLKSIZ);
+ goto notfound;
+ default:
+ /*
+ * Something failed; just fallback to do a linear
+ * search.
+ */
+ break;
+ }
+ }
/*
* If there is cached information on a previous search of
@@ -376,96 +421,38 @@
/*
* If necessary, get the next directory block.
*/
- if ((i_offset & bmask) == 0) {
- if (bp != NULL)
- brelse(bp);
- if ((error =
- ext2_blkatoff(vdp, (off_t)i_offset, NULL,
- &bp)) != 0)
- return (error);
- entryoffsetinblock = 0;
- }
+ if (bp != NULL)
+ brelse(bp);
+ error = ext2_blkatoff(vdp, (off_t)i_offset, NULL, &bp);
+ if (error != 0)
+ return (error);
+ entryoffsetinblock = 0;
/*
* If still looking for a slot, and at a DIRBLKSIZE
* boundary, have to start looking for free space again.
*/
- if (slotstatus == NONE &&
+ if (ss.slotstatus == NONE &&
(entryoffsetinblock & (DIRBLKSIZ - 1)) == 0) {
- slotoffset = -1;
- slotfreespace = 0;
+ ss.slotoffset = -1;
+ ss.slotfreespace = 0;
}
- /*
- * Get pointer to next entry.
- * Full validation checks are slow, so we only check
- * enough to insure forward progress through the
- * directory. Complete checks can be run by setting
- * "vfs.e2fs.dirchk" to be true.
- */
- ep = (struct ext2fs_direct_2 *)
- ((char *)bp->b_data + entryoffsetinblock);
- if (ep->e2d_reclen == 0 ||
- (dirchk && ext2_dirbadentry(vdp, ep, entryoffsetinblock))) {
- int i;
- ext2_dirbad(dp, i_offset, "mangled entry");
- i = DIRBLKSIZ - (entryoffsetinblock & (DIRBLKSIZ - 1));
- i_offset += i;
- entryoffsetinblock += i;
- continue;
+ error = ext2_search_dirblock(dp, bp->b_data, &entry_found,
+ cnp->cn_nameptr, cnp->cn_namelen,
+ &entryoffsetinblock, &i_offset, &prevoff,
+ &enduseful, &ss);
+ if (error != 0) {
+ brelse(bp);
+ return (error);
}
-
- /*
- * If an appropriate sized slot has not yet been found,
- * check to see if one is available. Also accumulate space
- * in the current block so that we can determine if
- * compaction is viable.
- */
- if (slotstatus != FOUND) {
- int size = ep->e2d_reclen;
-
- if (ep->e2d_ino != 0)
- size -= EXT2_DIR_REC_LEN(ep->e2d_namlen);
- if (size > 0) {
- if (size >= slotneeded) {
- slotstatus = FOUND;
- slotoffset = i_offset;
- slotsize = ep->e2d_reclen;
- } else if (slotstatus == NONE) {
- slotfreespace += size;
- if (slotoffset == -1)
- slotoffset = i_offset;
- if (slotfreespace >= slotneeded) {
- slotstatus = COMPACT;
- slotsize = i_offset +
- ep->e2d_reclen - slotoffset;
- }
- }
- }
+ if (entry_found) {
+ ep = (struct ext2fs_direct_2 *)((char *)bp->b_data +
+ (entryoffsetinblock & bmask));
+foundentry:
+ ino = ep->e2d_ino;
+ goto found;
}
-
- /*
- * Check for a name match.
- */
- if (ep->e2d_ino) {
- namlen = ep->e2d_namlen;
- if (namlen == cnp->cn_namelen &&
- !bcmp(cnp->cn_nameptr, ep->e2d_name,
- (unsigned)namlen)) {
- /*
- * Save directory entry's inode number and
- * reclen in ndp->ni_ufs area, and release
- * directory buffer.
- */
- ino = ep->e2d_ino;
- goto found;
- }
- }
- prevoff = i_offset;
- i_offset += ep->e2d_reclen;
- entryoffsetinblock += ep->e2d_reclen;
- if (ep->e2d_ino)
- enduseful = i_offset;
}
-/* notfound: */
+notfound:
/*
* If we started in the middle of the directory and failed
* to find our target, we must check the beginning as well.
@@ -476,7 +463,6 @@
endsearch = i_diroff;
goto searchloop;
}
- dp->i_offset = i_offset;
if (bp != NULL)
brelse(bp);
/*
@@ -501,18 +487,17 @@
* can be put in the range from dp->i_offset to
* dp->i_offset + dp->i_count.
*/
- if (slotstatus == NONE) {
+ if (ss.slotstatus == NONE) {
dp->i_offset = roundup2(dp->i_size, DIRBLKSIZ);
dp->i_count = 0;
enduseful = dp->i_offset;
} else {
- dp->i_offset = slotoffset;
- dp->i_count = slotsize;
- if (enduseful < slotoffset + slotsize)
- enduseful = slotoffset + slotsize;
+ dp->i_offset = ss.slotoffset;
+ dp->i_count = ss.slotsize;
+ if (enduseful < ss.slotoffset + ss.slotsize)
+ enduseful = ss.slotoffset + ss.slotsize;
}
dp->i_endoff = roundup2(enduseful, DIRBLKSIZ);
- dp->i_flag |= IN_CHANGE | IN_UPDATE;
/*
* We return with the directory locked, so that
* the parameters we set up above will still be
@@ -532,7 +517,7 @@
/*
* Insert name into cache (as non-existent) if appropriate.
*/
- if ((cnp->cn_flags & MAKEENTRY) && nameiop != CREATE)
+ if ((cnp->cn_flags & MAKEENTRY) != 0)
cache_enter(vdp, NULL, cnp);
return (ENOENT);
@@ -546,9 +531,9 @@
* of this entry.
*/
if (entryoffsetinblock + EXT2_DIR_REC_LEN(ep->e2d_namlen)
- > dp->i_size) {
+ > dp->i_size) {
ext2_dirbad(dp, i_offset, "i_size too small");
- dp->i_size = entryoffsetinblock+EXT2_DIR_REC_LEN(ep->e2d_namlen);
+ dp->i_size = entryoffsetinblock + EXT2_DIR_REC_LEN(ep->e2d_namlen);
dp->i_flag |= IN_CHANGE | IN_UPDATE;
}
brelse(bp);
@@ -560,12 +545,13 @@
*/
if ((flags & ISLASTCN) && nameiop == LOOKUP)
dp->i_diroff = i_offset &~ (DIRBLKSIZ - 1);
- dp->i_offset = i_offset;
/*
* If deleting, and at end of pathname, return
* parameters which can be used to remove file.
*/
if (nameiop == DELETE && (flags & ISLASTCN)) {
+ if (flags & LOCKPARENT)
+ ASSERT_VOP_ELOCKED(vdp, __FUNCTION__);
/*
* Write access to directory required to delete files.
*/
@@ -576,7 +562,13 @@
* and distance past previous entry (if there
* is a previous entry in this block) in dp->i_count.
* Save directory inode pointer in ndp->ni_dvp for dirremove().
+ *
+ * Technically we shouldn't be setting these in the
+ * WANTPARENT case (first lookup in rename()), but any
+ * lookups that will result in directory changes will
+ * overwrite these.
*/
+ dp->i_offset = i_offset;
if ((dp->i_offset & (DIRBLKSIZ - 1)) == 0)
dp->i_count = 0;
else
@@ -621,6 +613,7 @@
* Careful about locking second inode.
* This can only occur if the target is ".".
*/
+ dp->i_offset = i_offset;
if (dp->i_number == ino)
return (EISDIR);
if (dd_ino != NULL)
@@ -656,10 +649,7 @@
*/
pdp = vdp;
if (flags & ISDOTDOT) {
- ltype = VOP_ISLOCKED(pdp);
- VOP_UNLOCK(pdp, 0); /* race to get the inode */
- error = VFS_VGET(vdp->v_mount, ino, cnp->cn_lkflags, &tdp);
- vn_lock(pdp, ltype | LK_RETRY);
+ error = vn_vget_ino(pdp, ino, cnp->cn_lkflags, &tdp);
if (pdp->v_iflag & VI_DOOMED) {
if (error == 0)
vput(tdp);
@@ -692,7 +682,7 @@
if (ltype != VOP_ISLOCKED(vdp)) {
if (ltype == LK_EXCLUSIVE)
vn_lock(vdp, LK_UPGRADE | LK_RETRY);
- else /* if (ltype == LK_SHARED) */
+ else /* if (ltype == LK_SHARED) */
vn_lock(vdp, LK_DOWNGRADE | LK_RETRY);
}
*vpp = vdp;
@@ -711,6 +701,102 @@
return (0);
}
+int
+ext2_search_dirblock(struct inode *ip, void *data, int *foundp,
+ const char *name, int namelen, int *entryoffsetinblockp,
+ doff_t *offp, doff_t *prevoffp, doff_t *endusefulp,
+ struct ext2fs_searchslot *ssp)
+{
+ struct vnode *vdp;
+ struct ext2fs_direct_2 *ep, *top;
+ uint32_t bsize = ip->i_e2fs->e2fs_bsize;
+ int offset = *entryoffsetinblockp;
+ int namlen;
+
+ vdp = ITOV(ip);
+
+ ep = (struct ext2fs_direct_2 *)((char *)data + offset);
+ top = (struct ext2fs_direct_2 *)((char *)data +
+ bsize - EXT2_DIR_REC_LEN(0));
+
+ while (ep < top) {
+ /*
+ * Full validation checks are slow, so we only check
+ * enough to insure forward progress through the
+ * directory. Complete checks can be run by setting
+ * "vfs.e2fs.dirchk" to be true.
+ */
+ if (ep->e2d_reclen == 0 ||
+ (dirchk && ext2_dirbadentry(vdp, ep, offset))) {
+ int i;
+
+ ext2_dirbad(ip, *offp, "mangled entry");
+ i = bsize - (offset & (bsize - 1));
+ *offp += i;
+ offset += i;
+ continue;
+ }
+
+ /*
+ * If an appropriate sized slot has not yet been found,
+ * check to see if one is available. Also accumulate space
+ * in the current block so that we can determine if
+ * compaction is viable.
+ */
+ if (ssp->slotstatus != FOUND) {
+ int size = ep->e2d_reclen;
+
+ if (ep->e2d_ino != 0)
+ size -= EXT2_DIR_REC_LEN(ep->e2d_namlen);
+ if (size > 0) {
+ if (size >= ssp->slotneeded) {
+ ssp->slotstatus = FOUND;
+ ssp->slotoffset = *offp;
+ ssp->slotsize = ep->e2d_reclen;
+ } else if (ssp->slotstatus == NONE) {
+ ssp->slotfreespace += size;
+ if (ssp->slotoffset == -1)
+ ssp->slotoffset = *offp;
+ if (ssp->slotfreespace >= ssp->slotneeded) {
+ ssp->slotstatus = COMPACT;
+ ssp->slotsize = *offp +
+ ep->e2d_reclen -
+ ssp->slotoffset;
+ }
+ }
+ }
+ }
+ /*
+ * Check for a name match.
+ */
+ if (ep->e2d_ino) {
+ namlen = ep->e2d_namlen;
+ if (namlen == namelen &&
+ !bcmp(name, ep->e2d_name, (unsigned)namlen)) {
+ /*
+ * Save directory entry's inode number and
+ * reclen in ndp->ni_ufs area, and release
+ * directory buffer.
+ */
+ *foundp = 1;
+ return (0);
+ }
+ }
+ *prevoffp = *offp;
+ *offp += ep->e2d_reclen;
+ offset += ep->e2d_reclen;
+ *entryoffsetinblockp = offset;
+ if (ep->e2d_ino)
+ *endusefulp = *offp;
+ /*
+ * Get pointer to the next entry.
+ */
+ ep = (struct ext2fs_direct_2 *)((char *)data + offset);
+ }
+
+ return (0);
+}
+
void
ext2_dirbad(struct inode *ip, doff_t offset, char *how)
{
@@ -722,7 +808,7 @@
mp->mnt_stat.f_mntonname, (u_long)ip->i_number,(long)offset, how);
else
(void)printf("%s: bad dir ino %lu at offset %ld: %s\n",
- mp->mnt_stat.f_mntonname, (u_long)ip->i_number, (long)offset, how);
+ mp->mnt_stat.f_mntonname, (u_long)ip->i_number, (long)offset, how);
}
@@ -741,9 +827,9 @@
ext2_dirbadentry(struct vnode *dp, struct ext2fs_direct_2 *de,
int entryoffsetinblock)
{
- int DIRBLKSIZ = VTOI(dp)->i_e2fs->e2fs_bsize;
+ int DIRBLKSIZ = VTOI(dp)->i_e2fs->e2fs_bsize;
- char * error_msg = NULL;
+ char *error_msg = NULL;
if (de->e2d_reclen < EXT2_DIR_REC_LEN(1))
error_msg = "rec_len is smaller than minimal";
@@ -778,19 +864,15 @@
int
ext2_direnter(struct inode *ip, struct vnode *dvp, struct componentname *cnp)
{
- struct ext2fs_direct_2 *ep, *nep;
struct inode *dp;
- struct buf *bp;
struct ext2fs_direct_2 newdir;
struct iovec aiov;
struct uio auio;
- u_int dsize;
- int error, loc, newentrysize, spacefree;
- char *dirbuf;
- int DIRBLKSIZ = ip->i_e2fs->e2fs_bsize;
+ int error, newentrysize;
+ int DIRBLKSIZ = ip->i_e2fs->e2fs_bsize;
-#ifdef DIAGNOSTIC
+#ifdef INVARIANTS
if ((cnp->cn_flags & SAVENAME) == 0)
panic("ext2_direnter: missing name");
#endif
@@ -804,6 +886,28 @@
newdir.e2d_type = EXT2_FT_UNKNOWN;
bcopy(cnp->cn_nameptr, newdir.e2d_name, (unsigned)cnp->cn_namelen + 1);
newentrysize = EXT2_DIR_REC_LEN(newdir.e2d_namlen);
+
+ if (ext2_htree_has_idx(dp)) {
+ error = ext2_htree_add_entry(dvp, &newdir, cnp);
+ if (error) {
+ dp->i_flag &= ~IN_E3INDEX;
+ dp->i_flag |= IN_CHANGE | IN_UPDATE;
+ }
+ return (error);
+ }
+
+ if (EXT2_HAS_COMPAT_FEATURE(ip->i_e2fs, EXT2F_COMPAT_DIRHASHINDEX) &&
+ !ext2_htree_has_idx(dp)) {
+ if ((dp->i_size / DIRBLKSIZ) == 1 &&
+ dp->i_offset == DIRBLKSIZ) {
+ /*
+ * Making indexed directory when one block is not
+ * enough to save all entries.
+ */
+ return ext2_htree_create_index(dvp, cnp, &newdir);
+ }
+ }
+
if (dp->i_count == 0) {
/*
* If dp->i_count is 0, then namei could find no
@@ -835,6 +939,29 @@
return (error);
}
+ error = ext2_add_entry(dvp, &newdir);
+ if (!error && dp->i_endoff && dp->i_endoff < dp->i_size)
+ error = ext2_truncate(dvp, (off_t)dp->i_endoff, IO_SYNC,
+ cnp->cn_cred, cnp->cn_thread);
+ return (error);
+}
+
+/*
+ * Insert an entry into the directory block.
+ * Compact the contents.
+ */
+int
+ext2_add_entry(struct vnode *dvp, struct ext2fs_direct_2 *entry)
+{
+ struct ext2fs_direct_2 *ep, *nep;
+ struct inode *dp;
+ struct buf *bp;
+ u_int dsize;
+ int error, loc, newentrysize, spacefree;
+ char *dirbuf;
+
+ dp = VTOI(dvp);
+
/*
* If dp->i_count is non-zero, then namei found space
* for the new entry in the range dp->i_offset to
@@ -866,6 +993,7 @@
* dp->i_offset + dp->i_count would yield the
* space.
*/
+ newentrysize = EXT2_DIR_REC_LEN(entry->e2d_namlen);
ep = (struct ext2fs_direct_2 *)dirbuf;
dsize = EXT2_DIR_REC_LEN(ep->e2d_namlen);
spacefree = ep->e2d_reclen - dsize;
@@ -891,15 +1019,15 @@
if (ep->e2d_ino == 0) {
if (spacefree + dsize < newentrysize)
panic("ext2_direnter: compact1");
- newdir.e2d_reclen = spacefree + dsize;
+ entry->e2d_reclen = spacefree + dsize;
} else {
if (spacefree < newentrysize)
panic("ext2_direnter: compact2");
- newdir.e2d_reclen = spacefree;
+ entry->e2d_reclen = spacefree;
ep->e2d_reclen = dsize;
ep = (struct ext2fs_direct_2 *)((char *)ep + dsize);
}
- bcopy((caddr_t)&newdir, (caddr_t)ep, (u_int)newentrysize);
+ bcopy((caddr_t)entry, (caddr_t)ep, (u_int)newentrysize);
if (DOINGASYNC(dvp)) {
bdwrite(bp);
error = 0;
@@ -907,9 +1035,6 @@
error = bwrite(bp);
}
dp->i_flag |= IN_CHANGE | IN_UPDATE;
- if (!error && dp->i_endoff && dp->i_endoff < dp->i_size)
- error = ext2_truncate(dvp, (off_t)dp->i_endoff, IO_SYNC,
- cnp->cn_cred, cnp->cn_thread);
return (error);
}
@@ -1078,9 +1203,9 @@
break;
}
error = vn_rdwr(UIO_READ, vp, (caddr_t)&dirbuf,
- sizeof(struct dirtemplate), (off_t)0, UIO_SYSSPACE,
- IO_NODELOCKED | IO_NOMACCHECK, cred, NOCRED, NULL,
- NULL);
+ sizeof(struct dirtemplate), (off_t)0, UIO_SYSSPACE,
+ IO_NODELOCKED | IO_NOMACCHECK, cred, NOCRED, NULL,
+ NULL);
if (error != 0)
break;
namlen = dirbuf.dotdot_type; /* like ufs little-endian */
Modified: trunk/sys/fs/ext2fs/ext2_mount.h
===================================================================
--- trunk/sys/fs/ext2fs/ext2_mount.h 2018-05-27 22:18:36 UTC (rev 10027)
+++ trunk/sys/fs/ext2fs/ext2_mount.h 2018-05-27 22:19:26 UTC (rev 10028)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*-
* Copyright (c) 1982, 1986, 1989, 1993
* The Regents of the University of California. All rights reserved.
@@ -27,11 +28,11 @@
* SUCH DAMAGE.
*
* @(#)ufsmount.h 8.6 (Berkeley) 3/30/95
- * $MidnightBSD$
+ * $FreeBSD: stable/10/sys/fs/ext2fs/ext2_mount.h 311232 2017-01-04 02:43:33Z pfg $
*/
#ifndef _FS_EXT2FS_EXT2_MOUNT_H_
-#define _FS_EXT2FS_EXT2_MOUNT_H_
+#define _FS_EXT2FS_EXT2_MOUNT_H_
#ifdef _KERNEL
@@ -59,20 +60,20 @@
struct bufobj *um_bo;
};
-#define EXT2_LOCK(aa) mtx_lock(&(aa)->um_lock)
-#define EXT2_UNLOCK(aa) mtx_unlock(&(aa)->um_lock)
-#define EXT2_MTX(aa) (&(aa)->um_lock)
+#define EXT2_LOCK(aa) mtx_lock(&(aa)->um_lock)
+#define EXT2_UNLOCK(aa) mtx_unlock(&(aa)->um_lock)
+#define EXT2_MTX(aa) (&(aa)->um_lock)
/* Convert mount ptr to ext2fsmount ptr. */
-#define VFSTOEXT2(mp) ((struct ext2mount *)((mp)->mnt_data))
+#define VFSTOEXT2(mp) ((struct ext2mount *)((mp)->mnt_data))
/*
* Macros to access file system parameters in the ufsmount structure.
* Used by ufs_bmap.
*/
-#define MNINDIR(ump) ((ump)->um_nindir)
+#define MNINDIR(ump) ((ump)->um_nindir)
#define blkptrtodb(ump, b) ((b) << (ump)->um_bptrtodb)
#define is_sequential(ump, a, b) ((b) == (a) + ump->um_seqinc)
-#endif /* _KERNEL */
+#endif /* _KERNEL */
#endif /* !_FS_EXT2FS_EXT2_MOUNT_H_ */
Modified: trunk/sys/fs/ext2fs/ext2_subr.c
===================================================================
--- trunk/sys/fs/ext2fs/ext2_subr.c 2018-05-27 22:18:36 UTC (rev 10027)
+++ trunk/sys/fs/ext2fs/ext2_subr.c 2018-05-27 22:19:26 UTC (rev 10028)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*-
* modified for Lites 1.1
*
@@ -33,7 +34,7 @@
* SUCH DAMAGE.
*
* @(#)ffs_subr.c 8.2 (Berkeley) 9/21/93
- * $MidnightBSD$
+ * $FreeBSD: stable/10/sys/fs/ext2fs/ext2_subr.c 311232 2017-01-04 02:43:33Z pfg $
*/
#include <sys/param.h>
@@ -50,10 +51,11 @@
#include <fs/ext2fs/ext2_extern.h>
#include <fs/ext2fs/ext2fs.h>
#include <fs/ext2fs/fs.h>
+#include <fs/ext2fs/ext2_extents.h>
+#include <fs/ext2fs/ext2_mount.h>
+#include <fs/ext2fs/ext2_dinode.h>
#ifdef KDB
-#include <fs/ext2fs/ext2_mount.h>
-
void ext2_checkoverlap(struct buf *, struct inode *);
#endif
@@ -68,23 +70,65 @@
struct inode *ip;
struct m_ext2fs *fs;
struct buf *bp;
- int32_t lbn;
+ e2fs_lbn_t lbn;
int bsize, error;
+ daddr_t newblk;
+ struct ext4_extent *ep;
+ struct ext4_extent_path path;
ip = VTOI(vp);
fs = ip->i_e2fs;
lbn = lblkno(fs, offset);
bsize = blksize(fs, ip, lbn);
+ *bpp = NULL;
- *bpp = NULL;
- if ((error = bread(vp, lbn, bsize, NOCRED, &bp)) != 0) {
+ /*
+ * IN_E4EXTENTS requires special treatment as we can otherwise fall
+ * back to the normal path.
+ */
+ if (!(ip->i_flag & IN_E4EXTENTS))
+ goto normal;
+
+ memset(&path, 0, sizeof(path));
+ if (ext4_ext_find_extent(fs, ip, lbn, &path) == NULL)
+ goto normal;
+ ep = path.ep_ext;
+ if (ep == NULL)
+ goto normal;
+
+ newblk = lbn - ep->e_blk +
+ (ep->e_start_lo | (daddr_t)ep->e_start_hi << 32);
+
+ if (path.ep_bp != NULL) {
+ brelse(path.ep_bp);
+ path.ep_bp = NULL;
+ }
+ error = bread(ip->i_devvp, fsbtodb(fs, newblk), bsize, NOCRED, &bp);
+ if (error != 0) {
brelse(bp);
return (error);
}
if (res)
*res = (char *)bp->b_data + blkoff(fs, offset);
+ /*
+ * If IN_E4EXTENTS is enabled we would get a wrong offset so
+ * reset b_offset here.
+ */
+ bp->b_offset = lbn * bsize;
*bpp = bp;
return (0);
+
+normal:
+ if (*bpp == NULL) {
+ if ((error = bread(vp, lbn, bsize, NOCRED, &bp)) != 0) {
+ brelse(bp);
+ return (error);
+ }
+ if (res)
+ *res = (char *)bp->b_data + blkoff(fs, offset);
+ *bpp = bp;
+ }
+ return (0);
}
#ifdef KDB
@@ -92,7 +136,7 @@
ext2_checkoverlap(struct buf *bp, struct inode *ip)
{
struct buf *ebp, *ep;
- int32_t start, last;
+ e4fs_daddr_t start, last;
struct vnode *vp;
ebp = &buf[nbuf];
@@ -107,10 +151,10 @@
ep->b_blkno + btodb(ep->b_bcount) <= start)
continue;
vprint("Disk overlap", vp);
- (void)printf("\tstart %d, end %d overlap start %lld, end %ld\n",
- start, last, (long long)ep->b_blkno,
- (long)(ep->b_blkno + btodb(ep->b_bcount) - 1));
- panic("Disk buffer overlap");
+ printf("\tstart %jd, end %jd overlap start %jd, end %jd\n",
+ (intmax_t)start, (intmax_t)last, (intmax_t)ep->b_blkno,
+ (intmax_t)(ep->b_blkno + btodb(ep->b_bcount) - 1));
+ panic("ext2_checkoverlap: Disk buffer overlap");
}
}
#endif /* KDB */
@@ -130,6 +174,7 @@
/* Initialize the cluster summary array. */
if (fs->e2fs_clustersum[cg].cs_init == 0) {
int run = 0;
+
bit = 1;
loc = 0;
Modified: trunk/sys/fs/ext2fs/ext2_vfsops.c
===================================================================
--- trunk/sys/fs/ext2fs/ext2_vfsops.c 2018-05-27 22:18:36 UTC (rev 10027)
+++ trunk/sys/fs/ext2fs/ext2_vfsops.c 2018-05-27 22:19:26 UTC (rev 10028)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*-
* modified for EXT2FS support in Lites 1.1
*
@@ -33,7 +34,7 @@
* SUCH DAMAGE.
*
* @(#)ffs_vfsops.c 8.8 (Berkeley) 4/18/94
- * $MidnightBSD$
+ * $FreeBSD: stable/10/sys/fs/ext2fs/ext2_vfsops.c 311232 2017-01-04 02:43:33Z pfg $
*/
#include <sys/param.h>
@@ -112,7 +113,7 @@
struct vfsoptlist *opts;
struct vnode *devvp;
struct thread *td;
- struct ext2mount *ump = 0;
+ struct ext2mount *ump = NULL;
struct m_ext2fs *fs;
struct nameidata nd, *ndp = &nd;
accmode_t accmode;
@@ -141,7 +142,7 @@
*/
if (mp->mnt_flag & MNT_UPDATE) {
ump = VFSTOEXT2(mp);
- fs = ump->um_e2fs;
+ fs = ump->um_e2fs;
error = 0;
if (fs->e2fs_ronly == 0 &&
vfs_flagopt(opts, "ro", NULL, 0)) {
@@ -152,7 +153,7 @@
if (mp->mnt_flag & MNT_FORCE)
flags |= FORCECLOSE;
error = ext2_flushfiles(mp, flags, td);
- if ( error == 0 && fs->e2fs_wasvalid && ext2_cgupdate(ump, MNT_WAIT) == 0) {
+ if (error == 0 && fs->e2fs_wasvalid && ext2_cgupdate(ump, MNT_WAIT) == 0) {
fs->e2fs->e2fs_state |= E2FS_ISCLEAN;
ext2_sbupdate(ump, MNT_WAIT);
}
@@ -290,7 +291,8 @@
return (1);
}
if (es->e2fs_rev > E2FS_REV0) {
- if (es->e2fs_features_incompat & ~EXT2F_INCOMPAT_SUPP) {
+ if (es->e2fs_features_incompat & ~(EXT2F_INCOMPAT_SUPP |
+ EXT4F_RO_INCOMPAT_SUPP)) {
printf(
"WARNING: mount of %s denied due to unsupported optional features\n",
devtoname(dev));
@@ -307,8 +309,8 @@
}
/*
- * This computes the fields of the ext2_sb_info structure from the
- * data in the ext2_super_block structure read in.
+ * This computes the fields of the m_ext2fs structure from the
+ * data in the ext2fs structure read in.
*/
static int
compute_sb_data(struct vnode *devvp, struct ext2fs *es,
@@ -331,7 +333,7 @@
fs->e2fs_fpg = es->e2fs_fpg;
fs->e2fs_ipg = es->e2fs_ipg;
if (es->e2fs_rev == E2FS_REV0) {
- fs->e2fs_isize = E2FS_REV0_INODE_SIZE ;
+ fs->e2fs_isize = E2FS_REV0_INODE_SIZE;
} else {
fs->e2fs_isize = es->e2fs_inode_size;
@@ -354,17 +356,17 @@
}
fs->e2fs_ipb = fs->e2fs_bsize / EXT2_INODE_SIZE(fs);
- fs->e2fs_itpg = fs->e2fs_ipg /fs->e2fs_ipb;
+ fs->e2fs_itpg = fs->e2fs_ipg / fs->e2fs_ipb;
/* s_resuid / s_resgid ? */
- fs->e2fs_gcount = (es->e2fs_bcount - es->e2fs_first_dblock +
- EXT2_BLOCKS_PER_GROUP(fs) - 1) / EXT2_BLOCKS_PER_GROUP(fs);
+ fs->e2fs_gcount = howmany(es->e2fs_bcount - es->e2fs_first_dblock,
+ EXT2_BLOCKS_PER_GROUP(fs));
e2fs_descpb = fs->e2fs_bsize / sizeof(struct ext2_gd);
- db_count = (fs->e2fs_gcount + e2fs_descpb - 1) / e2fs_descpb;
+ db_count = howmany(fs->e2fs_gcount, e2fs_descpb);
fs->e2fs_gdbcount = db_count;
fs->e2fs_gd = malloc(db_count * fs->e2fs_bsize,
M_EXT2MNT, M_WAITOK);
fs->e2fs_contigdirs = malloc(fs->e2fs_gcount *
- sizeof(*fs->e2fs_contigdirs), M_EXT2MNT, M_WAITOK);
+ sizeof(*fs->e2fs_contigdirs), M_EXT2MNT, M_WAITOK | M_ZERO);
/*
* Adjust logic_sb_block.
@@ -371,13 +373,14 @@
* Godmar thinks: if the blocksize is greater than 1024, then
* the superblock is logically part of block zero.
*/
- if(fs->e2fs_bsize > SBSIZE)
+ if (fs->e2fs_bsize > SBSIZE)
logic_sb_block = 0;
for (i = 0; i < db_count; i++) {
- error = bread(devvp ,
- fsbtodb(fs, logic_sb_block + i + 1 ),
- fs->e2fs_bsize, NOCRED, &bp);
+ error = bread(devvp,
+ fsbtodb(fs, logic_sb_block + i + 1),
+ fs->e2fs_bsize, NOCRED, &bp);
if (error) {
+ free(fs->e2fs_contigdirs, M_EXT2MNT);
free(fs->e2fs_gd, M_EXT2MNT);
brelse(bp);
return (error);
@@ -384,21 +387,35 @@
}
e2fs_cgload((struct ext2_gd *)bp->b_data,
&fs->e2fs_gd[
- i * fs->e2fs_bsize / sizeof(struct ext2_gd)],
+ i * fs->e2fs_bsize / sizeof(struct ext2_gd)],
fs->e2fs_bsize);
brelse(bp);
bp = NULL;
}
+ /* Initialization for the ext2 Orlov allocator variant. */
fs->e2fs_total_dir = 0;
- for (i=0; i < fs->e2fs_gcount; i++){
+ for (i = 0; i < fs->e2fs_gcount; i++)
fs->e2fs_total_dir += fs->e2fs_gd[i].ext2bgd_ndirs;
- fs->e2fs_contigdirs[i] = 0;
- }
+
if (es->e2fs_rev == E2FS_REV0 ||
!EXT2_HAS_RO_COMPAT_FEATURE(fs, EXT2F_ROCOMPAT_LARGEFILE))
fs->e2fs_maxfilesize = 0x7fffffff;
- else
- fs->e2fs_maxfilesize = 0x7fffffffffffffff;
+ else {
+ fs->e2fs_maxfilesize = 0xffffffffffff;
+ if (EXT2_HAS_RO_COMPAT_FEATURE(fs, EXT2F_ROCOMPAT_HUGE_FILE))
+ fs->e2fs_maxfilesize = 0x7fffffffffffffff;
+ }
+ if (es->e4fs_flags & E2FS_UNSIGNED_HASH) {
+ fs->e2fs_uhash = 3;
+ } else if ((es->e4fs_flags & E2FS_SIGNED_HASH) == 0) {
+#ifdef __CHAR_UNSIGNED__
+ es->e4fs_flags |= E2FS_UNSIGNED_HASH;
+ fs->e2fs_uhash = 3;
+#else
+ es->e4fs_flags |= E2FS_SIGNED_HASH;
+#endif
+ }
+
return (0);
}
@@ -453,7 +470,7 @@
fs = VFSTOEXT2(mp)->um_e2fs;
bcopy(bp->b_data, fs->e2fs, sizeof(struct ext2fs));
- if((error = compute_sb_data(devvp, es, fs)) != 0) {
+ if ((error = compute_sb_data(devvp, es, fs)) != 0) {
brelse(bp);
return (error);
}
@@ -500,7 +517,7 @@
MNT_VNODE_FOREACH_ALL_ABORT(mp, mvp);
return (error);
}
- ext2_ei2i((struct ext2fs_dinode *) ((char *)bp->b_data +
+ ext2_ei2i((struct ext2fs_dinode *)((char *)bp->b_data +
EXT2_INODE_SIZE(fs) * ino_to_fsbo(fs, ip->i_number)), ip);
brelse(bp);
VOP_UNLOCK(vp, 0);
@@ -525,7 +542,8 @@
struct csum *sump;
int error;
int ronly;
- int i, size;
+ int i;
+ u_long size;
int32_t *lp;
int32_t e2fs_maxcontig;
@@ -584,13 +602,13 @@
/*
* I don't know whether this is the right strategy. Note that
- * we dynamically allocate both an ext2_sb_info and an ext2_super_block
+ * we dynamically allocate both an m_ext2fs and an ext2fs
* while Linux keeps the super block in a locked buffer.
*/
ump->um_e2fs = malloc(sizeof(struct m_ext2fs),
- M_EXT2MNT, M_WAITOK);
+ M_EXT2MNT, M_WAITOK | M_ZERO);
ump->um_e2fs->e2fs = malloc(sizeof(struct ext2fs),
- M_EXT2MNT, M_WAITOK);
+ M_EXT2MNT, M_WAITOK);
mtx_init(EXT2_MTX(ump), "EXT2FS", "EXT2FS Lock", MTX_DEF);
bcopy(es, ump->um_e2fs->e2fs, (u_int)sizeof(struct ext2fs));
if ((error = compute_sb_data(devvp, ump->um_e2fs->e2fs, ump->um_e2fs)))
@@ -598,8 +616,8 @@
/*
* Calculate the maximum contiguous blocks and size of cluster summary
- * array. In FFS this is done by newfs; however, the superblock
- * in ext2fs doesn't have these variables, so we can calculate
+ * array. In FFS this is done by newfs; however, the superblock
+ * in ext2fs doesn't have these variables, so we can calculate
* them here.
*/
e2fs_maxcontig = MAX(1, MAXPHYS / ump->um_e2fs->e2fs_bsize);
@@ -630,7 +648,7 @@
*/
fs->e2fs_wasvalid = fs->e2fs->e2fs_state & E2FS_ISCLEAN ? 1 : 0;
if (ronly == 0) {
- fs->e2fs_fmod = 1; /* mark it modified */
+ fs->e2fs_fmod = 1; /* mark it modified */
fs->e2fs->e2fs_state &= ~E2FS_ISCLEAN; /* set fs invalid */
}
mp->mnt_data = ump;
@@ -659,8 +677,8 @@
* Initialize filesystem stat information in mount struct.
*/
MNT_ILOCK(mp);
- mp->mnt_kern_flag |= MNTK_MPSAFE | MNTK_LOOKUP_SHARED |
- MNTK_EXTENDED_SHARED;
+ mp->mnt_kern_flag |= MNTK_LOOKUP_SHARED | MNTK_EXTENDED_SHARED |
+ MNTK_USES_BCACHE;
MNT_IUNLOCK(mp);
return (0);
out:
@@ -674,7 +692,7 @@
PICKUP_GIANT();
}
if (ump) {
- mtx_destroy(EXT2_MTX(ump));
+ mtx_destroy(EXT2_MTX(ump));
free(ump->um_e2fs->e2fs_gd, M_EXT2MNT);
free(ump->um_e2fs->e2fs_contigdirs, M_EXT2MNT);
free(ump->um_e2fs->e2fs, M_EXT2MNT);
@@ -709,8 +727,8 @@
ronly = fs->e2fs_ronly;
if (ronly == 0 && ext2_cgupdate(ump, MNT_WAIT) == 0) {
if (fs->e2fs_wasvalid)
- fs->e2fs->e2fs_state |= E2FS_ISCLEAN;
- ext2_sbupdate(ump, MNT_WAIT);
+ fs->e2fs->e2fs_state |= E2FS_ISCLEAN;
+ ext2_sbupdate(ump, MNT_WAIT);
}
DROP_GIANT();
@@ -747,8 +765,9 @@
error = vflush(mp, 0, flags, td);
return (error);
}
+
/*
- * Get file system statistics.
+ * Get filesystem statistics.
*/
int
ext2_statfs(struct mount *mp, struct statfs *sbp)
@@ -853,7 +872,7 @@
}
/*
- * Force stale file system control information to be flushed.
+ * Force stale filesystem control information to be flushed.
*/
if (waitfor != MNT_LAZY) {
vn_lock(ump->um_devvp, LK_EXCLUSIVE | LK_RETRY);
@@ -888,7 +907,6 @@
struct ext2mount *ump;
struct buf *bp;
struct vnode *vp;
- struct cdev *dev;
struct thread *td;
int i, error;
int used_blocks;
@@ -899,15 +917,6 @@
return (error);
ump = VFSTOEXT2(mp);
- dev = ump->um_dev;
-
- /*
- * If this malloc() is performed after the getnewvnode()
- * it might block, leaving a vnode with a NULL v_data to be
- * found by ext2_sync() if a sync happens to fire right then,
- * which will cause a panic because ext2_sync() blindly
- * dereferences vp->v_data (as well it should).
- */
ip = malloc(sizeof(struct inode), M_EXT2NODE, M_WAITOK | M_ZERO);
/* Allocate a new vnode/inode. */
@@ -919,7 +928,7 @@
vp->v_data = ip;
ip->i_vnode = vp;
ip->i_e2fs = fs = ump->um_e2fs;
- ip->i_ump = ump;
+ ip->i_ump = ump;
ip->i_number = ino;
lockmgr(vp->v_vnlock, LK_EXCLUSIVE, NULL);
@@ -948,8 +957,8 @@
return (error);
}
/* convert ext2 inode to dinode */
- ext2_ei2i((struct ext2fs_dinode *) ((char *)bp->b_data + EXT2_INODE_SIZE(fs) *
- ino_to_fsbo(fs, ino)), ip);
+ ext2_ei2i((struct ext2fs_dinode *)((char *)bp->b_data + EXT2_INODE_SIZE(fs) *
+ ino_to_fsbo(fs, ino)), ip);
ip->i_block_group = ino_to_cg(fs, ino);
ip->i_next_alloc_block = 0;
ip->i_next_alloc_goal = 0;
@@ -958,15 +967,19 @@
* Now we want to make sure that block pointers for unused
* blocks are zeroed out - ext2_balloc depends on this
* although for regular files and directories only
+ *
+ * If IN_E4EXTENTS is enabled, unused blocks are not zeroed
+ * out because we could corrupt the extent tree.
*/
- if(S_ISDIR(ip->i_mode) || S_ISREG(ip->i_mode)) {
- used_blocks = (ip->i_size+fs->e2fs_bsize-1) / fs->e2fs_bsize;
+ if (!(ip->i_flag & IN_E4EXTENTS) &&
+ (S_ISDIR(ip->i_mode) || S_ISREG(ip->i_mode))) {
+ used_blocks = howmany(ip->i_size, fs->e2fs_bsize);
for (i = used_blocks; i < EXT2_NDIR_BLOCKS; i++)
ip->i_db[i] = 0;
}
-/*
+#ifdef EXT2FS_DEBUG
ext2_print_inode(ip);
-*/
+#endif
bqrelse(bp);
/*
@@ -988,7 +1001,7 @@
* already have one. This should only happen on old filesystems.
*/
if (ip->i_gen == 0) {
- ip->i_gen = random() / 2 + 1;
+ ip->i_gen = random() + 1;
if ((vp->v_mount->mnt_flag & MNT_RDONLY) == 0)
ip->i_flag |= IN_MODIFIED;
}
@@ -1088,6 +1101,7 @@
allerror = error;
return (allerror);
}
+
/*
* Return the root of a filesystem.
*/
Modified: trunk/sys/fs/ext2fs/ext2_vnops.c
===================================================================
--- trunk/sys/fs/ext2fs/ext2_vnops.c 2018-05-27 22:18:36 UTC (rev 10027)
+++ trunk/sys/fs/ext2fs/ext2_vnops.c 2018-05-27 22:19:26 UTC (rev 10028)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*-
* modified for EXT2FS support in Lites 1.1
*
@@ -39,7 +40,7 @@
*
* @(#)ufs_vnops.c 8.7 (Berkeley) 2/3/94
* @(#)ufs_vnops.c 8.27 (Berkeley) 5/27/95
- * $MidnightBSD$
+ * $FreeBSD: stable/10/sys/fs/ext2fs/ext2_vnops.c 311232 2017-01-04 02:43:33Z pfg $
*/
#include "opt_suiddir.h"
@@ -48,11 +49,13 @@
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/fcntl.h>
+#include <sys/filio.h>
#include <sys/stat.h>
#include <sys/bio.h>
#include <sys/buf.h>
#include <sys/endian.h>
#include <sys/priv.h>
+#include <sys/rwlock.h>
#include <sys/mount.h>
#include <sys/unistd.h>
#include <sys/time.h>
@@ -64,15 +67,15 @@
#include <sys/file.h>
#include <vm/vm.h>
+#include <vm/vm_param.h>
+#include <vm/vm_extern.h>
+#include <vm/vm_object.h>
#include <vm/vm_page.h>
-#include <vm/vm_object.h>
-#include <vm/vm_extern.h>
+#include <vm/vm_pager.h>
#include <vm/vnode_pager.h>
#include "opt_directio.h"
-#include <fs/fifofs/fifo.h>
-
#include <ufs/ufs/dir.h>
#include <fs/ext2fs/fs.h>
@@ -85,6 +88,8 @@
static int ext2_makeinode(int mode, struct vnode *, struct vnode **, struct componentname *);
static void ext2_itimes_locked(struct vnode *);
+static int ext4_ext_read(struct vop_read_args *);
+static int ext2_ind_read(struct vop_read_args *);
static vop_access_t ext2_access;
static int ext2_chmod(struct vnode *, int, struct ucred *, struct thread *);
@@ -93,7 +98,9 @@
static vop_close_t ext2_close;
static vop_create_t ext2_create;
static vop_fsync_t ext2_fsync;
+static vop_getpages_t ext2_getpages;
static vop_getattr_t ext2_getattr;
+static vop_ioctl_t ext2_ioctl;
static vop_link_t ext2_link;
static vop_mkdir_t ext2_mkdir;
static vop_mknod_t ext2_mknod;
@@ -122,8 +129,10 @@
.vop_close = ext2_close,
.vop_create = ext2_create,
.vop_fsync = ext2_fsync,
+ .vop_getpages = ext2_getpages,
.vop_getattr = ext2_getattr,
.vop_inactive = ext2_inactive,
+ .vop_ioctl = ext2_ioctl,
.vop_link = ext2_link,
.vop_lookup = vfs_cache_lookup,
.vop_mkdir = ext2_mkdir,
@@ -184,7 +193,7 @@
struct inode *ip;
struct timespec ts;
- ASSERT_VI_LOCKED(vp, __func__);
+ ASSERT_VI_LOCKED(vp, __func__);
ip = VTOI(vp);
if ((ip->i_flag & (IN_ACCESS | IN_CHANGE | IN_UPDATE)) == 0)
@@ -232,8 +241,10 @@
error =
ext2_makeinode(MAKEIMODE(ap->a_vap->va_type, ap->a_vap->va_mode),
ap->a_dvp, ap->a_vpp, ap->a_cnp);
- if (error)
+ if (error != 0)
return (error);
+ if ((ap->a_cnp->cn_flags & MAKEENTRY) != 0)
+ cache_enter(ap->a_dvp, *ap->a_vpp, ap->a_cnp);
return (0);
}
@@ -373,7 +384,7 @@
}
if (vap->va_flags != VNOVAL) {
/* Disallow flags not supported by ext2fs. */
- if(vap->va_flags & ~(SF_APPEND | SF_IMMUTABLE | UF_NODUMP))
+ if (vap->va_flags & ~(SF_APPEND | SF_IMMUTABLE | UF_NODUMP))
return (EOPNOTSUPP);
if (vp->v_mount->mnt_flag & MNT_RDONLY)
@@ -392,21 +403,17 @@
* if securelevel > 0 and any existing system flags are set.
*/
if (!priv_check_cred(cred, PRIV_VFS_SYSFLAGS, 0)) {
- if (ip->i_flags &
- (SF_NOUNLINK | SF_IMMUTABLE | SF_APPEND)) {
+ if (ip->i_flags & (SF_IMMUTABLE | SF_APPEND)) {
error = securelevel_gt(cred, 0);
if (error)
return (error);
}
- ip->i_flags = vap->va_flags;
} else {
- if (ip->i_flags &
- (SF_NOUNLINK | SF_IMMUTABLE | SF_APPEND) ||
- (vap->va_flags & UF_SETTABLE) != vap->va_flags)
+ if (ip->i_flags & (SF_IMMUTABLE | SF_APPEND) ||
+ ((vap->va_flags ^ ip->i_flags) & SF_SETTABLE))
return (EPERM);
- ip->i_flags &= SF_SETTABLE;
- ip->i_flags |= (vap->va_flags & UF_SETTABLE);
}
+ ip->i_flags = vap->va_flags;
ip->i_flag |= IN_CHANGE;
if (ip->i_flags & (IMMUTABLE | APPEND))
return (0);
@@ -458,16 +465,14 @@
((vap->va_vaflags & VA_UTIMES_NULL) == 0 ||
(error = VOP_ACCESS(vp, VWRITE, cred, td))))
return (error);
- if (vap->va_atime.tv_sec != VNOVAL)
- ip->i_flag |= IN_ACCESS;
- if (vap->va_mtime.tv_sec != VNOVAL)
- ip->i_flag |= IN_CHANGE | IN_UPDATE;
- ext2_itimes(vp);
+ ip->i_flag |= IN_CHANGE | IN_MODIFIED;
if (vap->va_atime.tv_sec != VNOVAL) {
+ ip->i_flag &= ~IN_ACCESS;
ip->i_atime = vap->va_atime.tv_sec;
ip->i_atimensec = vap->va_atime.tv_nsec;
}
if (vap->va_mtime.tv_sec != VNOVAL) {
+ ip->i_flag &= ~IN_UPDATE;
ip->i_mtime = vap->va_mtime.tv_sec;
ip->i_mtimensec = vap->va_mtime.tv_nsec;
}
@@ -663,14 +668,10 @@
struct inode *ip;
int error;
-#ifdef DIAGNOSTIC
+#ifdef INVARIANTS
if ((cnp->cn_flags & HASBUF) == 0)
panic("ext2_link: no name");
#endif
- if (tdvp->v_mount != vp->v_mount) {
- error = EXDEV;
- goto out;
- }
ip = VTOI(vp);
if ((nlink_t)ip->i_nlink >= EXT2_LINK_MAX) {
error = EMLINK;
@@ -732,7 +733,7 @@
int error = 0;
u_char namlen;
-#ifdef DIAGNOSTIC
+#ifdef INVARIANTS
if ((tcnp->cn_flags & HASBUF) == 0 ||
(fcnp->cn_flags & HASBUF) == 0)
panic("ext2_rename: no name");
@@ -776,10 +777,10 @@
dp = VTOI(fdvp);
ip = VTOI(fvp);
if (ip->i_nlink >= EXT2_LINK_MAX) {
- VOP_UNLOCK(fvp, 0);
- error = EMLINK;
- goto abortit;
- }
+ VOP_UNLOCK(fvp, 0);
+ error = EMLINK;
+ goto abortit;
+ }
if ((ip->i_flags & (NOUNLINK | IMMUTABLE | APPEND))
|| (dp->i_flags & APPEND)) {
VOP_UNLOCK(fvp, 0);
@@ -895,7 +896,7 @@
vput(tdvp);
} else {
if (xp->i_devvp != dp->i_devvp || xp->i_devvp != ip->i_devvp)
- panic("ext2_rename: EXDEV");
+ panic("ext2_rename: EXDEV");
/*
* Short circuit rename(foo, foo).
*/
@@ -918,8 +919,8 @@
* to it. Also, ensure source and target are compatible
* (both directories, or both not directories).
*/
- if ((xp->i_mode&IFMT) == IFDIR) {
- if (! ext2_dirempty(xp, dp->i_number, tcnp->cn_cred) ||
+ if ((xp->i_mode & IFMT) == IFDIR) {
+ if (!ext2_dirempty(xp, dp->i_number, tcnp->cn_cred) ||
xp->i_nlink > 2) {
error = ENOTEMPTY;
goto bad;
@@ -943,8 +944,8 @@
* of the target directory.
*/
if (doingdirectory && !newparent) {
- dp->i_nlink--;
- dp->i_flag |= IN_CHANGE;
+ dp->i_nlink--;
+ dp->i_flag |= IN_CHANGE;
}
vput(tdvp);
/*
@@ -983,10 +984,10 @@
dp = VTOI(fdvp);
} else {
/*
- * From name has disappeared.
+ * From name has disappeared. IN_RENAME is not sufficient
+ * to protect against directory races due to timing windows,
+ * so we can't panic here.
*/
- if (doingdirectory)
- panic("ext2_rename: lost dir entry");
vrele(ap->a_fvp);
return (0);
}
@@ -1001,8 +1002,11 @@
* rename.
*/
if (xp != ip) {
- if (doingdirectory)
- panic("ext2_rename: lost dir entry");
+ /*
+ * From name resolves to a different inode. IN_RENAME is
+ * not sufficient protection against timing window races
+ * so we can't panic here.
+ */
} else {
/*
* If the source is a directory with a
@@ -1014,9 +1018,9 @@
dp->i_nlink--;
dp->i_flag |= IN_CHANGE;
error = vn_rdwr(UIO_READ, fvp, (caddr_t)&dirbuf,
- sizeof(struct dirtemplate), (off_t)0,
- UIO_SYSSPACE, IO_NODELOCKED | IO_NOMACCHECK,
- tcnp->cn_cred, NOCRED, NULL, NULL);
+ sizeof(struct dirtemplate), (off_t)0,
+ UIO_SYSSPACE, IO_NODELOCKED | IO_NOMACCHECK,
+ tcnp->cn_cred, NOCRED, NULL, NULL);
if (error == 0) {
/* Like ufs little-endian: */
namlen = dirbuf.dotdot_type;
@@ -1027,7 +1031,7 @@
"rename: mangled dir");
} else {
dirbuf.dotdot_ino = newparent;
- (void) vn_rdwr(UIO_WRITE, fvp,
+ (void)vn_rdwr(UIO_WRITE, fvp,
(caddr_t)&dirbuf,
sizeof(struct dirtemplate),
(off_t)0, UIO_SYSSPACE,
@@ -1083,7 +1087,7 @@
struct dirtemplate dirtemplate, *dtp;
int error, dmode;
-#ifdef DIAGNOSTIC
+#ifdef INVARIANTS
if ((cnp->cn_flags & HASBUF) == 0)
panic("ext2_mkdir: no name");
#endif
@@ -1110,12 +1114,12 @@
* if we are hacking owners here, (only do this where told to)
* and we are not giving it TOO root, (would subvert quotas)
* then go ahead and give it to the other user.
- * The new directory also inherits the SUID bit.
+ * The new directory also inherits the SUID bit.
* If user's UID and dir UID are the same,
* 'give it away' so that the SUID is still forced on.
*/
- if ( (dvp->v_mount->mnt_flag & MNT_SUIDDIR) &&
- (dp->i_mode & ISUID) && dp->i_uid) {
+ if ((dvp->v_mount->mnt_flag & MNT_SUIDDIR) &&
+ (dp->i_mode & ISUID) && dp->i_uid) {
dmode |= ISUID;
ip->i_uid = dp->i_uid;
} else {
@@ -1154,10 +1158,11 @@
dirtemplate = *dtp;
dirtemplate.dot_ino = ip->i_number;
dirtemplate.dotdot_ino = dp->i_number;
- /* note that in ext2 DIRBLKSIZ == blocksize, not DEV_BSIZE
- * so let's just redefine it - for this function only
+ /*
+ * note that in ext2 DIRBLKSIZ == blocksize, not DEV_BSIZE so let's
+ * just redefine it - for this function only
*/
-#undef DIRBLKSIZ
+#undef DIRBLKSIZ
#define DIRBLKSIZ VTOI(dvp)->i_e2fs->e2fs_bsize
dirtemplate.dotdot_reclen = DIRBLKSIZ - 12;
error = vn_rdwr(UIO_WRITE, tvp, (caddr_t)&dirtemplate,
@@ -1222,7 +1227,6 @@
* the current directory and thus be
* non-empty.)
*/
- error = 0;
if (ip->i_nlink != 2 || !ext2_dirempty(ip, dp->i_number, cnp->cn_cred)) {
error = ENOTEMPTY;
goto out;
@@ -1328,12 +1332,10 @@
{
struct buf *bp = ap->a_bp;
struct vnode *vp = ap->a_vp;
- struct inode *ip;
struct bufobj *bo;
- int32_t blkno;
+ daddr_t blkno;
int error;
- ip = VTOI(vp);
if (vp->v_type == VBLK || vp->v_type == VCHR)
panic("ext2_strategy: spec");
if (bp->b_blkno == bp->b_lblkno) {
@@ -1394,7 +1396,7 @@
/*
* Kqfilter wrapper for fifos.
*
- * Fall through to ext2 kqfilter routines if needed
+ * Fall through to ext2 kqfilter routines if needed
*/
static int
ext2fifo_kqfilter(struct vop_kqfilter_args *ap)
@@ -1413,30 +1415,68 @@
static int
ext2_pathconf(struct vop_pathconf_args *ap)
{
+ int error = 0;
switch (ap->a_name) {
case _PC_LINK_MAX:
*ap->a_retval = EXT2_LINK_MAX;
- return (0);
+ break;
case _PC_NAME_MAX:
*ap->a_retval = NAME_MAX;
- return (0);
+ break;
case _PC_PATH_MAX:
*ap->a_retval = PATH_MAX;
- return (0);
+ break;
case _PC_PIPE_BUF:
*ap->a_retval = PIPE_BUF;
- return (0);
+ break;
case _PC_CHOWN_RESTRICTED:
*ap->a_retval = 1;
- return (0);
+ break;
case _PC_NO_TRUNC:
*ap->a_retval = 1;
- return (0);
+ break;
+ case _PC_MIN_HOLE_SIZE:
+ *ap->a_retval = ap->a_vp->v_mount->mnt_stat.f_iosize;
+ break;
+ case _PC_ASYNC_IO:
+ /* _PC_ASYNC_IO should have been handled by upper layers. */
+ KASSERT(0, ("_PC_ASYNC_IO should not get here"));
+ error = EINVAL;
+ break;
+ case _PC_PRIO_IO:
+ *ap->a_retval = 0;
+ break;
+ case _PC_SYNC_IO:
+ *ap->a_retval = 0;
+ break;
+ case _PC_ALLOC_SIZE_MIN:
+ *ap->a_retval = ap->a_vp->v_mount->mnt_stat.f_bsize;
+ break;
+ case _PC_FILESIZEBITS:
+ *ap->a_retval = 64;
+ break;
+ case _PC_REC_INCR_XFER_SIZE:
+ *ap->a_retval = ap->a_vp->v_mount->mnt_stat.f_iosize;
+ break;
+ case _PC_REC_MAX_XFER_SIZE:
+ *ap->a_retval = -1; /* means ``unlimited'' */
+ break;
+ case _PC_REC_MIN_XFER_SIZE:
+ *ap->a_retval = ap->a_vp->v_mount->mnt_stat.f_iosize;
+ break;
+ case _PC_REC_XFER_ALIGN:
+ *ap->a_retval = PAGE_SIZE;
+ break;
+ case _PC_SYMLINK_MAX:
+ *ap->a_retval = MAXPATHLEN;
+ break;
+
default:
- return (EINVAL);
+ error = EINVAL;
+ break;
}
- /* NOTREACHED */
+ return (error);
}
/*
@@ -1492,7 +1532,7 @@
int error;
pdir = VTOI(dvp);
-#ifdef DIAGNOSTIC
+#ifdef INVARIANTS
if ((cnp->cn_flags & HASBUF) == 0)
panic("ext2_makeinode: no name");
#endif
@@ -1516,9 +1556,9 @@
* then go ahead and give it to the other user.
* Note that this drops off the execute bits for security.
*/
- if ( (dvp->v_mount->mnt_flag & MNT_SUIDDIR) &&
- (pdir->i_mode & ISUID) &&
- (pdir->i_uid != cnp->cn_cred->cr_uid) && pdir->i_uid) {
+ if ((dvp->v_mount->mnt_flag & MNT_SUIDDIR) &&
+ (pdir->i_mode & ISUID) &&
+ (pdir->i_uid != cnp->cn_cred->cr_uid) && pdir->i_uid) {
ip->i_uid = pdir->i_uid;
mode &= ~07111;
} else {
@@ -1572,6 +1612,28 @@
{
struct vnode *vp;
struct inode *ip;
+ int error;
+
+ vp = ap->a_vp;
+ ip = VTOI(vp);
+
+ /* EXT4_EXT_LOCK(ip); */
+ if (ip->i_flag & IN_E4EXTENTS)
+ error = ext4_ext_read(ap);
+ else
+ error = ext2_ind_read(ap);
+ /* EXT4_EXT_UNLOCK(ip); */
+ return (error);
+}
+
+/*
+ * Vnode op for reading.
+ */
+static int
+ext2_ind_read(struct vop_read_args *ap)
+{
+ struct vnode *vp;
+ struct inode *ip;
struct uio *uio;
struct m_ext2fs *fs;
struct buf *bp;
@@ -1606,7 +1668,7 @@
fs = ip->i_e2fs;
if (uio->uio_offset < ip->i_size &&
uio->uio_offset >= fs->e2fs_maxfilesize)
- return (EOVERFLOW);
+ return (EOVERFLOW);
for (error = 0, bp = NULL; uio->uio_resid > 0; bp = NULL) {
if ((bytesinfile = ip->i_size - uio->uio_offset) <= 0)
@@ -1624,11 +1686,13 @@
if (lblktosize(fs, nextlbn) >= ip->i_size)
error = bread(vp, lbn, size, NOCRED, &bp);
- else if ((vp->v_mount->mnt_flag & MNT_NOCLUSTERR) == 0)
+ else if ((vp->v_mount->mnt_flag & MNT_NOCLUSTERR) == 0) {
error = cluster_read(vp, ip->i_size, lbn, size,
- NOCRED, blkoffset + uio->uio_resid, seqcount, &bp);
- else if (seqcount > 1) {
- int nextsize = blksize(fs, ip, nextlbn);
+ NOCRED, blkoffset + uio->uio_resid, seqcount,
+ 0, &bp);
+ } else if (seqcount > 1) {
+ u_int nextsize = blksize(fs, ip, nextlbn);
+
error = breadn(vp, lbn,
size, &nextlbn, &nextsize, 1, NOCRED, &bp);
} else
@@ -1662,7 +1726,7 @@
xfersize = size;
}
error = uiomove((char *)bp->b_data + blkoffset,
- (int)xfersize, uio);
+ (int)xfersize, uio);
if (error)
break;
@@ -1686,11 +1750,11 @@
}
}
- /*
- * This can only happen in the case of an error
- * because the loop above resets bp to NULL on each iteration
- * and on normal completion has not set a new value into it.
- * so it must have come from a 'break' statement
+ /*
+ * This can only happen in the case of an error because the loop
+ * above resets bp to NULL on each iteration and on normal
+ * completion has not set a new value into it. so it must have come
+ * from a 'break' statement
*/
if (bp != NULL) {
if (ioflag & (IO_VMIO|IO_DIRECT)) {
@@ -1702,12 +1766,127 @@
}
if ((error == 0 || uio->uio_resid != orig_resid) &&
- (vp->v_mount->mnt_flag & MNT_NOATIME) == 0)
+ (vp->v_mount->mnt_flag & (MNT_NOATIME | MNT_RDONLY)) == 0)
ip->i_flag |= IN_ACCESS;
return (error);
}
+static int
+ext2_ioctl(struct vop_ioctl_args *ap)
+{
+
+ switch (ap->a_command) {
+ case FIOSEEKDATA:
+ case FIOSEEKHOLE:
+ return (vn_bmap_seekhole(ap->a_vp, ap->a_command,
+ (off_t *)ap->a_data, ap->a_cred));
+ default:
+ return (ENOTTY);
+ }
+}
+
/*
+ * this function handles ext4 extents block mapping
+ */
+static int
+ext4_ext_read(struct vop_read_args *ap)
+{
+ struct vnode *vp;
+ struct inode *ip;
+ struct uio *uio;
+ struct m_ext2fs *fs;
+ struct buf *bp;
+ struct ext4_extent nex, *ep;
+ struct ext4_extent_path path;
+ daddr_t lbn, newblk;
+ off_t bytesinfile;
+ int cache_type;
+ ssize_t orig_resid;
+ int error;
+ long size, xfersize, blkoffset;
+
+ vp = ap->a_vp;
+ ip = VTOI(vp);
+ uio = ap->a_uio;
+ memset(&path, 0, sizeof(path));
+
+ orig_resid = uio->uio_resid;
+ KASSERT(orig_resid >= 0, ("%s: uio->uio_resid < 0", __func__));
+ if (orig_resid == 0)
+ return (0);
+ KASSERT(uio->uio_offset >= 0, ("%s: uio->uio_offset < 0", __func__));
+ fs = ip->i_e2fs;
+ if (uio->uio_offset < ip->i_size && uio->uio_offset >= fs->e2fs_maxfilesize)
+ return (EOVERFLOW);
+
+ while (uio->uio_resid > 0) {
+ if ((bytesinfile = ip->i_size - uio->uio_offset) <= 0)
+ break;
+ lbn = lblkno(fs, uio->uio_offset);
+ size = blksize(fs, ip, lbn);
+ blkoffset = blkoff(fs, uio->uio_offset);
+
+ xfersize = fs->e2fs_fsize - blkoffset;
+ xfersize = MIN(xfersize, uio->uio_resid);
+ xfersize = MIN(xfersize, bytesinfile);
+
+ /* get block from ext4 extent cache */
+ cache_type = ext4_ext_in_cache(ip, lbn, &nex);
+ switch (cache_type) {
+ case EXT4_EXT_CACHE_NO:
+ ext4_ext_find_extent(fs, ip, lbn, &path);
+ ep = path.ep_ext;
+ if (ep == NULL)
+ return (EIO);
+
+ ext4_ext_put_cache(ip, ep, EXT4_EXT_CACHE_IN);
+
+ newblk = lbn - ep->e_blk + (ep->e_start_lo |
+ (daddr_t)ep->e_start_hi << 32);
+
+ if (path.ep_bp != NULL) {
+ brelse(path.ep_bp);
+ path.ep_bp = NULL;
+ }
+ break;
+
+ case EXT4_EXT_CACHE_GAP:
+ /* block has not been allocated yet */
+ return (0);
+
+ case EXT4_EXT_CACHE_IN:
+ newblk = lbn - nex.e_blk + (nex.e_start_lo |
+ (daddr_t)nex.e_start_hi << 32);
+ break;
+
+ default:
+ panic("%s: invalid cache type", __func__);
+ }
+
+ error = bread(ip->i_devvp, fsbtodb(fs, newblk), size, NOCRED, &bp);
+ if (error) {
+ brelse(bp);
+ return (error);
+ }
+
+ size -= bp->b_resid;
+ if (size < xfersize) {
+ if (size == 0) {
+ bqrelse(bp);
+ break;
+ }
+ xfersize = size;
+ }
+ error = uiomove(bp->b_data + blkoffset, (int)xfersize, uio);
+ bqrelse(bp);
+ if (error)
+ return (error);
+ }
+
+ return (0);
+}
+
+/*
* Vnode op for writing.
*/
static int
@@ -1746,7 +1925,7 @@
case VDIR:
/* XXX differs from ffs -- this is called from ext2_mkdir(). */
if ((ioflag & IO_SYNC) == 0)
- panic("ext2_write: nonsync dir write");
+ panic("ext2_write: nonsync dir write");
break;
default:
panic("ext2_write: type %p %d (%jd,%jd)", (void *)vp,
@@ -1784,10 +1963,10 @@
if (uio->uio_offset + xfersize > ip->i_size)
vnode_pager_setsize(vp, uio->uio_offset + xfersize);
- /*
+ /*
* We must perform a read-before-write if the transfer size
* does not cover the entire buffer.
- */
+ */
if (fs->e2fs_bsize > xfersize)
flags |= BA_CLRBUF;
else
@@ -1797,16 +1976,7 @@
if (error != 0)
break;
- /*
- * If the buffer is not valid and we did not clear garbage
- * out above, we have to do so here even though the write
- * covers the entire buffer in order to avoid a mmap()/write
- * race where another process may see the garbage prior to
- * the uiomove() for a write replacing it.
- */
- if ((bp->b_flags & B_CACHE) == 0 && fs->e2fs_bsize <= xfersize)
- vfs_bio_clrbuf(bp);
- if ((ioflag & (IO_SYNC|IO_INVAL)) == (IO_SYNC|IO_INVAL))
+ if ((ioflag & (IO_SYNC | IO_INVAL)) == (IO_SYNC | IO_INVAL))
bp->b_flags |= B_NOCACHE;
if (uio->uio_offset + xfersize > ip->i_size)
ip->i_size = uio->uio_offset + xfersize;
@@ -1816,6 +1986,26 @@
error =
uiomove((char *)bp->b_data + blkoffset, (int)xfersize, uio);
+ /*
+ * If the buffer is not already filled and we encounter an
+ * error while trying to fill it, we have to clear out any
+ * garbage data from the pages instantiated for the buffer.
+ * If we do not, a failed uiomove() during a write can leave
+ * the prior contents of the pages exposed to a userland mmap.
+ *
+ * Note that we need only clear buffers with a transfer size
+ * equal to the block size because buffers with a shorter
+ * transfer size were cleared above by the call to ext2_balloc()
+ * with the BA_CLRBUF flag set.
+ *
+ * If the source region for uiomove identically mmaps the
+ * buffer, uiomove() performed the NOP copy, and the buffer
+ * content remains valid because the page fault handler
+ * validated the pages.
+ */
+ if (error != 0 && (bp->b_flags & B_CACHE) == 0 &&
+ fs->e2fs_bsize == xfersize)
+ vfs_bio_clrbuf(bp);
if (ioflag & (IO_VMIO|IO_DIRECT)) {
bp->b_flags |= B_RELBUF;
}
@@ -1830,7 +2020,7 @@
if (ioflag & IO_SYNC) {
(void)bwrite(bp);
} else if (vm_page_count_severe() ||
- buf_dirty_count_severe() ||
+ buf_dirty_count_severe() ||
(ioflag & IO_ASYNC)) {
bp->b_flags |= B_CLUSTEROK;
bawrite(bp);
@@ -1837,7 +2027,7 @@
} else if (xfersize + blkoffset == fs->e2fs_fsize) {
if ((vp->v_mount->mnt_flag & MNT_NOCLUSTERW) == 0) {
bp->b_flags |= B_CLUSTEROK;
- cluster_write(vp, bp, ip->i_size, seqcount);
+ cluster_write(vp, bp, ip->i_size, seqcount, 0);
} else {
bawrite(bp);
}
@@ -1870,9 +2060,49 @@
}
}
if (uio->uio_resid != resid) {
- ip->i_flag |= IN_CHANGE | IN_UPDATE;
- if (ioflag & IO_SYNC)
- error = ext2_update(vp, 1);
- }
+ ip->i_flag |= IN_CHANGE | IN_UPDATE;
+ if (ioflag & IO_SYNC)
+ error = ext2_update(vp, 1);
+ }
return (error);
}
+
+/*
+ * get page routine
+ */
+static int
+ext2_getpages(struct vop_getpages_args *ap)
+{
+ int i;
+ vm_page_t mreq;
+ int pcount;
+
+ pcount = round_page(ap->a_count) / PAGE_SIZE;
+ mreq = ap->a_m[ap->a_reqpage];
+
+ /*
+ * if ANY DEV_BSIZE blocks are valid on a large filesystem block,
+ * then the entire page is valid. Since the page may be mapped,
+ * user programs might reference data beyond the actual end of file
+ * occuring within the page. We have to zero that data.
+ */
+ VM_OBJECT_WLOCK(mreq->object);
+ if (mreq->valid) {
+ if (mreq->valid != VM_PAGE_BITS_ALL)
+ vm_page_zero_invalid(mreq, TRUE);
+ for (i = 0; i < pcount; i++) {
+ if (i != ap->a_reqpage) {
+ vm_page_lock(ap->a_m[i]);
+ vm_page_free(ap->a_m[i]);
+ vm_page_unlock(ap->a_m[i]);
+ }
+ }
+ VM_OBJECT_WUNLOCK(mreq->object);
+ return VM_PAGER_OK;
+ }
+ VM_OBJECT_WUNLOCK(mreq->object);
+
+ return vnode_pager_generic_getpages(ap->a_vp, ap->a_m,
+ ap->a_count,
+ ap->a_reqpage);
+}
Modified: trunk/sys/fs/ext2fs/ext2fs.h
===================================================================
--- trunk/sys/fs/ext2fs/ext2fs.h 2018-05-27 22:18:36 UTC (rev 10027)
+++ trunk/sys/fs/ext2fs/ext2fs.h 2018-05-27 22:19:26 UTC (rev 10028)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*-
* modified for EXT2FS support in Lites 1.1
*
@@ -4,7 +5,7 @@
* Aug 1995, Godmar Back (gback at cs.utah.edu)
* University of Utah, Department of Computer Science
*
- * $MidnightBSD$
+ * $FreeBSD: stable/10/sys/fs/ext2fs/ext2fs.h 320839 2017-07-09 15:09:15Z pfg $
*/
/*-
* Copyright (c) 2009 Aditya Sarawgi
@@ -31,47 +32,15 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- *
+ *
*/
#ifndef _FS_EXT2FS_EXT2FS_H_
-#define _FS_EXT2FS_EXT2FS_H_
+#define _FS_EXT2FS_EXT2FS_H_
#include <sys/types.h>
/*
- * Maximal count of links to a file
- */
-#define EXT2_LINK_MAX 32000
-
-/*
- * A summary of contiguous blocks of various sizes is maintained
- * in each cylinder group. Normally this is set by the initial
- * value of fs_maxcontig.
- *
- * XXX:FS_MAXCONTIG is set to 16 to conserve space. Here we set
- * EXT2_MAXCONTIG to 32 for better performance.
- */
-#define EXT2_MAXCONTIG 32
-
-/*
- * Constants relative to the data blocks
- */
-#define EXT2_NDIR_BLOCKS 12
-#define EXT2_IND_BLOCK EXT2_NDIR_BLOCKS
-#define EXT2_DIND_BLOCK (EXT2_IND_BLOCK + 1)
-#define EXT2_TIND_BLOCK (EXT2_DIND_BLOCK + 1)
-#define EXT2_N_BLOCKS (EXT2_TIND_BLOCK + 1)
-#define EXT2_MAXSYMLINKLEN (EXT2_N_BLOCKS * sizeof(uint32_t))
-
-/*
- * The path name on which the file system is mounted is maintained
- * in fs_fsmnt. MAXMNTLEN defines the amount of space allocated in
- * the super block for this name.
- */
-#define MAXMNTLEN 512
-
-/*
* Super block for an ext2fs file system.
*/
struct ext2fs {
@@ -104,12 +73,12 @@
uint32_t e2fs_first_ino; /* first non-reserved inode */
uint16_t e2fs_inode_size; /* size of inode structure */
uint16_t e2fs_block_group_nr; /* block grp number of this sblk*/
- uint32_t e2fs_features_compat; /* compatible feature set */
+ uint32_t e2fs_features_compat; /* compatible feature set */
uint32_t e2fs_features_incompat; /* incompatible feature set */
uint32_t e2fs_features_rocompat; /* RO-compatible feature set */
uint8_t e2fs_uuid[16]; /* 128-bit uuid for volume */
char e2fs_vname[16]; /* volume name */
- char e2fs_fsmnt[64]; /* name mounted on */
+ char e2fs_fsmnt[64]; /* name mounted on */
uint32_t e2fs_algo; /* For compression */
uint8_t e2fs_prealloc; /* # of blocks for old prealloc */
uint8_t e2fs_dir_prealloc; /* # of blocks for old prealloc dirs */
@@ -120,27 +89,62 @@
uint32_t e3fs_last_orphan; /* start of list of inodes to delete */
uint32_t e3fs_hash_seed[4]; /* HTREE hash seed */
char e3fs_def_hash_version; /* Default hash version to use */
- char e3fs_reserved_char_pad;
+ char e3fs_jnl_backup_type;
+ uint16_t e3fs_desc_size; /* size of group descriptor */
uint32_t e3fs_default_mount_opts;
uint32_t e3fs_first_meta_bg; /* First metablock block group */
- uint32_t e3fs_mkfs_time; /* when the fs was created */
- uint32_t e3fs_jnl_blks[17]; /* backup of the journal inode */
- uint32_t e4fs_bcount_hi; /* block count */
- uint32_t e4fs_rbcount_hi; /* reserved blocks count */
- uint32_t e4fs_fbcount_hi; /* free blocks count */
- uint16_t e4fs_min_extra_isize;/* all inodes have at least some bytes */
+ uint32_t e3fs_mkfs_time; /* when the fs was created */
+ uint32_t e3fs_jnl_blks[17]; /* backup of the journal inode */
+ uint32_t e4fs_bcount_hi; /* high bits of blocks count */
+ uint32_t e4fs_rbcount_hi; /* high bits of reserved blocks count */
+ uint32_t e4fs_fbcount_hi; /* high bits of free blocks count */
+ uint16_t e4fs_min_extra_isize; /* all inodes have at least some bytes */
uint16_t e4fs_want_extra_isize; /* inodes must reserve some bytes */
- uint32_t e4fs_flags; /* miscellaneous flags */
- uint16_t e4fs_raid_stride; /* RAID stride */
- uint16_t e4fs_mmpintv; /* number of seconds to wait in MMP checking */
- uint64_t e4fs_mmpblk; /* block for multi-mount protection */
- uint32_t e4fs_raid_stripe_wid;/* blocks on all data disks (N * stride) */
- uint8_t e4fs_log_gpf; /* FLEX_BG group size */
- uint8_t e4fs_char_pad2;
- uint16_t e4fs_pad;
- uint32_t reserved2[162]; /* Padding to the end of the block */
+ uint32_t e4fs_flags; /* miscellaneous flags */
+ uint16_t e4fs_raid_stride; /* RAID stride */
+ uint16_t e4fs_mmpintv; /* number of seconds to wait in MMP checking */
+ uint64_t e4fs_mmpblk; /* block for multi-mount protection */
+ uint32_t e4fs_raid_stripe_wid; /* blocks on all data disks (N * stride) */
+ uint8_t e4fs_log_gpf; /* FLEX_BG group size */
+ uint8_t e4fs_chksum_type; /* metadata checksum algorithm used */
+ uint8_t e4fs_encrypt; /* versioning level for encryption */
+ uint8_t e4fs_reserved_pad;
+ uint64_t e4fs_kbytes_written; /* number of lifetime kilobytes */
+ uint32_t e4fs_snapinum; /* inode number of active snapshot */
+ uint32_t e4fs_snapid; /* sequential ID of active snapshot */
+ uint64_t e4fs_snaprbcount; /* reserved blocks for active snapshot */
+ uint32_t e4fs_snaplist; /* inode number for on-disk snapshot */
+ uint32_t e4fs_errcount; /* number of file system errors */
+ uint32_t e4fs_first_errtime; /* first time an error happened */
+ uint32_t e4fs_first_errino; /* inode involved in first error */
+ uint64_t e4fs_first_errblk; /* block involved of first error */
+ uint8_t e4fs_first_errfunc[32]; /* function where error happened */
+ uint32_t e4fs_first_errline; /* line number where error happened */
+ uint32_t e4fs_last_errtime; /* most recent time of an error */
+ uint32_t e4fs_last_errino; /* inode involved in last error */
+ uint32_t e4fs_last_errline; /* line number where error happened */
+ uint64_t e4fs_last_errblk; /* block involved of last error */
+ uint8_t e4fs_last_errfunc[32]; /* function where error happened */
+ uint8_t e4fs_mount_opts[64];
+ uint32_t e4fs_usrquota_inum; /* inode for tracking user quota */
+ uint32_t e4fs_grpquota_inum; /* inode for tracking group quota */
+ uint32_t e4fs_overhead_clusters; /* overhead blocks/clusters */
+ uint32_t e4fs_backup_bgs[2]; /* groups with sparse_super2 SBs */
+ uint8_t e4fs_encrypt_algos[4]; /* encryption algorithms in use */
+ uint8_t e4fs_encrypt_pw_salt[16]; /* salt used for string2key */
+ uint32_t e4fs_lpf_ino; /* location of the lost+found inode */
+ uint32_t e4fs_proj_quota_inum; /* inode for tracking project quota */
+ uint32_t e4fs_chksum_seed; /* checksum seed */
+ uint32_t e4fs_reserved[98]; /* padding to the end of the block */
+ uint32_t e4fs_sbchksum; /* superblock checksum */
};
+/*
+ * The path name on which the file system is mounted is maintained
+ * in fs_fsmnt. MAXMNTLEN defines the amount of space allocated in
+ * the super block for this name.
+ */
+#define MAXMNTLEN 512
/*
* In-Memory Superblock
@@ -149,77 +153,89 @@
struct m_ext2fs {
struct ext2fs * e2fs;
char e2fs_fsmnt[MAXMNTLEN];/* name mounted on */
- char e2fs_ronly; /* mounted read-only flag */
- char e2fs_fmod; /* super block modified flag */
- uint32_t e2fs_bsize; /* Block size */
- uint32_t e2fs_bshift; /* calc of logical block no */
- int32_t e2fs_bpg; /* Number of blocks per group */
- int64_t e2fs_qbmask; /* = s_blocksize -1 */
- uint32_t e2fs_fsbtodb; /* Shift to get disk block */
+ char e2fs_ronly; /* mounted read-only flag */
+ char e2fs_fmod; /* super block modified flag */
+ uint32_t e2fs_bsize; /* Block size */
+ uint32_t e2fs_bshift; /* calc of logical block no */
+ uint32_t e2fs_bpg; /* Number of blocks per group */
+ int64_t e2fs_qbmask; /* = s_blocksize -1 */
+ uint32_t e2fs_fsbtodb; /* Shift to get disk block */
uint32_t e2fs_ipg; /* Number of inodes per group */
uint32_t e2fs_ipb; /* Number of inodes per block */
- uint32_t e2fs_itpg; /* Number of inode table per group */
- uint32_t e2fs_fsize; /* Size of fragments per block */
+ uint32_t e2fs_itpg; /* Number of inode table per group */
+ uint32_t e2fs_fsize; /* Size of fragments per block */
uint32_t e2fs_fpb; /* Number of fragments per block */
uint32_t e2fs_fpg; /* Number of fragments per group */
- uint32_t e2fs_gdbcount; /* Number of group descriptors */
- uint32_t e2fs_gcount; /* Number of groups */
- int32_t e2fs_isize; /* Size of inode */
+ uint32_t e2fs_gdbcount; /* Number of group descriptors */
+ uint32_t e2fs_gcount; /* Number of groups */
+ uint32_t e2fs_isize; /* Size of inode */
uint32_t e2fs_total_dir; /* Total number of directories */
uint8_t *e2fs_contigdirs; /* (u) # of contig. allocated dirs */
- char e2fs_wasvalid; /* valid at mount time */
+ char e2fs_wasvalid; /* valid at mount time */
off_t e2fs_maxfilesize;
struct ext2_gd *e2fs_gd; /* Group Descriptors */
int32_t e2fs_contigsumsize; /* size of cluster summary array */
int32_t *e2fs_maxcluster; /* max cluster in each cyl group */
struct csum *e2fs_clustersum; /* cluster summary in each cyl group */
+ int32_t e2fs_uhash; /* 3 if hash should be signed, 0 if not */
};
-/*
- * The second extended file system version
- */
-#define E2FS_DATE "95/08/09"
-#define E2FS_VERSION "0.5b"
+/* cluster summary information */
+struct csum {
+ int8_t cs_init; /* cluster summary has been initialized */
+ int32_t *cs_sum; /* cluster summary array */
+};
+
/*
* The second extended file system magic number
*/
-#define E2FS_MAGIC 0xEF53
+#define E2FS_MAGIC 0xEF53
/*
* Revision levels
*/
-#define E2FS_REV0 0 /* The good old (original) format */
-#define E2FS_REV1 1 /* V2 format w/ dynamic inode sizes */
+#define E2FS_REV0 0 /* The good old (original) format */
+#define E2FS_REV1 1 /* V2 format w/ dynamic inode sizes */
-#define E2FS_CURRENT_REV E2FS_REV0
-#define E2FS_MAX_SUPP_REV E2FS_REV1
+#define E2FS_REV0_INODE_SIZE 128
-#define E2FS_REV0_INODE_SIZE 128
-
/*
* compatible/incompatible features
*/
-#define EXT2F_COMPAT_PREALLOC 0x0001
-#define EXT2F_COMPAT_HASJOURNAL 0x0004
-#define EXT2F_COMPAT_RESIZE 0x0010
-#define EXT2F_COMPAT_DIRHASHINDEX 0x0020
+#define EXT2F_COMPAT_PREALLOC 0x0001
+#define EXT2F_COMPAT_HASJOURNAL 0x0004
+#define EXT2F_COMPAT_RESIZE 0x0010
+#define EXT2F_COMPAT_DIRHASHINDEX 0x0020
+#define EXT2F_COMPAT_SPARSESUPER2 0x0200
-#define EXT2F_ROCOMPAT_SPARSESUPER 0x0001
-#define EXT2F_ROCOMPAT_LARGEFILE 0x0002
-#define EXT2F_ROCOMPAT_BTREE_DIR 0x0004
-#define EXT2F_ROCOMPAT_HUGE_FILE 0x0008
-#define EXT2F_ROCOMPAT_GDT_CSUM 0x0010
-#define EXT2F_ROCOMPAT_DIR_NLINK 0x0020
-#define EXT2F_ROCOMPAT_EXTRA_ISIZE 0x0040
+#define EXT2F_ROCOMPAT_SPARSESUPER 0x0001
+#define EXT2F_ROCOMPAT_LARGEFILE 0x0002
+#define EXT2F_ROCOMPAT_BTREE_DIR 0x0004
+#define EXT2F_ROCOMPAT_HUGE_FILE 0x0008
+#define EXT2F_ROCOMPAT_GDT_CSUM 0x0010
+#define EXT2F_ROCOMPAT_DIR_NLINK 0x0020
+#define EXT2F_ROCOMPAT_EXTRA_ISIZE 0x0040
+#define EXT2F_ROCOMPAT_QUOTA 0x0100
+#define EXT2F_ROCOMPAT_BIGALLOC 0x0200
+#define EXT2F_ROCOMPAT_METADATA_CKSUM 0x0400
+#define EXT2F_ROCOMPAT_READONLY 0x1000
+#define EXT2F_ROCOMPAT_PROJECT 0x2000
-#define EXT2F_INCOMPAT_COMP 0x0001
-#define EXT2F_INCOMPAT_FTYPE 0x0002
-#define EXT2F_INCOMPAT_META_BG 0x0010
-#define EXT2F_INCOMPAT_EXTENTS 0x0040
-#define EXT2F_INCOMPAT_64BIT 0x0080
-#define EXT2F_INCOMPAT_MMP 0x0100
-#define EXT2F_INCOMPAT_FLEX_BG 0x0200
+#define EXT2F_INCOMPAT_COMP 0x0001
+#define EXT2F_INCOMPAT_FTYPE 0x0002
+#define EXT2F_INCOMPAT_RECOVER 0x0004
+#define EXT2F_INCOMPAT_META_BG 0x0010
+#define EXT2F_INCOMPAT_EXTENTS 0x0040
+#define EXT2F_INCOMPAT_64BIT 0x0080
+#define EXT2F_INCOMPAT_MMP 0x0100
+#define EXT2F_INCOMPAT_FLEX_BG 0x0200
+#define EXT2F_INCOMPAT_EA_INODE 0x0400
+#define EXT2F_INCOMPAT_DIRDATA 0x1000
+#define EXT2F_INCOMPAT_CSUM_SEED 0x2000
+#define EXT2F_INCOMPAT_LARGEDIR 0x4000
+#define EXT2F_INCOMPAT_INLINE_DATA 0x8000
+#define EXT2F_INCOMPAT_ENCRYPT 0x10000
/*
* Features supported in this implementation
@@ -227,52 +243,57 @@
* We support the following REV1 features:
* - EXT2F_ROCOMPAT_SPARSESUPER
* - EXT2F_ROCOMPAT_LARGEFILE
+ * - EXT2F_ROCOMPAT_EXTRA_ISIZE
* - EXT2F_INCOMPAT_FTYPE
+ *
+ * We partially support (read-only) the following EXT4 features:
+ * - EXT2F_ROCOMPAT_HUGE_FILE
+ * - EXT2F_INCOMPAT_EXTENTS
+ *
+ * We do not support these EXT4 features but they are irrelevant
+ * for read-only support:
+ * - EXT2F_INCOMPAT_RECOVER
+ * - EXT2F_INCOMPAT_FLEX_BG
+ * - EXT2F_INCOMPAT_META_BG
*/
-#define EXT2F_COMPAT_SUPP 0x0000
-#define EXT2F_ROCOMPAT_SUPP (EXT2F_ROCOMPAT_SPARSESUPER | \
+#define EXT2F_COMPAT_SUPP EXT2F_COMPAT_DIRHASHINDEX
+#define EXT2F_ROCOMPAT_SUPP (EXT2F_ROCOMPAT_SPARSESUPER | \
EXT2F_ROCOMPAT_LARGEFILE | \
+ EXT2F_ROCOMPAT_HUGE_FILE | \
EXT2F_ROCOMPAT_EXTRA_ISIZE)
-#define EXT2F_INCOMPAT_SUPP EXT2F_INCOMPAT_FTYPE
+#define EXT2F_INCOMPAT_SUPP EXT2F_INCOMPAT_FTYPE
+#define EXT4F_RO_INCOMPAT_SUPP (EXT2F_INCOMPAT_EXTENTS | \
+ EXT2F_INCOMPAT_RECOVER | \
+ EXT2F_INCOMPAT_FLEX_BG | \
+ EXT2F_INCOMPAT_META_BG )
/* Assume that user mode programs are passing in an ext2fs superblock, not
* a kernel struct super_block. This will allow us to call the feature-test
* macros from user land. */
-#define EXT2_SB(sb) (sb)
+#define EXT2_SB(sb) (sb)
/*
* Feature set definitions
*/
-#define EXT2_HAS_COMPAT_FEATURE(sb,mask) \
+#define EXT2_HAS_COMPAT_FEATURE(sb,mask) \
( EXT2_SB(sb)->e2fs->e2fs_features_compat & htole32(mask) )
-#define EXT2_HAS_RO_COMPAT_FEATURE(sb,mask) \
+#define EXT2_HAS_RO_COMPAT_FEATURE(sb,mask) \
( EXT2_SB(sb)->e2fs->e2fs_features_rocompat & htole32(mask) )
-#define EXT2_HAS_INCOMPAT_FEATURE(sb,mask) \
+#define EXT2_HAS_INCOMPAT_FEATURE(sb,mask) \
( EXT2_SB(sb)->e2fs->e2fs_features_incompat & htole32(mask) )
/*
- * Definitions of behavior on errors
+ * File clean flags
*/
-#define E2FS_BEH_CONTINUE 1 /* continue operation */
-#define E2FS_BEH_READONLY 2 /* remount fs read only */
-#define E2FS_BEH_PANIC 3 /* cause panic */
-#define E2FS_BEH_DEFAULT E2FS_BEH_CONTINUE
+#define E2FS_ISCLEAN 0x0001 /* Unmounted cleanly */
+#define E2FS_ERRORS 0x0002 /* Errors detected */
/*
- * OS identification
+ * Filesystem miscellaneous flags
*/
-#define E2FS_OS_LINUX 0
-#define E2FS_OS_HURD 1
-#define E2FS_OS_MASIX 2
-#define E2FS_OS_FREEBSD 3
-#define E2FS_OS_LITES 4
+#define E2FS_SIGNED_HASH 0x0001
+#define E2FS_UNSIGNED_HASH 0x0002
-/*
- * File clean flags
- */
-#define E2FS_ISCLEAN 0x0001 /* Unmounted cleanly */
-#define E2FS_ERRORS 0x0002 /* Errors detected */
-
/* ext2 file system block group descriptor */
struct ext2_gd {
@@ -282,49 +303,43 @@
uint16_t ext2bgd_nbfree; /* number of free blocks */
uint16_t ext2bgd_nifree; /* number of free inodes */
uint16_t ext2bgd_ndirs; /* number of directories */
- uint16_t ext2bgd_flags; /* block group flags */
- uint32_t ext2bgd_x_bitmap; /* snapshot exclusion bitmap loc. */
- uint16_t ext2bgd_b_bmap_csum; /* block bitmap checksum */
- uint16_t ext2bgd_i_bmap_csum; /* inode bitmap checksum */
- uint16_t ext2bgd_i_unused; /* unused inode count */
- uint16_t ext2bgd_csum; /* group descriptor checksum */
+ uint16_t ext4bgd_flags; /* block group flags */
+ uint32_t ext4bgd_x_bitmap; /* snapshot exclusion bitmap loc. */
+ uint16_t ext4bgd_b_bmap_csum; /* block bitmap checksum */
+ uint16_t ext4bgd_i_bmap_csum; /* inode bitmap checksum */
+ uint16_t ext4bgd_i_unused; /* unused inode count */
+ uint16_t ext4bgd_csum; /* group descriptor checksum */
};
-/* cluster summary information */
-struct csum {
- int8_t cs_init; /* cluster summary has been initialized */
- int32_t *cs_sum; /* cluster summary array */
-};
-
/* EXT2FS metadatas are stored in little-endian byte order. These macros
* helps reading these metadatas
*/
-#define e2fs_cgload(old, new, size) memcpy((new), (old), (size));
-#define e2fs_cgsave(old, new, size) memcpy((new), (old), (size));
+#define e2fs_cgload(old, new, size) memcpy((new), (old), (size));
+#define e2fs_cgsave(old, new, size) memcpy((new), (old), (size));
/*
* Macro-instructions used to manage several block sizes
*/
#define EXT2_MAX_BLOCK_SIZE 4096
-#define EXT2_MIN_BLOCK_LOG_SIZE 10
-#define EXT2_BLOCK_SIZE(s) ((s)->e2fs_bsize)
+#define EXT2_MIN_BLOCK_LOG_SIZE 10
+#define EXT2_BLOCK_SIZE(s) ((s)->e2fs_bsize)
#define EXT2_ADDR_PER_BLOCK(s) (EXT2_BLOCK_SIZE(s) / sizeof(uint32_t))
-#define EXT2_INODE_SIZE(s) (EXT2_SB(s)->e2fs_isize)
+#define EXT2_INODE_SIZE(s) (EXT2_SB(s)->e2fs_isize)
/*
* Macro-instructions used to manage fragments
*/
-#define EXT2_MIN_FRAG_SIZE 1024
+#define EXT2_MIN_FRAG_SIZE 1024
#define EXT2_MAX_FRAG_SIZE 4096
-#define EXT2_MIN_FRAG_LOG_SIZE 10
-#define EXT2_FRAG_SIZE(s) (EXT2_SB(s)->e2fs_fsize)
-#define EXT2_FRAGS_PER_BLOCK(s) (EXT2_SB(s)->e2fs_fpb)
+#define EXT2_MIN_FRAG_LOG_SIZE 10
+#define EXT2_FRAG_SIZE(s) (EXT2_SB(s)->e2fs_fsize)
+#define EXT2_FRAGS_PER_BLOCK(s) (EXT2_SB(s)->e2fs_fpb)
/*
* Macro-instructions used to manage group descriptors
*/
-#define EXT2_BLOCKS_PER_GROUP(s) (EXT2_SB(s)->e2fs_bpg)
+#define EXT2_BLOCKS_PER_GROUP(s) (EXT2_SB(s)->e2fs_bpg)
#endif /* !_FS_EXT2FS_EXT2FS_H_ */
Modified: trunk/sys/fs/ext2fs/fs.h
===================================================================
--- trunk/sys/fs/ext2fs/fs.h 2018-05-27 22:18:36 UTC (rev 10027)
+++ trunk/sys/fs/ext2fs/fs.h 2018-05-27 22:19:26 UTC (rev 10028)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*-
* modified for EXT2FS support in Lites 1.1
*
@@ -33,11 +34,11 @@
* SUCH DAMAGE.
*
* @(#)fs.h 8.7 (Berkeley) 4/19/94
- * $MidnightBSD$
+ * $FreeBSD: stable/10/sys/fs/ext2fs/fs.h 311232 2017-01-04 02:43:33Z pfg $
*/
#ifndef _FS_EXT2FS_FS_H_
-#define _FS_EXT2FS_FS_H_
+#define _FS_EXT2FS_FS_H_
/*
* Each disk drive contains some number of file systems.
@@ -54,17 +55,27 @@
* The first boot and super blocks are given in absolute disk addresses.
* The byte-offset forms are preferred, as they don't imply a sector size.
*/
-#define SBSIZE 1024
-#define SBLOCK 2
+#define SBSIZE 1024
+#define SBLOCK 2
/*
* The path name on which the file system is mounted is maintained
- * in fs_fsmnt. MAXMNTLEN defines the amount of space allocated in
- * the super block for this name.
+ * in fs_fsmnt. MAXMNTLEN defines the amount of space allocated in
+ * the super block for this name.
*/
-#define MAXMNTLEN 512
+#define MAXMNTLEN 512
/*
+ * A summary of contiguous blocks of various sizes is maintained
+ * in each cylinder group. Normally this is set by the initial
+ * value of fs_maxcontig.
+ *
+ * XXX:FS_MAXCONTIG is set to 16 to conserve space. Here we set
+ * EXT2_MAXCONTIG to 32 for better performance.
+ */
+#define EXT2_MAXCONTIG 32
+
+/*
* Grigoriy Orlov <gluk at ptci.ru> has done some extensive work to fine
* tune the layout preferences for directories within a filesystem.
* His algorithm can be tuned by adjusting the following parameters
@@ -72,13 +83,13 @@
* of files per directory. These defaults are well selected for typical
* filesystems, but may need to be tuned for odd cases like filesystems
* being used for squid caches or news spools.
- * AVFPDIR is the expected number of files per directory. AVGDIRSIZE is
- * obtained by multiplying AVFPDIR and AVFILESIZ which is assumed to be
+ * AVFPDIR is the expected number of files per directory. AVGDIRSIZE is
+ * obtained by multiplying AVFPDIR and AVFILESIZ which is assumed to be
* 16384.
*/
-#define AFPDIR 64
-#define AVGDIRSIZE 1048576
+#define AFPDIR 64
+#define AVGDIRSIZE 1048576
/*
* Macros for access to superblock array structures
@@ -88,14 +99,14 @@
* Turn file system block numbers into disk block addresses.
* This maps file system blocks to device size blocks.
*/
-#define fsbtodb(fs, b) ((b) << ((fs)->e2fs_fsbtodb))
-#define dbtofsb(fs, b) ((b) >> ((fs)->e2fs_fsbtodb))
+#define fsbtodb(fs, b) ((daddr_t)(b) << (fs)->e2fs_fsbtodb)
+#define dbtofsb(fs, b) ((b) >> (fs)->e2fs_fsbtodb)
/* get group containing inode */
-#define ino_to_cg(fs, x) (((x) - 1) / (fs->e2fs_ipg))
+#define ino_to_cg(fs, x) (((x) - 1) / (fs->e2fs_ipg))
/* get block containing inode from its number x */
-#define ino_to_fsba(fs, x) \
+#define ino_to_fsba(fs, x) \
((fs)->e2fs_gd[ino_to_cg((fs), (x))].ext2bgd_i_tables + \
(((x) - 1) % (fs)->e2fs->e2fs_ipg) / (fs)->e2fs_ipb)
@@ -116,20 +127,20 @@
* quantities by using shifts and masks in place of divisions
* modulos and multiplications.
*/
-#define blkoff(fs, loc) /* calculates (loc % fs->fs_bsize) */ \
+#define blkoff(fs, loc) /* calculates (loc % fs->fs_bsize) */ \
((loc) & (fs)->e2fs_qbmask)
-#define lblktosize(fs, blk) /* calculates (blk * fs->fs_bsize) */ \
+#define lblktosize(fs, blk) /* calculates (blk * fs->fs_bsize) */ \
((blk) << (fs->e2fs_bshift))
-#define lblkno(fs, loc) /* calculates (loc / fs->fs_bsize) */ \
+#define lblkno(fs, loc) /* calculates (loc / fs->fs_bsize) */ \
((loc) >> (fs->e2fs_bshift))
/* no fragments -> logical block number equal # of frags */
-#define numfrags(fs, loc) /* calculates (loc / fs->fs_fsize) */ \
+#define numfrags(fs, loc) /* calculates (loc / fs->fs_fsize) */ \
((loc) >> (fs->e2fs_bshift))
-#define fragroundup(fs, size) /* calculates roundup(size, fs->fs_fsize) */ \
+#define fragroundup(fs, size) /* calculates roundup(size, fs->fs_fsize) */ \
roundup(size, fs->e2fs_fsize)
/* was (((size) + (fs)->fs_qfmask) & (fs)->fs_fmask) */
@@ -137,7 +148,7 @@
* Determining the size of a file block in the file system.
* easy w/o fragments
*/
-#define blksize(fs, ip, lbn) ((fs)->e2fs_fsize)
+#define blksize(fs, ip, lbn) ((fs)->e2fs_fsize)
/*
* INOPB is the number of inodes in a secondary storage block.
@@ -149,4 +160,4 @@
*/
#define NINDIR(fs) (EXT2_ADDR_PER_BLOCK(fs))
-#endif /* !_FS_EXT2FS_FS_H_ */
+#endif /* !_FS_EXT2FS_FS_H_ */
Added: trunk/sys/fs/ext2fs/htree.h
===================================================================
--- trunk/sys/fs/ext2fs/htree.h (rev 0)
+++ trunk/sys/fs/ext2fs/htree.h 2018-05-27 22:19:26 UTC (rev 10028)
@@ -0,0 +1,101 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2010, 2012 Zheng Liu <lz at freebsd.org>
+ * Copyright (c) 2012, Vyacheslav Matyushin
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: stable/10/sys/fs/ext2fs/htree.h 311232 2017-01-04 02:43:33Z pfg $
+ */
+
+#ifndef _FS_EXT2FS_HTREE_H_
+#define _FS_EXT2FS_HTREE_H_
+
+/* EXT3 HTree directory indexing */
+
+#define EXT2_HTREE_LEGACY 0
+#define EXT2_HTREE_HALF_MD4 1
+#define EXT2_HTREE_TEA 2
+#define EXT2_HTREE_LEGACY_UNSIGNED 3
+#define EXT2_HTREE_HALF_MD4_UNSIGNED 4
+#define EXT2_HTREE_TEA_UNSIGNED 5
+
+#define EXT2_HTREE_EOF 0x7FFFFFFF
+
+struct ext2fs_fake_direct {
+ uint32_t e2d_ino; /* inode number of entry */
+ uint16_t e2d_reclen; /* length of this record */
+ uint8_t e2d_namlen; /* length of string in d_name */
+ uint8_t e2d_type; /* file type */
+};
+
+struct ext2fs_htree_count {
+ uint16_t h_entries_max;
+ uint16_t h_entries_num;
+};
+
+struct ext2fs_htree_entry {
+ uint32_t h_hash;
+ uint32_t h_blk;
+};
+
+struct ext2fs_htree_root_info {
+ uint32_t h_reserved1;
+ uint8_t h_hash_version;
+ uint8_t h_info_len;
+ uint8_t h_ind_levels;
+ uint8_t h_reserved2;
+};
+
+struct ext2fs_htree_root {
+ struct ext2fs_fake_direct h_dot;
+ char h_dot_name[4];
+ struct ext2fs_fake_direct h_dotdot;
+ char h_dotdot_name[4];
+ struct ext2fs_htree_root_info h_info;
+ struct ext2fs_htree_entry h_entries[0];
+};
+
+struct ext2fs_htree_node {
+ struct ext2fs_fake_direct h_fake_dirent;
+ struct ext2fs_htree_entry h_entries[0];
+};
+
+struct ext2fs_htree_lookup_level {
+ struct buf *h_bp;
+ struct ext2fs_htree_entry *h_entries;
+ struct ext2fs_htree_entry *h_entry;
+};
+
+struct ext2fs_htree_lookup_info {
+ struct ext2fs_htree_lookup_level h_levels[2];
+ uint32_t h_levels_num;
+};
+
+struct ext2fs_htree_sort_entry {
+ uint16_t h_offset;
+ uint16_t h_size;
+ uint32_t h_hash;
+};
+
+#endif /* !_FS_EXT2FS_HTREE_H_ */
Property changes on: trunk/sys/fs/ext2fs/htree.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Modified: trunk/sys/fs/ext2fs/inode.h
===================================================================
--- trunk/sys/fs/ext2fs/inode.h 2018-05-27 22:18:36 UTC (rev 10027)
+++ trunk/sys/fs/ext2fs/inode.h 2018-05-27 22:19:26 UTC (rev 10028)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*-
* Copyright (c) 1982, 1989, 1993
* The Regents of the University of California. All rights reserved.
@@ -32,17 +33,18 @@
* SUCH DAMAGE.
*
* @(#)inode.h 8.9 (Berkeley) 5/14/95
- * $MidnightBSD$
+ * $FreeBSD: stable/10/sys/fs/ext2fs/inode.h 311232 2017-01-04 02:43:33Z pfg $
*/
#ifndef _FS_EXT2FS_INODE_H_
#define _FS_EXT2FS_INODE_H_
+#include <sys/param.h>
#include <sys/lock.h>
+#include <sys/mutex.h>
#include <sys/queue.h>
-#define NDADDR 12 /* Direct addresses in inode. */
-#define NIADDR 3 /* Indirect addresses in inode. */
+#include <fs/ext2fs/ext2_extents.h>
/*
* This must agree with the definition in <ufs/ufs/dir.h>.
@@ -49,7 +51,17 @@
*/
#define doff_t int32_t
+#define NDADDR 12 /* Direct addresses in inode. */
+#define NIADDR 3 /* Indirect addresses in inode. */
+
/*
+ * The size of physical and logical block numbers in EXT2FS.
+ */
+typedef uint32_t e2fs_daddr_t;
+typedef int64_t e2fs_lbn_t;
+typedef int64_t e4fs_daddr_t;
+
+/*
* The inode is used to describe each active (or recently active) file in the
* EXT2FS filesystem. It is composed of two types of information. The first
* part is the information that is needed only while the file is active (such
@@ -81,7 +93,10 @@
/* Fields from struct dinode in UFS. */
uint16_t i_mode; /* IFMT, permissions; see below. */
int16_t i_nlink; /* File link count. */
+ uint32_t i_uid; /* File owner. */
+ uint32_t i_gid; /* File group. */
uint64_t i_size; /* File byte count. */
+ uint64_t i_blocks; /* Blocks actually held. */
int32_t i_atime; /* Last access time. */
int32_t i_mtime; /* Last modified time. */
int32_t i_ctime; /* Last inode change time. */
@@ -90,13 +105,12 @@
int32_t i_atimensec; /* Last access time. */
int32_t i_ctimensec; /* Last inode change time. */
int32_t i_birthnsec; /* Inode creation time. */
+ uint32_t i_gen; /* Generation number. */
+ uint32_t i_flags; /* Status flags (chflags). */
uint32_t i_db[NDADDR]; /* Direct disk blocks. */
uint32_t i_ib[NIADDR]; /* Indirect disk blocks. */
- uint32_t i_flags; /* Status flags (chflags). */
- uint32_t i_blocks; /* Blocks actually held. */
- uint32_t i_gen; /* Generation number. */
- uint32_t i_uid; /* File owner. */
- uint32_t i_gid; /* File group. */
+
+ struct ext4_extent_cache i_ext_cache; /* cache for ext4 extent */
};
/*
@@ -137,9 +151,16 @@
#define IN_HASHED 0x0020 /* Inode is on hash list */
#define IN_LAZYMOD 0x0040 /* Modified, but don't write yet. */
#define IN_SPACECOUNTED 0x0080 /* Blocks to be freed in free count. */
-#define IN_LAZYACCESS 0x0100 /* Process IN_ACCESS after the
+#define IN_LAZYACCESS 0x0100 /* Process IN_ACCESS after the
suspension finished */
+/*
+ * These are translation flags for some attributes that Ext4
+ * passes as inode flags but that we cannot pass directly.
+ */
+#define IN_E3INDEX 0x010000
+#define IN_E4EXTENTS 0x020000
+
#define i_devvp i_ump->um_devvp
#ifdef _KERNEL
@@ -148,7 +169,7 @@
* ext2_getlbns and used by truncate and bmap code.
*/
struct indir {
- int32_t in_lbn; /* Logical block number. */
+ e2fs_lbn_t in_lbn; /* Logical block number. */
int in_off; /* Offset in buffer. */
};
@@ -158,11 +179,11 @@
/* This overlays the fid structure (see mount.h). */
struct ufid {
- uint16_t ufid_len; /* Length of structure. */
- uint16_t ufid_pad; /* Force 32-bit alignment. */
- ino_t ufid_ino; /* File number (ino). */
- uint32_t ufid_gen; /* Generation number. */
+ uint16_t ufid_len; /* Length of structure. */
+ uint16_t ufid_pad; /* Force 32-bit alignment. */
+ ino_t ufid_ino; /* File number (ino). */
+ uint32_t ufid_gen; /* Generation number. */
};
-#endif /* _KERNEL */
+#endif /* _KERNEL */
-#endif /* !_FS_EXT2FS_INODE_H_ */
+#endif /* !_FS_EXT2FS_INODE_H_ */
Modified: trunk/sys/fs/fdescfs/fdesc.h
===================================================================
--- trunk/sys/fs/fdescfs/fdesc.h 2018-05-27 22:18:36 UTC (rev 10027)
+++ trunk/sys/fs/fdescfs/fdesc.h 2018-05-27 22:19:26 UTC (rev 10028)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*-
* Copyright (c) 1992, 1993
* The Regents of the University of California. All rights reserved.
@@ -31,7 +32,7 @@
*
* @(#)fdesc.h 8.5 (Berkeley) 1/21/94
*
- * $MidnightBSD$
+ * $FreeBSD: stable/10/sys/fs/fdescfs/fdesc.h 191990 2009-05-11 15:33:26Z attilio $
*/
#ifdef _KERNEL
Modified: trunk/sys/fs/fdescfs/fdesc_vfsops.c
===================================================================
--- trunk/sys/fs/fdescfs/fdesc_vfsops.c 2018-05-27 22:18:36 UTC (rev 10027)
+++ trunk/sys/fs/fdescfs/fdesc_vfsops.c 2018-05-27 22:19:26 UTC (rev 10028)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*-
* Copyright (c) 1992, 1993, 1995
* The Regents of the University of California. All rights reserved.
@@ -31,7 +32,7 @@
*
* @(#)fdesc_vfsops.c 8.4 (Berkeley) 1/21/94
*
- * $MidnightBSD$
+ * $FreeBSD: stable/10/sys/fs/fdescfs/fdesc_vfsops.c 277985 2015-01-31 17:35:53Z jamie $
*/
/*
@@ -42,6 +43,7 @@
#include <sys/systm.h>
#include <sys/filedesc.h>
#include <sys/kernel.h>
+#include <sys/jail.h>
#include <sys/lock.h>
#include <sys/mutex.h>
#include <sys/malloc.h>
@@ -78,8 +80,12 @@
{
int error = 0;
struct fdescmount *fmp;
+ struct thread *td = curthread;
struct vnode *rvp;
+ if (!prison_allow(td->td_ucred, PR_ALLOW_MOUNT_FDESCFS))
+ return (EPERM);
+
/*
* Update is a no-op
*/
@@ -98,7 +104,7 @@
error = fdesc_allocvp(Froot, -1, FD_ROOT, mp, &rvp);
if (error) {
free(fmp, M_FDESCMNT);
- mp->mnt_data = 0;
+ mp->mnt_data = NULL;
return (error);
}
rvp->v_type = VDIR;
@@ -107,9 +113,6 @@
VOP_UNLOCK(rvp, 0);
/* XXX -- don't mark as local to work around fts() problems */
/*mp->mnt_flag |= MNT_LOCAL;*/
- MNT_ILOCK(mp);
- mp->mnt_kern_flag |= MNTK_MPSAFE;
- MNT_IUNLOCK(mp);
vfs_getnewfsid(mp);
vfs_mountedfrom(mp, "fdescfs");
@@ -152,7 +155,7 @@
*/
mtx_lock(&fdesc_hashmtx);
data = mp->mnt_data;
- mp->mnt_data = 0;
+ mp->mnt_data = NULL;
mtx_unlock(&fdesc_hashmtx);
free(data, M_FDESCMNT); /* XXX */
@@ -208,7 +211,7 @@
last = min(fdp->fd_nfiles, lim);
freefd = 0;
for (i = fdp->fd_freefile; i < last; i++)
- if (fdp->fd_ofiles[i] == NULL)
+ if (fdp->fd_ofiles[i].fde_file == NULL)
freefd++;
/*
@@ -240,4 +243,4 @@
.vfs_unmount = fdesc_unmount,
};
-VFS_SET(fdesc_vfsops, fdescfs, VFCF_SYNTHETIC);
+VFS_SET(fdesc_vfsops, fdescfs, VFCF_SYNTHETIC | VFCF_JAIL);
Modified: trunk/sys/fs/fdescfs/fdesc_vnops.c
===================================================================
--- trunk/sys/fs/fdescfs/fdesc_vnops.c 2018-05-27 22:18:36 UTC (rev 10027)
+++ trunk/sys/fs/fdescfs/fdesc_vnops.c 2018-05-27 22:19:26 UTC (rev 10028)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*-
* Copyright (c) 1992, 1993
* The Regents of the University of California. All rights reserved.
@@ -31,7 +32,7 @@
*
* @(#)fdesc_vnops.c 8.9 (Berkeley) 1/21/94
*
- * $MidnightBSD: src/sys/fs/fdescfs/fdesc_vnops.c,v 1.6 2013/01/06 17:29:31 laffer1 Exp $
+ * $FreeBSD: stable/10/sys/fs/fdescfs/fdesc_vnops.c 280258 2015-03-19 13:37:36Z rwatson $
*/
/*
@@ -40,7 +41,7 @@
#include <sys/param.h>
#include <sys/systm.h>
-#include <sys/capability.h>
+#include <sys/capsicum.h>
#include <sys/conf.h>
#include <sys/dirent.h>
#include <sys/filedesc.h>
@@ -247,6 +248,28 @@
return (0);
}
+struct fdesc_get_ino_args {
+ fdntype ftype;
+ unsigned fd_fd;
+ int ix;
+ struct file *fp;
+ struct thread *td;
+};
+
+static int
+fdesc_get_ino_alloc(struct mount *mp, void *arg, int lkflags,
+ struct vnode **rvp)
+{
+ struct fdesc_get_ino_args *a;
+ int error;
+
+ a = arg;
+ error = fdesc_allocvp(a->ftype, a->fd_fd, a->ix, mp, rvp);
+ fdrop(a->fp, a->td);
+ return (error);
+}
+
+
/*
* vp is the current namei directory
* ndp is the name to locate in that directory...
@@ -265,6 +288,7 @@
char *pname = cnp->cn_nameptr;
struct thread *td = cnp->cn_thread;
struct file *fp;
+ struct fdesc_get_ino_args arg;
int nlen = cnp->cn_namelen;
u_int fd, fd1;
int error;
@@ -309,7 +333,7 @@
/*
* No rights to check since 'fp' isn't actually used.
*/
- if ((error = fget(td, fd, 0, &fp)) != 0)
+ if ((error = fget(td, fd, NULL, &fp)) != 0)
goto bad;
/* Check if we're looking up ourselves. */
@@ -326,6 +350,8 @@
vn_lock(dvp, LK_RETRY | LK_EXCLUSIVE);
vdrop(dvp);
fvp = dvp;
+ if ((dvp->v_iflag & VI_DOOMED) != 0)
+ error = ENOENT;
} else {
/*
* Unlock our root node (dvp) when doing this, since we might
@@ -333,18 +359,15 @@
* and the root vnode lock will be obtained afterwards (in case
* we're looking up the fd of the root vnode), which will be the
* opposite lock order. Vhold the root vnode first so we don't
- * loose it.
+ * lose it.
*/
- vhold(dvp);
- VOP_UNLOCK(dvp, 0);
- error = fdesc_allocvp(Fdesc, fd, FD_DESC + fd, dvp->v_mount,
- &fvp);
- fdrop(fp, td);
- /*
- * The root vnode must be locked last to prevent deadlock condition.
- */
- vn_lock(dvp, LK_RETRY | LK_EXCLUSIVE);
- vdrop(dvp);
+ arg.ftype = Fdesc;
+ arg.fd_fd = fd;
+ arg.ix = FD_DESC + fd;
+ arg.fp = fp;
+ arg.td = td;
+ error = vn_vget_ino_gen(dvp, fdesc_get_ino_alloc, &arg,
+ LK_EXCLUSIVE, &fvp);
}
if (error)
@@ -445,6 +468,7 @@
struct mount *mp;
struct file *fp;
struct thread *td = curthread;
+ cap_rights_t rights;
unsigned fd;
int error;
@@ -459,7 +483,8 @@
/*
* Allow setattr where there is an underlying vnode.
*/
- error = getvnode(td->td_proc->p_fd, fd, CAP_EXTATTR_SET, &fp);
+ error = getvnode(td->td_proc->p_fd, fd,
+ cap_rights_init(&rights, CAP_EXTATTR_SET), &fp);
if (error) {
/*
* getvnode() returns EINVAL if the file descriptor is not
@@ -534,7 +559,7 @@
dp->d_type = DT_DIR;
break;
default:
- if (fdp->fd_ofiles[fcnt] == NULL)
+ if (fdp->fd_ofiles[fcnt].fde_file == NULL)
break;
dp->d_namlen = sprintf(dp->d_name, "%d", fcnt);
dp->d_reclen = UIO_MX;
Modified: trunk/sys/fs/fifofs/fifo_vnops.c
===================================================================
--- trunk/sys/fs/fifofs/fifo_vnops.c 2018-05-27 22:18:36 UTC (rev 10027)
+++ trunk/sys/fs/fifofs/fifo_vnops.c 2018-05-27 22:19:26 UTC (rev 10028)
@@ -1,7 +1,9 @@
+/* $MidnightBSD$ */
/*-
* Copyright (c) 1990, 1993, 1995
* The Regents of the University of California.
* Copyright (c) 2005 Robert N. M. Watson
+ * Copyright (c) 2012 Giovanni Trematerra
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -29,7 +31,7 @@
* SUCH DAMAGE.
*
* @(#)fifo_vnops.c 8.10 (Berkeley) 5/27/95
- * $MidnightBSD$
+ * $FreeBSD: stable/10/sys/fs/fifofs/fifo_vnops.c 288282 2015-09-27 01:06:45Z kib $
*/
#include <sys/param.h>
@@ -42,55 +44,29 @@
#include <sys/lock.h>
#include <sys/mutex.h>
#include <sys/malloc.h>
-#include <sys/poll.h>
+#include <sys/selinfo.h>
+#include <sys/pipe.h>
#include <sys/proc.h>
#include <sys/signalvar.h>
-#include <sys/socket.h>
-#include <sys/socketvar.h>
#include <sys/sx.h>
#include <sys/systm.h>
#include <sys/un.h>
#include <sys/unistd.h>
#include <sys/vnode.h>
-#include <fs/fifofs/fifo.h>
-static fo_rdwr_t fifo_read_f;
-static fo_rdwr_t fifo_write_f;
-static fo_ioctl_t fifo_ioctl_f;
-static fo_poll_t fifo_poll_f;
-static fo_kqfilter_t fifo_kqfilter_f;
-static fo_stat_t fifo_stat_f;
-static fo_close_t fifo_close_f;
-static fo_truncate_t fifo_truncate_f;
-
-struct fileops fifo_ops_f = {
- .fo_read = fifo_read_f,
- .fo_write = fifo_write_f,
- .fo_truncate = fifo_truncate_f,
- .fo_ioctl = fifo_ioctl_f,
- .fo_poll = fifo_poll_f,
- .fo_kqfilter = fifo_kqfilter_f,
- .fo_stat = fifo_stat_f,
- .fo_close = fifo_close_f,
- .fo_chmod = vn_chmod,
- .fo_chown = vn_chown,
- .fo_flags = DFLAG_PASSABLE
-};
-
/*
* This structure is associated with the FIFO vnode and stores
* the state associated with the FIFO.
* Notes about locking:
- * - fi_readsock and fi_writesock are invariant since init time.
- * - fi_readers and fi_writers are vnode lock protected.
- * - fi_wgen is fif_mtx lock protected.
+ * - fi_pipe is invariant since init time.
+ * - fi_readers and fi_writers are protected by the vnode lock.
*/
struct fifoinfo {
- struct socket *fi_readsock;
- struct socket *fi_writesock;
- long fi_readers;
- long fi_writers;
- int fi_wgen;
+ struct pipe *fi_pipe;
+ long fi_readers;
+ long fi_writers;
+ u_int fi_rgen;
+ u_int fi_wgen;
};
static vop_print_t fifo_print;
@@ -99,29 +75,6 @@
static vop_pathconf_t fifo_pathconf;
static vop_advlock_t fifo_advlock;
-static void filt_fifordetach(struct knote *kn);
-static int filt_fiforead(struct knote *kn, long hint);
-static void filt_fifowdetach(struct knote *kn);
-static int filt_fifowrite(struct knote *kn, long hint);
-static void filt_fifodetach_notsup(struct knote *kn);
-static int filt_fifo_notsup(struct knote *kn, long hint);
-
-static struct filterops fiforead_filtops = {
- .f_isfd = 1,
- .f_detach = filt_fifordetach,
- .f_event = filt_fiforead,
-};
-static struct filterops fifowrite_filtops = {
- .f_isfd = 1,
- .f_detach = filt_fifowdetach,
- .f_event = filt_fifowrite,
-};
-static struct filterops fifo_notsup_filtops = {
- .f_isfd = 1,
- .f_detach = filt_fifodetach_notsup,
- .f_event = filt_fifo_notsup,
-};
-
struct vop_vector fifo_specops = {
.vop_default = &default_vnodeops,
@@ -150,9 +103,6 @@
.vop_write = VOP_PANIC,
};
-struct mtx fifo_mtx;
-MTX_SYSINIT(fifo, &fifo_mtx, "fifo mutex", MTX_DEF);
-
/*
* Dispose of fifo resources.
*/
@@ -159,13 +109,13 @@
static void
fifo_cleanup(struct vnode *vp)
{
- struct fifoinfo *fip = vp->v_fifoinfo;
+ struct fifoinfo *fip;
ASSERT_VOP_ELOCKED(vp, "fifo_cleanup");
+ fip = vp->v_fifoinfo;
if (fip->fi_readers == 0 && fip->fi_writers == 0) {
vp->v_fifoinfo = NULL;
- (void)soclose(fip->fi_readsock);
- (void)soclose(fip->fi_writesock);
+ pipe_dtor(fip->fi_pipe);
free(fip, M_VNODE);
}
}
@@ -185,101 +135,85 @@
struct file *a_fp;
} */ *ap;
{
- struct vnode *vp = ap->a_vp;
+ struct vnode *vp;
+ struct file *fp;
+ struct thread *td;
struct fifoinfo *fip;
- struct thread *td = ap->a_td;
- struct ucred *cred = ap->a_cred;
- struct file *fp = ap->a_fp;
- struct socket *rso, *wso;
- int error;
+ struct pipe *fpipe;
+ u_int gen;
+ int error, stops_deferred;
+ vp = ap->a_vp;
+ fp = ap->a_fp;
+ td = ap->a_td;
ASSERT_VOP_ELOCKED(vp, "fifo_open");
- if (fp == NULL)
+ if (fp == NULL || (ap->a_mode & FEXEC) != 0)
return (EINVAL);
if ((fip = vp->v_fifoinfo) == NULL) {
+ pipe_named_ctor(&fpipe, td);
fip = malloc(sizeof(*fip), M_VNODE, M_WAITOK);
- error = socreate(AF_LOCAL, &rso, SOCK_STREAM, 0, cred, td);
- if (error)
- goto fail1;
- fip->fi_readsock = rso;
- error = socreate(AF_LOCAL, &wso, SOCK_STREAM, 0, cred, td);
- if (error)
- goto fail2;
- fip->fi_writesock = wso;
- error = soconnect2(wso, rso);
- /* Close the direction we do not use, so we can get POLLHUP. */
- if (error == 0)
- error = soshutdown(rso, SHUT_WR);
- if (error) {
- (void)soclose(wso);
-fail2:
- (void)soclose(rso);
-fail1:
- free(fip, M_VNODE);
- return (error);
- }
- fip->fi_wgen = fip->fi_readers = fip->fi_writers = 0;
- wso->so_snd.sb_lowat = PIPE_BUF;
- SOCKBUF_LOCK(&rso->so_rcv);
- rso->so_rcv.sb_state |= SBS_CANTRCVMORE;
- SOCKBUF_UNLOCK(&rso->so_rcv);
- KASSERT(vp->v_fifoinfo == NULL,
- ("fifo_open: v_fifoinfo race"));
+ fip->fi_pipe = fpipe;
+ fpipe->pipe_wgen = fip->fi_readers = fip->fi_writers = 0;
+ KASSERT(vp->v_fifoinfo == NULL, ("fifo_open: v_fifoinfo race"));
vp->v_fifoinfo = fip;
}
+ fpipe = fip->fi_pipe;
+ KASSERT(fpipe != NULL, ("fifo_open: pipe is NULL"));
/*
- * Use the fifo_mtx lock here, in addition to the vnode lock,
+ * Use the pipe mutex here, in addition to the vnode lock,
* in order to allow vnode lock dropping before msleep() calls
* and still avoiding missed wakeups.
*/
- mtx_lock(&fifo_mtx);
+ PIPE_LOCK(fpipe);
if (ap->a_mode & FREAD) {
fip->fi_readers++;
+ fip->fi_rgen++;
if (fip->fi_readers == 1) {
- SOCKBUF_LOCK(&fip->fi_writesock->so_snd);
- fip->fi_writesock->so_snd.sb_state &= ~SBS_CANTSENDMORE;
- SOCKBUF_UNLOCK(&fip->fi_writesock->so_snd);
- if (fip->fi_writers > 0) {
+ fpipe->pipe_state &= ~PIPE_EOF;
+ if (fip->fi_writers > 0)
wakeup(&fip->fi_writers);
- sowwakeup(fip->fi_writesock);
- }
}
- fp->f_seqcount = fip->fi_wgen - fip->fi_writers;
+ fp->f_seqcount = fpipe->pipe_wgen - fip->fi_writers;
}
if (ap->a_mode & FWRITE) {
if ((ap->a_mode & O_NONBLOCK) && fip->fi_readers == 0) {
- mtx_unlock(&fifo_mtx);
+ PIPE_UNLOCK(fpipe);
if (fip->fi_writers == 0)
fifo_cleanup(vp);
return (ENXIO);
}
fip->fi_writers++;
+ fip->fi_wgen++;
if (fip->fi_writers == 1) {
- SOCKBUF_LOCK(&fip->fi_readsock->so_rcv);
- fip->fi_readsock->so_rcv.sb_state &= ~SBS_CANTRCVMORE;
- SOCKBUF_UNLOCK(&fip->fi_readsock->so_rcv);
- if (fip->fi_readers > 0) {
+ fpipe->pipe_state &= ~PIPE_EOF;
+ if (fip->fi_readers > 0)
wakeup(&fip->fi_readers);
- sorwakeup(fip->fi_readsock);
- }
}
}
if ((ap->a_mode & O_NONBLOCK) == 0) {
if ((ap->a_mode & FREAD) && fip->fi_writers == 0) {
+ gen = fip->fi_wgen;
VOP_UNLOCK(vp, 0);
- error = msleep(&fip->fi_readers, &fifo_mtx,
+ stops_deferred = sigallowstop();
+ error = msleep(&fip->fi_readers, PIPE_MTX(fpipe),
PDROP | PCATCH | PSOCK, "fifoor", 0);
+ if (stops_deferred)
+ sigdeferstop();
vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
- if (error) {
+ if (error != 0 && gen == fip->fi_wgen) {
fip->fi_readers--;
if (fip->fi_readers == 0) {
- socantsendmore(fip->fi_writesock);
+ PIPE_LOCK(fpipe);
+ fpipe->pipe_state |= PIPE_EOF;
+ if (fpipe->pipe_state & PIPE_WANTW)
+ wakeup(fpipe);
+ PIPE_UNLOCK(fpipe);
fifo_cleanup(vp);
}
return (error);
}
- mtx_lock(&fifo_mtx);
+ PIPE_LOCK(fpipe);
/*
* We must have got woken up because we had a writer.
* That (and not still having one) is the condition
@@ -287,17 +221,23 @@
*/
}
if ((ap->a_mode & FWRITE) && fip->fi_readers == 0) {
+ gen = fip->fi_rgen;
VOP_UNLOCK(vp, 0);
- error = msleep(&fip->fi_writers, &fifo_mtx,
+ stops_deferred = sigallowstop();
+ error = msleep(&fip->fi_writers, PIPE_MTX(fpipe),
PDROP | PCATCH | PSOCK, "fifoow", 0);
+ if (stops_deferred)
+ sigdeferstop();
vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
- if (error) {
+ if (error != 0 && gen == fip->fi_rgen) {
fip->fi_writers--;
if (fip->fi_writers == 0) {
- socantrcvmore(fip->fi_readsock);
- mtx_lock(&fifo_mtx);
- fip->fi_wgen++;
- mtx_unlock(&fifo_mtx);
+ PIPE_LOCK(fpipe);
+ fpipe->pipe_state |= PIPE_EOF;
+ if (fpipe->pipe_state & PIPE_WANTR)
+ wakeup(fpipe);
+ fpipe->pipe_wgen++;
+ PIPE_UNLOCK(fpipe);
fifo_cleanup(vp);
}
return (error);
@@ -307,85 +247,16 @@
* a reader. That (and not still having one)
* is the condition that we must wait for.
*/
- mtx_lock(&fifo_mtx);
+ PIPE_LOCK(fpipe);
}
}
- mtx_unlock(&fifo_mtx);
+ PIPE_UNLOCK(fpipe);
KASSERT(fp != NULL, ("can't fifo/vnode bypass"));
KASSERT(fp->f_ops == &badfileops, ("not badfileops in fifo_open"));
- finit(fp, fp->f_flag, DTYPE_FIFO, fip, &fifo_ops_f);
+ finit(fp, fp->f_flag, DTYPE_FIFO, fpipe, &pipeops);
return (0);
}
-static void
-filt_fifordetach(struct knote *kn)
-{
- struct socket *so = (struct socket *)kn->kn_hook;
-
- SOCKBUF_LOCK(&so->so_rcv);
- knlist_remove(&so->so_rcv.sb_sel.si_note, kn, 1);
- if (knlist_empty(&so->so_rcv.sb_sel.si_note))
- so->so_rcv.sb_flags &= ~SB_KNOTE;
- SOCKBUF_UNLOCK(&so->so_rcv);
-}
-
-static int
-filt_fiforead(struct knote *kn, long hint)
-{
- struct socket *so = (struct socket *)kn->kn_hook;
-
- SOCKBUF_LOCK_ASSERT(&so->so_rcv);
- kn->kn_data = so->so_rcv.sb_cc;
- if (so->so_rcv.sb_state & SBS_CANTRCVMORE) {
- kn->kn_flags |= EV_EOF;
- return (1);
- } else {
- kn->kn_flags &= ~EV_EOF;
- return (kn->kn_data > 0);
- }
-}
-
-static void
-filt_fifowdetach(struct knote *kn)
-{
- struct socket *so = (struct socket *)kn->kn_hook;
-
- SOCKBUF_LOCK(&so->so_snd);
- knlist_remove(&so->so_snd.sb_sel.si_note, kn, 1);
- if (knlist_empty(&so->so_snd.sb_sel.si_note))
- so->so_snd.sb_flags &= ~SB_KNOTE;
- SOCKBUF_UNLOCK(&so->so_snd);
-}
-
-static int
-filt_fifowrite(struct knote *kn, long hint)
-{
- struct socket *so = (struct socket *)kn->kn_hook;
-
- SOCKBUF_LOCK_ASSERT(&so->so_snd);
- kn->kn_data = sbspace(&so->so_snd);
- if (so->so_snd.sb_state & SBS_CANTSENDMORE) {
- kn->kn_flags |= EV_EOF;
- return (1);
- } else {
- kn->kn_flags &= ~EV_EOF;
- return (kn->kn_data >= so->so_snd.sb_lowat);
- }
-}
-
-static void
-filt_fifodetach_notsup(struct knote *kn)
-{
-
-}
-
-static int
-filt_fifo_notsup(struct knote *kn, long hint)
-{
-
- return (0);
-}
-
/*
* Device close routine
*/
@@ -399,26 +270,39 @@
struct thread *a_td;
} */ *ap;
{
- struct vnode *vp = ap->a_vp;
- struct fifoinfo *fip = vp->v_fifoinfo;
+ struct vnode *vp;
+ struct fifoinfo *fip;
+ struct pipe *cpipe;
+ vp = ap->a_vp;
+ fip = vp->v_fifoinfo;
+ cpipe = fip->fi_pipe;
ASSERT_VOP_ELOCKED(vp, "fifo_close");
- if (fip == NULL) {
- printf("fifo_close: no v_fifoinfo %p\n", vp);
- return (0);
- }
if (ap->a_fflag & FREAD) {
fip->fi_readers--;
- if (fip->fi_readers == 0)
- socantsendmore(fip->fi_writesock);
+ if (fip->fi_readers == 0) {
+ PIPE_LOCK(cpipe);
+ cpipe->pipe_state |= PIPE_EOF;
+ if ((cpipe->pipe_state & PIPE_WANTW)) {
+ cpipe->pipe_state &= ~PIPE_WANTW;
+ wakeup(cpipe);
+ }
+ pipeselwakeup(cpipe);
+ PIPE_UNLOCK(cpipe);
+ }
}
if (ap->a_fflag & FWRITE) {
fip->fi_writers--;
if (fip->fi_writers == 0) {
- socantrcvmore(fip->fi_readsock);
- mtx_lock(&fifo_mtx);
- fip->fi_wgen++;
- mtx_unlock(&fifo_mtx);
+ PIPE_LOCK(cpipe);
+ cpipe->pipe_state |= PIPE_EOF;
+ if ((cpipe->pipe_state & PIPE_WANTR)) {
+ cpipe->pipe_state &= ~PIPE_WANTR;
+ wakeup(cpipe);
+ }
+ cpipe->pipe_wgen++;
+ pipeselwakeup(cpipe);
+ PIPE_UNLOCK(cpipe);
}
}
fifo_cleanup(vp);
@@ -504,212 +388,3 @@
return (ap->a_flags & F_FLOCK ? EOPNOTSUPP : EINVAL);
}
-static int
-fifo_close_f(struct file *fp, struct thread *td)
-{
-
- return (vnops.fo_close(fp, td));
-}
-
-/*
- * The implementation of ioctl() for named fifos is complicated by the fact
- * that we permit O_RDWR fifo file descriptors, meaning that the actions of
- * ioctls may have to be applied to both the underlying sockets rather than
- * just one. The original implementation simply forward the ioctl to one
- * or both sockets based on fp->f_flag. We now consider each ioctl
- * separately, as the composition effect requires careful ordering.
- *
- * We do not blindly pass all ioctls through to the socket in order to avoid
- * providing unnecessary ioctls that might be improperly depended on by
- * applications (such as socket-specific, routing, and interface ioctls).
- *
- * Unlike sys_pipe.c, fifos do not implement the deprecated TIOCSPGRP and
- * TIOCGPGRP ioctls. Earlier implementations of fifos did forward SIOCSPGRP
- * and SIOCGPGRP ioctls, so we might need to re-add those here.
- */
-static int
-fifo_ioctl_f(struct file *fp, u_long com, void *data, struct ucred *cred,
- struct thread *td)
-{
- struct fifoinfo *fi;
- struct file filetmp; /* Local, so need not be locked. */
- int error;
-
- error = ENOTTY;
- fi = fp->f_data;
-
- switch (com) {
- case FIONBIO:
- /*
- * Non-blocking I/O is implemented at the fifo layer using
- * MSG_NBIO, so does not need to be forwarded down the stack.
- */
- return (0);
-
- case FIOASYNC:
- case FIOSETOWN:
- case FIOGETOWN:
- /*
- * These socket ioctls don't have any ordering requirements,
- * so are called in an arbitrary order, and only on the
- * sockets indicated by the file descriptor rights.
- *
- * XXXRW: If O_RDWR and the read socket accepts an ioctl but
- * the write socket doesn't, the socketpair is left in an
- * inconsistent state.
- */
- if (fp->f_flag & FREAD) {
- filetmp.f_data = fi->fi_readsock;
- filetmp.f_cred = cred;
- error = soo_ioctl(&filetmp, com, data, cred, td);
- if (error)
- return (error);
- }
- if (fp->f_flag & FWRITE) {
- filetmp.f_data = fi->fi_writesock;
- filetmp.f_cred = cred;
- error = soo_ioctl(&filetmp, com, data, cred, td);
- }
- return (error);
-
- case FIONREAD:
- /*
- * FIONREAD will return 0 for non-readable descriptors, and
- * the results of FIONREAD on the read socket for readable
- * descriptors.
- */
- if (!(fp->f_flag & FREAD)) {
- *(int *)data = 0;
- return (0);
- }
- filetmp.f_data = fi->fi_readsock;
- filetmp.f_cred = cred;
- return (soo_ioctl(&filetmp, com, data, cred, td));
-
- default:
- return (ENOTTY);
- }
-}
-
-/*
- * Because fifos are now a file descriptor layer object, EVFILT_VNODE is not
- * implemented. Likely, fifo_kqfilter() should be removed, and
- * fifo_kqfilter_f() should know how to forward the request to the underling
- * vnode using f_vnode in the file descriptor here.
- */
-static int
-fifo_kqfilter_f(struct file *fp, struct knote *kn)
-{
- struct fifoinfo *fi;
- struct socket *so;
- struct sockbuf *sb;
-
- fi = fp->f_data;
-
- /*
- * If a filter is requested that is not supported by this file
- * descriptor, don't return an error, but also don't ever generate an
- * event.
- */
- if ((kn->kn_filter == EVFILT_READ) && !(fp->f_flag & FREAD)) {
- kn->kn_fop = &fifo_notsup_filtops;
- return (0);
- }
-
- if ((kn->kn_filter == EVFILT_WRITE) && !(fp->f_flag & FWRITE)) {
- kn->kn_fop = &fifo_notsup_filtops;
- return (0);
- }
-
- switch (kn->kn_filter) {
- case EVFILT_READ:
- kn->kn_fop = &fiforead_filtops;
- so = fi->fi_readsock;
- sb = &so->so_rcv;
- break;
- case EVFILT_WRITE:
- kn->kn_fop = &fifowrite_filtops;
- so = fi->fi_writesock;
- sb = &so->so_snd;
- break;
- default:
- return (EINVAL);
- }
-
- kn->kn_hook = (caddr_t)so;
-
- SOCKBUF_LOCK(sb);
- knlist_add(&sb->sb_sel.si_note, kn, 1);
- sb->sb_flags |= SB_KNOTE;
- SOCKBUF_UNLOCK(sb);
-
- return (0);
-}
-
-static int
-fifo_poll_f(struct file *fp, int events, struct ucred *cred, struct thread *td)
-{
- struct fifoinfo *fip;
- struct file filetmp;
- int levents, revents = 0;
-
- fip = fp->f_data;
- levents = events &
- (POLLIN | POLLINIGNEOF | POLLPRI | POLLRDNORM | POLLRDBAND);
- if ((fp->f_flag & FREAD) && levents) {
- filetmp.f_data = fip->fi_readsock;
- filetmp.f_cred = cred;
- mtx_lock(&fifo_mtx);
- if (fp->f_seqcount == fip->fi_wgen)
- levents |= POLLINIGNEOF;
- mtx_unlock(&fifo_mtx);
- revents |= soo_poll(&filetmp, levents, cred, td);
- }
- levents = events & (POLLOUT | POLLWRNORM | POLLWRBAND);
- if ((fp->f_flag & FWRITE) && levents) {
- filetmp.f_data = fip->fi_writesock;
- filetmp.f_cred = cred;
- revents |= soo_poll(&filetmp, levents, cred, td);
- }
- return (revents);
-}
-
-static int
-fifo_read_f(struct file *fp, struct uio *uio, struct ucred *cred, int flags, struct thread *td)
-{
- struct fifoinfo *fip;
- int sflags;
-
- fip = fp->f_data;
- KASSERT(uio->uio_rw == UIO_READ,("fifo_read mode"));
- if (uio->uio_resid == 0)
- return (0);
- sflags = (fp->f_flag & FNONBLOCK) ? MSG_NBIO : 0;
- return (soreceive(fip->fi_readsock, NULL, uio, NULL, NULL, &sflags));
-}
-
-static int
-fifo_stat_f(struct file *fp, struct stat *sb, struct ucred *cred, struct thread *td)
-{
-
- return (vnops.fo_stat(fp, sb, cred, td));
-}
-
-static int
-fifo_truncate_f(struct file *fp, off_t length, struct ucred *cred, struct thread *td)
-{
-
- return (vnops.fo_truncate(fp, length, cred, td));
-}
-
-static int
-fifo_write_f(struct file *fp, struct uio *uio, struct ucred *cred, int flags, struct thread *td)
-{
- struct fifoinfo *fip;
- int sflags;
-
- fip = fp->f_data;
- KASSERT(uio->uio_rw == UIO_WRITE,("fifo_write mode"));
- sflags = (fp->f_flag & FNONBLOCK) ? MSG_NBIO : 0;
- return (sosend(fip->fi_writesock, NULL, uio, 0, NULL, sflags, td));
-}
Modified: trunk/sys/fs/msdosfs/bootsect.h
===================================================================
--- trunk/sys/fs/msdosfs/bootsect.h 2018-05-27 22:18:36 UTC (rev 10027)
+++ trunk/sys/fs/msdosfs/bootsect.h 2018-05-27 22:19:26 UTC (rev 10028)
@@ -1,4 +1,5 @@
/* $MidnightBSD$ */
+/* $FreeBSD: stable/10/sys/fs/msdosfs/bootsect.h 203827 2010-02-13 12:41:07Z kib $ */
/* $NetBSD: bootsect.h,v 1.9 1997/11/17 15:36:17 ws Exp $ */
/*-
Modified: trunk/sys/fs/msdosfs/bpb.h
===================================================================
--- trunk/sys/fs/msdosfs/bpb.h 2018-05-27 22:18:36 UTC (rev 10027)
+++ trunk/sys/fs/msdosfs/bpb.h 2018-05-27 22:19:26 UTC (rev 10028)
@@ -1,4 +1,5 @@
/* $MidnightBSD$ */
+/* $FreeBSD: stable/10/sys/fs/msdosfs/bpb.h 203827 2010-02-13 12:41:07Z kib $ */
/* $NetBSD: bpb.h,v 1.7 1997/11/17 15:36:24 ws Exp $ */
/*-
Modified: trunk/sys/fs/msdosfs/denode.h
===================================================================
--- trunk/sys/fs/msdosfs/denode.h 2018-05-27 22:18:36 UTC (rev 10027)
+++ trunk/sys/fs/msdosfs/denode.h 2018-05-27 22:19:26 UTC (rev 10028)
@@ -1,4 +1,5 @@
/* $MidnightBSD$ */
+/* $FreeBSD: stable/10/sys/fs/msdosfs/denode.h 234605 2012-04-23 13:21:28Z trasz $ */
/* $NetBSD: denode.h,v 1.25 1997/11/17 15:36:28 ws Exp $ */
/*-
@@ -276,6 +277,6 @@
int createde(struct denode *dep, struct denode *ddep, struct denode **depp, struct componentname *cnp);
int deupdat(struct denode *dep, int waitfor);
int removede(struct denode *pdep, struct denode *dep);
-int detrunc(struct denode *dep, u_long length, int flags, struct ucred *cred, struct thread *td);
+int detrunc(struct denode *dep, u_long length, int flags, struct ucred *cred);
int doscheckpath( struct denode *source, struct denode *target);
#endif /* _KERNEL */
Modified: trunk/sys/fs/msdosfs/direntry.h
===================================================================
--- trunk/sys/fs/msdosfs/direntry.h 2018-05-27 22:18:36 UTC (rev 10027)
+++ trunk/sys/fs/msdosfs/direntry.h 2018-05-27 22:19:26 UTC (rev 10028)
@@ -1,4 +1,5 @@
/* $MidnightBSD$ */
+/* $FreeBSD: stable/10/sys/fs/msdosfs/direntry.h 298799 2016-04-29 20:19:41Z kp $ */
/* $NetBSD: direntry.h,v 1.14 1997/11/17 15:36:32 ws Exp $ */
/*-
@@ -145,7 +146,7 @@
char *mbnambuf_flush(struct mbnambuf *nbp, struct dirent *dp);
void mbnambuf_init(struct mbnambuf *nbp);
-void mbnambuf_write(struct mbnambuf *nbp, char *name, int id);
+int mbnambuf_write(struct mbnambuf *nbp, char *name, int id);
int dos2unixfn(u_char dn[11], u_char *un, int lower,
struct msdosfsmount *pmp);
int unix2dosfn(const u_char *un, u_char dn[12], size_t unlen, u_int gen,
Modified: trunk/sys/fs/msdosfs/fat.h
===================================================================
--- trunk/sys/fs/msdosfs/fat.h 2018-05-27 22:18:36 UTC (rev 10027)
+++ trunk/sys/fs/msdosfs/fat.h 2018-05-27 22:19:26 UTC (rev 10028)
@@ -1,4 +1,5 @@
/* $MidnightBSD$ */
+/* $FreeBSD: stable/10/sys/fs/msdosfs/fat.h 139776 2005-01-06 18:10:42Z imp $ */
/* $NetBSD: fat.h,v 1.12 1997/11/17 15:36:36 ws Exp $ */
/*-
Modified: trunk/sys/fs/msdosfs/msdosfs_conv.c
===================================================================
--- trunk/sys/fs/msdosfs/msdosfs_conv.c 2018-05-27 22:18:36 UTC (rev 10027)
+++ trunk/sys/fs/msdosfs/msdosfs_conv.c 2018-05-27 22:19:26 UTC (rev 10028)
@@ -1,4 +1,5 @@
/* $MidnightBSD$ */
+/* $FreeBSD: stable/10/sys/fs/msdosfs/msdosfs_conv.c 333611 2018-05-14 19:21:57Z pfg $ */
/* $NetBSD: msdosfs_conv.c,v 1.25 1997/11/17 15:36:40 ws Exp $ */
/*-
@@ -257,7 +258,7 @@
* Copy the name portion into the unix filename string.
*/
for (i = 8; i > 0 && *dn != ' ';) {
- c = dos2unixchr(tmpbuf, (const u_char **)&dn, &i,
+ c = dos2unixchr(tmpbuf, __DECONST(const u_char **, &dn), &i,
lower & LCASE_BASE, pmp);
while (*c != '\0') {
*un++ = *c++;
@@ -274,8 +275,8 @@
*un++ = '.';
thislong++;
for (i = 3; i > 0 && *dn != ' ';) {
- c = dos2unixchr(tmpbuf, (const u_char **)&dn, &i,
- lower & LCASE_EXT, pmp);
+ c = dos2unixchr(tmpbuf, __DECONST(const u_char **, &dn),
+ &i, lower & LCASE_EXT, pmp);
while (*c != '\0') {
*un++ = *c++;
thislong++;
@@ -581,7 +582,7 @@
if (!code)
end = WIN_LAST;
}
- if (*un == '\0')
+ if (!unlen)
end = WIN_LAST;
wep->weCnt |= end;
return !end;
@@ -629,7 +630,8 @@
* to look up or create files in case sensitive even when
* it's a long file name.
*/
- c1 = unix2winchr((const u_char **)&np, &len, LCASE_BASE, pmp);
+ c1 = unix2winchr(__DECONST(const u_char **, &np), &len,
+ LCASE_BASE, pmp);
c2 = unix2winchr(&un, &unlen, LCASE_BASE, pmp);
if (c1 != c2)
return -2;
@@ -677,7 +679,9 @@
switch (code) {
case 0:
*np = '\0';
- mbnambuf_write(nbp, name, (wep->weCnt & WIN_CNT) - 1);
+ if (mbnambuf_write(nbp, name,
+ (wep->weCnt & WIN_CNT) - 1) != 0)
+ return -1;
return chksum;
case '/':
*np = '\0';
@@ -695,7 +699,9 @@
switch (code) {
case 0:
*np = '\0';
- mbnambuf_write(nbp, name, (wep->weCnt & WIN_CNT) - 1);
+ if (mbnambuf_write(nbp, name,
+ (wep->weCnt & WIN_CNT) - 1) != 0)
+ return -1;
return chksum;
case '/':
*np = '\0';
@@ -713,7 +719,9 @@
switch (code) {
case 0:
*np = '\0';
- mbnambuf_write(nbp, name, (wep->weCnt & WIN_CNT) - 1);
+ if (mbnambuf_write(nbp, name,
+ (wep->weCnt & WIN_CNT) - 1) != 0)
+ return -1;
return chksum;
case '/':
*np = '\0';
@@ -727,7 +735,8 @@
cp += 2;
}
*np = '\0';
- mbnambuf_write(nbp, name, (wep->weCnt & WIN_CNT) - 1);
+ if (mbnambuf_write(nbp, name, (wep->weCnt & WIN_CNT) - 1) != 0)
+ return -1;
return chksum;
}
@@ -774,7 +783,7 @@
}
/*
- * Determine the number of bytes neccesary for Win95 names
+ * Determine the number of bytes neccessary for Win95 names
*/
size_t
winLenFixup(un, unlen)
@@ -788,7 +797,7 @@
}
/*
- * Store an area with multi byte string instr, and reterns left
+ * Store an area with multi byte string instr, and returns left
* byte of instr and moves pointer forward. The area's size is
* inlen or outlen.
*/
@@ -947,8 +956,8 @@
ilen = 2;
olen = len = 4;
inp = inbuf;
- msdosfs_iconv->convchr(pmp->pm_w2u, (const char **)&inp, &ilen,
- (char **)&outp, &olen);
+ msdosfs_iconv->convchr(pmp->pm_w2u, __DECONST(const char **,
+ &inp), &ilen, (char **)&outp, &olen);
len -= olen;
/*
@@ -1029,7 +1038,7 @@
* This only penalizes portions of substrings that contain more than
* WIN_CHARS bytes when they are first encountered.
*/
-void
+int
mbnambuf_write(struct mbnambuf *nbp, char *name, int id)
{
char *slot;
@@ -1040,7 +1049,7 @@
printf("msdosfs: non-decreasing id: id %d, last id %d\n",
id, nbp->nb_last_id);
#endif
- return;
+ return (EINVAL);
}
/* Will store this substring in a WIN_CHARS-aligned slot. */
@@ -1051,17 +1060,24 @@
#ifdef MSDOSFS_DEBUG
printf("msdosfs: file name length %zu too large\n", newlen);
#endif
- return;
+ return (ENAMETOOLONG);
}
/* Shift suffix upwards by the amount length exceeds WIN_CHARS. */
- if (count > WIN_CHARS && nbp->nb_len != 0)
+ if (count > WIN_CHARS && nbp->nb_len != 0) {
+ if ((id * WIN_CHARS + count + nbp->nb_len) >
+ sizeof(nbp->nb_buf))
+ return (ENAMETOOLONG);
+
bcopy(slot + WIN_CHARS, slot + count, nbp->nb_len);
+ }
/* Copy in the substring to its slot and update length so far. */
bcopy(name, slot, count);
nbp->nb_len = newlen;
nbp->nb_last_id = id;
+
+ return (0);
}
/*
Modified: trunk/sys/fs/msdosfs/msdosfs_denode.c
===================================================================
--- trunk/sys/fs/msdosfs/msdosfs_denode.c 2018-05-27 22:18:36 UTC (rev 10027)
+++ trunk/sys/fs/msdosfs/msdosfs_denode.c 2018-05-27 22:19:26 UTC (rev 10028)
@@ -1,4 +1,5 @@
/* $MidnightBSD$ */
+/* $FreeBSD: stable/10/sys/fs/msdosfs/msdosfs_denode.c 254627 2013-08-21 23:04:48Z ken $ */
/* $NetBSD: msdosfs_denode.c,v 1.28 1998/02/10 14:10:00 mrg Exp $ */
/*-
@@ -142,12 +143,6 @@
KASSERT((*depp)->de_diroffset == diroffset, ("wrong diroffset"));
return (0);
}
-
- /*
- * Do the malloc before the getnewvnode since doing so afterward
- * might cause a bogus v_data pointer to get dereferenced
- * elsewhere if malloc should block.
- */
ldep = malloc(sizeof(struct denode), M_MSDOSFSNODE, M_WAITOK | M_ZERO);
/*
@@ -310,8 +305,8 @@
if ((dep->de_flag & DE_MODIFIED) == 0 && waitfor == 0)
return (0);
dep->de_flag &= ~DE_MODIFIED;
- if (dep->de_Attributes & ATTR_DIRECTORY)
- return (0);
+ if (DETOV(dep)->v_vflag & VV_ROOT)
+ return (EINVAL);
if (dep->de_refcnt <= 0)
return (0);
error = readde(dep, &bp, &dirp);
@@ -340,12 +335,11 @@
* Truncate the file described by dep to the length specified by length.
*/
int
-detrunc(dep, length, flags, cred, td)
+detrunc(dep, length, flags, cred)
struct denode *dep;
u_long length;
int flags;
struct ucred *cred;
- struct thread *td;
{
int error;
int allerror;
@@ -440,7 +434,7 @@
dep->de_FileSize = length;
if (!isadir)
dep->de_flag |= DE_UPDATE | DE_MODIFIED;
- allerror = vtruncbuf(DETOV(dep), cred, td, length, pmp->pm_bpcluster);
+ allerror = vtruncbuf(DETOV(dep), cred, length, pmp->pm_bpcluster);
#ifdef MSDOSFS_DEBUG
if (allerror)
printf("detrunc(): vtruncbuf error %d\n", allerror);
@@ -518,7 +512,7 @@
error = extendfile(dep, count, NULL, NULL, DE_CLEAR);
if (error) {
/* truncate the added clusters away again */
- (void) detrunc(dep, dep->de_FileSize, 0, cred, NULL);
+ (void) detrunc(dep, dep->de_FileSize, 0, cred);
return (error);
}
}
@@ -598,7 +592,6 @@
{
struct vnode *vp = ap->a_vp;
struct denode *dep = VTODE(vp);
- struct thread *td = ap->a_td;
int error = 0;
#ifdef MSDOSFS_DEBUG
@@ -621,7 +614,7 @@
dep, dep->de_refcnt, vp->v_mount->mnt_flag, MNT_RDONLY);
#endif
if (dep->de_refcnt <= 0 && (vp->v_mount->mnt_flag & MNT_RDONLY) == 0) {
- error = detrunc(dep, (u_long) 0, 0, NOCRED, td);
+ error = detrunc(dep, (u_long) 0, 0, NOCRED);
dep->de_flag |= DE_UPDATE;
dep->de_Name[0] = SLOT_DELETED;
}
@@ -637,6 +630,6 @@
vrefcnt(vp), dep->de_Name[0]);
#endif
if (dep->de_Name[0] == SLOT_DELETED || dep->de_Name[0] == SLOT_EMPTY)
- vrecycle(vp, td);
+ vrecycle(vp);
return (error);
}
Modified: trunk/sys/fs/msdosfs/msdosfs_fat.c
===================================================================
--- trunk/sys/fs/msdosfs/msdosfs_fat.c 2018-05-27 22:18:36 UTC (rev 10027)
+++ trunk/sys/fs/msdosfs/msdosfs_fat.c 2018-05-27 22:19:26 UTC (rev 10028)
@@ -1,4 +1,5 @@
/* $MidnightBSD$ */
+/* $FreeBSD: stable/10/sys/fs/msdosfs/msdosfs_fat.c 308551 2016-11-11 20:06:07Z kib $ */
/* $NetBSD: msdosfs_fat.c,v 1.28 1997/11/17 15:36:49 ws Exp $ */
/*-
@@ -60,6 +61,8 @@
#include <fs/msdosfs/fat.h>
#include <fs/msdosfs/msdosfsmount.h>
+#define FULL_RUN ((u_int)0xffffffff)
+
static int chainalloc(struct msdosfsmount *pmp, u_long start,
u_long count, u_long fillwith, u_long *retcluster,
u_long *got);
@@ -399,6 +402,10 @@
MSDOSFS_ASSERT_MP_LOCKED(pmp);
+ KASSERT(cn <= pmp->pm_maxcluster, ("cn too large %lu %lu", cn,
+ pmp->pm_maxcluster));
+ KASSERT((pmp->pm_flags & MSDOSFSMNT_RONLY) == 0,
+ ("usemap_alloc on ro msdosfs mount"));
KASSERT((pmp->pm_inusemap[cn / N_INUSEBITS] & (1 << (cn % N_INUSEBITS)))
== 0, ("Allocating used sector %ld %ld %x", cn, cn % N_INUSEBITS,
(unsigned)pmp->pm_inusemap[cn / N_INUSEBITS]));
@@ -415,6 +422,11 @@
{
MSDOSFS_ASSERT_MP_LOCKED(pmp);
+
+ KASSERT(cn <= pmp->pm_maxcluster, ("cn too large %lu %lu", cn,
+ pmp->pm_maxcluster));
+ KASSERT((pmp->pm_flags & MSDOSFSMNT_RONLY) == 0,
+ ("usemap_free on ro msdosfs mount"));
pmp->pm_freeclustercount++;
pmp->pm_flags |= MSDOSFS_FSIMOD;
KASSERT((pmp->pm_inusemap[cn / N_INUSEBITS] & (1 << (cn % N_INUSEBITS)))
@@ -666,6 +678,8 @@
MSDOSFS_ASSERT_MP_LOCKED(pmp);
+ if (start > pmp->pm_maxcluster)
+ return (0);
max_idx = pmp->pm_maxcluster / N_INUSEBITS;
idx = start / N_INUSEBITS;
start %= N_INUSEBITS;
@@ -673,11 +687,18 @@
map &= ~((1 << start) - 1);
if (map) {
len = ffs(map) - 1 - start;
- return (len > count ? count : len);
+ len = MIN(len, count);
+ if (start + len > pmp->pm_maxcluster)
+ len = pmp->pm_maxcluster - start + 1;
+ return (len);
}
len = N_INUSEBITS - start;
- if (len >= count)
- return (count);
+ if (len >= count) {
+ len = count;
+ if (start + len > pmp->pm_maxcluster)
+ len = pmp->pm_maxcluster - start + 1;
+ return (len);
+ }
while (++idx <= max_idx) {
if (len >= count)
break;
@@ -688,7 +709,10 @@
}
len += N_INUSEBITS;
}
- return (len > count ? count : len);
+ len = MIN(len, count);
+ if (start + len > pmp->pm_maxcluster)
+ len = pmp->pm_maxcluster - start + 1;
+ return (len);
}
/*
@@ -715,6 +739,8 @@
u_long cl, n;
MSDOSFS_ASSERT_MP_LOCKED(pmp);
+ KASSERT((pmp->pm_flags & MSDOSFSMNT_RONLY) == 0,
+ ("chainalloc on ro msdosfs mount"));
for (cl = start, n = count; n-- > 0;)
usemap_alloc(pmp, cl++);
@@ -723,8 +749,11 @@
pmp->pm_nxtfree = CLUST_FIRST;
pmp->pm_flags |= MSDOSFS_FSIMOD;
error = fatchain(pmp, start, count, fillwith);
- if (error != 0)
+ if (error != 0) {
+ for (cl = start, n = count; n-- > 0;)
+ usemap_free(pmp, cl++);
return (error);
+ }
#ifdef MSDOSFS_DEBUG
printf("clusteralloc(): allocated cluster chain at %lu (%lu clusters)\n",
start, count);
@@ -786,8 +815,8 @@
idx = cn / N_INUSEBITS;
map = pmp->pm_inusemap[idx];
map |= (1 << (cn % N_INUSEBITS)) - 1;
- if (map != (u_int)-1) {
- cn = idx * N_INUSEBITS + ffs(map^(u_int)-1) - 1;
+ if (map != FULL_RUN) {
+ cn = idx * N_INUSEBITS + ffs(map ^ FULL_RUN) - 1;
if ((l = chainlength(pmp, cn, count)) >= count)
return (chainalloc(pmp, cn, count, fillwith, retcluster, got));
if (l > foundl) {
@@ -803,8 +832,8 @@
idx = cn / N_INUSEBITS;
map = pmp->pm_inusemap[idx];
map |= (1 << (cn % N_INUSEBITS)) - 1;
- if (map != (u_int)-1) {
- cn = idx * N_INUSEBITS + ffs(map^(u_int)-1) - 1;
+ if (map != FULL_RUN) {
+ cn = idx * N_INUSEBITS + ffs(map ^ FULL_RUN) - 1;
if ((l = chainlength(pmp, cn, count)) >= count)
return (chainalloc(pmp, cn, count, fillwith, retcluster, got));
if (l > foundl) {
@@ -915,7 +944,7 @@
* loop further down.
*/
for (cn = 0; cn < (pmp->pm_maxcluster + N_INUSEBITS) / N_INUSEBITS; cn++)
- pmp->pm_inusemap[cn] = (u_int)-1;
+ pmp->pm_inusemap[cn] = FULL_RUN;
/*
* Figure how many free clusters are in the filesystem by ripping
@@ -945,11 +974,16 @@
readcn >>= 4;
readcn &= pmp->pm_fatmask;
- if (readcn == 0)
+ if (readcn == CLUST_FREE)
usemap_free(pmp, cn);
}
if (bp != NULL)
brelse(bp);
+
+ for (cn = pmp->pm_maxcluster + 1; cn < (pmp->pm_maxcluster +
+ N_INUSEBITS) / N_INUSEBITS; cn++)
+ pmp->pm_inusemap[cn / N_INUSEBITS] |= 1 << (cn % N_INUSEBITS);
+
return (0);
}
@@ -1013,12 +1047,14 @@
while (count > 0) {
/*
* Allocate a new cluster chain and cat onto the end of the
- * file. * If the file is empty we make de_StartCluster point
- * to the new block. Note that de_StartCluster being 0 is
- * sufficient to be sure the file is empty since we exclude
- * attempts to extend the root directory above, and the root
- * dir is the only file with a startcluster of 0 that has
- * blocks allocated (sort of).
+ * file.
+ * If the file is empty we make de_StartCluster point
+ * to the new block. Note that de_StartCluster being
+ * 0 is sufficient to be sure the file is empty since
+ * we exclude attempts to extend the root directory
+ * above, and the root dir is the only file with a
+ * startcluster of 0 that has blocks allocated (sort
+ * of).
*/
if (dep->de_StartCluster == 0)
cn = 0;
Modified: trunk/sys/fs/msdosfs/msdosfs_fileno.c
===================================================================
--- trunk/sys/fs/msdosfs/msdosfs_fileno.c 2018-05-27 22:18:36 UTC (rev 10027)
+++ trunk/sys/fs/msdosfs/msdosfs_fileno.c 2018-05-27 22:19:26 UTC (rev 10028)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*-
* Copyright (c) 2003-2004 Tim J. Robbins.
* All rights reserved.
@@ -43,7 +44,7 @@
*/
#include <sys/cdefs.h>
-__MBSDID("$MidnightBSD$");
+__FBSDID("$FreeBSD: stable/10/sys/fs/msdosfs/msdosfs_fileno.c 263670 2014-03-23 19:48:30Z pfg $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -75,7 +76,7 @@
RB_INIT(&pmp->pm_filenos);
pmp->pm_nfileno = FILENO_FIRST_DYN;
- if (pmp->pm_HugeSectors > 0xffffffff /
+ if (pmp->pm_HugeSectors > 0xffffffff /
(pmp->pm_BytesPerSec / sizeof(struct direntry)) + 1)
pmp->pm_flags |= MSDOSFS_LARGEFS;
}
Modified: trunk/sys/fs/msdosfs/msdosfs_iconv.c
===================================================================
--- trunk/sys/fs/msdosfs/msdosfs_iconv.c 2018-05-27 22:18:36 UTC (rev 10027)
+++ trunk/sys/fs/msdosfs/msdosfs_iconv.c 2018-05-27 22:19:26 UTC (rev 10028)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*-
* Copyright (c) 2003 Ryuichiro Imura
* All rights reserved.
@@ -25,7 +26,7 @@
*/
#include <sys/cdefs.h>
-__MBSDID("$MidnightBSD$");
+__FBSDID("$FreeBSD: stable/10/sys/fs/msdosfs/msdosfs_iconv.c 171753 2007-08-07 02:25:56Z bde $");
#include <sys/param.h>
#include <sys/iconv.h>
Modified: trunk/sys/fs/msdosfs/msdosfs_lookup.c
===================================================================
--- trunk/sys/fs/msdosfs/msdosfs_lookup.c 2018-05-27 22:18:36 UTC (rev 10027)
+++ trunk/sys/fs/msdosfs/msdosfs_lookup.c 2018-05-27 22:19:26 UTC (rev 10028)
@@ -1,4 +1,5 @@
/* $MidnightBSD$ */
+/* $FreeBSD: stable/10/sys/fs/msdosfs/msdosfs_lookup.c 276500 2015-01-01 10:44:20Z kib $ */
/* $NetBSD: msdosfs_lookup.c,v 1.37 1997/11/17 15:36:54 ws Exp $ */
/*-
@@ -63,8 +64,6 @@
static int msdosfs_lookup_(struct vnode *vdp, struct vnode **vpp,
struct componentname *cnp, u_int64_t *inum);
-static int msdosfs_deget_dotdot(struct vnode *vp, u_long cluster, int blkoff,
- struct vnode **rvp);
int
msdosfs_lookup(struct vop_cachedlookup_args *ap)
@@ -73,6 +72,28 @@
return (msdosfs_lookup_(ap->a_dvp, ap->a_vpp, ap->a_cnp, NULL));
}
+struct deget_dotdot {
+ u_long cluster;
+ int blkoff;
+};
+
+static int
+msdosfs_deget_dotdot(struct mount *mp, void *arg, int lkflags,
+ struct vnode **rvp)
+{
+ struct deget_dotdot *dd_arg;
+ struct denode *rdp;
+ struct msdosfsmount *pmp;
+ int error;
+
+ pmp = VFSTOMSDOSFS(mp);
+ dd_arg = arg;
+ error = deget(pmp, dd_arg->cluster, dd_arg->blkoff, &rdp);
+ if (error == 0)
+ *rvp = DETOV(rdp);
+ return (error);
+}
+
/*
* When we search a directory the blocks containing directory entries are
* read and examined. The directory entries contain information that would
@@ -108,8 +129,9 @@
struct denode *dp;
struct denode *tdp;
struct msdosfsmount *pmp;
- struct buf *bp = 0;
+ struct buf *bp = NULL;
struct direntry *dep = NULL;
+ struct deget_dotdot dd_arg;
u_char dosfilename[12];
int flags = cnp->cn_flags;
int nameiop = cnp->cn_nameiop;
@@ -395,7 +417,7 @@
* and 8.3 filenames. Hence, it may not invalidate all negative
* entries if a file with this name is later created.
*/
- if ((cnp->cn_flags & MAKEENTRY) && nameiop != CREATE)
+ if ((cnp->cn_flags & MAKEENTRY) != 0)
cache_enter(vdp, *vpp, cnp);
#endif
return (ENOENT);
@@ -524,8 +546,11 @@
*/
pdp = vdp;
if (flags & ISDOTDOT) {
- error = msdosfs_deget_dotdot(pdp, cluster, blkoff, vpp);
- if (error) {
+ dd_arg.cluster = cluster;
+ dd_arg.blkoff = blkoff;
+ error = vn_vget_ino_gen(vdp, msdosfs_deget_dotdot,
+ &dd_arg, cnp->cn_lkflags, vpp);
+ if (error != 0) {
*vpp = NULL;
return (error);
}
@@ -560,54 +585,6 @@
return (0);
}
-static int
-msdosfs_deget_dotdot(struct vnode *vp, u_long cluster, int blkoff,
- struct vnode **rvp)
-{
- struct mount *mp;
- struct msdosfsmount *pmp;
- struct denode *rdp;
- int ltype, error;
-
- mp = vp->v_mount;
- pmp = VFSTOMSDOSFS(mp);
- ltype = VOP_ISLOCKED(vp);
- KASSERT(ltype == LK_EXCLUSIVE || ltype == LK_SHARED,
- ("msdosfs_deget_dotdot: vp not locked"));
-
- error = vfs_busy(mp, MBF_NOWAIT);
- if (error != 0) {
- vfs_ref(mp);
- VOP_UNLOCK(vp, 0);
- error = vfs_busy(mp, 0);
- vn_lock(vp, ltype | LK_RETRY);
- vfs_rel(mp);
- if (error != 0)
- return (ENOENT);
- if (vp->v_iflag & VI_DOOMED) {
- vfs_unbusy(mp);
- return (ENOENT);
- }
- }
- VOP_UNLOCK(vp, 0);
- error = deget(pmp, cluster, blkoff, &rdp);
- vfs_unbusy(mp);
- if (error == 0)
- *rvp = DETOV(rdp);
- if (*rvp != vp)
- vn_lock(vp, ltype | LK_RETRY);
- if (vp->v_iflag & VI_DOOMED) {
- if (error == 0) {
- if (*rvp == vp)
- vunref(*rvp);
- else
- vput(*rvp);
- }
- error = ENOENT;
- }
- return (error);
-}
-
/*
* dep - directory entry to copy into the directory
* ddep - directory to add to
@@ -649,7 +626,7 @@
dirclust = de_clcount(pmp, diroffset);
error = extendfile(ddep, dirclust, 0, 0, DE_CLEAR);
if (error) {
- (void)detrunc(ddep, ddep->de_FileSize, 0, NOCRED, NULL);
+ (void)detrunc(ddep, ddep->de_FileSize, 0, NOCRED);
return error;
}
Modified: trunk/sys/fs/msdosfs/msdosfs_vfsops.c
===================================================================
--- trunk/sys/fs/msdosfs/msdosfs_vfsops.c 2018-05-27 22:18:36 UTC (rev 10027)
+++ trunk/sys/fs/msdosfs/msdosfs_vfsops.c 2018-05-27 22:19:26 UTC (rev 10028)
@@ -1,4 +1,5 @@
/* $MidnightBSD$ */
+/* $FreeBSD: stable/10/sys/fs/msdosfs/msdosfs_vfsops.c 308552 2016-11-11 20:08:45Z kib $ */
/* $NetBSD: msdosfs_vfsops.c,v 1.51 1997/11/17 15:36:58 ws Exp $ */
/*-
@@ -175,24 +176,8 @@
if (pmp->pm_flags & MSDOSFSMNT_NOWIN95)
pmp->pm_flags |= MSDOSFSMNT_SHORTNAME;
- else if (!(pmp->pm_flags &
- (MSDOSFSMNT_SHORTNAME | MSDOSFSMNT_LONGNAME))) {
- struct vnode *rootvp;
-
- /*
- * Try to divine whether to support Win'95 long filenames
- */
- if (FAT32(pmp))
- pmp->pm_flags |= MSDOSFSMNT_LONGNAME;
- else {
- if ((error =
- msdosfs_root(mp, LK_EXCLUSIVE, &rootvp)) != 0)
- return error;
- pmp->pm_flags |= findwin95(VTODE(rootvp)) ?
- MSDOSFSMNT_LONGNAME : MSDOSFSMNT_SHORTNAME;
- vput(rootvp);
- }
- }
+ else
+ pmp->pm_flags |= MSDOSFSMNT_LONGNAME;
return 0;
}
@@ -759,7 +744,7 @@
mp->mnt_stat.f_fsid.val[1] = mp->mnt_vfc->vfc_typenum;
MNT_ILOCK(mp);
mp->mnt_flag |= MNT_LOCAL;
- mp->mnt_kern_flag |= MNTK_MPSAFE;
+ mp->mnt_kern_flag |= MNTK_USES_BCACHE | MNTK_NO_IOPF;
MNT_IUNLOCK(mp);
if (pmp->pm_flags & MSDOSFS_LARGEFS)
@@ -779,8 +764,7 @@
}
if (pmp) {
lockdestroy(&pmp->pm_fatlock);
- if (pmp->pm_inusemap)
- free(pmp->pm_inusemap, M_MSDOSFSFAT);
+ free(pmp->pm_inusemap, M_MSDOSFSFAT);
free(pmp, M_MSDOSFSMNT);
mp->mnt_data = NULL;
}
@@ -797,13 +781,17 @@
struct msdosfsmount *pmp;
int error, flags;
- flags = 0;
- if (mntflags & MNT_FORCE)
+ error = flags = 0;
+ pmp = VFSTOMSDOSFS(mp);
+ if ((pmp->pm_flags & MSDOSFSMNT_RONLY) == 0)
+ error = msdosfs_sync(mp, MNT_WAIT);
+ if ((mntflags & MNT_FORCE) != 0)
flags |= FORCECLOSE;
+ else if (error != 0)
+ return (error);
error = vflush(mp, 0, flags, curthread);
- if (error && error != ENXIO)
- return error;
- pmp = VFSTOMSDOSFS(mp);
+ if (error != 0 && error != ENXIO)
+ return (error);
if ((pmp->pm_flags & MSDOSFSMNT_RONLY) == 0) {
error = markvoldirty(pmp, 0);
if (error && error != ENXIO) {
Modified: trunk/sys/fs/msdosfs/msdosfs_vnops.c
===================================================================
--- trunk/sys/fs/msdosfs/msdosfs_vnops.c 2018-05-27 22:18:36 UTC (rev 10027)
+++ trunk/sys/fs/msdosfs/msdosfs_vnops.c 2018-05-27 22:19:26 UTC (rev 10028)
@@ -1,4 +1,5 @@
/* $MidnightBSD$ */
+/* $FreeBSD: stable/10/sys/fs/msdosfs/msdosfs_vnops.c 308552 2016-11-11 20:08:45Z kib $ */
/* $NetBSD: msdosfs_vnops.c,v 1.68 1998/02/10 14:10:04 mrg Exp $ */
/*-
@@ -172,8 +173,7 @@
if (error)
goto bad;
- ndirent.de_Attributes = (ap->a_vap->va_mode & VWRITE) ?
- ATTR_ARCHIVE : ATTR_ARCHIVE | ATTR_READONLY;
+ ndirent.de_Attributes = ATTR_ARCHIVE;
ndirent.de_LowerCase = 0;
ndirent.de_StartCluster = 0;
ndirent.de_FileSize = 0;
@@ -185,6 +185,8 @@
if (error)
goto bad;
*ap->a_vpp = DETOV(dep);
+ if ((cnp->cn_flags & MAKEENTRY) != 0)
+ cache_enter(ap->a_dvp, *ap->a_vpp, cnp);
return (0);
bad:
@@ -256,8 +258,7 @@
mode_t file_mode;
accmode_t accmode = ap->a_accmode;
- file_mode = (S_IXUSR|S_IXGRP|S_IXOTH) | (S_IRUSR|S_IRGRP|S_IROTH) |
- ((dep->de_Attributes & ATTR_READONLY) ? 0 : (S_IWUSR|S_IWGRP|S_IWOTH));
+ file_mode = S_IRWXU|S_IRWXG|S_IRWXO;
file_mode &= (vp->v_type == VDIR ? pmp->pm_dirmask : pmp->pm_mask);
/*
@@ -266,8 +267,8 @@
*/
if (accmode & VWRITE) {
switch (vp->v_type) {
+ case VREG:
case VDIR:
- case VREG:
if (vp->v_mount->mnt_flag & MNT_RDONLY)
return (EROFS);
break;
@@ -322,10 +323,7 @@
else
vap->va_fileid = (long)fileid;
- if ((dep->de_Attributes & ATTR_READONLY) == 0)
- mode = S_IRWXU|S_IRWXG|S_IRWXO;
- else
- mode = S_IRUSR|S_IXUSR|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH;
+ mode = S_IRWXU|S_IRWXG|S_IRWXO;
vap->va_mode = mode &
(ap->a_vp->v_type == VDIR ? pmp->pm_dirmask : pmp->pm_mask);
vap->va_uid = pmp->pm_uid;
@@ -345,8 +343,14 @@
vap->va_birthtime.tv_nsec = 0;
}
vap->va_flags = 0;
- if ((dep->de_Attributes & ATTR_ARCHIVE) == 0)
- vap->va_flags |= SF_ARCHIVED;
+ if (dep->de_Attributes & ATTR_ARCHIVE)
+ vap->va_flags |= UF_ARCHIVE;
+ if (dep->de_Attributes & ATTR_HIDDEN)
+ vap->va_flags |= UF_HIDDEN;
+ if (dep->de_Attributes & ATTR_READONLY)
+ vap->va_flags |= UF_READONLY;
+ if (dep->de_Attributes & ATTR_SYSTEM)
+ vap->va_flags |= UF_SYSTEM;
vap->va_gen = 0;
vap->va_blocksize = pmp->pm_bpcluster;
vap->va_bytes =
@@ -395,6 +399,18 @@
#endif
return (EINVAL);
}
+
+ /*
+ * We don't allow setting attributes on the root directory.
+ * The special case for the root directory is because before
+ * FAT32, the root directory didn't have an entry for itself
+ * (and was otherwise special). With FAT32, the root
+ * directory is not so special, but still doesn't have an
+ * entry for itself.
+ */
+ if (vp->v_vflag & VV_ROOT)
+ return (EINVAL);
+
if (vap->va_flags != VNOVAL) {
if (vp->v_mount->mnt_flag & MNT_RDONLY)
return (EROFS);
@@ -408,24 +424,29 @@
* attributes. We ignored the access time and the
* read and execute bits. We were strict for the other
* attributes.
- *
- * Here we are strict, stricter than ufs in not allowing
- * users to attempt to set SF_SETTABLE bits or anyone to
- * set unsupported bits. However, we ignore attempts to
- * set ATTR_ARCHIVE for directories `cp -pr' from a more
- * sensible filesystem attempts it a lot.
*/
- if (vap->va_flags & SF_SETTABLE) {
- error = priv_check_cred(cred, PRIV_VFS_SYSFLAGS, 0);
- if (error)
- return (error);
- }
- if (vap->va_flags & ~SF_ARCHIVED)
+ if (vap->va_flags & ~(UF_ARCHIVE | UF_HIDDEN | UF_READONLY |
+ UF_SYSTEM))
return EOPNOTSUPP;
- if (vap->va_flags & SF_ARCHIVED)
+ if (vap->va_flags & UF_ARCHIVE)
+ dep->de_Attributes |= ATTR_ARCHIVE;
+ else
dep->de_Attributes &= ~ATTR_ARCHIVE;
- else if (!(dep->de_Attributes & ATTR_DIRECTORY))
- dep->de_Attributes |= ATTR_ARCHIVE;
+ if (vap->va_flags & UF_HIDDEN)
+ dep->de_Attributes |= ATTR_HIDDEN;
+ else
+ dep->de_Attributes &= ~ATTR_HIDDEN;
+ /* We don't allow changing the readonly bit on directories. */
+ if (vp->v_type != VDIR) {
+ if (vap->va_flags & UF_READONLY)
+ dep->de_Attributes |= ATTR_READONLY;
+ else
+ dep->de_Attributes &= ~ATTR_READONLY;
+ }
+ if (vap->va_flags & UF_SYSTEM)
+ dep->de_Attributes |= ATTR_SYSTEM;
+ else
+ dep->de_Attributes &= ~ATTR_SYSTEM;
dep->de_flag |= DE_MODIFIED;
}
@@ -476,7 +497,7 @@
*/
break;
}
- error = detrunc(dep, vap->va_size, 0, cred, td);
+ error = detrunc(dep, vap->va_size, 0, cred);
if (error)
return error;
}
@@ -483,27 +504,27 @@
if (vap->va_atime.tv_sec != VNOVAL || vap->va_mtime.tv_sec != VNOVAL) {
if (vp->v_mount->mnt_flag & MNT_RDONLY)
return (EROFS);
- if (vap->va_vaflags & VA_UTIMES_NULL) {
- error = VOP_ACCESS(vp, VADMIN, cred, td);
- if (error)
- error = VOP_ACCESS(vp, VWRITE, cred, td);
- } else
- error = VOP_ACCESS(vp, VADMIN, cred, td);
- if (vp->v_type != VDIR) {
- if ((pmp->pm_flags & MSDOSFSMNT_NOWIN95) == 0 &&
- vap->va_atime.tv_sec != VNOVAL) {
- dep->de_flag &= ~DE_ACCESS;
- timespec2fattime(&vap->va_atime, 0,
- &dep->de_ADate, NULL, NULL);
- }
- if (vap->va_mtime.tv_sec != VNOVAL) {
- dep->de_flag &= ~DE_UPDATE;
- timespec2fattime(&vap->va_mtime, 0,
- &dep->de_MDate, &dep->de_MTime, NULL);
- }
+ error = vn_utimes_perm(vp, vap, cred, td);
+ if (error != 0)
+ return (error);
+ if ((pmp->pm_flags & MSDOSFSMNT_NOWIN95) == 0 &&
+ vap->va_atime.tv_sec != VNOVAL) {
+ dep->de_flag &= ~DE_ACCESS;
+ timespec2fattime(&vap->va_atime, 0,
+ &dep->de_ADate, NULL, NULL);
+ }
+ if (vap->va_mtime.tv_sec != VNOVAL) {
+ dep->de_flag &= ~DE_UPDATE;
+ timespec2fattime(&vap->va_mtime, 0,
+ &dep->de_MDate, &dep->de_MTime, NULL);
+ }
+ /*
+ * We don't set the archive bit when modifying the time of
+ * a directory to emulate the Windows/DOS behavior.
+ */
+ if (vp->v_type != VDIR)
dep->de_Attributes |= ATTR_ARCHIVE;
- dep->de_flag |= DE_MODIFIED;
- }
+ dep->de_flag |= DE_MODIFIED;
}
/*
* DOS files only have the ability to have their writability
@@ -600,7 +621,7 @@
error = bread(vp, lbn, blsize, NOCRED, &bp);
} else if ((vp->v_mount->mnt_flag & MNT_NOCLUSTERR) == 0) {
error = cluster_read(vp, dep->de_FileSize, lbn, blsize,
- NOCRED, on + uio->uio_resid, seqcount, &bp);
+ NOCRED, on + uio->uio_resid, seqcount, 0, &bp);
} else if (seqcount > 1) {
rasize = blsize;
error = breadn(vp, lbn,
@@ -620,11 +641,11 @@
diff = blsize - bp->b_resid;
if (diff < n)
n = diff;
- error = uiomove(bp->b_data + on, (int) n, uio);
+ error = vn_io_fault_uiomove(bp->b_data + on, (int) n, uio);
brelse(bp);
} while (error == 0 && uio->uio_resid > 0 && n != 0);
if (!isadir && (error == 0 || uio->uio_resid != orig_resid) &&
- (vp->v_mount->mnt_flag & MNT_NOATIME) == 0)
+ (vp->v_mount->mnt_flag & (MNT_NOATIME | MNT_RDONLY)) == 0)
dep->de_flag |= DE_ACCESS;
return (error);
}
@@ -756,6 +777,12 @@
* then no need to read data from disk.
*/
bp = getblk(thisvp, bn, pmp->pm_bpcluster, 0, 0, 0);
+ /*
+ * This call to vfs_bio_clrbuf() ensures that
+ * even if vn_io_fault_uiomove() below faults,
+ * garbage from the newly instantiated buffer
+ * is not exposed to the userspace via mmap().
+ */
vfs_bio_clrbuf(bp);
/*
* Do the bmap now, since pcbmap needs buffers
@@ -793,7 +820,7 @@
/*
* Copy the data from user space into the buf header.
*/
- error = uiomove(bp->b_data + croffset, n, uio);
+ error = vn_io_fault_uiomove(bp->b_data + croffset, n, uio);
if (error) {
brelse(bp);
break;
@@ -820,7 +847,7 @@
else if (n + croffset == pmp->pm_bpcluster) {
if ((vp->v_mount->mnt_flag & MNT_NOCLUSTERW) == 0)
cluster_write(vp, bp, dep->de_FileSize,
- seqcount);
+ seqcount, 0);
else
bawrite(bp);
} else
@@ -835,11 +862,11 @@
errexit:
if (error) {
if (ioflag & IO_UNIT) {
- detrunc(dep, osize, ioflag & IO_SYNC, NOCRED, NULL);
+ detrunc(dep, osize, ioflag & IO_SYNC, NOCRED);
uio->uio_offset -= resid - uio->uio_resid;
uio->uio_resid = resid;
} else {
- detrunc(dep, dep->de_FileSize, ioflag & IO_SYNC, NOCRED, NULL);
+ detrunc(dep, dep->de_FileSize, ioflag & IO_SYNC, NOCRED);
if (uio->uio_resid != resid)
error = 0;
}
@@ -1219,6 +1246,17 @@
VOP_UNLOCK(fvp, 0);
goto bad;
}
+ /*
+ * If ip is for a directory, then its name should always
+ * be "." since it is for the directory entry in the
+ * directory itself (msdosfs_lookup() always translates
+ * to the "." entry so as to get a unique denode, except
+ * for the root directory there are different
+ * complications). However, we just corrupted its name
+ * to pass the correct name to createde(). Undo this.
+ */
+ if ((ip->de_Attributes & ATTR_DIRECTORY) != 0)
+ bcopy(oldname, ip->de_Name, 11);
ip->de_refcnt++;
zp->de_fndoffset = from_diroffset;
error = removede(zp, ip);
@@ -1460,7 +1498,6 @@
struct vnode *dvp = ap->a_dvp;
struct componentname *cnp = ap->a_cnp;
struct denode *ip, *dp;
- struct thread *td = cnp->cn_thread;
int error;
ip = VTODE(vp);
@@ -1498,7 +1535,7 @@
/*
* Truncate the directory that is being deleted.
*/
- error = detrunc(ip, (u_long)0, IO_SYNC, cnp->cn_cred, td);
+ error = detrunc(ip, (u_long)0, IO_SYNC, cnp->cn_cred);
cache_purge(vp);
out:
Modified: trunk/sys/fs/msdosfs/msdosfsmount.h
===================================================================
--- trunk/sys/fs/msdosfs/msdosfsmount.h 2018-05-27 22:18:36 UTC (rev 10027)
+++ trunk/sys/fs/msdosfs/msdosfsmount.h 2018-05-27 22:19:26 UTC (rev 10028)
@@ -1,4 +1,5 @@
/* $MidnightBSD$ */
+/* $FreeBSD: stable/10/sys/fs/msdosfs/msdosfsmount.h 281095 2015-04-05 01:03:11Z kib $ */
/* $NetBSD: msdosfsmount.h,v 1.17 1997/11/17 15:37:07 ws Exp $ */
/*-
@@ -239,8 +240,8 @@
gid_t gid; /* gid that owns msdosfs files */
mode_t mask; /* file mask to be applied for msdosfs perms */
int flags; /* see below */
- int magic; /* version number */
- u_int16_t u2w[128]; /* Local->Unicode table */
+ int unused1; /* unused, was version number */
+ u_int16_t unused2[128]; /* no longer used, was Local->Unicode table */
char *cs_win; /* Windows(Unicode) Charset */
char *cs_dos; /* DOS Charset */
char *cs_local; /* Local Charset */
@@ -264,6 +265,4 @@
#define MSDOSFS_LARGEFS 0x10000000 /* perform fileno mapping */
#define MSDOSFS_FSIMOD 0x01000000
-#define MSDOSFS_ARGSMAGIC 0xe4eff300
-
#endif /* !_MSDOSFS_MSDOSFSMOUNT_H_ */
More information about the Midnightbsd-cvs
mailing list