Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/ufs/lfs Dust off the orphan detection code and try to ma...
details: https://anonhg.NetBSD.org/src/rev/1db942d02994
branches: trunk
changeset: 969563:1db942d02994
user: riastradh <riastradh%NetBSD.org@localhost>
date: Sun Feb 23 08:49:46 2020 +0000
description:
Dust off the orphan detection code and try to make it work.
diffstat:
sys/ufs/lfs/lfs_alloc.c | 162 +++++++++++++++++++++++++++++++++++-----------
sys/ufs/lfs/lfs_extern.h | 5 +-
sys/ufs/lfs/lfs_vfsops.c | 13 ++-
3 files changed, 133 insertions(+), 47 deletions(-)
diffs (283 lines):
diff -r baeed3547f18 -r 1db942d02994 sys/ufs/lfs/lfs_alloc.c
--- a/sys/ufs/lfs/lfs_alloc.c Sun Feb 23 08:49:34 2020 +0000
+++ b/sys/ufs/lfs/lfs_alloc.c Sun Feb 23 08:49:46 2020 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: lfs_alloc.c,v 1.140 2020/02/23 08:49:34 riastradh Exp $ */
+/* $NetBSD: lfs_alloc.c,v 1.141 2020/02/23 08:49:46 riastradh Exp $ */
/*-
* Copyright (c) 1999, 2000, 2001, 2002, 2003, 2007 The NetBSD Foundation, Inc.
@@ -60,7 +60,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: lfs_alloc.c,v 1.140 2020/02/23 08:49:34 riastradh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: lfs_alloc.c,v 1.141 2020/02/23 08:49:46 riastradh Exp $");
#if defined(_KERNEL_OPT)
#include "opt_quota.h"
@@ -705,16 +705,16 @@
* Takes the segmenet lock.
*/
void
-lfs_order_freelist(struct lfs *fs)
+lfs_order_freelist(struct lfs *fs, ino_t **orphanp, size_t *norphanp)
{
CLEANERINFO *cip;
IFILE *ifp = NULL;
struct buf *bp;
ino_t ino, firstino, lastino, maxino;
-#ifdef notyet
- struct vnode *vp;
-#endif
-
+ ino_t *orphan = NULL;
+ size_t norphan = 0;
+ size_t norphan_alloc = 0;
+
ASSERT_NO_SEGLOCK(fs);
lfs_seglock(fs, SEGM_PROT);
@@ -745,7 +745,6 @@
if (ino == LFS_UNUSED_INUM || ino == LFS_IFILE_INUM)
continue;
-#ifdef notyet
/*
* Address orphaned files.
*
@@ -757,40 +756,26 @@
* but presumably it doesn't work... not sure what
* happens to such files currently. -- dholland 20160806
*/
- if (lfs_if_getnextfree(fs, ifp) == LFS_ORPHAN_NEXTFREE(fs) &&
- VFS_VGET(fs->lfs_ivnode->v_mount, ino, LK_EXCLUSIVE, &vp)
- == 0) {
- unsigned segno;
-
- /* get the segment the inode in on disk */
- segno = lfs_dtosn(fs, lfs_if_getdaddr(fs, ifp));
-
- /* truncate the inode */
- lfs_truncate(vp, 0, 0, NOCRED);
- vput(vp);
-
- /* load the segment summary */
- LFS_SEGENTRY(sup, fs, segno, bp);
- /* update the number of bytes in the segment */
- KASSERT(sup->su_nbytes >= DINOSIZE(fs));
- sup->su_nbytes -= DINOSIZE(fs);
- /* write the segment summary */
- LFS_WRITESEGENTRY(sup, fs, segno, bp);
-
- /* Drop the on-disk address */
- lfs_if_setdaddr(fs, ifp, LFS_UNUSED_DADDR);
- /* write the ifile entry */
- LFS_BWRITE_LOG(bp);
-
- /*
- * and reload it (XXX: why? I guess
- * LFS_BWRITE_LOG drops it...)
- */
- LFS_IENTRY(ifp, fs, ino, bp);
-
- /* Fall through to next if block */
+ if (lfs_if_getnextfree(fs, ifp) == LFS_ORPHAN_NEXTFREE(fs)) {
+ if (orphan == NULL) {
+ norphan_alloc = 32; /* XXX pulled from arse */
+ orphan = kmem_zalloc(sizeof(orphan[0]) *
+ norphan_alloc, KM_SLEEP);
+ } else if (norphan == norphan_alloc) {
+ ino_t *orphan_new;
+ if (norphan_alloc >= 4096)
+ norphan_alloc += 4096;
+ else
+ norphan_alloc *= 2;
+ orphan_new = kmem_zalloc(sizeof(orphan[0]) *
+ norphan_alloc, KM_SLEEP);
+ memcpy(orphan_new, orphan, sizeof(orphan[0]) *
+ norphan);
+ kmem_free(orphan, sizeof(orphan[0]) * norphan);
+ orphan = orphan_new;
+ }
+ orphan[norphan++] = ino;
}
-#endif
if (lfs_if_getdaddr(fs, ifp) == LFS_UNUSED_DADDR) {
@@ -837,6 +822,22 @@
/* done */
lfs_segunlock(fs);
+
+ /*
+ * Shrink the array of orphans so we don't have to carry around
+ * the allocation size.
+ */
+ if (norphan < norphan_alloc) {
+ ino_t *orphan_new = kmem_alloc(sizeof(orphan[0]) * norphan,
+ KM_SLEEP);
+ memcpy(orphan_new, orphan, sizeof(orphan[0]) * norphan);
+ kmem_free(orphan, sizeof(orphan[0]) * norphan_alloc);
+ orphan = orphan_new;
+ norphan_alloc = norphan;
+ }
+
+ *orphanp = orphan;
+ *norphanp = norphan;
}
/*
@@ -855,3 +856,82 @@
lfs_if_setnextfree(fs, ifp, LFS_ORPHAN_NEXTFREE(fs));
LFS_BWRITE_LOG(bp);
}
+
+/*
+ * Free orphans discovered during mount. This is a separate stage
+ * because it requires fs->lfs_suflags to be set up, which is not done
+ * by the time we run lfs_order_freelist. It's possible that we could
+ * run lfs_order_freelist later (i.e., set up fs->lfs_suflags sooner)
+ * but that requires more thought than I can put into this at the
+ * moment.
+ */
+void
+lfs_free_orphans(struct lfs *fs, ino_t *orphan, size_t norphan)
+{
+ size_t i;
+
+ for (i = 0; i < norphan; i++) {
+ ino_t ino = orphan[i];
+ unsigned segno;
+ struct vnode *vp;
+ struct inode *ip;
+ struct buf *bp;
+ IFILE *ifp;
+ SEGUSE *sup;
+ int error;
+
+ /* Get the segment the inode is in on disk. */
+ LFS_IENTRY(ifp, fs, ino, bp);
+ segno = lfs_dtosn(fs, lfs_if_getdaddr(fs, ifp));
+ brelse(bp, 0);
+
+ /*
+ * Try to get the vnode. If we can't, tough -- hope
+ * you have backups!
+ */
+ error = VFS_VGET(fs->lfs_ivnode->v_mount, ino, LK_EXCLUSIVE,
+ &vp);
+ if (error) {
+ printf("orphan %jd vget error %d\n", (intmax_t)ino,
+ error);
+ continue;
+ }
+
+ /*
+ * Sanity-check the inode.
+ *
+ * XXX What to do if it is still referenced?
+ */
+ ip = VTOI(vp);
+ if (ip->i_nlink != 0)
+ printf("orphan %jd nlink %d\n", (intmax_t)ino,
+ ip->i_nlink);
+
+ /*
+ * Truncate the inode, to free any blocks allocated for
+ * it, and release it, to free the inode number.
+ *
+ * XXX Isn't it redundant to truncate? Won't vput do
+ * that for us?
+ */
+ error = lfs_truncate(vp, 0, 0, NOCRED);
+ if (error)
+ printf("orphan %jd truncate error %d", (intmax_t)ino,
+ error);
+ vput(vp);
+
+ /* Update the number of bytes in the segment summary. */
+ LFS_SEGENTRY(sup, fs, segno, bp);
+ KASSERT(sup->su_nbytes >= DINOSIZE(fs));
+ sup->su_nbytes -= DINOSIZE(fs);
+ LFS_WRITESEGENTRY(sup, fs, segno, bp);
+
+ /* Drop the on-disk address. */
+ LFS_IENTRY(ifp, fs, ino, bp);
+ lfs_if_setdaddr(fs, ifp, LFS_UNUSED_DADDR);
+ LFS_BWRITE_LOG(bp);
+ }
+
+ if (orphan)
+ kmem_free(orphan, sizeof(orphan[0]) * norphan);
+}
diff -r baeed3547f18 -r 1db942d02994 sys/ufs/lfs/lfs_extern.h
--- a/sys/ufs/lfs/lfs_extern.h Sun Feb 23 08:49:34 2020 +0000
+++ b/sys/ufs/lfs/lfs_extern.h Sun Feb 23 08:49:46 2020 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: lfs_extern.h,v 1.117 2020/02/23 08:42:53 riastradh Exp $ */
+/* $NetBSD: lfs_extern.h,v 1.118 2020/02/23 08:49:46 riastradh Exp $ */
/*-
* Copyright (c) 1999, 2000, 2001, 2002, 2003 The NetBSD Foundation, Inc.
@@ -127,9 +127,10 @@
int lfs_valloc(struct vnode *, int, kauth_cred_t, ino_t *, int *);
int lfs_valloc_fixed(struct lfs *, ino_t, int);
int lfs_vfree(struct vnode *, ino_t, int);
-void lfs_order_freelist(struct lfs *);
+void lfs_order_freelist(struct lfs *, ino_t **, size_t *);
int lfs_extend_ifile(struct lfs *, kauth_cred_t);
void lfs_orphan(struct lfs *, ino_t);
+void lfs_free_orphans(struct lfs *, ino_t *, size_t);
/* lfs_balloc.c */
int lfs_balloc(struct vnode *, off_t, int, kauth_cred_t, int, struct buf **);
diff -r baeed3547f18 -r 1db942d02994 sys/ufs/lfs/lfs_vfsops.c
--- a/sys/ufs/lfs/lfs_vfsops.c Sun Feb 23 08:49:34 2020 +0000
+++ b/sys/ufs/lfs/lfs_vfsops.c Sun Feb 23 08:49:46 2020 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: lfs_vfsops.c,v 1.372 2020/02/23 08:40:49 riastradh Exp $ */
+/* $NetBSD: lfs_vfsops.c,v 1.373 2020/02/23 08:49:46 riastradh Exp $ */
/*-
* Copyright (c) 1999, 2000, 2001, 2002, 2003, 2007, 2007
@@ -61,7 +61,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: lfs_vfsops.c,v 1.372 2020/02/23 08:40:49 riastradh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: lfs_vfsops.c,v 1.373 2020/02/23 08:49:46 riastradh Exp $");
#if defined(_KERNEL_OPT)
#include "opt_lfs.h"
@@ -870,6 +870,8 @@
CLEANERINFO *cip;
SEGUSE *sup;
daddr_t sb_addr;
+ ino_t *orphan;
+ size_t norphan;
cred = l ? l->l_cred : NOCRED;
@@ -1162,8 +1164,8 @@
fs->lfs_ivnode = vp;
vref(vp);
- /* Set up inode bitmap and order free list */
- lfs_order_freelist(fs);
+ /* Set up inode bitmap, order free list, and gather orphans. */
+ lfs_order_freelist(fs, &orphan, &norphan);
/* Set up segment usage flags for the autocleaner. */
fs->lfs_nactive = 0;
@@ -1202,6 +1204,9 @@
brelse(bp, 0);
}
+ /* Free the orphans we discovered while ordering the freelist. */
+ lfs_free_orphans(fs, orphan, norphan);
+
/*
* XXX: if the fs has quotas, quotas should be on even if
* readonly. Otherwise you can't query the quota info!
Home |
Main Index |
Thread Index |
Old Index