Source-Changes-HG archive

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

[src/trunk]: src/sys/ufs/ffs ffs_indirtrunc(): for !wapbl, restore rev 1.117 ...



details:   https://anonhg.NetBSD.org/src/rev/bb0f5c4c63ff
branches:  trunk
changeset: 348832:bb0f5c4c63ff
user:      jdolecek <jdolecek%NetBSD.org@localhost>
date:      Thu Nov 10 19:10:05 2016 +0000

description:
ffs_indirtrunc(): for !wapbl, restore rev 1.117 behavior of writing the zeroed
(indirect) block before freeing the referenced blocks; it's necessary for
fsck to recover the filesystem, if system goes down during truncate

patch courtesy of hannken@ with only sligh tweaks

diffstat:

 sys/ufs/ffs/ffs_inode.c |  61 +++++++++++++++++++++++++++++++++++++-----------
 1 files changed, 47 insertions(+), 14 deletions(-)

diffs (119 lines):

diff -r ad86af02831f -r bb0f5c4c63ff sys/ufs/ffs/ffs_inode.c
--- a/sys/ufs/ffs/ffs_inode.c   Thu Nov 10 18:35:17 2016 +0000
+++ b/sys/ufs/ffs/ffs_inode.c   Thu Nov 10 19:10:05 2016 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: ffs_inode.c,v 1.120 2016/11/07 21:14:23 jdolecek Exp $ */
+/*     $NetBSD: ffs_inode.c,v 1.121 2016/11/10 19:10:05 jdolecek Exp $ */
 
 /*-
  * Copyright (c) 2008 The NetBSD Foundation, Inc.
@@ -61,7 +61,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ffs_inode.c,v 1.120 2016/11/07 21:14:23 jdolecek Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ffs_inode.c,v 1.121 2016/11/10 19:10:05 jdolecek Exp $");
 
 #if defined(_KERNEL_OPT)
 #include "opt_ffs.h"
@@ -533,6 +533,8 @@
         * blocks were deallocated creating a hole, but that is okay.
         */
        if (error == EAGAIN) {
+               if (!allerror)
+                       allerror = error;
                length = osize;
                uvm_vnp_setsize(ovp, length);
        }
@@ -573,10 +575,12 @@
        int64_t *bap2 = NULL;
        struct vnode *vp;
        daddr_t nb, nlbn, last;
+       char *copy = NULL;
        int64_t factor;
        int64_t nblocks;
-       int error = 0;
+       int error = 0, allerror = 0;
        const int needswap = UFS_FSNEEDSWAP(fs);
+       const int wapbl = (ip->i_ump->um_mountp->mnt_wapbl != NULL);
 
 #define RBAP(ip, i) (((ip)->i_ump->um_fstype == UFS1) ? \
            ufs_rw32(bap1[i], needswap) : ufs_rw64(bap2[i], needswap))
@@ -602,7 +606,7 @@
        nblocks = btodb(fs->fs_bsize);
        /*
         * Get buffer of block pointers, zero those entries corresponding
-        * to blocks to be free'd, and update on disk copy.  Since
+        * to blocks to be free'd, and update on disk copy first.  Since
         * double(triple) indirect before single(double) indirect, calls
         * to bmap on these blocks will fail.  However, we already have
         * the on disk address, so we have to set the b_blkno field
@@ -635,13 +639,35 @@
                return error;
        }
 
-       if (ip->i_ump->um_fstype == UFS1)
-               bap1 = (int32_t *)bp->b_data;
-       else
-               bap2 = (int64_t *)bp->b_data;
+       /*
+        * Clear reference to blocks to be removed on disk, before actually
+        * reclaiming them, so that fsck is more likely to be able to recover
+        * the filesystem if system goes down during the truncate process.
+        * This assumes the truncate process would not fail, contrary
+        * to the wapbl case.
+        */
+       if (lastbn >= 0 && !wapbl) {
+               copy = kmem_alloc(fs->fs_bsize, KM_SLEEP);
+               memcpy((void *)copy, bp->b_data, (u_int)fs->fs_bsize);
+               for (i = last + 1; i < FFS_NINDIR(fs); i++)
+                       BAP_ASSIGN(ip, i, 0);
+               error = bwrite(bp);
+               if (error)
+                       allerror = error;
+
+               if (ip->i_ump->um_fstype == UFS1)
+                       bap1 = (int32_t *)copy;
+               else
+                       bap2 = (int64_t *)copy;
+       } else {
+               if (ip->i_ump->um_fstype == UFS1)
+                       bap1 = (int32_t *)bp->b_data;
+               else
+                       bap2 = (int64_t *)bp->b_data;
+       }
 
        /*
-        * Recursively free totally unused blocks, starting from first.
+        * Recursively free totally unused blocks.
         */
        for (i = FFS_NINDIR(fs) - 1, nlbn = lbn + 1 - i * factor; i > last;
            i--, nlbn += factor) {
@@ -686,15 +712,22 @@
        }
 
 out:
-       if (lastbn < 0 && error == 0) {
+       if (error && !allerror)
+               allerror = error;
+
+       if (copy != NULL) {
+               kmem_free(copy, fs->fs_bsize);
+       } else if (lastbn < 0 && error == 0) {
                /* all freed, release without writing back */
                brelse(bp, BC_INVAL);
-       } else {
-               /* only partially freed, write the updated block */
-               (void) bwrite(bp);
+       } else if (wapbl) {
+               /* only partially freed, write the updated block */
+               error = bwrite(bp);
+               if (!allerror)
+                       allerror = error;
        }
 
-       return (error);
+       return (allerror);
 }
 
 void



Home | Main Index | Thread Index | Old Index