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;