Module Name:    src
Committed By:   martin
Date:           Wed Jan 28 18:34:11 UTC 2015

Modified Files:
        src/sys/ufs/ffs [netbsd-7]: ffs_vfsops.c
        src/sys/ufs/ufs [netbsd-7]: ufs_extern.h ufs_inode.c ufs_vnops.c

Log Message:
Pull up following revision(s) (requested by christos in ticket #425):
        sys/ufs/ufs/ufs_inode.c: revision 1.91-1.92
        sys/ufs/ufs/ufs_vnops.c: revision 1.223-1.224
        sys/ufs/ufs/ufs_extern.h: revision 1.76-1.77
        sys/ufs/ffs/ffs_vfsops.c: revision 1.303-1.305
Add debugging for mount...
Merge some error returns
Check more errors
Restore apple ufs error handling.
Move and unify indirect block truncate algorithm into a separate function.
PR/39371: Tobias Nygren: Don't fail mounting root if WAPBL log is corrupt.
Patch from Sergio L. Pascual.


To generate a diff of this commit:
cvs rdiff -u -r1.299.2.2 -r1.299.2.3 src/sys/ufs/ffs/ffs_vfsops.c
cvs rdiff -u -r1.75 -r1.75.2.1 src/sys/ufs/ufs/ufs_extern.h
cvs rdiff -u -r1.90 -r1.90.2.1 src/sys/ufs/ufs/ufs_inode.c
cvs rdiff -u -r1.221 -r1.221.2.1 src/sys/ufs/ufs/ufs_vnops.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/ufs/ffs/ffs_vfsops.c
diff -u src/sys/ufs/ffs/ffs_vfsops.c:1.299.2.2 src/sys/ufs/ffs/ffs_vfsops.c:1.299.2.3
--- src/sys/ufs/ffs/ffs_vfsops.c:1.299.2.2	Mon Dec 29 16:28:14 2014
+++ src/sys/ufs/ffs/ffs_vfsops.c	Wed Jan 28 18:34:11 2015
@@ -1,4 +1,4 @@
-/*	$NetBSD: ffs_vfsops.c,v 1.299.2.2 2014/12/29 16:28:14 martin Exp $	*/
+/*	$NetBSD: ffs_vfsops.c,v 1.299.2.3 2015/01/28 18:34:11 martin Exp $	*/
 
 /*-
  * Copyright (c) 2008, 2009 The NetBSD Foundation, Inc.
@@ -61,7 +61,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ffs_vfsops.c,v 1.299.2.2 2014/12/29 16:28:14 martin Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ffs_vfsops.c,v 1.299.2.3 2015/01/28 18:34:11 martin Exp $");
 
 #if defined(_KERNEL_OPT)
 #include "opt_ffs.h"
@@ -120,6 +120,12 @@ static kauth_listener_t ffs_snapshot_lis
 /* how many times ffs_init() was called */
 int ffs_initcount = 0;
 
+#ifdef DEBUG_FFS_MOUNT
+#define DPRINTF(a)	printf a
+#else
+#define DPRINTF(a)	do {} while (/*CONSTCOND*/0)
+#endif
+
 extern const struct vnodeopv_desc ffs_vnodeop_opv_desc;
 extern const struct vnodeopv_desc ffs_specop_opv_desc;
 extern const struct vnodeopv_desc ffs_fifoop_opv_desc;
@@ -346,15 +352,22 @@ ffs_mount(struct mount *mp, const char *
 	int error = 0, flags, update;
 	mode_t accessmode;
 
-	if (args == NULL)
+	if (args == NULL) {
+		DPRINTF(("%s: NULL args\n", __func__));
 		return EINVAL;
-	if (*data_len < sizeof *args)
+	}
+	if (*data_len < sizeof(*args)) {
+		DPRINTF(("%s: bad size args %zu != %zu\n",
+		    __func__, *data_len, sizeof(*args)));
 		return EINVAL;
+	}
 
 	if (mp->mnt_flag & MNT_GETARGS) {
 		ump = VFSTOUFS(mp);
-		if (ump == NULL)
+		if (ump == NULL) {
+			DPRINTF(("%s: no ump\n", __func__));
 			return EIO;
+		}
 		args->fspec = NULL;
 		*data_len = sizeof *args;
 		return 0;
@@ -368,18 +381,26 @@ ffs_mount(struct mount *mp, const char *
 		 * Look up the name and verify that it's sane.
 		 */
 		error = namei_simple_user(args->fspec,
-					NSM_FOLLOW_NOEMULROOT, &devvp);
-		if (error != 0)
-			return (error);
+		    NSM_FOLLOW_NOEMULROOT, &devvp);
+		if (error != 0) {
+			DPRINTF(("%s: namei_simple_user %d\n", __func__,
+			    error));
+			return error;
+		}
 
 		if (!update) {
 			/*
 			 * Be sure this is a valid block device
 			 */
-			if (devvp->v_type != VBLK)
+			if (devvp->v_type != VBLK) {
+				DPRINTF(("%s: non block device %d\n",
+				    __func__, devvp->v_type));
 				error = ENOTBLK;
-			else if (bdevsw_lookup(devvp->v_rdev) == NULL)
+			} else if (bdevsw_lookup(devvp->v_rdev) == NULL) {
+				DPRINTF(("%s: can't find block device 0x%jx\n",
+				    __func__, devvp->v_rdev));
 				error = ENXIO;
+			}
 		} else {
 			/*
 			 * Be sure we're still naming the same device
@@ -387,9 +408,13 @@ ffs_mount(struct mount *mp, const char *
 			 */
 			ump = VFSTOUFS(mp);
 			if (devvp != ump->um_devvp) {
-				if (devvp->v_rdev != ump->um_devvp->v_rdev)
+				if (devvp->v_rdev != ump->um_devvp->v_rdev) {
+					DPRINTF(("%s: wrong device 0x%jx"
+					    " != 0x%jx\n", __func__,
+					    (uintmax_t)devvp->v_rdev,
+					    (uintmax_t)ump->um_devvp->v_rdev));
 					error = EINVAL;
-				else {
+				} else {
 					vrele(devvp);
 					devvp = ump->um_devvp;
 					vref(devvp);
@@ -399,7 +424,8 @@ ffs_mount(struct mount *mp, const char *
 	} else {
 		if (!update) {
 			/* New mounts must have a filename for the device */
-			return (EINVAL);
+			DPRINTF(("%s: no filename for mount\n", __func__));
+			return EINVAL;
 		} else {
 			/* Use the extant mount */
 			ump = VFSTOUFS(mp);
@@ -426,6 +452,9 @@ ffs_mount(struct mount *mp, const char *
 		error = kauth_authorize_system(l->l_cred, KAUTH_SYSTEM_MOUNT,
 		    KAUTH_REQ_SYSTEM_MOUNT_DEVICE, mp, devvp,
 		    KAUTH_ARG(accessmode));
+		if (error) {
+			DPRINTF(("%s: kauth %d\n", __func__, error));
+		}
 		VOP_UNLOCK(devvp);
 	}
 
@@ -453,10 +482,13 @@ ffs_mount(struct mount *mp, const char *
 		vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY);
 		error = VOP_OPEN(devvp, xflags, FSCRED);
 		VOP_UNLOCK(devvp);
-		if (error)
+		if (error) {	
+			DPRINTF(("%s: VOP_OPEN %d\n", __func__, error));
 			goto fail;
+		}
 		error = ffs_mountfs(devvp, mp, l);
 		if (error) {
+			DPRINTF(("%s: ffs_mountfs %d\n", __func__, error));
 			vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY);
 			(void)VOP_CLOSE(devvp, xflags, NOCRED);
 			VOP_UNLOCK(devvp);
@@ -497,17 +529,21 @@ ffs_mount(struct mount *mp, const char *
 				fs->fs_clean = FS_ISCLEAN;
 				(void) ffs_sbupdate(ump, MNT_WAIT);
 			}
-			if (error == 0)
-				UFS_WAPBL_END(mp);
-			if (error)
-				return (error);
+			if (error) {
+				DPRINTF(("%s: wapbl %d\n", __func__, error));
+				return error;
+			}
+			UFS_WAPBL_END(mp);
 		}
 
 #ifdef WAPBL
 		if ((mp->mnt_flag & MNT_LOG) == 0) {
 			error = ffs_wapbl_stop(mp, mp->mnt_flag & MNT_FORCE);
-			if (error)
+			if (error) {
+				DPRINTF(("%s: ffs_wapbl_stop %d\n",
+				    __func__, error));
 				return error;
+			}
 		}
 #endif /* WAPBL */
 
@@ -521,8 +557,11 @@ ffs_mount(struct mount *mp, const char *
 
 		if (mp->mnt_flag & MNT_RELOAD) {
 			error = ffs_reload(mp, l->l_cred, l);
-			if (error)
-				return (error);
+			if (error) {
+				DPRINTF(("%s: ffs_reload %d\n",
+				    __func__, error));
+				return error;
+			}
 		}
 
 		if (fs->fs_ronly && (mp->mnt_iflag & IMNT_WANTRDWR)) {
@@ -536,6 +575,8 @@ ffs_mount(struct mount *mp, const char *
 				    mp->mnt_stat.f_mntonname,
 				    (mp->mnt_flag & MNT_FORCE) ? "" :
 				    ", not mounting");
+				DPRINTF(("%s: ffs_quota2 %d\n",
+				    __func__, EINVAL));
 				return EINVAL;
 			}
 #endif
@@ -544,12 +585,19 @@ ffs_mount(struct mount *mp, const char *
 			fs->fs_fmod = 1;
 #ifdef WAPBL
 			if (fs->fs_flags & FS_DOWAPBL) {
-				printf("%s: replaying log to disk\n",
-				    mp->mnt_stat.f_mntonname);
-				KDASSERT(mp->mnt_wapbl_replay);
+				const char *nm = mp->mnt_stat.f_mntonname;
+				if (!mp->mnt_wapbl_replay) {
+					printf("%s: log corrupted;"
+					    " replay cancelled\n", nm);
+					return EFTYPE;
+				}
+				printf("%s: replaying log to disk\n", nm);
 				error = wapbl_replay_write(mp->mnt_wapbl_replay,
-							   devvp);
+				    devvp);
 				if (error) {
+					DPRINTF((
+					    "%s: %s: wapbl_replay_write %d\n",
+					    __func__, nm, error));
 					return error;
 				}
 				wapbl_replay_stop(mp->mnt_wapbl_replay);
@@ -562,14 +610,19 @@ ffs_mount(struct mount *mp, const char *
 
 #ifdef WAPBL
 		error = ffs_wapbl_start(mp);
-		if (error)
+		if (error) {
+			DPRINTF(("%s: ffs_wapbl_start %d\n",
+			    __func__, error));
 			return error;
+		}
 #endif /* WAPBL */
 
 #ifdef QUOTA2
 		if (!fs->fs_ronly) {
 			error = ffs_quota2_mount(mp);
 			if (error) {
+				DPRINTF(("%s: ffs_quota2_mount %d\n",
+				    __func__, error));
 				return error;
 			}
 		}
@@ -587,6 +640,9 @@ ffs_mount(struct mount *mp, const char *
 	if (error == 0)
 		(void)strncpy(fs->fs_fsmnt, mp->mnt_stat.f_mntonname,
 		    sizeof(fs->fs_fsmnt));
+	else {
+	    DPRINTF(("%s: set_statvfs_info %d\n", __func__, error));
+	}
 	fs->fs_flags &= ~FS_DOSOFTDEP;
 	if (fs->fs_fmod != 0) {	/* XXX */
 		int err;
@@ -722,10 +778,11 @@ ffs_reload(struct mount *mp, kauth_cred_
 		 * EINVAL is most probably a blocksize or alignment problem,
 		 * it is unlikely that this is an Apple UFS filesystem then.
 		 */
-		error = bread(devvp, (daddr_t)(APPLEUFS_LABEL_OFFSET / DEV_BSIZE),
-			APPLEUFS_LABEL_SIZE, cred, 0, &bp);
+		error = bread(devvp,
+		    (daddr_t)(APPLEUFS_LABEL_OFFSET / DEV_BSIZE),
+		    APPLEUFS_LABEL_SIZE, cred, 0, &bp);
 		if (error && error != EINVAL) {
-			return (error);
+			return error;
 		}
 		if (error == 0) {
 			error = ffs_appleufs_validate(fs->fs_fsmnt,
@@ -877,8 +934,10 @@ ffs_mountfs(struct vnode *devvp, struct 
 	vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY);
 	error = vinvalbuf(devvp, V_SAVE, cred, l, 0, 0);
 	VOP_UNLOCK(devvp);
-	if (error)
-		return (error);
+	if (error) {
+		DPRINTF(("%s: vinvalbuf %d\n", __func__, error));
+		return error;
+	}
 
 	ronly = (mp->mnt_flag & MNT_RDONLY) != 0;
 
@@ -889,14 +948,18 @@ ffs_mountfs(struct vnode *devvp, struct 
 	fstype = 0;
 
 	error = fstrans_mount(mp);
-	if (error)
+	if (error) {
+		DPRINTF(("%s: fstrans_mount %d\n", __func__, error));
 		return error;
+	}
 
 	ump = kmem_zalloc(sizeof(*ump), KM_SLEEP);
 	mutex_init(&ump->um_lock, MUTEX_DEFAULT, IPL_NONE);
 	error = ffs_snapshot_init(ump);
-	if (error)
+	if (error) {
+		DPRINTF(("%s: ffs_snapshot_init %d\n", __func__, error));
 		goto out;
+	}
 	ump->um_ops = &ffs_ufsops;
 
 #ifdef WAPBL
@@ -911,18 +974,22 @@ ffs_mountfs(struct vnode *devvp, struct 
 			bp = NULL;
 		}
 		if (sblock_try[i] == -1) {
+			DPRINTF(("%s: sblock_try\n", __func__));
 			error = EINVAL;
 			fs = NULL;
 			goto out;
 		}
-		error = bread(devvp, sblock_try[i] / DEV_BSIZE, SBLOCKSIZE, cred,
-			      0, &bp);
+		error = bread(devvp, sblock_try[i] / DEV_BSIZE, SBLOCKSIZE,
+		    cred, 0, &bp);
 		if (error) {
+			DPRINTF(("%s: bread@0x%x %d\n", __func__,
+			    sblock_try[i] / DEV_BSIZE, error));
 			fs = NULL;
 			goto out;
 		}
 		fs = (struct fs*)bp->b_data;
 		fsblockloc = sblockloc = sblock_try[i];
+		DPRINTF(("%s: fs_magic 0x%x\n", __func__, fs->fs_magic));
 		if (fs->fs_magic == FS_UFS1_MAGIC) {
 			sbsize = fs->fs_sbsize;
 			fstype = UFS1;
@@ -1003,8 +1070,11 @@ ffs_mountfs(struct vnode *devvp, struct 
 #ifdef WAPBL
 	if ((mp->mnt_wapbl_replay == 0) && (fs->fs_flags & FS_DOWAPBL)) {
 		error = ffs_wapbl_replay_start(mp, fs, devvp);
-		if (error && (mp->mnt_flag & MNT_FORCE) == 0)
+		if (error && (mp->mnt_flag & MNT_FORCE) == 0) {
+			DPRINTF(("%s: ffs_wapbl_replay_start %d\n", __func__,
+			    error));
 			goto out;
+		}
 		if (!error) {
 			if (!ronly) {
 				/* XXX fsmnt may be stale. */
@@ -1012,8 +1082,11 @@ ffs_mountfs(struct vnode *devvp, struct 
 				    fs->fs_fsmnt);
 				error = wapbl_replay_write(mp->mnt_wapbl_replay,
 				    devvp);
-				if (error)
+				if (error) {
+					DPRINTF(("%s: wapbl_replay_write %d\n",
+					    __func__, error));
 					goto out;
+				}
 				wapbl_replay_stop(mp->mnt_wapbl_replay);
 				fs->fs_clean = FS_WASCLEAN;
 			} else {
@@ -1033,6 +1106,7 @@ ffs_mountfs(struct vnode *devvp, struct 
 #else /* !WAPBL */
 	if ((fs->fs_flags & FS_DOWAPBL) && (mp->mnt_flag & MNT_FORCE) == 0) {
 		error = EPERM;
+		DPRINTF(("%s: no force %d\n", __func__, error));
 		goto out;
 	}
 #endif /* !WAPBL */
@@ -1046,6 +1120,7 @@ ffs_mountfs(struct vnode *devvp, struct 
 		    (mp->mnt_flag & MNT_FORCE) ? "" : ", not mounting");
 		if ((mp->mnt_flag & MNT_FORCE) == 0) {
 			error = EINVAL;
+			DPRINTF(("%s: no force %d\n", __func__, error));
 			goto out;
 		}
 	}
@@ -1073,20 +1148,25 @@ ffs_mountfs(struct vnode *devvp, struct 
 		/* Manually look for an apple ufs label, and if a valid one
 		 * is found, then treat it like an Apple UFS filesystem anyway
 		 */
-		error = bread(devvp, (daddr_t)(APPLEUFS_LABEL_OFFSET / DEV_BSIZE),
-			APPLEUFS_LABEL_SIZE, cred, 0, &bp);
-		if (error)
+		error = bread(devvp,
+		    (daddr_t)(APPLEUFS_LABEL_OFFSET / DEV_BSIZE),
+		    APPLEUFS_LABEL_SIZE, cred, 0, &bp);
+		if (error) {
+			DPRINTF(("%s: apple bread@0x%jx %d\n", __func__,
+			    (intmax_t)(APPLEUFS_LABEL_OFFSET / DEV_BSIZE),
+			    error));
 			goto out;
+		}
 		error = ffs_appleufs_validate(fs->fs_fsmnt,
-			(struct appleufslabel *)bp->b_data, NULL);
-		if (error == 0) {
+		    (struct appleufslabel *)bp->b_data, NULL);
+		if (error == 0)
 			ump->um_flags |= UFS_ISAPPLEUFS;
-		}
 		brelse(bp, 0);
 		bp = NULL;
 	}
 #else
 	if (ump->um_flags & UFS_ISAPPLEUFS) {
+		DPRINTF(("%s: bad apple\n", __func__));
 		error = EINVAL;
 		goto out;
 	}
@@ -1131,11 +1211,17 @@ ffs_mountfs(struct vnode *devvp, struct 
 		error = bread(devvp, FFS_FSBTODB(fs, fs->fs_size - 1),
 		    fs->fs_fsize, cred, 0, &bp);
 		if (error) {
+			DPRINTF(("%s: bread@0x%jx %d\n", __func__,
+			    (intmax_t)FFS_FSBTODB(fs, fs->fs_size - 1),
+			    error));
 			bset = BC_INVAL;
 			goto out;
 		}
-		if (bp->b_bcount != fs->fs_fsize)
+		if (bp->b_bcount != fs->fs_fsize) {
+			DPRINTF(("%s: bcount %x != fsize %x\n", __func__,
+			    bp->b_bcount, fs->fs_fsize));
 			error = EINVAL;
+		}
 		brelse(bp, BC_INVAL);
 		bp = NULL;
 	}
@@ -1162,8 +1248,10 @@ ffs_mountfs(struct vnode *devvp, struct 
 		error = bread(devvp, FFS_FSBTODB(fs, fs->fs_csaddr + i), bsize,
 			      cred, 0, &bp);
 		if (error) {
-			kmem_free(fs->fs_csp, allocsbsize);
-			goto out;
+			DPRINTF(("%s: bread@0x%jx %d\n", __func__,
+			    (intmax_t)FFS_FSBTODB(fs, fs->fs_csaddr + i),
+			    error));
+			goto out1;
 		}
 #ifdef FFS_EI
 		if (needswap)
@@ -1242,12 +1330,16 @@ ffs_mountfs(struct vnode *devvp, struct 
 		 * ffs_wapbl_start() needs mp->mnt_stat initialised if it
 		 * needs to create a new log file in-filesystem.
 		 */
-		ffs_statvfs(mp, &mp->mnt_stat);
+		error = ffs_statvfs(mp, &mp->mnt_stat);
+		if (error) {
+			DPRINTF(("%s: ffs_statvfs %d\n", __func__, error));
+			goto out1;
+		}
 
 		error = ffs_wapbl_start(mp);
 		if (error) {
-			kmem_free(fs->fs_csp, allocsbsize);
-			goto out;
+			DPRINTF(("%s: ffs_wapbl_start %d\n", __func__, error));
+			goto out1;
 		}
 	}
 #endif /* WAPBL */
@@ -1255,8 +1347,8 @@ ffs_mountfs(struct vnode *devvp, struct 
 #ifdef QUOTA2
 		error = ffs_quota2_mount(mp);
 		if (error) {
-			kmem_free(fs->fs_csp, allocsbsize);
-			goto out;
+			DPRINTF(("%s: ffs_quota2_mount %d\n", __func__, error));
+			goto out1;
 		}
 #else
 		if (fs->fs_flags & FS_DOQUOTA2) {
@@ -1266,8 +1358,9 @@ ffs_mountfs(struct vnode *devvp, struct 
 			    (mp->mnt_flag & MNT_FORCE) ? "" : ", not mounting");
 			if ((mp->mnt_flag & MNT_FORCE) == 0) {
 				error = EINVAL;
-				kmem_free(fs->fs_csp, allocsbsize);
-				goto out;
+				DPRINTF(("%s: quota disabled %d\n", __func__,
+				    error));
+				goto out1;
 			}
 		}
 #endif
@@ -1277,6 +1370,8 @@ ffs_mountfs(struct vnode *devvp, struct 
 		ump->um_discarddata = ffs_discard_init(devvp, fs);
 
 	return (0);
+out1:
+	kmem_free(fs->fs_csp, allocsbsize);
 out:
 #ifdef WAPBL
 	if (mp->mnt_wapbl_replay) {

Index: src/sys/ufs/ufs/ufs_extern.h
diff -u src/sys/ufs/ufs/ufs_extern.h:1.75 src/sys/ufs/ufs/ufs_extern.h:1.75.2.1
--- src/sys/ufs/ufs/ufs_extern.h:1.75	Sun May 25 13:48:40 2014
+++ src/sys/ufs/ufs/ufs_extern.h	Wed Jan 28 18:34:11 2015
@@ -1,4 +1,4 @@
-/*	$NetBSD: ufs_extern.h,v 1.75 2014/05/25 13:48:40 hannken Exp $	*/
+/*	$NetBSD: ufs_extern.h,v 1.75.2.1 2015/01/28 18:34:11 martin Exp $	*/
 
 /*-
  * Copyright (c) 1991, 1993, 1994
@@ -111,6 +111,7 @@ int	ufs_getlbns(struct vnode *, daddr_t,
 /* ufs_inode.c */
 int	ufs_reclaim(struct vnode *);
 int	ufs_balloc_range(struct vnode *, off_t, off_t, kauth_cred_t, int);
+int	ufs_truncate(struct vnode *, uint64_t, kauth_cred_t);
 
 /* ufs_lookup.c */
 void	ufs_dirbad(struct inode *, doff_t, const char *);

Index: src/sys/ufs/ufs/ufs_inode.c
diff -u src/sys/ufs/ufs/ufs_inode.c:1.90 src/sys/ufs/ufs/ufs_inode.c:1.90.2.1
--- src/sys/ufs/ufs/ufs_inode.c:1.90	Thu May  8 08:21:53 2014
+++ src/sys/ufs/ufs/ufs_inode.c	Wed Jan 28 18:34:11 2015
@@ -1,4 +1,4 @@
-/*	$NetBSD: ufs_inode.c,v 1.90 2014/05/08 08:21:53 hannken Exp $	*/
+/*	$NetBSD: ufs_inode.c,v 1.90.2.1 2015/01/28 18:34:11 martin Exp $	*/
 
 /*
  * Copyright (c) 1991, 1993
@@ -37,7 +37,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ufs_inode.c,v 1.90 2014/05/08 08:21:53 hannken Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ufs_inode.c,v 1.90.2.1 2015/01/28 18:34:11 martin Exp $");
 
 #if defined(_KERNEL_OPT)
 #include "opt_ffs.h"
@@ -87,7 +87,6 @@ ufs_inactive(void *v)
 	struct mount *transmp;
 	mode_t mode;
 	int error = 0;
-	int logged = 0;
 
 	UFS_WAPBL_JUNLOCK_ASSERT(vp->v_mount);
 
@@ -102,41 +101,8 @@ ufs_inactive(void *v)
 #ifdef UFS_EXTATTR
 		ufs_extattr_vnode_inactive(vp, curlwp);
 #endif
-		error = UFS_WAPBL_BEGIN(vp->v_mount);
-		if (error)
-			goto out;
-		logged = 1;
-		if (ip->i_size != 0) {
-			/*
-			 * When journaling, only truncate one indirect block
-			 * at a time
-			 */
-			if (vp->v_mount->mnt_wapbl) {
-				uint64_t incr = MNINDIR(ip->i_ump) <<
-				    vp->v_mount->mnt_fs_bshift; /* Power of 2 */
-				uint64_t base = UFS_NDADDR <<
-				    vp->v_mount->mnt_fs_bshift;
-				while (!error && ip->i_size > base + incr) {
-					/*
-					 * round down to next full indirect
-					 * block boundary.
-					 */
-					uint64_t nsize = base +
-					    ((ip->i_size - base - 1) &
-					    ~(incr - 1));
-					error = UFS_TRUNCATE(vp, nsize, 0,
-					    NOCRED);
-					if (error)
-						break;
-					UFS_WAPBL_END(vp->v_mount);
-					error = UFS_WAPBL_BEGIN(vp->v_mount);
-					if (error)
-						goto out;
-				}
-			}
-			if (!error)
-				error = UFS_TRUNCATE(vp, (off_t)0, 0, NOCRED);
-		}
+		if (ip->i_size != 0)
+			error = ufs_truncate(vp, 0, NOCRED);
 #if defined(QUOTA) || defined(QUOTA2)
 		(void)chkiq(ip, -1, NOCRED, 0);
 #endif
@@ -152,16 +118,12 @@ ufs_inactive(void *v)
 	}
 
 	if (ip->i_flag & (IN_CHANGE | IN_UPDATE | IN_MODIFIED)) {
-		if (!logged++) {
-			int err;
-			err = UFS_WAPBL_BEGIN(vp->v_mount);
-			if (err)
-				goto out;
-		}
+		error = UFS_WAPBL_BEGIN(vp->v_mount);
+		if (error)
+			goto out;
 		UFS_UPDATE(vp, NULL, NULL, 0);
-	}
-	if (logged)
 		UFS_WAPBL_END(vp->v_mount);
+	}
 out:
 	/*
 	 * If we are done with the inode, reclaim it
@@ -309,3 +271,50 @@ ufs_balloc_range(struct vnode *vp, off_t
  	kmem_free(pgs, pgssize);
 	return error;
 }
+
+static int
+ufs_wapbl_truncate(struct vnode *vp, uint64_t newsize, kauth_cred_t cred)
+{
+	struct inode *ip = VTOI(vp);
+	int error = 0;
+	uint64_t base, incr;
+
+	base = UFS_NDADDR << vp->v_mount->mnt_fs_bshift;
+	incr = MNINDIR(ip->i_ump) << vp->v_mount->mnt_fs_bshift;/* Power of 2 */
+	while (ip->i_size > base + incr &&
+	    (newsize == 0 || ip->i_size > newsize + incr)) {
+		/*
+		 * round down to next full indirect
+		 * block boundary.
+		 */
+		uint64_t nsize = base + ((ip->i_size - base - 1) & ~(incr - 1));
+		error = UFS_TRUNCATE(vp, nsize, 0, cred);
+		if (error)
+			break;
+		UFS_WAPBL_END(vp->v_mount);
+		error = UFS_WAPBL_BEGIN(vp->v_mount);
+		if (error)
+			return error;
+	}
+	return error;
+}
+
+int
+ufs_truncate(struct vnode *vp, uint64_t newsize, kauth_cred_t cred)
+{
+	int error;
+
+	error = UFS_WAPBL_BEGIN(vp->v_mount);
+	if (error)
+		return error;
+
+	if (vp->v_mount->mnt_wapbl)
+		error = ufs_wapbl_truncate(vp, newsize, cred);
+
+	if (error == 0)
+		error = UFS_TRUNCATE(vp, newsize, 0, cred);
+	UFS_WAPBL_END(vp->v_mount);
+
+	return error;
+}
+

Index: src/sys/ufs/ufs/ufs_vnops.c
diff -u src/sys/ufs/ufs/ufs_vnops.c:1.221 src/sys/ufs/ufs/ufs_vnops.c:1.221.2.1
--- src/sys/ufs/ufs/ufs_vnops.c:1.221	Sun May 25 13:46:16 2014
+++ src/sys/ufs/ufs/ufs_vnops.c	Wed Jan 28 18:34:11 2015
@@ -1,4 +1,4 @@
-/*	$NetBSD: ufs_vnops.c,v 1.221 2014/05/25 13:46:16 hannken Exp $	*/
+/*	$NetBSD: ufs_vnops.c,v 1.221.2.1 2015/01/28 18:34:11 martin Exp $	*/
 
 /*-
  * Copyright (c) 2008 The NetBSD Foundation, Inc.
@@ -66,7 +66,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ufs_vnops.c,v 1.221 2014/05/25 13:46:16 hannken Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ufs_vnops.c,v 1.221.2.1 2015/01/28 18:34:11 martin Exp $");
 
 #if defined(_KERNEL_OPT)
 #include "opt_ffs.h"
@@ -579,39 +579,7 @@ ufs_setattr(void *v)
 				error = EPERM;
 				goto out;
 			}
-			error = UFS_WAPBL_BEGIN(vp->v_mount);
-			if (error)
-				goto out;
-			/*
-			 * When journaling, only truncate one indirect block
-			 * at a time.
-			 */
-			if (vp->v_mount->mnt_wapbl) {
-				uint64_t incr = MNINDIR(ip->i_ump) <<
-				    vp->v_mount->mnt_fs_bshift; /* Power of 2 */
-				uint64_t base = UFS_NDADDR <<
-				    vp->v_mount->mnt_fs_bshift;
-				while (!error && ip->i_size > base + incr &&
-				    ip->i_size > vap->va_size + incr) {
-					/*
-					 * round down to next full indirect
-					 * block boundary.
-					 */
-					uint64_t nsize = base +
-					    ((ip->i_size - base - 1) &
-					    ~(incr - 1));
-					error = UFS_TRUNCATE(vp, nsize, 0,
-					    cred);
-					if (error == 0) {
-						UFS_WAPBL_END(vp->v_mount);
-						error =
-						   UFS_WAPBL_BEGIN(vp->v_mount);
-					}
-				}
-			}
-			if (!error)
-				error = UFS_TRUNCATE(vp, vap->va_size, 0, cred);
-			UFS_WAPBL_END(vp->v_mount);
+			error = ufs_truncate(vp, vap->va_size, cred);
 			if (error)
 				goto out;
 			break;

Reply via email to