Source-Changes-HG archive

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

[src/trunk]: src/sys/ufs/ffs Refine the scope of WAPBL transactions so we sho...



details:   https://anonhg.NetBSD.org/src/rev/cfa0de4895ec
branches:  trunk
changeset: 762158:cfa0de4895ec
user:      hannken <hannken%NetBSD.org@localhost>
date:      Wed Feb 16 19:43:50 2011 +0000

description:
Refine the scope of WAPBL transactions so we should no longer get
a "wapbl_flush: current transaction too big to flush" panic when
creating or removing snapshots on larger logging disks.

Adresses PR #44568 (WAPBL doens't play nice with snapshots).

diffstat:

 sys/ufs/ffs/ffs_snapshot.c |  155 +++++++++++++++++++++++++++++++++-----------
 1 files changed, 116 insertions(+), 39 deletions(-)

diffs (truncated from 408 to 300 lines):

diff -r 1e35eedfad09 -r cfa0de4895ec sys/ufs/ffs/ffs_snapshot.c
--- a/sys/ufs/ffs/ffs_snapshot.c        Wed Feb 16 19:43:05 2011 +0000
+++ b/sys/ufs/ffs/ffs_snapshot.c        Wed Feb 16 19:43:50 2011 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: ffs_snapshot.c,v 1.102 2010/12/20 00:25:47 matt Exp $  */
+/*     $NetBSD: ffs_snapshot.c,v 1.103 2011/02/16 19:43:50 hannken Exp $       */
 
 /*
  * Copyright 2000 Marshall Kirk McKusick. All Rights Reserved.
@@ -38,7 +38,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ffs_snapshot.c,v 1.102 2010/12/20 00:25:47 matt Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ffs_snapshot.c,v 1.103 2011/02/16 19:43:50 hannken Exp $");
 
 #if defined(_KERNEL_OPT)
 #include "opt_ffs.h"
@@ -114,6 +114,7 @@
 static int rwfsblk(struct vnode *, int, void *, daddr_t);
 static int syncsnap(struct vnode *);
 static int wrsnapblk(struct vnode *, void *, daddr_t);
+static int blocks_in_journal(struct fs *);
 
 static inline bool is_active_snapshot(struct snap_info *, struct inode *);
 static inline daddr_t db_get(struct inode *, int);
@@ -403,11 +404,12 @@
 static int
 snapshot_setup(struct mount *mp, struct vnode *vp)
 {
-       int error, i, len, loc;
+       int error, n, len, loc;
        daddr_t blkno, numblks;
        struct buf *ibp, *nbp;
        struct fs *fs = VFSTOUFS(mp)->um_fs;
        struct lwp *l = curlwp;
+       const int wbreak = blocks_in_journal(fs)/8;
 
        /*
         * Check mount, exclusive reference and owner.
@@ -452,13 +454,13 @@
        error = UFS_WAPBL_BEGIN(mp);
        if (error)
                return error;
-       for (blkno = NDADDR, i = 0; blkno < numblks; blkno += NINDIR(fs)) {
+       for (blkno = NDADDR, n = 0; blkno < numblks; blkno += NINDIR(fs)) {
                error = ffs_balloc(vp, lblktosize(fs, (off_t)blkno),
                    fs->fs_bsize, l->l_cred, B_METAONLY, &ibp);
                if (error)
                        goto out;
                brelse(ibp, 0);
-               if ((++i % 16) == 0) {
+               if (wbreak > 0 && (++n % wbreak) == 0) {
                        UFS_WAPBL_END(mp);
                        error = UFS_WAPBL_BEGIN(mp);
                        if (error)
@@ -561,7 +563,6 @@
 snapshot_expunge(struct mount *mp, struct vnode *vp, struct fs *copy_fs,
     daddr_t *snaplistsize, daddr_t **snaplist)
 {
-       bool has_wapbl = false;
        int cg, error, len, loc;
        daddr_t blkno, *blkp;
        struct fs *fs = VFSTOUFS(mp)->um_fs;
@@ -593,10 +594,6 @@
         */
        *snaplistsize = fs->fs_ncg + howmany(fs->fs_cssize, fs->fs_bsize) +
            FSMAXSNAP + 1 /* superblock */ + 1 /* last block */ + 1 /* size */;
-       error = UFS_WAPBL_BEGIN(mp);
-       if (error)
-               goto out;
-       has_wapbl = true;
        mutex_enter(&mntvnode_lock);
        /*
         * NOTE: not using the TAILQ_FOREACH here since in this loop vgone()
@@ -648,19 +645,30 @@
                if (loc < NDADDR) {
                        len = fragroundup(fs, blkoff(fs, xp->i_size));
                        if (len > 0 && len < fs->fs_bsize) {
+                               error = UFS_WAPBL_BEGIN(mp);
+                               if (error) {
+                                       (void)vunmark(mvp);
+                                       goto out;
+                               }
                                ffs_blkfree_snap(copy_fs, vp, db_get(xp, loc),
                                    len, xp->i_number);
                                blkno = db_get(xp, loc);
                                db_assign(xp, loc, 0);
+                               UFS_WAPBL_END(mp);
                        }
                }
                *snaplistsize += 1;
                error = expunge(vp, xp, copy_fs, fullacct, BLK_NOCOPY);
                if (blkno)
                        db_assign(xp, loc, blkno);
-               if (!error)
-                       error = ffs_freefile_snap(copy_fs, vp, xp->i_number,
-                           xp->i_mode);
+               if (!error) {
+                       error = UFS_WAPBL_BEGIN(mp);
+                       if (!error) {
+                               error = ffs_freefile_snap(copy_fs, vp,
+                                   xp->i_number, xp->i_mode);
+                               UFS_WAPBL_END(mp);
+                       }
+               }
                if (error) {
                        (void)vunmark(mvp);
                        goto out;
@@ -688,8 +696,6 @@
        (*snaplist)[0] = blkp - &(*snaplist)[0];
 
 out:
-       if (has_wapbl)
-               UFS_WAPBL_END(mp);
        if (mvp != NULL)
                vnfree(mvp);
        if (logvp != NULL)
@@ -711,16 +717,13 @@
 snapshot_expunge_snap(struct mount *mp, struct vnode *vp,
     struct fs *copy_fs, daddr_t snaplistsize)
 {
-       int error, i;
+       int error = 0, i;
        daddr_t numblks, *snaplist = NULL;
        struct fs *fs = VFSTOUFS(mp)->um_fs;
        struct inode *ip = VTOI(vp), *xp;
        struct lwp *l = curlwp;
        struct snap_info *si = VFSTOUFS(mp)->um_snapinfo;
 
-       error = UFS_WAPBL_BEGIN(mp);
-       if (error)
-               return error;
        TAILQ_FOREACH(xp, &si->si_snapshots, i_nextsnap) {
                if (xp == ip)
                        break;
@@ -729,7 +732,11 @@
                        break;
                if (xp->i_nlink != 0)
                        continue;
+               error = UFS_WAPBL_BEGIN(mp);
+               if (error)
+                       break;
                error = ffs_freefile_snap(copy_fs, vp, xp->i_number, xp->i_mode);
+               UFS_WAPBL_END(mp);
                if (error)
                        break;
        }
@@ -761,12 +768,10 @@
                snaplist[i] = ufs_rw64(snaplist[i], UFS_FSNEEDSWAP(fs));
        error = vn_rdwr(UIO_WRITE, vp, (void *)snaplist,
            snaplistsize * sizeof(daddr_t), lblktosize(fs, (off_t)numblks),
-           UIO_SYSSPACE, IO_NODELOCKED | IO_JOURNALLOCKED | IO_UNIT,
-           l->l_cred, NULL, NULL);
+           UIO_SYSSPACE, IO_NODELOCKED | IO_UNIT, l->l_cred, NULL, NULL);
        for (i = 0; i < snaplistsize; i++)
                snaplist[i] = ufs_rw64(snaplist[i], UFS_FSNEEDSWAP(fs));
 out:
-       UFS_WAPBL_END(mp);
        if (error && snaplist != NULL) {
                free(snaplist, M_UFSMNT);
                ip->i_snapblklist = NULL;
@@ -859,13 +864,10 @@
 static int
 cgaccount(struct vnode *vp, int passno, int *redo)
 {
-       int cg, error;
+       int cg, error = 0;
        struct buf *nbp;
        struct fs *fs = VTOI(vp)->i_fs;
 
-       error = UFS_WAPBL_BEGIN(vp->v_mount);
-       if (error)
-               return error;
        if (redo != NULL)
                *redo = 0;
        if (passno == 1)
@@ -874,18 +876,24 @@
        for (cg = 0; cg < fs->fs_ncg; cg++) {
                if (passno == 2 && ACTIVECG_ISSET(fs, cg))
                        continue;
+
                if (redo != NULL)
                        *redo += 1;
+               error = UFS_WAPBL_BEGIN(vp->v_mount);
+               if (error)
+                       return error;
                error = ffs_balloc(vp, lfragtosize(fs, cgtod(fs, cg)),
                    fs->fs_bsize, curlwp->l_cred, 0, &nbp);
-               if (error)
+               if (error) {
+                       UFS_WAPBL_END(vp->v_mount);
                        break;
+               }
                error = cgaccount1(cg, vp, nbp->b_data, passno);
                bawrite(nbp);
+               UFS_WAPBL_END(vp->v_mount);
                if (error)
                        break;
        }
-       UFS_WAPBL_END(vp->v_mount);
        return error;
 }
 
@@ -992,8 +1000,14 @@
        struct lwp *l = curlwp;
        void *bap;
        struct buf *bp;
+       struct mount *mp;
 
        ns = UFS_FSNEEDSWAP(fs);
+       mp = snapvp->v_mount;
+
+       error = UFS_WAPBL_BEGIN(mp);
+       if (error)
+               return error;
        /*
         * Prepare to expunge the inode. If its inode block has not
         * yet been copied, then allocate and fill the copy.
@@ -1011,8 +1025,10 @@
                if (! error)
                        error = rwfsblk(snapvp, B_READ, bp->b_data, lbn);
        }
-       if (error)
+       if (error) {
+               UFS_WAPBL_END(mp);
                return error;
+       }
        /*
         * Set a snapshot inode to be a zero length file, regular files
         * or unlinked snapshots to be completely unallocated.
@@ -1039,6 +1055,7 @@
                memset(&dip2->di_db[0], 0, (NDADDR + NIADDR) * sizeof(int64_t));
        }
        bdwrite(bp);
+       UFS_WAPBL_END(mp);
        /*
         * Now go through and expunge all the blocks in the file
         * using the function requested.
@@ -1048,13 +1065,15 @@
                bap = &cancelip->i_ffs1_db[0];
        else
                bap = &cancelip->i_ffs2_db[0];
-       if ((error = (*acctfunc)(snapvp, bap, 0, NDADDR, fs, 0, expungetype)))
+       error = (*acctfunc)(snapvp, bap, 0, NDADDR, fs, 0, expungetype);
+       if (error)
                return (error);
        if (fs->fs_magic == FS_UFS1_MAGIC)
                bap = &cancelip->i_ffs1_ib[0];
        else
                bap = &cancelip->i_ffs2_ib[0];
-       if ((error = (*acctfunc)(snapvp, bap, 0, NIADDR, fs, -1, expungetype)))
+       error = (*acctfunc)(snapvp, bap, 0, NIADDR, fs, -1, expungetype);
+       if (error)
                return (error);
        blksperindir = 1;
        lbn = -NDADDR;
@@ -1170,12 +1189,17 @@
 {
        struct inode *ip = VTOI(vp);
        struct lwp *l = curlwp;
+       struct mount *mp = vp->v_mount;
        daddr_t blkno;
        daddr_t lbn;
        struct buf *ibp;
-       int error;
+       int error, n;
+       const int wbreak = blocks_in_journal(VFSTOUFS(mp)->um_fs)/8;
 
-       for ( ; oldblkp < lastblkp; oldblkp++) {
+       error = UFS_WAPBL_BEGIN(mp);
+       if (error)
+               return error;
+       for ( n = 0; oldblkp < lastblkp; oldblkp++) {
                blkno = idb_get(ip, bap, oldblkp);
                if (blkno == 0 || blkno == BLK_NOCOPY || blkno == BLK_SNAP)
                        continue;
@@ -1187,7 +1211,7 @@
                        error = ffs_balloc(vp, lblktosize(fs, (off_t)lbn),
                            fs->fs_bsize, l->l_cred, B_METAONLY, &ibp);
                        if (error)
-                               return (error);
+                               break;
                        blkno = idb_get(ip, ibp->b_data,
                            (lbn - NDADDR) % NINDIR(fs));
                }
@@ -1211,8 +1235,15 @@
                                bdwrite(ibp);
                        }
                }
+               if (wbreak > 0 && (++n % wbreak) == 0) {
+                       UFS_WAPBL_END(mp);
+                       error = UFS_WAPBL_BEGIN(mp);
+                       if (error)
+                               return error;
+               }
        }
-       return (0);
+       UFS_WAPBL_END(mp);
+       return error;



Home | Main Index | Thread Index | Old Index