git: d7770a5495b1 - main - Eliminate snaplk / bufwait LOR when creating UFS snapshots

Kirk McKusick mckusick at FreeBSD.org
Sun Sep 19 00:03:05 UTC 2021


The branch main has been updated by mckusick:

URL: https://cgit.FreeBSD.org/src/commit/?id=d7770a5495b19a987dddc77cabcdeadf18413b4d

commit d7770a5495b19a987dddc77cabcdeadf18413b4d
Author:     Kirk McKusick <mckusick at FreeBSD.org>
AuthorDate: 2021-09-18 23:51:07 +0000
Commit:     Kirk McKusick <mckusick at FreeBSD.org>
CommitDate: 2021-09-19 00:02:30 +0000

    Eliminate snaplk / bufwait LOR when creating UFS snapshots
    
    Each vnode has an embedded lock that controls access to its contents.
    However vnodes describing a UFS snapshot all share a single snapshot
    lock to coordinate their access and update. As part of creating a
    new UFS snapshot, it has to have its individual vnode lock replaced
    with the filesystem's snapshot lock.
    
    The lock order for regular vnodes with respect to buffer locks is that
    they must first acquire the vnode lock, then a buffer lock. The order
    for the snapshot lock is reversed: a buffer lock must be acquired before
    the snapshot lock.
    
    When creating a new snapshot, the snapshot file must retain its vnode
    lock until it has allocated all the blocks that it needs before
    switching to the snapshot lock. This update moves one final piece of
    the initial snapshot block allocation so that it is done before the
    newly created snapshot is switched to use the snapshot lock.
    
    Reported by:  Witness code
    MFC after:    1 week
    Sponsored by: Netflix
---
 sys/ufs/ffs/ffs_snapshot.c | 42 +++++++++++++++++++++---------------------
 1 file changed, 21 insertions(+), 21 deletions(-)

diff --git a/sys/ufs/ffs/ffs_snapshot.c b/sys/ufs/ffs/ffs_snapshot.c
index 6da84fb46bb0..baad50cab2ba 100644
--- a/sys/ufs/ffs/ffs_snapshot.c
+++ b/sys/ufs/ffs/ffs_snapshot.c
@@ -650,6 +650,27 @@ loop:
 			    BLK_NOCOPY, 0);
 		vput(xvp);
 	}
+	/*
+	 * Preallocate all the direct blocks in the snapshot inode so
+	 * that we never have to write the inode itself to commit an
+	 * update to the contents of the snapshot. Note that once
+	 * created, the size of the snapshot will never change, so
+	 * there will never be a need to write the inode except to
+	 * update the non-integrity-critical time fields and
+	 * allocated-block count.
+	 */
+	for (blockno = 0; blockno < UFS_NDADDR; blockno++) {
+		if (DIP(ip, i_db[blockno]) != 0)
+			continue;
+		error = UFS_BALLOC(vp, lblktosize(fs, blockno),
+		    fs->fs_bsize, KERNCRED, BA_CLRBUF, &bp);
+		if (error)
+			goto resumefs;
+		error = readblock(vp, bp, blockno);
+		bawrite(bp);
+		if (error != 0)
+			goto resumefs;
+	}
 	/*
 	 * Acquire a lock on the snapdata structure, creating it if necessary.
 	 */
@@ -691,27 +712,6 @@ loop:
 		sn->sn_listsize = blkp - snapblklist;
 		VI_UNLOCK(devvp);
 	}
-	/*
-	 * Preallocate all the direct blocks in the snapshot inode so
-	 * that we never have to write the inode itself to commit an
-	 * update to the contents of the snapshot. Note that once
-	 * created, the size of the snapshot will never change, so
-	 * there will never be a need to write the inode except to
-	 * update the non-integrity-critical time fields and
-	 * allocated-block count.
-	 */
-	for (blockno = 0; blockno < UFS_NDADDR; blockno++) {
-		if (DIP(ip, i_db[blockno]) != 0)
-			continue;
-		error = UFS_BALLOC(vp, lblktosize(fs, blockno),
-		    fs->fs_bsize, KERNCRED, BA_CLRBUF, &bp);
-		if (error)
-			goto resumefs;
-		error = readblock(vp, bp, blockno);
-		bawrite(bp);
-		if (error != 0)
-			goto resumefs;
-	}
 	/*
 	 * Record snapshot inode. Since this is the newest snapshot,
 	 * it must be placed at the end of the list.


More information about the dev-commits-src-main mailing list