Pull up following revision(s) (requested by kardel in ticket #1697):
sys/ufs/ffs/ffs_alloc.c: revision 1.164 PR/53990, PR/52380, PR/52102: UFS2 cylinder group inode allocation botch Fix rare allocation botch in ffs_nodealloccg(). Conditions: a) less than #_of_initialized_inodes(cg->cg_initediblk) - inodes_per_filesystem_block are allocated in the cylinder group b) cg->cg_irotor points to a uninterupted run of allocated inodes in the inode bitmap up to the end of dynamically initialized inodes (cg->cg_initediblk) In this case the next inode after this run was returned without initializing the respective inode block. As the block is not initialized these inodes could trigger panics on inode consistency due to old (uninitialized) disk data. In very rare cases data loss could occur when the uninitialized inode block is initialized via the normal mechanism. Further conditions to occur after the above: c) no panic d) no (forced) fsck e) and more than cg->cg_initediblk - inodes_per_filesystem_block allocated inodes. Fix: Always insure allocation always in initialized inode range extending the initialized inode range as needed. Add KASSERTMSG() safeguards. ok hannken@
This commit is contained in:
parent
5864656c76
commit
784cecf3c2
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: ffs_alloc.c,v 1.146.2.1 2015/08/14 05:29:14 msaitoh Exp $ */
|
||||
/* $NetBSD: ffs_alloc.c,v 1.146.2.1.2.1 2019/05/29 15:55:18 martin Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2008, 2009 The NetBSD Foundation, Inc.
|
||||
|
@ -70,7 +70,7 @@
|
|||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: ffs_alloc.c,v 1.146.2.1 2015/08/14 05:29:14 msaitoh Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: ffs_alloc.c,v 1.146.2.1.2.1 2019/05/29 15:55:18 martin Exp $");
|
||||
|
||||
#if defined(_KERNEL_OPT)
|
||||
#include "opt_ffs.h"
|
||||
|
@ -1283,7 +1283,7 @@ ffs_nodealloccg(struct inode *ip, int cg, daddr_t ipref, int mode, int flags)
|
|||
struct buf *bp, *ibp;
|
||||
u_int8_t *inosused;
|
||||
int error, start, len, loc, map, i;
|
||||
int32_t initediblk;
|
||||
int32_t initediblk, maxiblk, irotor;
|
||||
daddr_t nalloc;
|
||||
struct ufs2_dinode *dp2;
|
||||
const int needswap = UFS_FSNEEDSWAP(fs);
|
||||
|
@ -1295,7 +1295,13 @@ ffs_nodealloccg(struct inode *ip, int cg, daddr_t ipref, int mode, int flags)
|
|||
return (0);
|
||||
mutex_exit(&ump->um_lock);
|
||||
ibp = NULL;
|
||||
initediblk = -1;
|
||||
if (fs->fs_magic == FS_UFS2_MAGIC) {
|
||||
initediblk = -1;
|
||||
} else {
|
||||
initediblk = fs->fs_ipg;
|
||||
}
|
||||
maxiblk = initediblk;
|
||||
|
||||
retry:
|
||||
error = bread(ip->i_devvp, FFS_FSBTODB(fs, cgtod(fs, cg)),
|
||||
(int)fs->fs_cgsize, NOCRED, B_MODIFY, &bp);
|
||||
|
@ -1315,7 +1321,8 @@ retry:
|
|||
* Check to see if we need to initialize more inodes.
|
||||
*/
|
||||
if (fs->fs_magic == FS_UFS2_MAGIC && ibp == NULL) {
|
||||
initediblk = ufs_rw32(cgp->cg_initediblk, needswap);
|
||||
initediblk = ufs_rw32(cgp->cg_initediblk, needswap);
|
||||
maxiblk = initediblk;
|
||||
nalloc = fs->fs_ipg - ufs_rw32(cgp->cg_cs.cs_nifree, needswap);
|
||||
if (nalloc + FFS_INOPB(fs) > initediblk &&
|
||||
initediblk < ufs_rw32(cgp->cg_niblk, needswap)) {
|
||||
|
@ -1331,6 +1338,9 @@ retry:
|
|||
FFS_NOBLK, fs->fs_bsize, false, &ibp);
|
||||
if (error)
|
||||
goto fail;
|
||||
|
||||
maxiblk += FFS_INOPB(fs);
|
||||
|
||||
goto retry;
|
||||
}
|
||||
}
|
||||
|
@ -1340,14 +1350,22 @@ retry:
|
|||
(fs->fs_old_flags & FS_FLAGS_UPDATED))
|
||||
cgp->cg_time = ufs_rw64(time_second, needswap);
|
||||
inosused = cg_inosused(cgp, needswap);
|
||||
|
||||
if (ipref) {
|
||||
ipref %= fs->fs_ipg;
|
||||
if (isclr(inosused, ipref))
|
||||
/* safeguard to stay in (to be) allocated range */
|
||||
if (ipref < maxiblk && isclr(inosused, ipref))
|
||||
goto gotit;
|
||||
}
|
||||
start = ufs_rw32(cgp->cg_irotor, needswap) / NBBY;
|
||||
len = howmany(fs->fs_ipg - ufs_rw32(cgp->cg_irotor, needswap),
|
||||
NBBY);
|
||||
|
||||
irotor = ufs_rw32(cgp->cg_irotor, needswap);
|
||||
|
||||
KASSERTMSG(irotor < initediblk, "%s: allocation botch: cg=%d, irotor %d"
|
||||
" out of bounds, initediblk=%d",
|
||||
__func__, cg, irotor, initediblk);
|
||||
|
||||
start = irotor / NBBY;
|
||||
len = howmany(maxiblk - irotor, NBBY);
|
||||
loc = skpc(0xff, len, &inosused[start]);
|
||||
if (loc == 0) {
|
||||
len = start + 1;
|
||||
|
@ -1367,9 +1385,17 @@ retry:
|
|||
printf("fs = %s\n", fs->fs_fsmnt);
|
||||
panic("ffs_nodealloccg: block not in map");
|
||||
}
|
||||
|
||||
ipref = i * NBBY + ffs(map) - 1;
|
||||
|
||||
cgp->cg_irotor = ufs_rw32(ipref, needswap);
|
||||
|
||||
gotit:
|
||||
KASSERTMSG(ipref < maxiblk, "%s: allocation botch: cg=%d attempt to "
|
||||
"allocate inode index %d beyond max allocated index %d"
|
||||
" of %d inodes/cg",
|
||||
__func__, cg, (int)ipref, maxiblk, cgp->cg_niblk);
|
||||
|
||||
UFS_WAPBL_REGISTER_INODE(ip->i_ump->um_mountp, cg * fs->fs_ipg + ipref,
|
||||
mode);
|
||||
/*
|
||||
|
|
Loading…
Reference in New Issue