Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/ufs/ffs adjust ffs_realloccg() so that the logic about a...



details:   https://anonhg.NetBSD.org/src/rev/63be85dd550a
branches:  trunk
changeset: 818099:63be85dd550a
user:      jdolecek <jdolecek%NetBSD.org@localhost>
date:      Sun Sep 25 17:14:59 2016 +0000

description:
adjust ffs_realloccg() so that the logic about allocating full
contiguous block for future fragment expansion doesn't need to
UFS_WAPBL_REGISTER_DEALLOCATION() or ffs_blkfree(); the free blocks
are now immediatelly available for use by the expanding file in further i/o

primary driver is safe removal of the deallocation registration and
hence failure point, but this also fixes degenerate case for wapbl,
and similar also for discard - if the file would be actually expanded
before wapbl commit, or before discard queue would be processed,
the filesystem would not yet see the contiguous free blocks, and
would be forced to allocate another fragment elsewhere

diffstat:

 sys/ufs/ffs/ffs_alloc.c |  78 ++++++++++++++++++++++++++++--------------------
 1 files changed, 45 insertions(+), 33 deletions(-)

diffs (211 lines):

diff -r acd07bd682e6 -r 63be85dd550a sys/ufs/ffs/ffs_alloc.c
--- a/sys/ufs/ffs/ffs_alloc.c   Sun Sep 25 12:59:19 2016 +0000
+++ b/sys/ufs/ffs/ffs_alloc.c   Sun Sep 25 17:14:59 2016 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: ffs_alloc.c,v 1.151 2015/08/12 14:52:35 riastradh Exp $        */
+/*     $NetBSD: ffs_alloc.c,v 1.152 2016/09/25 17:14:59 jdolecek 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.151 2015/08/12 14:52:35 riastradh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ffs_alloc.c,v 1.152 2016/09/25 17:14:59 jdolecek Exp $");
 
 #if defined(_KERNEL_OPT)
 #include "opt_ffs.h"
@@ -107,14 +107,14 @@
 #include <uvm/uvm.h>
 #endif
 
-static daddr_t ffs_alloccg(struct inode *, int, daddr_t, int, int);
-static daddr_t ffs_alloccgblk(struct inode *, struct buf *, daddr_t, int);
+static daddr_t ffs_alloccg(struct inode *, int, daddr_t, int, int, int);
+static daddr_t ffs_alloccgblk(struct inode *, struct buf *, daddr_t, int, int);
 static ino_t ffs_dirpref(struct inode *);
 static daddr_t ffs_fragextend(struct inode *, int, daddr_t, int, int);
 static void ffs_fserr(struct fs *, kauth_cred_t, const char *);
-static daddr_t ffs_hashalloc(struct inode *, int, daddr_t, int, int,
-    daddr_t (*)(struct inode *, int, daddr_t, int, int));
-static daddr_t ffs_nodealloccg(struct inode *, int, daddr_t, int, int);
+static daddr_t ffs_hashalloc(struct inode *, int, daddr_t, int, int, int,
+    daddr_t (*)(struct inode *, int, daddr_t, int, int, int));
+static daddr_t ffs_nodealloccg(struct inode *, int, daddr_t, int, int, int);
 static int32_t ffs_mapsearch(struct fs *, struct cg *,
                                      daddr_t, int);
 static void ffs_blkfree_common(struct ufsmount *, struct fs *, dev_t, struct buf *,
@@ -174,8 +174,8 @@
  * => releases um_lock before returning
  */
 int
-ffs_alloc(struct inode *ip, daddr_t lbn, daddr_t bpref, int size, int flags,
-    kauth_cred_t cred, daddr_t *bnp)
+ffs_alloc(struct inode *ip, daddr_t lbn, daddr_t bpref, int size,
+    int flags, kauth_cred_t cred, daddr_t *bnp)
 {
        struct ufsmount *ump;
        struct fs *fs;
@@ -257,7 +257,7 @@
                cg = ino_to_cg(fs, ip->i_number);
        else
                cg = dtog(fs, bpref);
-       bno = ffs_hashalloc(ip, cg, bpref, size, flags, ffs_alloccg);
+       bno = ffs_hashalloc(ip, cg, bpref, size, 0, flags, ffs_alloccg);
        if (bno > 0) {
                DIP_ADD(ip, blocks, btodb(size));
                ip->i_flag |= IN_CHANGE | IN_UPDATE;
@@ -476,7 +476,7 @@
                panic("ffs_realloccg: bad optim");
                /* NOTREACHED */
        }
-       bno = ffs_hashalloc(ip, cg, bpref, request, 0, ffs_alloccg);
+       bno = ffs_hashalloc(ip, cg, bpref, request, nsize, 0, ffs_alloccg);
        if (bno > 0) {
                if ((ip->i_ump->um_mountp->mnt_wapbl) &&
                    (ITOV(ip)->v_type != VREG)) {
@@ -487,18 +487,6 @@
                        ffs_blkfree(fs, ip->i_devvp, bprev, (long)osize,
                            ip->i_number);
                }
-               if (nsize < request) {
-                       if ((ip->i_ump->um_mountp->mnt_wapbl) &&
-                           (ITOV(ip)->v_type != VREG)) {
-                               UFS_WAPBL_REGISTER_DEALLOCATION(
-                                   ip->i_ump->um_mountp,
-                                   FFS_FSBTODB(fs, (bno + ffs_numfrags(fs, nsize))),
-                                   request - nsize);
-                       } else
-                               ffs_blkfree(fs, ip->i_devvp,
-                                   bno + ffs_numfrags(fs, nsize),
-                                   (long)(request - nsize), ip->i_number);
-               }
                DIP_ADD(ip, blocks, btodb(nsize - osize));
                ip->i_flag |= IN_CHANGE | IN_UPDATE;
                if (bpp != NULL) {
@@ -595,7 +583,7 @@
                if (fs->fs_contigdirs[cg] > 0)
                        fs->fs_contigdirs[cg]--;
        }
-       ino = (ino_t)ffs_hashalloc(pip, cg, ipref, mode, 0, ffs_nodealloccg);
+       ino = (ino_t)ffs_hashalloc(pip, cg, ipref, mode, 0, 0, ffs_nodealloccg);
        if (ino == 0)
                goto noinodes;
        UFS_WAPBL_END(pvp->v_mount);
@@ -900,7 +888,9 @@
 static daddr_t
 ffs_hashalloc(struct inode *ip, int cg, daddr_t pref,
     int size /* size for data blocks, mode for inodes */,
-    int flags, daddr_t (*allocator)(struct inode *, int, daddr_t, int, int))
+    int realsize,
+    int flags,
+    daddr_t (*allocator)(struct inode *, int, daddr_t, int, int, int))
 {
        struct fs *fs;
        daddr_t result;
@@ -910,7 +900,7 @@
        /*
         * 1: preferred cylinder group
         */
-       result = (*allocator)(ip, cg, pref, size, flags);
+       result = (*allocator)(ip, cg, pref, size, realsize, flags);
        if (result)
                return (result);
 
@@ -923,7 +913,7 @@
                cg += i;
                if (cg >= fs->fs_ncg)
                        cg -= fs->fs_ncg;
-               result = (*allocator)(ip, cg, 0, size, flags);
+               result = (*allocator)(ip, cg, 0, size, realsize, flags);
                if (result)
                        return (result);
        }
@@ -934,7 +924,7 @@
         */
        cg = (icg + 2) % fs->fs_ncg;
        for (i = 2; i < fs->fs_ncg; i++) {
-               result = (*allocator)(ip, cg, 0, size, flags);
+               result = (*allocator)(ip, cg, 0, size, realsize, flags);
                if (result)
                        return (result);
                cg++;
@@ -1034,7 +1024,8 @@
  * and if it is, allocate it.
  */
 static daddr_t
-ffs_alloccg(struct inode *ip, int cg, daddr_t bpref, int size, int flags)
+ffs_alloccg(struct inode *ip, int cg, daddr_t bpref, int size, int realsize,
+    int flags)
 {
        struct ufsmount *ump;
        struct fs *fs = ip->i_fs;
@@ -1067,9 +1058,23 @@
                cgp->cg_time = ufs_rw64(time_second, needswap);
        if (size == fs->fs_bsize) {
                mutex_enter(&ump->um_lock);
-               blkno = ffs_alloccgblk(ip, bp, bpref, flags);
+               blkno = ffs_alloccgblk(ip, bp, bpref, realsize, flags);
                ACTIVECG_CLR(fs, cg);
                mutex_exit(&ump->um_lock);
+
+               /*
+                * If actually needed size is lower, free the extra blocks now.
+                * This is safe to call here, there is no outside reference
+                * to this block yet. It is not necessary to keep um_lock
+                * locked.
+                */
+               if (realsize != 0 && realsize < size) {
+                       ffs_blkfree_common(ip->i_ump, ip->i_fs,
+                           ip->i_devvp->v_rdev,
+                           bp, blkno + ffs_numfrags(fs, realsize),
+                           (long)(size - realsize), false);
+               }
+
                bdwrite(bp);
                return (blkno);
        }
@@ -1091,7 +1096,7 @@
                if (cgp->cg_cs.cs_nbfree == 0)
                        goto fail;
                mutex_enter(&ump->um_lock);
-               blkno = ffs_alloccgblk(ip, bp, bpref, flags);
+               blkno = ffs_alloccgblk(ip, bp, bpref, realsize, flags);
                bno = dtogd(fs, blkno);
                for (i = frags; i < fs->fs_frag; i++)
                        setbit(blksfree, bno + i);
@@ -1150,7 +1155,8 @@
  * blocks may be fragmented by the routine that allocates them.
  */
 static daddr_t
-ffs_alloccgblk(struct inode *ip, struct buf *bp, daddr_t bpref, int flags)
+ffs_alloccgblk(struct inode *ip, struct buf *bp, daddr_t bpref, int realsize,
+    int flags)
 {
        struct fs *fs = ip->i_fs;
        struct cg *cgp;
@@ -1186,8 +1192,13 @@
         * Take the next available block in this cylinder group.
         */
        bno = ffs_mapsearch(fs, cgp, bpref, (int)fs->fs_frag);
+#if 0 
+       /*
+        * XXX jdolecek ffs_mapsearch() succeeds or panics
+        */
        if (bno < 0)
                return (0);
+#endif
        cgp->cg_rotor = ufs_rw32(bno, needswap);
 gotit:
        blkno = ffs_fragstoblks(fs, bno);
@@ -1224,7 +1235,8 @@
  *      inode in the specified cylinder group.
  */
 static daddr_t
-ffs_nodealloccg(struct inode *ip, int cg, daddr_t ipref, int mode, int flags)
+ffs_nodealloccg(struct inode *ip, int cg, daddr_t ipref, int mode, int realsize,
+    int flags)
 {
        struct ufsmount *ump = ip->i_ump;
        struct fs *fs = ip->i_fs;



Home | Main Index | Thread Index | Old Index