Fri Apr 29 09:45:15 2011 UTC ()
Before expunging all snapshots take the snapshot lock and resume the file
system as this is sufficient for the remaining operations.

Reduces the time the file system is suspended and should make this time
independent of the number of snapshots already present.


(hannken)
diff -r1.113 -r1.114 src/sys/ufs/ffs/ffs_snapshot.c

cvs diff -r1.113 -r1.114 src/sys/ufs/ffs/ffs_snapshot.c (expand / switch to unified diff)

--- src/sys/ufs/ffs/ffs_snapshot.c 2011/04/23 08:23:52 1.113
+++ src/sys/ufs/ffs/ffs_snapshot.c 2011/04/29 09:45:15 1.114
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: ffs_snapshot.c,v 1.113 2011/04/23 08:23:52 hannken Exp $ */ 1/* $NetBSD: ffs_snapshot.c,v 1.114 2011/04/29 09:45:15 hannken Exp $ */
2 2
3/* 3/*
4 * Copyright 2000 Marshall Kirk McKusick. All Rights Reserved. 4 * Copyright 2000 Marshall Kirk McKusick. All Rights Reserved.
5 * 5 *
6 * Further information about snapshots can be obtained from: 6 * Further information about snapshots can be obtained from:
7 * 7 *
8 * Marshall Kirk McKusick http://www.mckusick.com/softdep/ 8 * Marshall Kirk McKusick http://www.mckusick.com/softdep/
9 * 1614 Oxford Street mckusick@mckusick.com 9 * 1614 Oxford Street mckusick@mckusick.com
10 * Berkeley, CA 94709-1608 +1-510-843-9542 10 * Berkeley, CA 94709-1608 +1-510-843-9542
11 * USA 11 * USA
12 * 12 *
13 * Redistribution and use in source and binary forms, with or without 13 * Redistribution and use in source and binary forms, with or without
14 * modification, are permitted provided that the following conditions 14 * modification, are permitted provided that the following conditions
@@ -28,27 +28,27 @@ @@ -28,27 +28,27 @@
28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 * SUCH DAMAGE. 33 * SUCH DAMAGE.
34 * 34 *
35 * @(#)ffs_snapshot.c 8.11 (McKusick) 7/23/00 35 * @(#)ffs_snapshot.c 8.11 (McKusick) 7/23/00
36 * 36 *
37 * from FreeBSD: ffs_snapshot.c,v 1.79 2004/02/13 02:02:06 kuriyama Exp 37 * from FreeBSD: ffs_snapshot.c,v 1.79 2004/02/13 02:02:06 kuriyama Exp
38 */ 38 */
39 39
40#include <sys/cdefs.h> 40#include <sys/cdefs.h>
41__KERNEL_RCSID(0, "$NetBSD: ffs_snapshot.c,v 1.113 2011/04/23 08:23:52 hannken Exp $"); 41__KERNEL_RCSID(0, "$NetBSD: ffs_snapshot.c,v 1.114 2011/04/29 09:45:15 hannken Exp $");
42 42
43#if defined(_KERNEL_OPT) 43#if defined(_KERNEL_OPT)
44#include "opt_ffs.h" 44#include "opt_ffs.h"
45#include "opt_quota.h" 45#include "opt_quota.h"
46#endif 46#endif
47 47
48#include <sys/param.h> 48#include <sys/param.h>
49#include <sys/kernel.h> 49#include <sys/kernel.h>
50#include <sys/systm.h> 50#include <sys/systm.h>
51#include <sys/conf.h> 51#include <sys/conf.h>
52#include <sys/buf.h> 52#include <sys/buf.h>
53#include <sys/proc.h> 53#include <sys/proc.h>
54#include <sys/namei.h> 54#include <sys/namei.h>
@@ -167,27 +167,27 @@ ffs_snapshot_fini(struct ufsmount *ump) @@ -167,27 +167,27 @@ ffs_snapshot_fini(struct ufsmount *ump)
167} 167}
168 168
169/* 169/*
170 * Create a snapshot file and initialize it for the filesystem. 170 * Create a snapshot file and initialize it for the filesystem.
171 * Vnode is locked on entry and return. 171 * Vnode is locked on entry and return.
172 */ 172 */
173int 173int
174ffs_snapshot(struct mount *mp, struct vnode *vp, struct timespec *ctime) 174ffs_snapshot(struct mount *mp, struct vnode *vp, struct timespec *ctime)
175{ 175{
176#if defined(FFS_NO_SNAPSHOT) 176#if defined(FFS_NO_SNAPSHOT)
177 return EOPNOTSUPP; 177 return EOPNOTSUPP;
178} 178}
179#else /* defined(FFS_NO_SNAPSHOT) */ 179#else /* defined(FFS_NO_SNAPSHOT) */
180 bool suspended = false; 180 bool suspended = false, snapshot_locked = false;
181 int error, redo = 0, snaploc; 181 int error, redo = 0, snaploc;
182 void *sbbuf = NULL; 182 void *sbbuf = NULL;
183 daddr_t *snaplist = NULL, snaplistsize = 0; 183 daddr_t *snaplist = NULL, snaplistsize = 0;
184 struct buf *bp, *nbp; 184 struct buf *bp, *nbp;
185 struct fs *copy_fs = NULL; 185 struct fs *copy_fs = NULL;
186 struct fs *fs = VFSTOUFS(mp)->um_fs; 186 struct fs *fs = VFSTOUFS(mp)->um_fs;
187 struct inode *ip = VTOI(vp); 187 struct inode *ip = VTOI(vp);
188 struct lwp *l = curlwp; 188 struct lwp *l = curlwp;
189 struct snap_info *si = VFSTOUFS(mp)->um_snapinfo; 189 struct snap_info *si = VFSTOUFS(mp)->um_snapinfo;
190 struct timespec ts; 190 struct timespec ts;
191 struct timeval starttime; 191 struct timeval starttime;
192#ifdef DEBUG 192#ifdef DEBUG
193 struct timeval endtime; 193 struct timeval endtime;
@@ -300,26 +300,44 @@ ffs_snapshot(struct mount *mp, struct vn @@ -300,26 +300,44 @@ ffs_snapshot(struct mount *mp, struct vn
300 mutex_exit(&si->si_lock); 300 mutex_exit(&si->si_lock);
301 301
302 vp->v_vflag |= VV_SYSTEM; 302 vp->v_vflag |= VV_SYSTEM;
303 /* 303 /*
304 * Set the mtime to the time the snapshot has been taken. 304 * Set the mtime to the time the snapshot has been taken.
305 */ 305 */
306 TIMEVAL_TO_TIMESPEC(&starttime, &ts); 306 TIMEVAL_TO_TIMESPEC(&starttime, &ts);
307 if (ctime) 307 if (ctime)
308 *ctime = ts; 308 *ctime = ts;
309 DIP_ASSIGN(ip, mtime, ts.tv_sec); 309 DIP_ASSIGN(ip, mtime, ts.tv_sec);
310 DIP_ASSIGN(ip, mtimensec, ts.tv_nsec); 310 DIP_ASSIGN(ip, mtimensec, ts.tv_nsec);
311 ip->i_flag |= IN_CHANGE | IN_UPDATE; 311 ip->i_flag |= IN_CHANGE | IN_UPDATE;
312 /* 312 /*
 313 * Lock the snapshot and resume file system.
 314 */
 315 mutex_enter(&si->si_snaplock);
 316 mutex_enter(&si->si_lock);
 317 si->si_owner = curlwp;
 318 mutex_exit(&si->si_lock);
 319 snapshot_locked = true;
 320 KASSERT(suspended);
 321 vfs_resume(vp->v_mount);
 322 suspended = false;
 323#ifdef DEBUG
 324 getmicrotime(&endtime);
 325 timersub(&endtime, &starttime, &endtime);
 326 printf("%s: suspended %lld.%03d sec, redo %d of %d\n",
 327 mp->mnt_stat.f_mntonname, (long long)endtime.tv_sec,
 328 endtime.tv_usec / 1000, redo, fs->fs_ncg);
 329#endif
 330 /*
313 * Copy allocation information from all snapshots and then 331 * Copy allocation information from all snapshots and then
314 * expunge them from our view. 332 * expunge them from our view.
315 */ 333 */
316 error = snapshot_expunge_snap(mp, vp, copy_fs, snaplistsize); 334 error = snapshot_expunge_snap(mp, vp, copy_fs, snaplistsize);
317 if (error) 335 if (error)
318 goto out; 336 goto out;
319 /* 337 /*
320 * Write the superblock and its summary information to the snapshot. 338 * Write the superblock and its summary information to the snapshot.
321 */ 339 */
322 error = snapshot_writefs(mp, vp, sbbuf); 340 error = snapshot_writefs(mp, vp, sbbuf);
323 if (error) 341 if (error)
324 goto out; 342 goto out;
325 /* 343 /*
@@ -371,35 +389,33 @@ out: @@ -371,35 +389,33 @@ out:
371 } 389 }
372 if (error) { 390 if (error) {
373 fs->fs_snapinum[snaploc] = 0; 391 fs->fs_snapinum[snaploc] = 0;
374 } else { 392 } else {
375 /* 393 /*
376 * As this is the newest list, it is the most inclusive, so 394 * As this is the newest list, it is the most inclusive, so
377 * should replace the previous list. 395 * should replace the previous list.
378 */ 396 */
379 si->si_snapblklist = ip->i_snapblklist; 397 si->si_snapblklist = ip->i_snapblklist;
380 } 398 }
381 si->si_gen++; 399 si->si_gen++;
382 mutex_exit(&si->si_lock); 400 mutex_exit(&si->si_lock);
383 401
384 if (suspended) { 402 if (suspended)
385 vfs_resume(vp->v_mount); 403 vfs_resume(vp->v_mount);
386#ifdef DEBUG 404 if (snapshot_locked) {
387 getmicrotime(&endtime); 405 mutex_enter(&si->si_lock);
388 timersub(&endtime, &starttime, &endtime); 406 si->si_owner = NULL;
389 printf("%s: suspended %lld.%03d sec, redo %d of %d\n", 407 mutex_exit(&si->si_lock);
390 mp->mnt_stat.f_mntonname, (long long)endtime.tv_sec, 408 mutex_exit(&si->si_snaplock);
391 endtime.tv_usec / 1000, redo, fs->fs_ncg); 
392#endif 
393 } 409 }
394 if (error) { 410 if (error) {
395 if (!UFS_WAPBL_BEGIN(mp)) { 411 if (!UFS_WAPBL_BEGIN(mp)) {
396 (void) ffs_truncate(vp, (off_t)0, 0, NOCRED); 412 (void) ffs_truncate(vp, (off_t)0, 0, NOCRED);
397 UFS_WAPBL_END(mp); 413 UFS_WAPBL_END(mp);
398 } 414 }
399 } else if (ip->i_nlink > 0) 415 } else if (ip->i_nlink > 0)
400 vref(vp); 416 vref(vp);
401 return (error); 417 return (error);
402} 418}
403 419
404/* 420/*
405 * Prepare vnode to become a snapshot. 421 * Prepare vnode to become a snapshot.