Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/ufs/lfs Comments
details: https://anonhg.NetBSD.org/src/rev/f8cefedc8acc
branches: trunk
changeset: 346919:f8cefedc8acc
user: dholland <dholland%NetBSD.org@localhost>
date: Sun Aug 07 00:12:48 2016 +0000
description:
Comments
diffstat:
sys/ufs/lfs/lfs_alloc.c | 264 +++++++++++++++++++++++++++++++++++++++++++----
1 files changed, 241 insertions(+), 23 deletions(-)
diffs (truncated from 609 to 300 lines):
diff -r 8d0c08c06906 -r f8cefedc8acc sys/ufs/lfs/lfs_alloc.c
--- a/sys/ufs/lfs/lfs_alloc.c Sat Aug 06 23:46:30 2016 +0000
+++ b/sys/ufs/lfs/lfs_alloc.c Sun Aug 07 00:12:48 2016 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: lfs_alloc.c,v 1.131 2015/10/10 22:34:33 dholland Exp $ */
+/* $NetBSD: lfs_alloc.c,v 1.132 2016/08/07 00:12:48 dholland 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.131 2015/10/10 22:34:33 dholland Exp $");
+__KERNEL_RCSID(0, "$NetBSD: lfs_alloc.c,v 1.132 2016/08/07 00:12:48 dholland Exp $");
#if defined(_KERNEL_OPT)
#include "opt_quota.h"
@@ -127,6 +127,13 @@
ASSERT_SEGLOCK(fs);
+ /* XXX should check or assert that we aren't readonly. */
+
+ /*
+ * Get a block and extend the ifile inode. Leave the buffer for
+ * the block in bp.
+ */
+
vp = fs->lfs_ivnode;
ip = VTOI(vp);
blkno = lfs_lblkno(fs, ip->i_size);
@@ -138,6 +145,11 @@
lfs_dino_setsize(fs, ip->i_din, ip->i_size);
uvm_vnp_setsize(vp, ip->i_size);
+ /*
+ * Compute the new number of inodes, and reallocate the in-memory
+ * inode freemap.
+ */
+
maxino = ((ip->i_size >> lfs_sb_getbshift(fs)) - lfs_sb_getcleansz(fs) -
lfs_sb_getsegtabsz(fs)) * lfs_sb_getifpb(fs);
fs->lfs_ino_bitmap = (lfs_bm_t *)
@@ -145,6 +157,7 @@
sizeof(lfs_bm_t), M_SEGMENT, M_WAITOK);
KASSERT(fs->lfs_ino_bitmap != NULL);
+ /* first new inode number */
i = (blkno - lfs_sb_getsegtabsz(fs) - lfs_sb_getcleansz(fs)) *
lfs_sb_getifpb(fs);
@@ -160,8 +173,17 @@
if (lfs_sb_getfreehd(fs) == LFS_UNUSED_INUM)
panic("inode 0 allocated [2]");
#endif /* DIAGNOSTIC */
+
+ /* inode number to stop at (XXX: why *x*max?) */
xmax = i + lfs_sb_getifpb(fs);
+ /*
+ * Initialize the ifile block.
+ *
+ * XXX: these loops should be restructured to use the accessor
+ * functions instead of using cutpaste polymorphism.
+ */
+
if (fs->lfs_is64) {
for (ifp64 = (IFILE64 *)bp->b_data; i < xmax; ++ifp64) {
SET_BITMAP_FREE(fs, i);
@@ -192,12 +214,23 @@
}
LFS_PUT_TAILFREE(fs, cip, cbp, xmax - 1);
+ /*
+ * Write out the new block.
+ */
+
(void) LFS_BWRITE_LOG(bp); /* Ifile */
return 0;
}
-/* Allocate a new inode. */
+/*
+ * Allocate an inode for a new file.
+ *
+ * Takes the segment lock. Also (while holding it) takes lfs_lock
+ * to frob fs->lfs_fmod.
+ *
+ * XXX: the mode argument is unused; should just get rid of it.
+ */
/* ARGSUSED */
/* VOP_BWRITE 2i times */
int
@@ -220,32 +253,48 @@
/* Get the head of the freelist. */
LFS_GET_HEADFREE(fs, cip, cbp, ino);
+
+ /* paranoia */
KASSERT(*ino != LFS_UNUSED_INUM && *ino != LFS_IFILE_INUM);
-
DLOG((DLOG_ALLOC, "lfs_valloc: allocate inode %" PRId64 "\n",
*ino));
+ /* Update the in-memory inode freemap */
+ CLR_BITMAP_FREE(fs, *ino);
+
/*
- * Remove the inode from the free list and write the new start
- * of the free list into the superblock.
+ * Fetch the ifile entry and make sure the inode is really
+ * free.
*/
- CLR_BITMAP_FREE(fs, *ino);
LFS_IENTRY(ifp, fs, *ino, bp);
if (lfs_if_getdaddr(fs, ifp) != LFS_UNUSED_DADDR)
panic("lfs_valloc: inuse inode %" PRId64 " on the free list",
*ino);
+
+ /* Update the inode freelist head in the superblock. */
LFS_PUT_HEADFREE(fs, cip, cbp, lfs_if_getnextfree(fs, ifp));
DLOG((DLOG_ALLOC, "lfs_valloc: headfree %" PRId64 " -> %ju\n",
*ino, (uintmax_t)lfs_if_getnextfree(fs, ifp)));
- /* version was updated by vfree */
+ /*
+ * Retrieve the version number from the ifile entry. It was
+ * bumped by vfree, so don't bump it again.
+ */
*gen = lfs_if_getversion(fs, ifp);
+
+ /* Done with ifile entry */
brelse(bp, 0);
- /* Extend IFILE so that the next lfs_valloc will succeed. */
if (lfs_sb_getfreehd(fs) == LFS_UNUSED_INUM) {
+ /*
+ * No more inodes; extend the ifile so that the next
+ * lfs_valloc will succeed.
+ */
if ((error = lfs_extend_ifile(fs, cred)) != 0) {
+ /* restore the freelist */
LFS_PUT_HEADFREE(fs, cip, cbp, *ino);
+
+ /* unlock and return */
lfs_segunlock(fs);
return error;
}
@@ -255,19 +304,28 @@
panic("inode 0 allocated [3]");
#endif /* DIAGNOSTIC */
- /* Set superblock modified bit and increment file count. */
+ /* Set superblock modified bit */
mutex_enter(&lfs_lock);
fs->lfs_fmod = 1;
mutex_exit(&lfs_lock);
+
+ /* increment file count */
lfs_sb_addnfiles(fs, 1);
+ /* done */
lfs_segunlock(fs);
-
return 0;
}
/*
- * Allocate a new inode with given inode number and version.
+ * Allocate an inode for a new file, with given inode number and
+ * version.
+ *
+ * Called in the same context as lfs_valloc and therefore shares the
+ * same locking assumptions.
+ *
+ * XXX: WHICH MEANS IT OUGHT TO TAKE THE SEGLOCK WHILE FROBBING THIS
+ * XXX: STUFF. REALLY.
*/
int
lfs_valloc_fixed(struct lfs *fs, ino_t ino, int vers)
@@ -277,42 +335,68 @@
ino_t headino, thisino, oldnext;
CLEANERINFO *cip;
- /* If the Ifile is too short to contain this inum, extend it */
+ /* XXX: check for readonly */
+ /* XXX: assert no seglock */
+ /* XXX: should take seglock (as noted above) */
+
+ /*
+ * If the ifile is too short to contain this inum, extend it.
+ *
+ * XXX: lfs_extend_ifile should take a size instead of always
+ * doing just one block at time.
+ */
while (VTOI(fs->lfs_ivnode)->i_size <= (ino /
lfs_sb_getifpb(fs) + lfs_sb_getcleansz(fs) + lfs_sb_getsegtabsz(fs))
<< lfs_sb_getbshift(fs)) {
lfs_extend_ifile(fs, NOCRED);
}
+ /*
+ * fetch the ifile entry; get the inode freelist next pointer,
+ * and set the version as directed.
+ */
LFS_IENTRY(ifp, fs, ino, bp);
oldnext = lfs_if_getnextfree(fs, ifp);
lfs_if_setversion(fs, ifp, vers);
brelse(bp, 0);
+ /* Get head of inode freelist */
LFS_GET_HEADFREE(fs, cip, cbp, &headino);
if (headino == ino) {
+ /* Easy case: the inode we wanted was at the head */
LFS_PUT_HEADFREE(fs, cip, cbp, oldnext);
} else {
ino_t nextfree;
+ /* Have to find the desired inode in the freelist... */
+
thisino = headino;
while (1) {
+ /* read this ifile entry */
LFS_IENTRY(ifp, fs, thisino, bp);
nextfree = lfs_if_getnextfree(fs, ifp);
+ /* stop if we find it or we hit the end */
if (nextfree == ino ||
nextfree == LFS_UNUSED_INUM)
break;
+ /* nope, keep going... */
thisino = nextfree;
brelse(bp, 0);
}
if (nextfree == LFS_UNUSED_INUM) {
+ /* hit the end -- this inode is not available */
brelse(bp, 0);
+ /* XXX release seglock (see above) */
return ENOENT;
}
+ /* found it; update the next pointer */
lfs_if_setnextfree(fs, ifp, oldnext);
+ /* write the ifile block */
LFS_BWRITE_LOG(bp);
}
+ /* done */
+ /* XXX release seglock (see above) */
return 0;
}
@@ -340,14 +424,18 @@
/*
* Find the previous (next lowest numbered) free inode, if any.
* If there is none, return LFS_UNUSED_INUM.
+ *
+ * XXX: locking?
*/
static inline ino_t
lfs_freelist_prev(struct lfs *fs, ino_t ino)
{
ino_t tino, bound, bb, freehdbb;
- if (lfs_sb_getfreehd(fs) == LFS_UNUSED_INUM) /* No free inodes at all */
+ if (lfs_sb_getfreehd(fs) == LFS_UNUSED_INUM) {
+ /* No free inodes at all */
return LFS_UNUSED_INUM;
+ }
/* Search our own word first */
bound = ino & ~BMMASK;
@@ -375,13 +463,18 @@
if (ISSET_BITMAP_FREE(fs, tino))
break;
+ /* Avoid returning reserved inode numbers */
if (tino <= LFS_IFILE_INUM)
tino = LFS_UNUSED_INUM;
return tino;
}
-/* Free an inode. */
+/*
+ * Free an inode.
+ *
+ * Takes lfs_seglock. Also (independently) takes vp->v_interlock.
+ */
/* ARGUSED */
/* VOP_BWRITE 2i times */
int
@@ -401,6 +494,8 @@
fs = ip->i_lfs;
ino = ip->i_number;
+ /* XXX: assert not readonly */
+
ASSERT_NO_SEGLOCK(fs);
DLOG((DLOG_ALLOC, "lfs_vfree: free ino %lld\n", (long long)ino));
Home |
Main Index |
Thread Index |
Old Index