Fri Jan 7 03:14:46 2011 UTC ()
Quiet gcc.


(matt)
diff -r1.82.4.3 -r1.82.4.3.4.1 src/sys/ufs/ffs/ffs_snapshot.c

cvs diff -r1.82.4.3 -r1.82.4.3.4.1 src/sys/ufs/ffs/ffs_snapshot.c (switch to unified diff)

--- src/sys/ufs/ffs/ffs_snapshot.c 2010/03/28 17:28:33 1.82.4.3
+++ src/sys/ufs/ffs/ffs_snapshot.c 2011/01/07 03:14:46 1.82.4.3.4.1
@@ -1,1179 +1,1179 @@ @@ -1,1179 +1,1179 @@
1/* $NetBSD: ffs_snapshot.c,v 1.82.4.3 2010/03/28 17:28:33 snj Exp $ */ 1/* $NetBSD: ffs_snapshot.c,v 1.82.4.3.4.1 2011/01/07 03:14:46 matt 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
15 * are met: 15 * are met:
16 * 16 *
17 * 1. Redistributions of source code must retain the above copyright 17 * 1. Redistributions of source code must retain the above copyright
18 * notice, this list of conditions and the following disclaimer. 18 * notice, this list of conditions and the following disclaimer.
19 * 2. Redistributions in binary form must reproduce the above copyright 19 * 2. Redistributions in binary form must reproduce the above copyright
20 * notice, this list of conditions and the following disclaimer in the 20 * notice, this list of conditions and the following disclaimer in the
21 * documentation and/or other materials provided with the distribution. 21 * documentation and/or other materials provided with the distribution.
22 * 22 *
23 * THIS SOFTWARE IS PROVIDED BY MARSHALL KIRK MCKUSICK ``AS IS'' AND ANY 23 * THIS SOFTWARE IS PROVIDED BY MARSHALL KIRK MCKUSICK ``AS IS'' AND ANY
24 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 24 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
25 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 25 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
26 * DISCLAIMED. IN NO EVENT SHALL MARSHALL KIRK MCKUSICK BE LIABLE FOR 26 * DISCLAIMED. IN NO EVENT SHALL MARSHALL KIRK MCKUSICK BE LIABLE FOR
27 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
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.82.4.3 2010/03/28 17:28:33 snj Exp $"); 41__KERNEL_RCSID(0, "$NetBSD: ffs_snapshot.c,v 1.82.4.3.4.1 2011/01/07 03:14:46 matt Exp $");
42 42
43#if defined(_KERNEL_OPT) 43#if defined(_KERNEL_OPT)
44#include "opt_ffs.h" 44#include "opt_ffs.h"
45#endif 45#endif
46 46
47#include <sys/param.h> 47#include <sys/param.h>
48#include <sys/kernel.h> 48#include <sys/kernel.h>
49#include <sys/systm.h> 49#include <sys/systm.h>
50#include <sys/conf.h> 50#include <sys/conf.h>
51#include <sys/buf.h> 51#include <sys/buf.h>
52#include <sys/proc.h> 52#include <sys/proc.h>
53#include <sys/namei.h> 53#include <sys/namei.h>
54#include <sys/sched.h> 54#include <sys/sched.h>
55#include <sys/stat.h> 55#include <sys/stat.h>
56#include <sys/malloc.h> 56#include <sys/malloc.h>
57#include <sys/mount.h> 57#include <sys/mount.h>
58#include <sys/resource.h> 58#include <sys/resource.h>
59#include <sys/resourcevar.h> 59#include <sys/resourcevar.h>
60#include <sys/vnode.h> 60#include <sys/vnode.h>
61#include <sys/kauth.h> 61#include <sys/kauth.h>
62#include <sys/fstrans.h> 62#include <sys/fstrans.h>
63#include <sys/wapbl.h> 63#include <sys/wapbl.h>
64 64
65#include <miscfs/specfs/specdev.h> 65#include <miscfs/specfs/specdev.h>
66 66
67#include <ufs/ufs/quota.h> 67#include <ufs/ufs/quota.h>
68#include <ufs/ufs/ufsmount.h> 68#include <ufs/ufs/ufsmount.h>
69#include <ufs/ufs/inode.h> 69#include <ufs/ufs/inode.h>
70#include <ufs/ufs/ufs_extern.h> 70#include <ufs/ufs/ufs_extern.h>
71#include <ufs/ufs/ufs_bswap.h> 71#include <ufs/ufs/ufs_bswap.h>
72#include <ufs/ufs/ufs_wapbl.h> 72#include <ufs/ufs/ufs_wapbl.h>
73 73
74#include <ufs/ffs/fs.h> 74#include <ufs/ffs/fs.h>
75#include <ufs/ffs/ffs_extern.h> 75#include <ufs/ffs/ffs_extern.h>
76 76
77#include <uvm/uvm.h> 77#include <uvm/uvm.h>
78 78
79struct snap_info { 79struct snap_info {
80 kmutex_t si_lock; /* Lock this snapinfo */ 80 kmutex_t si_lock; /* Lock this snapinfo */
81 kmutex_t si_snaplock; /* Snapshot vnode common lock */ 81 kmutex_t si_snaplock; /* Snapshot vnode common lock */
82 TAILQ_HEAD(inodelst, inode) si_snapshots; /* List of active snapshots */ 82 TAILQ_HEAD(inodelst, inode) si_snapshots; /* List of active snapshots */
83 daddr_t *si_snapblklist; /* Snapshot block hints list */ 83 daddr_t *si_snapblklist; /* Snapshot block hints list */
84 uint32_t si_gen; /* Incremented on change */ 84 uint32_t si_gen; /* Incremented on change */
85}; 85};
86 86
87#if !defined(FFS_NO_SNAPSHOT) 87#if !defined(FFS_NO_SNAPSHOT)
88typedef int (*acctfunc_t) 88typedef int (*acctfunc_t)
89 (struct vnode *, void *, int, int, struct fs *, daddr_t, int); 89 (struct vnode *, void *, int, int, struct fs *, daddr_t, int);
90 90
91static int snapshot_setup(struct mount *, struct vnode *); 91static int snapshot_setup(struct mount *, struct vnode *);
92static int snapshot_copyfs(struct mount *, struct vnode *, void **); 92static int snapshot_copyfs(struct mount *, struct vnode *, void **);
93static int snapshot_expunge(struct mount *, struct vnode *, 93static int snapshot_expunge(struct mount *, struct vnode *,
94 struct fs *, daddr_t *, daddr_t **); 94 struct fs *, daddr_t *, daddr_t **);
95static int snapshot_expunge_snap(struct mount *, struct vnode *, 95static int snapshot_expunge_snap(struct mount *, struct vnode *,
96 struct fs *, daddr_t); 96 struct fs *, daddr_t);
97static int snapshot_writefs(struct mount *, struct vnode *, void *); 97static int snapshot_writefs(struct mount *, struct vnode *, void *);
98static int cgaccount(struct vnode *, int, int *); 98static int cgaccount(struct vnode *, int, int *);
99static int cgaccount1(int, struct vnode *, void *, int); 99static int cgaccount1(int, struct vnode *, void *, int);
100static int expunge(struct vnode *, struct inode *, struct fs *, 100static int expunge(struct vnode *, struct inode *, struct fs *,
101 acctfunc_t, int); 101 acctfunc_t, int);
102static int indiracct(struct vnode *, struct vnode *, int, daddr_t, 102static int indiracct(struct vnode *, struct vnode *, int, daddr_t,
103 daddr_t, daddr_t, daddr_t, daddr_t, struct fs *, acctfunc_t, int); 103 daddr_t, daddr_t, daddr_t, daddr_t, struct fs *, acctfunc_t, int);
104static int fullacct(struct vnode *, void *, int, int, struct fs *, 104static int fullacct(struct vnode *, void *, int, int, struct fs *,
105 daddr_t, int); 105 daddr_t, int);
106static int snapacct(struct vnode *, void *, int, int, struct fs *, 106static int snapacct(struct vnode *, void *, int, int, struct fs *,
107 daddr_t, int); 107 daddr_t, int);
108static int mapacct(struct vnode *, void *, int, int, struct fs *, 108static int mapacct(struct vnode *, void *, int, int, struct fs *,
109 daddr_t, int); 109 daddr_t, int);
110#endif /* !defined(FFS_NO_SNAPSHOT) */ 110#endif /* !defined(FFS_NO_SNAPSHOT) */
111 111
112static int ffs_copyonwrite(void *, struct buf *, bool); 112static int ffs_copyonwrite(void *, struct buf *, bool);
113static int snapblkaddr(struct vnode *, daddr_t, daddr_t *); 113static int snapblkaddr(struct vnode *, daddr_t, daddr_t *);
114static int rwfsblk(struct vnode *, int, void *, daddr_t); 114static int rwfsblk(struct vnode *, int, void *, daddr_t);
115static int syncsnap(struct vnode *); 115static int syncsnap(struct vnode *);
116static int wrsnapblk(struct vnode *, void *, daddr_t); 116static int wrsnapblk(struct vnode *, void *, daddr_t);
117 117
118static inline bool is_active_snapshot(struct snap_info *, struct inode *); 118static inline bool is_active_snapshot(struct snap_info *, struct inode *);
119static inline daddr_t db_get(struct inode *, int); 119static inline daddr_t db_get(struct inode *, int);
120static inline void db_assign(struct inode *, int, daddr_t); 120static inline void db_assign(struct inode *, int, daddr_t);
121static inline daddr_t ib_get(struct inode *, int); 121static inline daddr_t ib_get(struct inode *, int);
122static inline void ib_assign(struct inode *, int, daddr_t); 122static inline void ib_assign(struct inode *, int, daddr_t);
123static inline daddr_t idb_get(struct inode *, void *, int); 123static inline daddr_t idb_get(struct inode *, void *, int);
124static inline void idb_assign(struct inode *, void *, int, daddr_t); 124static inline void idb_assign(struct inode *, void *, int, daddr_t);
125 125
126#ifdef DEBUG 126#ifdef DEBUG
127static int snapdebug = 0; 127static int snapdebug = 0;
128#endif 128#endif
129 129
130int 130int
131ffs_snapshot_init(struct ufsmount *ump) 131ffs_snapshot_init(struct ufsmount *ump)
132{ 132{
133 struct snap_info *si; 133 struct snap_info *si;
134 134
135 si = ump->um_snapinfo = kmem_alloc(sizeof(*si), KM_SLEEP); 135 si = ump->um_snapinfo = kmem_alloc(sizeof(*si), KM_SLEEP);
136 if (si == NULL) 136 if (si == NULL)
137 return ENOMEM; 137 return ENOMEM;
138 138
139 TAILQ_INIT(&si->si_snapshots); 139 TAILQ_INIT(&si->si_snapshots);
140 mutex_init(&si->si_lock, MUTEX_DEFAULT, IPL_NONE); 140 mutex_init(&si->si_lock, MUTEX_DEFAULT, IPL_NONE);
141 mutex_init(&si->si_snaplock, MUTEX_DEFAULT, IPL_NONE); 141 mutex_init(&si->si_snaplock, MUTEX_DEFAULT, IPL_NONE);
142 si->si_gen = 0; 142 si->si_gen = 0;
143 si->si_snapblklist = NULL; 143 si->si_snapblklist = NULL;
144 144
145 return 0; 145 return 0;
146} 146}
147 147
148void 148void
149ffs_snapshot_fini(struct ufsmount *ump) 149ffs_snapshot_fini(struct ufsmount *ump)
150{ 150{
151 struct snap_info *si; 151 struct snap_info *si;
152 152
153 si = ump->um_snapinfo; 153 si = ump->um_snapinfo;
154 ump->um_snapinfo = NULL; 154 ump->um_snapinfo = NULL;
155 155
156 KASSERT(TAILQ_EMPTY(&si->si_snapshots)); 156 KASSERT(TAILQ_EMPTY(&si->si_snapshots));
157 mutex_destroy(&si->si_lock); 157 mutex_destroy(&si->si_lock);
158 mutex_destroy(&si->si_snaplock); 158 mutex_destroy(&si->si_snaplock);
159 KASSERT(si->si_snapblklist == NULL); 159 KASSERT(si->si_snapblklist == NULL);
160 kmem_free(si, sizeof(*si)); 160 kmem_free(si, sizeof(*si));
161} 161}
162 162
163/* 163/*
164 * Create a snapshot file and initialize it for the filesystem. 164 * Create a snapshot file and initialize it for the filesystem.
165 * Vnode is locked on entry and return. 165 * Vnode is locked on entry and return.
166 */ 166 */
167int 167int
168ffs_snapshot(struct mount *mp, struct vnode *vp, struct timespec *ctime) 168ffs_snapshot(struct mount *mp, struct vnode *vp, struct timespec *ctime)
169{ 169{
170#if defined(FFS_NO_SNAPSHOT) 170#if defined(FFS_NO_SNAPSHOT)
171 return EOPNOTSUPP; 171 return EOPNOTSUPP;
172} 172}
173#else /* defined(FFS_NO_SNAPSHOT) */ 173#else /* defined(FFS_NO_SNAPSHOT) */
174 bool suspended = false; 174 bool suspended = false;
175 bool snapshot_locked = false; 175 bool snapshot_locked = false;
176 int error, redo = 0, snaploc; 176 int error, redo = 0, snaploc;
177 void *sbbuf = NULL; 177 void *sbbuf = NULL;
178 daddr_t *snaplist = NULL, snaplistsize = 0; 178 daddr_t *snaplist = NULL, snaplistsize = 0;
179 struct buf *bp, *nbp; 179 struct buf *bp, *nbp;
180 struct fs *copy_fs, *fs = VFSTOUFS(mp)->um_fs; 180 struct fs *copy_fs = NULL, *fs = VFSTOUFS(mp)->um_fs;
181 struct inode *ip = VTOI(vp); 181 struct inode *ip = VTOI(vp);
182 struct lwp *l = curlwp; 182 struct lwp *l = curlwp;
183 struct snap_info *si = VFSTOUFS(mp)->um_snapinfo; 183 struct snap_info *si = VFSTOUFS(mp)->um_snapinfo;
184 struct timespec ts; 184 struct timespec ts;
185 struct timeval starttime; 185 struct timeval starttime;
186#ifdef DEBUG 186#ifdef DEBUG
187 struct timeval endtime; 187 struct timeval endtime;
188#endif 188#endif
189 struct vnode *devvp = ip->i_devvp; 189 struct vnode *devvp = ip->i_devvp;
190 190
191 /* 191 /*
192 * If the vnode already is a snapshot, return. 192 * If the vnode already is a snapshot, return.
193 */ 193 */
194 if (VTOI(vp)->i_flags & SF_SNAPSHOT) { 194 if (VTOI(vp)->i_flags & SF_SNAPSHOT) {
195 if (ctime) { 195 if (ctime) {
196 ctime->tv_sec = DIP(VTOI(vp), mtime); 196 ctime->tv_sec = DIP(VTOI(vp), mtime);
197 ctime->tv_nsec = DIP(VTOI(vp), mtimensec); 197 ctime->tv_nsec = DIP(VTOI(vp), mtimensec);
198 } 198 }
199 return 0; 199 return 0;
200 } 200 }
201 /* 201 /*
202 * Check for free snapshot slot in the superblock. 202 * Check for free snapshot slot in the superblock.
203 */ 203 */
204 for (snaploc = 0; snaploc < FSMAXSNAP; snaploc++) 204 for (snaploc = 0; snaploc < FSMAXSNAP; snaploc++)
205 if (fs->fs_snapinum[snaploc] == 0) 205 if (fs->fs_snapinum[snaploc] == 0)
206 break; 206 break;
207 if (snaploc == FSMAXSNAP) 207 if (snaploc == FSMAXSNAP)
208 return (ENOSPC); 208 return (ENOSPC);
209 /* 209 /*
210 * Prepare the vnode to become a snapshot. 210 * Prepare the vnode to become a snapshot.
211 */ 211 */
212 error = snapshot_setup(mp, vp); 212 error = snapshot_setup(mp, vp);
213 if (error) 213 if (error)
214 goto out; 214 goto out;
215 /* 215 /*
216 * Change inode to snapshot type file. 216 * Change inode to snapshot type file.
217 */ 217 */
218 ip->i_flags |= SF_SNAPSHOT; 218 ip->i_flags |= SF_SNAPSHOT;
219 DIP_ASSIGN(ip, flags, ip->i_flags); 219 DIP_ASSIGN(ip, flags, ip->i_flags);
220 ip->i_flag |= IN_CHANGE | IN_UPDATE; 220 ip->i_flag |= IN_CHANGE | IN_UPDATE;
221 /* 221 /*
222 * Copy all the cylinder group maps. Although the 222 * Copy all the cylinder group maps. Although the
223 * filesystem is still active, we hope that only a few 223 * filesystem is still active, we hope that only a few
224 * cylinder groups will change between now and when we 224 * cylinder groups will change between now and when we
225 * suspend operations. Thus, we will be able to quickly 225 * suspend operations. Thus, we will be able to quickly
226 * touch up the few cylinder groups that changed during 226 * touch up the few cylinder groups that changed during
227 * the suspension period. 227 * the suspension period.
228 */ 228 */
229 error = cgaccount(vp, 1, NULL); 229 error = cgaccount(vp, 1, NULL);
230 if (error) 230 if (error)
231 goto out; 231 goto out;
232 /* 232 /*
233 * Ensure that the snapshot is completely on disk. 233 * Ensure that the snapshot is completely on disk.
234 * Since we have marked it as a snapshot it is safe to 234 * Since we have marked it as a snapshot it is safe to
235 * unlock it as no process will be allowed to write to it. 235 * unlock it as no process will be allowed to write to it.
236 */ 236 */
237 error = VOP_FSYNC(vp, l->l_cred, FSYNC_WAIT, 0, 0); 237 error = VOP_FSYNC(vp, l->l_cred, FSYNC_WAIT, 0, 0);
238 if (error) 238 if (error)
239 goto out; 239 goto out;
240 VOP_UNLOCK(vp, 0); 240 VOP_UNLOCK(vp, 0);
241 /* 241 /*
242 * All allocations are done, so we can now suspend the filesystem. 242 * All allocations are done, so we can now suspend the filesystem.
243 */ 243 */
244 error = vfs_suspend(vp->v_mount, 0); 244 error = vfs_suspend(vp->v_mount, 0);
245 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); 245 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
246 if (error) 246 if (error)
247 goto out; 247 goto out;
248 suspended = true; 248 suspended = true;
249 getmicrotime(&starttime); 249 getmicrotime(&starttime);
250 /* 250 /*
251 * First, copy all the cylinder group maps that have changed. 251 * First, copy all the cylinder group maps that have changed.
252 */ 252 */
253 error = cgaccount(vp, 2, &redo); 253 error = cgaccount(vp, 2, &redo);
254 if (error) 254 if (error)
255 goto out; 255 goto out;
256 /* 256 /*
257 * Create a copy of the superblock and its summary information. 257 * Create a copy of the superblock and its summary information.
258 */ 258 */
259 error = snapshot_copyfs(mp, vp, &sbbuf); 259 error = snapshot_copyfs(mp, vp, &sbbuf);
260 copy_fs = (struct fs *)((char *)sbbuf + blkoff(fs, fs->fs_sblockloc)); 260 copy_fs = (struct fs *)((char *)sbbuf + blkoff(fs, fs->fs_sblockloc));
261 if (error) 261 if (error)
262 goto out; 262 goto out;
263 /* 263 /*
264 * Expunge unlinked files from our view. 264 * Expunge unlinked files from our view.
265 */ 265 */
266 error = snapshot_expunge(mp, vp, copy_fs, &snaplistsize, &snaplist); 266 error = snapshot_expunge(mp, vp, copy_fs, &snaplistsize, &snaplist);
267 if (error) 267 if (error)
268 goto out; 268 goto out;
269 /* 269 /*
270 * Acquire the snapshot lock. 270 * Acquire the snapshot lock.
271 */ 271 */
272 mutex_enter(&si->si_snaplock); 272 mutex_enter(&si->si_snaplock);
273 snapshot_locked = true; 273 snapshot_locked = true;
274 /* 274 /*
275 * Record snapshot inode. Since this is the newest snapshot, 275 * Record snapshot inode. Since this is the newest snapshot,
276 * it must be placed at the end of the list. 276 * it must be placed at the end of the list.
277 */ 277 */
278 fs->fs_snapinum[snaploc] = ip->i_number; 278 fs->fs_snapinum[snaploc] = ip->i_number;
279 279
280 mutex_enter(&si->si_lock); 280 mutex_enter(&si->si_lock);
281 if (is_active_snapshot(si, ip)) 281 if (is_active_snapshot(si, ip))
282 panic("ffs_snapshot: %"PRIu64" already on list", ip->i_number); 282 panic("ffs_snapshot: %"PRIu64" already on list", ip->i_number);
283 TAILQ_INSERT_TAIL(&si->si_snapshots, ip, i_nextsnap); 283 TAILQ_INSERT_TAIL(&si->si_snapshots, ip, i_nextsnap);
284 if (TAILQ_FIRST(&si->si_snapshots) == ip) { 284 if (TAILQ_FIRST(&si->si_snapshots) == ip) {
285 /* 285 /*
286 * If this is the first snapshot on this filesystem, put the 286 * If this is the first snapshot on this filesystem, put the
287 * preliminary list in place and establish the cow handler. 287 * preliminary list in place and establish the cow handler.
288 */ 288 */
289 si->si_snapblklist = snaplist; 289 si->si_snapblklist = snaplist;
290 fscow_establish(mp, ffs_copyonwrite, devvp); 290 fscow_establish(mp, ffs_copyonwrite, devvp);
291 } 291 }
292 si->si_gen++; 292 si->si_gen++;
293 mutex_exit(&si->si_lock); 293 mutex_exit(&si->si_lock);
294 294
295 vp->v_vflag |= VV_SYSTEM; 295 vp->v_vflag |= VV_SYSTEM;
296 /* 296 /*
297 * Set the mtime to the time the snapshot has been taken. 297 * Set the mtime to the time the snapshot has been taken.
298 */ 298 */
299 TIMEVAL_TO_TIMESPEC(&starttime, &ts); 299 TIMEVAL_TO_TIMESPEC(&starttime, &ts);
300 if (ctime) 300 if (ctime)
301 *ctime = ts; 301 *ctime = ts;
302 DIP_ASSIGN(ip, mtime, ts.tv_sec); 302 DIP_ASSIGN(ip, mtime, ts.tv_sec);
303 DIP_ASSIGN(ip, mtimensec, ts.tv_nsec); 303 DIP_ASSIGN(ip, mtimensec, ts.tv_nsec);
304 ip->i_flag |= IN_CHANGE | IN_UPDATE; 304 ip->i_flag |= IN_CHANGE | IN_UPDATE;
305 /* 305 /*
306 * Copy allocation information from all snapshots and then 306 * Copy allocation information from all snapshots and then
307 * expunge them from our view. 307 * expunge them from our view.
308 */ 308 */
309 error = snapshot_expunge_snap(mp, vp, copy_fs, snaplistsize); 309 error = snapshot_expunge_snap(mp, vp, copy_fs, snaplistsize);
310 if (error) 310 if (error)
311 goto out; 311 goto out;
312 /* 312 /*
313 * Write the superblock and its summary information to the snapshot. 313 * Write the superblock and its summary information to the snapshot.
314 */ 314 */
315 error = snapshot_writefs(mp, vp, sbbuf); 315 error = snapshot_writefs(mp, vp, sbbuf);
316 if (error) 316 if (error)
317 goto out; 317 goto out;
318 /* 318 /*
319 * We're nearly done, ensure that the snapshot is completely on disk. 319 * We're nearly done, ensure that the snapshot is completely on disk.
320 */ 320 */
321 error = VOP_FSYNC(vp, l->l_cred, FSYNC_WAIT, 0, 0); 321 error = VOP_FSYNC(vp, l->l_cred, FSYNC_WAIT, 0, 0);
322 if (error) 322 if (error)
323 goto out; 323 goto out;
324 /* 324 /*
325 * Invalidate and free all pages on the snapshot vnode. 325 * Invalidate and free all pages on the snapshot vnode.
326 * We will read and write through the buffercache. 326 * We will read and write through the buffercache.
327 */ 327 */
328 mutex_enter(&vp->v_interlock); 328 mutex_enter(&vp->v_interlock);
329 error = VOP_PUTPAGES(vp, 0, 0, 329 error = VOP_PUTPAGES(vp, 0, 0,
330 PGO_ALLPAGES | PGO_CLEANIT | PGO_SYNCIO | PGO_FREE); 330 PGO_ALLPAGES | PGO_CLEANIT | PGO_SYNCIO | PGO_FREE);
331 if (error) 331 if (error)
332 goto out; 332 goto out;
333 /* 333 /*
334 * Invalidate short ( < fs_bsize ) buffers. We will always read 334 * Invalidate short ( < fs_bsize ) buffers. We will always read
335 * full size buffers later. 335 * full size buffers later.
336 */ 336 */
337 mutex_enter(&bufcache_lock); 337 mutex_enter(&bufcache_lock);
338 KASSERT(LIST_FIRST(&vp->v_dirtyblkhd) == NULL); 338 KASSERT(LIST_FIRST(&vp->v_dirtyblkhd) == NULL);
339 for (bp = LIST_FIRST(&vp->v_cleanblkhd); bp; bp = nbp) { 339 for (bp = LIST_FIRST(&vp->v_cleanblkhd); bp; bp = nbp) {
340 nbp = LIST_NEXT(bp, b_vnbufs); 340 nbp = LIST_NEXT(bp, b_vnbufs);
341 KASSERT((bp->b_cflags & BC_BUSY) == 0); 341 KASSERT((bp->b_cflags & BC_BUSY) == 0);
342 if (bp->b_bcount < fs->fs_bsize) { 342 if (bp->b_bcount < fs->fs_bsize) {
343 bp->b_cflags |= BC_BUSY; 343 bp->b_cflags |= BC_BUSY;
344 brelsel(bp, BC_INVAL | BC_VFLUSH); 344 brelsel(bp, BC_INVAL | BC_VFLUSH);
345 } 345 }
346 } 346 }
347 mutex_exit(&bufcache_lock); 347 mutex_exit(&bufcache_lock);
348 348
349out: 349out:
350 if (sbbuf != NULL) { 350 if (sbbuf != NULL) {
351 free(copy_fs->fs_csp, M_UFSMNT); 351 free(copy_fs->fs_csp, M_UFSMNT);
352 free(sbbuf, M_UFSMNT); 352 free(sbbuf, M_UFSMNT);
353 } 353 }
354 if (fs->fs_active != NULL) { 354 if (fs->fs_active != NULL) {
355 free(fs->fs_active, M_DEVBUF); 355 free(fs->fs_active, M_DEVBUF);
356 fs->fs_active = NULL; 356 fs->fs_active = NULL;
357 } 357 }
358 358
359 mutex_enter(&si->si_lock); 359 mutex_enter(&si->si_lock);
360 if (snaplist != NULL) { 360 if (snaplist != NULL) {
361 if (si->si_snapblklist == snaplist) 361 if (si->si_snapblklist == snaplist)
362 si->si_snapblklist = NULL; 362 si->si_snapblklist = NULL;
363 free(snaplist, M_UFSMNT); 363 free(snaplist, M_UFSMNT);
364 } 364 }
365 if (error) { 365 if (error) {
366 fs->fs_snapinum[snaploc] = 0; 366 fs->fs_snapinum[snaploc] = 0;
367 } else { 367 } else {
368 /* 368 /*
369 * As this is the newest list, it is the most inclusive, so 369 * As this is the newest list, it is the most inclusive, so
370 * should replace the previous list. 370 * should replace the previous list.
371 */ 371 */
372 si->si_snapblklist = ip->i_snapblklist; 372 si->si_snapblklist = ip->i_snapblklist;
373 } 373 }
374 si->si_gen++; 374 si->si_gen++;
375 mutex_exit(&si->si_lock); 375 mutex_exit(&si->si_lock);
376 376
377 if (snapshot_locked) 377 if (snapshot_locked)
378 mutex_exit(&si->si_snaplock); 378 mutex_exit(&si->si_snaplock);
379 if (suspended) { 379 if (suspended) {
380 vfs_resume(vp->v_mount); 380 vfs_resume(vp->v_mount);
381#ifdef DEBUG 381#ifdef DEBUG
382 getmicrotime(&endtime); 382 getmicrotime(&endtime);
383 timersub(&endtime, &starttime, &endtime); 383 timersub(&endtime, &starttime, &endtime);
384 printf("%s: suspended %ld.%03ld sec, redo %d of %d\n", 384 printf("%s: suspended %ld.%03ld sec, redo %d of %d\n",
385 mp->mnt_stat.f_mntonname, (long)endtime.tv_sec, 385 mp->mnt_stat.f_mntonname, (long)endtime.tv_sec,
386 endtime.tv_usec / 1000, redo, fs->fs_ncg); 386 endtime.tv_usec / 1000, redo, fs->fs_ncg);
387#endif 387#endif
388 } 388 }
389 if (error) { 389 if (error) {
390 if (!UFS_WAPBL_BEGIN(mp)) { 390 if (!UFS_WAPBL_BEGIN(mp)) {
391 (void) ffs_truncate(vp, (off_t)0, 0, NOCRED); 391 (void) ffs_truncate(vp, (off_t)0, 0, NOCRED);
392 UFS_WAPBL_END(mp); 392 UFS_WAPBL_END(mp);
393 } 393 }
394 } else 394 } else
395 vref(vp); 395 vref(vp);
396 return (error); 396 return (error);
397} 397}
398 398
399/* 399/*
400 * Prepare vnode to become a snapshot. 400 * Prepare vnode to become a snapshot.
401 */ 401 */
402static int 402static int
403snapshot_setup(struct mount *mp, struct vnode *vp) 403snapshot_setup(struct mount *mp, struct vnode *vp)
404{ 404{
405 int error, i, len, loc; 405 int error, i, len, loc;
406 daddr_t blkno, numblks; 406 daddr_t blkno, numblks;
407 struct buf *ibp, *nbp; 407 struct buf *ibp, *nbp;
408 struct fs *fs = VFSTOUFS(mp)->um_fs; 408 struct fs *fs = VFSTOUFS(mp)->um_fs;
409 struct lwp *l = curlwp; 409 struct lwp *l = curlwp;
410 410
411 /* 411 /*
412 * Check mount, exclusive reference and owner. 412 * Check mount, exclusive reference and owner.
413 */ 413 */
414 if (vp->v_mount != mp) 414 if (vp->v_mount != mp)
415 return EXDEV; 415 return EXDEV;
416 if (vp->v_usecount != 1 || vp->v_writecount != 0) 416 if (vp->v_usecount != 1 || vp->v_writecount != 0)
417 return EBUSY; 417 return EBUSY;
418 if (kauth_authorize_generic(l->l_cred, KAUTH_GENERIC_ISSUSER, 418 if (kauth_authorize_generic(l->l_cred, KAUTH_GENERIC_ISSUSER,
419 NULL) != 0 && 419 NULL) != 0 &&
420 VTOI(vp)->i_uid != kauth_cred_geteuid(l->l_cred)) 420 VTOI(vp)->i_uid != kauth_cred_geteuid(l->l_cred))
421 return EACCES; 421 return EACCES;
422 422
423 if (vp->v_size != 0) { 423 if (vp->v_size != 0) {
424 error = ffs_truncate(vp, 0, 0, NOCRED); 424 error = ffs_truncate(vp, 0, 0, NOCRED);
425 if (error) 425 if (error)
426 return error; 426 return error;
427 } 427 }
428 /* 428 /*
429 * Write an empty list of preallocated blocks to the end of 429 * Write an empty list of preallocated blocks to the end of
430 * the snapshot to set size to at least that of the filesystem. 430 * the snapshot to set size to at least that of the filesystem.
431 */ 431 */
432 numblks = howmany(fs->fs_size, fs->fs_frag); 432 numblks = howmany(fs->fs_size, fs->fs_frag);
433 blkno = 1; 433 blkno = 1;
434 blkno = ufs_rw64(blkno, UFS_FSNEEDSWAP(fs)); 434 blkno = ufs_rw64(blkno, UFS_FSNEEDSWAP(fs));
435 error = vn_rdwr(UIO_WRITE, vp, 435 error = vn_rdwr(UIO_WRITE, vp,
436 (void *)&blkno, sizeof(blkno), lblktosize(fs, (off_t)numblks), 436 (void *)&blkno, sizeof(blkno), lblktosize(fs, (off_t)numblks),
437 UIO_SYSSPACE, IO_NODELOCKED|IO_UNIT, l->l_cred, NULL, NULL); 437 UIO_SYSSPACE, IO_NODELOCKED|IO_UNIT, l->l_cred, NULL, NULL);
438 if (error) 438 if (error)
439 return error; 439 return error;
440 /* 440 /*
441 * Preallocate critical data structures so that we can copy 441 * Preallocate critical data structures so that we can copy
442 * them in without further allocation after we suspend all 442 * them in without further allocation after we suspend all
443 * operations on the filesystem. We would like to just release 443 * operations on the filesystem. We would like to just release
444 * the allocated buffers without writing them since they will 444 * the allocated buffers without writing them since they will
445 * be filled in below once we are ready to go, but this upsets 445 * be filled in below once we are ready to go, but this upsets
446 * the soft update code, so we go ahead and write the new buffers. 446 * the soft update code, so we go ahead and write the new buffers.
447 * 447 *
448 * Allocate all indirect blocks and mark all of them as not 448 * Allocate all indirect blocks and mark all of them as not
449 * needing to be copied. 449 * needing to be copied.
450 */ 450 */
451 error = UFS_WAPBL_BEGIN(mp); 451 error = UFS_WAPBL_BEGIN(mp);
452 if (error) 452 if (error)
453 return error; 453 return error;
454 for (blkno = NDADDR, i = 0; blkno < numblks; blkno += NINDIR(fs)) { 454 for (blkno = NDADDR, i = 0; blkno < numblks; blkno += NINDIR(fs)) {
455 error = ffs_balloc(vp, lblktosize(fs, (off_t)blkno), 455 error = ffs_balloc(vp, lblktosize(fs, (off_t)blkno),
456 fs->fs_bsize, l->l_cred, B_METAONLY, &ibp); 456 fs->fs_bsize, l->l_cred, B_METAONLY, &ibp);
457 if (error) 457 if (error)
458 goto out; 458 goto out;
459 if (DOINGSOFTDEP(vp)) 459 if (DOINGSOFTDEP(vp))
460 bawrite(ibp); 460 bawrite(ibp);
461 else 461 else
462 brelse(ibp, 0); 462 brelse(ibp, 0);
463 if ((++i % 16) == 0) { 463 if ((++i % 16) == 0) {
464 UFS_WAPBL_END(mp); 464 UFS_WAPBL_END(mp);
465 error = UFS_WAPBL_BEGIN(mp); 465 error = UFS_WAPBL_BEGIN(mp);
466 if (error) 466 if (error)
467 return error; 467 return error;
468 } 468 }
469 } 469 }
470 /* 470 /*
471 * Allocate copies for the superblock and its summary information. 471 * Allocate copies for the superblock and its summary information.
472 */ 472 */
473 error = ffs_balloc(vp, fs->fs_sblockloc, fs->fs_sbsize, l->l_cred, 473 error = ffs_balloc(vp, fs->fs_sblockloc, fs->fs_sbsize, l->l_cred,
474 0, &nbp); 474 0, &nbp);
475 if (error) 475 if (error)
476 goto out; 476 goto out;
477 bawrite(nbp); 477 bawrite(nbp);
478 blkno = fragstoblks(fs, fs->fs_csaddr); 478 blkno = fragstoblks(fs, fs->fs_csaddr);
479 len = howmany(fs->fs_cssize, fs->fs_bsize); 479 len = howmany(fs->fs_cssize, fs->fs_bsize);
480 for (loc = 0; loc < len; loc++) { 480 for (loc = 0; loc < len; loc++) {
481 error = ffs_balloc(vp, lblktosize(fs, (off_t)(blkno + loc)), 481 error = ffs_balloc(vp, lblktosize(fs, (off_t)(blkno + loc)),
482 fs->fs_bsize, l->l_cred, 0, &nbp); 482 fs->fs_bsize, l->l_cred, 0, &nbp);
483 if (error) 483 if (error)
484 goto out; 484 goto out;
485 bawrite(nbp); 485 bawrite(nbp);
486 } 486 }
487 487
488out: 488out:
489 UFS_WAPBL_END(mp); 489 UFS_WAPBL_END(mp);
490 return error; 490 return error;
491} 491}
492 492
493/* 493/*
494 * Create a copy of the superblock and its summary information. 494 * Create a copy of the superblock and its summary information.
495 * It is up to the caller to free copyfs and copy_fs->fs_csp. 495 * It is up to the caller to free copyfs and copy_fs->fs_csp.
496 */ 496 */
497static int 497static int
498snapshot_copyfs(struct mount *mp, struct vnode *vp, void **sbbuf) 498snapshot_copyfs(struct mount *mp, struct vnode *vp, void **sbbuf)
499{ 499{
500 int error, i, len, loc, size; 500 int error, i, len, loc, size;
501 void *space; 501 void *space;
502 int32_t *lp; 502 int32_t *lp;
503 struct buf *bp; 503 struct buf *bp;
504 struct fs *copyfs, *fs = VFSTOUFS(mp)->um_fs; 504 struct fs *copyfs, *fs = VFSTOUFS(mp)->um_fs;
505 struct lwp *l = curlwp; 505 struct lwp *l = curlwp;
506 struct vnode *devvp = VTOI(vp)->i_devvp; 506 struct vnode *devvp = VTOI(vp)->i_devvp;
507 507
508 /* 508 /*
509 * Grab a copy of the superblock and its summary information. 509 * Grab a copy of the superblock and its summary information.
510 * We delay writing it until the suspension is released below. 510 * We delay writing it until the suspension is released below.
511 */ 511 */
512 *sbbuf = malloc(fs->fs_bsize, M_UFSMNT, M_WAITOK); 512 *sbbuf = malloc(fs->fs_bsize, M_UFSMNT, M_WAITOK);
513 loc = blkoff(fs, fs->fs_sblockloc); 513 loc = blkoff(fs, fs->fs_sblockloc);
514 if (loc > 0) 514 if (loc > 0)
515 memset(*sbbuf, 0, loc); 515 memset(*sbbuf, 0, loc);
516 copyfs = (struct fs *)((char *)(*sbbuf) + loc); 516 copyfs = (struct fs *)((char *)(*sbbuf) + loc);
517 bcopy(fs, copyfs, fs->fs_sbsize); 517 bcopy(fs, copyfs, fs->fs_sbsize);
518 size = fs->fs_bsize < SBLOCKSIZE ? fs->fs_bsize : SBLOCKSIZE; 518 size = fs->fs_bsize < SBLOCKSIZE ? fs->fs_bsize : SBLOCKSIZE;
519 if (fs->fs_sbsize < size) 519 if (fs->fs_sbsize < size)
520 memset((char *)(*sbbuf) + loc + fs->fs_sbsize, 0,  520 memset((char *)(*sbbuf) + loc + fs->fs_sbsize, 0,
521 size - fs->fs_sbsize); 521 size - fs->fs_sbsize);
522 size = blkroundup(fs, fs->fs_cssize); 522 size = blkroundup(fs, fs->fs_cssize);
523 if (fs->fs_contigsumsize > 0) 523 if (fs->fs_contigsumsize > 0)
524 size += fs->fs_ncg * sizeof(int32_t); 524 size += fs->fs_ncg * sizeof(int32_t);
525 space = malloc(size, M_UFSMNT, M_WAITOK); 525 space = malloc(size, M_UFSMNT, M_WAITOK);
526 copyfs->fs_csp = space; 526 copyfs->fs_csp = space;
527 bcopy(fs->fs_csp, copyfs->fs_csp, fs->fs_cssize); 527 bcopy(fs->fs_csp, copyfs->fs_csp, fs->fs_cssize);
528 space = (char *)space + fs->fs_cssize; 528 space = (char *)space + fs->fs_cssize;
529 loc = howmany(fs->fs_cssize, fs->fs_fsize); 529 loc = howmany(fs->fs_cssize, fs->fs_fsize);
530 i = fs->fs_frag - loc % fs->fs_frag; 530 i = fs->fs_frag - loc % fs->fs_frag;
531 len = (i == fs->fs_frag) ? 0 : i * fs->fs_fsize; 531 len = (i == fs->fs_frag) ? 0 : i * fs->fs_fsize;
532 if (len > 0) { 532 if (len > 0) {
533 if ((error = bread(devvp, fsbtodb(fs, fs->fs_csaddr + loc), 533 if ((error = bread(devvp, fsbtodb(fs, fs->fs_csaddr + loc),
534 len, l->l_cred, 0, &bp)) != 0) { 534 len, l->l_cred, 0, &bp)) != 0) {
535 brelse(bp, 0); 535 brelse(bp, 0);
536 free(copyfs->fs_csp, M_UFSMNT); 536 free(copyfs->fs_csp, M_UFSMNT);
537 free(*sbbuf, M_UFSMNT); 537 free(*sbbuf, M_UFSMNT);
538 *sbbuf = NULL; 538 *sbbuf = NULL;
539 return error; 539 return error;
540 } 540 }
541 bcopy(bp->b_data, space, (u_int)len); 541 bcopy(bp->b_data, space, (u_int)len);
542 space = (char *)space + len; 542 space = (char *)space + len;
543 brelse(bp, BC_INVAL | BC_NOCACHE); 543 brelse(bp, BC_INVAL | BC_NOCACHE);
544 } 544 }
545 if (fs->fs_contigsumsize > 0) { 545 if (fs->fs_contigsumsize > 0) {
546 copyfs->fs_maxcluster = lp = space; 546 copyfs->fs_maxcluster = lp = space;
547 for (i = 0; i < fs->fs_ncg; i++) 547 for (i = 0; i < fs->fs_ncg; i++)
548 *lp++ = fs->fs_contigsumsize; 548 *lp++ = fs->fs_contigsumsize;
549 } 549 }
550 if (mp->mnt_wapbl) 550 if (mp->mnt_wapbl)
551 copyfs->fs_flags &= ~FS_DOWAPBL; 551 copyfs->fs_flags &= ~FS_DOWAPBL;
552 return 0; 552 return 0;
553} 553}
554 554
555/* 555/*
556 * We must check for active files that have been unlinked (e.g., with a zero 556 * We must check for active files that have been unlinked (e.g., with a zero
557 * link count). We have to expunge all trace of these files from the snapshot 557 * link count). We have to expunge all trace of these files from the snapshot
558 * so that they are not reclaimed prematurely by fsck or unnecessarily dumped. 558 * so that they are not reclaimed prematurely by fsck or unnecessarily dumped.
559 * Note that we skip unlinked snapshot files as they will be handled separately. 559 * Note that we skip unlinked snapshot files as they will be handled separately.
560 * Calculate the snapshot list size and create a preliminary list. 560 * Calculate the snapshot list size and create a preliminary list.
561 */ 561 */
562static int 562static int
563snapshot_expunge(struct mount *mp, struct vnode *vp, struct fs *copy_fs, 563snapshot_expunge(struct mount *mp, struct vnode *vp, struct fs *copy_fs,
564 daddr_t *snaplistsize, daddr_t **snaplist) 564 daddr_t *snaplistsize, daddr_t **snaplist)
565{ 565{
566 bool has_wapbl = false; 566 bool has_wapbl = false;
567 int cg, error, len, loc; 567 int cg, error, len, loc;
568 daddr_t blkno, *blkp; 568 daddr_t blkno, *blkp;
569 struct fs *fs = VFSTOUFS(mp)->um_fs; 569 struct fs *fs = VFSTOUFS(mp)->um_fs;
570 struct inode *xp; 570 struct inode *xp;
571 struct lwp *l = curlwp; 571 struct lwp *l = curlwp;
572 struct vattr vat; 572 struct vattr vat;
573 struct vnode *logvp = NULL, *mvp = NULL, *xvp; 573 struct vnode *logvp = NULL, *mvp = NULL, *xvp;
574 574
575 *snaplist = NULL; 575 *snaplist = NULL;
576 /* 576 /*
577 * Get the log inode if any. 577 * Get the log inode if any.
578 */ 578 */
579 if ((fs->fs_flags & FS_DOWAPBL) && 579 if ((fs->fs_flags & FS_DOWAPBL) &&
580 fs->fs_journal_location == UFS_WAPBL_JOURNALLOC_IN_FILESYSTEM) { 580 fs->fs_journal_location == UFS_WAPBL_JOURNALLOC_IN_FILESYSTEM) {
581 error = VFS_VGET(mp, 581 error = VFS_VGET(mp,
582 fs->fs_journallocs[UFS_WAPBL_INFS_INO], &logvp); 582 fs->fs_journallocs[UFS_WAPBL_INFS_INO], &logvp);
583 if (error) 583 if (error)
584 goto out; 584 goto out;
585 } 585 }
586 /* 586 /*
587 * Allocate a marker vnode. 587 * Allocate a marker vnode.
588 */ 588 */
589 if ((mvp = vnalloc(mp)) == NULL) { 589 if ((mvp = vnalloc(mp)) == NULL) {
590 error = ENOMEM; 590 error = ENOMEM;
591 goto out; 591 goto out;
592 } 592 }
593 /* 593 /*
594 * We also calculate the needed size for the snapshot list. 594 * We also calculate the needed size for the snapshot list.
595 */ 595 */
596 *snaplistsize = fs->fs_ncg + howmany(fs->fs_cssize, fs->fs_bsize) + 596 *snaplistsize = fs->fs_ncg + howmany(fs->fs_cssize, fs->fs_bsize) +
597 FSMAXSNAP + 1 /* superblock */ + 1 /* last block */ + 1 /* size */; 597 FSMAXSNAP + 1 /* superblock */ + 1 /* last block */ + 1 /* size */;
598 error = UFS_WAPBL_BEGIN(mp); 598 error = UFS_WAPBL_BEGIN(mp);
599 if (error) 599 if (error)
600 goto out; 600 goto out;
601 has_wapbl = true; 601 has_wapbl = true;
602 mutex_enter(&mntvnode_lock); 602 mutex_enter(&mntvnode_lock);
603 /* 603 /*
604 * NOTE: not using the TAILQ_FOREACH here since in this loop vgone() 604 * NOTE: not using the TAILQ_FOREACH here since in this loop vgone()
605 * and vclean() can be called indirectly 605 * and vclean() can be called indirectly
606 */ 606 */
607 for (xvp = TAILQ_FIRST(&mp->mnt_vnodelist); xvp; xvp = vunmark(mvp)) { 607 for (xvp = TAILQ_FIRST(&mp->mnt_vnodelist); xvp; xvp = vunmark(mvp)) {
608 vmark(mvp, xvp); 608 vmark(mvp, xvp);
609 /* 609 /*
610 * Make sure this vnode wasn't reclaimed in getnewvnode(). 610 * Make sure this vnode wasn't reclaimed in getnewvnode().
611 * Start over if it has (it won't be on the list anymore). 611 * Start over if it has (it won't be on the list anymore).
612 */ 612 */
613 if (xvp->v_mount != mp || vismarker(xvp)) 613 if (xvp->v_mount != mp || vismarker(xvp))
614 continue; 614 continue;
615 mutex_enter(&xvp->v_interlock); 615 mutex_enter(&xvp->v_interlock);
616 if ((xvp->v_iflag & VI_XLOCK) || 616 if ((xvp->v_iflag & VI_XLOCK) ||
617 xvp->v_usecount == 0 || xvp->v_type == VNON || 617 xvp->v_usecount == 0 || xvp->v_type == VNON ||
618 VTOI(xvp) == NULL || 618 VTOI(xvp) == NULL ||
619 (VTOI(xvp)->i_flags & SF_SNAPSHOT)) { 619 (VTOI(xvp)->i_flags & SF_SNAPSHOT)) {
620 mutex_exit(&xvp->v_interlock); 620 mutex_exit(&xvp->v_interlock);
621 continue; 621 continue;
622 } 622 }
623 mutex_exit(&mntvnode_lock); 623 mutex_exit(&mntvnode_lock);
624 /* 624 /*
625 * XXXAD should increase vnode ref count to prevent it 625 * XXXAD should increase vnode ref count to prevent it
626 * disappearing or being recycled. 626 * disappearing or being recycled.
627 */ 627 */
628 mutex_exit(&xvp->v_interlock); 628 mutex_exit(&xvp->v_interlock);
629#ifdef DEBUG 629#ifdef DEBUG
630 if (snapdebug) 630 if (snapdebug)
631 vprint("ffs_snapshot: busy vnode", xvp); 631 vprint("ffs_snapshot: busy vnode", xvp);
632#endif 632#endif
633 xp = VTOI(xvp); 633 xp = VTOI(xvp);
634 if (xvp != logvp) { 634 if (xvp != logvp) {
635 if (VOP_GETATTR(xvp, &vat, l->l_cred) == 0 && 635 if (VOP_GETATTR(xvp, &vat, l->l_cred) == 0 &&
636 vat.va_nlink > 0) { 636 vat.va_nlink > 0) {
637 mutex_enter(&mntvnode_lock); 637 mutex_enter(&mntvnode_lock);
638 continue; 638 continue;
639 } 639 }
640 if (ffs_checkfreefile(copy_fs, vp, xp->i_number)) { 640 if (ffs_checkfreefile(copy_fs, vp, xp->i_number)) {
641 mutex_enter(&mntvnode_lock); 641 mutex_enter(&mntvnode_lock);
642 continue; 642 continue;
643 } 643 }
644 } 644 }
645 /* 645 /*
646 * If there is a fragment, clear it here. 646 * If there is a fragment, clear it here.
647 */ 647 */
648 blkno = 0; 648 blkno = 0;
649 loc = howmany(xp->i_size, fs->fs_bsize) - 1; 649 loc = howmany(xp->i_size, fs->fs_bsize) - 1;
650 if (loc < NDADDR) { 650 if (loc < NDADDR) {
651 len = fragroundup(fs, blkoff(fs, xp->i_size)); 651 len = fragroundup(fs, blkoff(fs, xp->i_size));
652 if (len > 0 && len < fs->fs_bsize) { 652 if (len > 0 && len < fs->fs_bsize) {
653 ffs_blkfree(copy_fs, vp, db_get(xp, loc), 653 ffs_blkfree(copy_fs, vp, db_get(xp, loc),
654 len, xp->i_number); 654 len, xp->i_number);
655 blkno = db_get(xp, loc); 655 blkno = db_get(xp, loc);
656 db_assign(xp, loc, 0); 656 db_assign(xp, loc, 0);
657 } 657 }
658 } 658 }
659 *snaplistsize += 1; 659 *snaplistsize += 1;
660 error = expunge(vp, xp, copy_fs, fullacct, BLK_NOCOPY); 660 error = expunge(vp, xp, copy_fs, fullacct, BLK_NOCOPY);
661 if (blkno) 661 if (blkno)
662 db_assign(xp, loc, blkno); 662 db_assign(xp, loc, blkno);
663 if (!error) 663 if (!error)
664 error = ffs_freefile(copy_fs, vp, xp->i_number, 664 error = ffs_freefile(copy_fs, vp, xp->i_number,
665 xp->i_mode); 665 xp->i_mode);
666 if (error) { 666 if (error) {
667 (void)vunmark(mvp); 667 (void)vunmark(mvp);
668 goto out; 668 goto out;
669 } 669 }
670 mutex_enter(&mntvnode_lock); 670 mutex_enter(&mntvnode_lock);
671 } 671 }
672 mutex_exit(&mntvnode_lock); 672 mutex_exit(&mntvnode_lock);
673 /* 673 /*
674 * Create a preliminary list of preallocated snapshot blocks. 674 * Create a preliminary list of preallocated snapshot blocks.
675 */ 675 */
676 *snaplist = malloc(*snaplistsize * sizeof(daddr_t), M_UFSMNT, M_WAITOK); 676 *snaplist = malloc(*snaplistsize * sizeof(daddr_t), M_UFSMNT, M_WAITOK);
677 blkp = &(*snaplist)[1]; 677 blkp = &(*snaplist)[1];
678 *blkp++ = lblkno(fs, fs->fs_sblockloc); 678 *blkp++ = lblkno(fs, fs->fs_sblockloc);
679 blkno = fragstoblks(fs, fs->fs_csaddr); 679 blkno = fragstoblks(fs, fs->fs_csaddr);
680 for (cg = 0; cg < fs->fs_ncg; cg++) { 680 for (cg = 0; cg < fs->fs_ncg; cg++) {
681 if (fragstoblks(fs, cgtod(fs, cg)) > blkno) 681 if (fragstoblks(fs, cgtod(fs, cg)) > blkno)
682 break; 682 break;
683 *blkp++ = fragstoblks(fs, cgtod(fs, cg)); 683 *blkp++ = fragstoblks(fs, cgtod(fs, cg));
684 } 684 }
685 len = howmany(fs->fs_cssize, fs->fs_bsize); 685 len = howmany(fs->fs_cssize, fs->fs_bsize);
686 for (loc = 0; loc < len; loc++) 686 for (loc = 0; loc < len; loc++)
687 *blkp++ = blkno + loc; 687 *blkp++ = blkno + loc;
688 for (; cg < fs->fs_ncg; cg++) 688 for (; cg < fs->fs_ncg; cg++)
689 *blkp++ = fragstoblks(fs, cgtod(fs, cg)); 689 *blkp++ = fragstoblks(fs, cgtod(fs, cg));
690 690
691out: 691out:
692 if (has_wapbl) 692 if (has_wapbl)
693 UFS_WAPBL_END(mp); 693 UFS_WAPBL_END(mp);
694 if (mvp != NULL) 694 if (mvp != NULL)
695 vnfree(mvp); 695 vnfree(mvp);
696 if (logvp != NULL) 696 if (logvp != NULL)
697 vput(logvp); 697 vput(logvp);
698 if (error && *snaplist != NULL) { 698 if (error && *snaplist != NULL) {
699 free(*snaplist, M_UFSMNT); 699 free(*snaplist, M_UFSMNT);
700 *snaplist = NULL; 700 *snaplist = NULL;
701 } 701 }
702 702
703 return error; 703 return error;
704} 704}
705 705
706/* 706/*
707 * Copy allocation information from all the snapshots in this snapshot and 707 * Copy allocation information from all the snapshots in this snapshot and
708 * then expunge them from its view. Also, collect the list of allocated 708 * then expunge them from its view. Also, collect the list of allocated
709 * blocks in i_snapblklist. 709 * blocks in i_snapblklist.
710 */ 710 */
711static int 711static int
712snapshot_expunge_snap(struct mount *mp, struct vnode *vp, 712snapshot_expunge_snap(struct mount *mp, struct vnode *vp,
713 struct fs *copy_fs, daddr_t snaplistsize) 713 struct fs *copy_fs, daddr_t snaplistsize)
714{ 714{
715 int error, i; 715 int error, i;
716 daddr_t numblks, *snaplist = NULL; 716 daddr_t numblks, *snaplist = NULL;
717 struct fs *fs = VFSTOUFS(mp)->um_fs; 717 struct fs *fs = VFSTOUFS(mp)->um_fs;
718 struct inode *ip = VTOI(vp), *xp; 718 struct inode *ip = VTOI(vp), *xp;
719 struct lwp *l = curlwp; 719 struct lwp *l = curlwp;
720 struct snap_info *si = VFSTOUFS(mp)->um_snapinfo; 720 struct snap_info *si = VFSTOUFS(mp)->um_snapinfo;
721 721
722 error = UFS_WAPBL_BEGIN(mp); 722 error = UFS_WAPBL_BEGIN(mp);
723 if (error) 723 if (error)
724 return error; 724 return error;
725 TAILQ_FOREACH(xp, &si->si_snapshots, i_nextsnap) { 725 TAILQ_FOREACH(xp, &si->si_snapshots, i_nextsnap) {
726 if (xp == ip) 726 if (xp == ip)
727 break; 727 break;
728 error = expunge(vp, xp, fs, snapacct, BLK_SNAP); 728 error = expunge(vp, xp, fs, snapacct, BLK_SNAP);
729 if (error) 729 if (error)
730 break; 730 break;
731 if (xp->i_ffs_effnlink != 0) 731 if (xp->i_ffs_effnlink != 0)
732 continue; 732 continue;
733 error = ffs_freefile(copy_fs, vp, xp->i_number, xp->i_mode); 733 error = ffs_freefile(copy_fs, vp, xp->i_number, xp->i_mode);
734 if (error) 734 if (error)
735 break; 735 break;
736 } 736 }
737 if (error) 737 if (error)
738 goto out; 738 goto out;
739 /* 739 /*
740 * Allocate space for the full list of preallocated snapshot blocks. 740 * Allocate space for the full list of preallocated snapshot blocks.
741 */ 741 */
742 snaplist = malloc(snaplistsize * sizeof(daddr_t), M_UFSMNT, M_WAITOK); 742 snaplist = malloc(snaplistsize * sizeof(daddr_t), M_UFSMNT, M_WAITOK);
743 ip->i_snapblklist = &snaplist[1]; 743 ip->i_snapblklist = &snaplist[1];
744 /* 744 /*
745 * Expunge the blocks used by the snapshots from the set of 745 * Expunge the blocks used by the snapshots from the set of
746 * blocks marked as used in the snapshot bitmaps. Also, collect 746 * blocks marked as used in the snapshot bitmaps. Also, collect
747 * the list of allocated blocks in i_snapblklist. 747 * the list of allocated blocks in i_snapblklist.
748 */ 748 */
749 error = expunge(vp, ip, copy_fs, mapacct, BLK_SNAP); 749 error = expunge(vp, ip, copy_fs, mapacct, BLK_SNAP);
750 if (error) 750 if (error)
751 goto out; 751 goto out;
752 if (snaplistsize < ip->i_snapblklist - snaplist) 752 if (snaplistsize < ip->i_snapblklist - snaplist)
753 panic("ffs_snapshot: list too small"); 753 panic("ffs_snapshot: list too small");
754 snaplistsize = ip->i_snapblklist - snaplist; 754 snaplistsize = ip->i_snapblklist - snaplist;
755 snaplist[0] = snaplistsize; 755 snaplist[0] = snaplistsize;
756 ip->i_snapblklist = &snaplist[0]; 756 ip->i_snapblklist = &snaplist[0];
757 /* 757 /*
758 * Write out the list of allocated blocks to the end of the snapshot. 758 * Write out the list of allocated blocks to the end of the snapshot.
759 */ 759 */
760 numblks = howmany(fs->fs_size, fs->fs_frag); 760 numblks = howmany(fs->fs_size, fs->fs_frag);
761 for (i = 0; i < snaplistsize; i++) 761 for (i = 0; i < snaplistsize; i++)
762 snaplist[i] = ufs_rw64(snaplist[i], UFS_FSNEEDSWAP(fs)); 762 snaplist[i] = ufs_rw64(snaplist[i], UFS_FSNEEDSWAP(fs));
763 error = vn_rdwr(UIO_WRITE, vp, (void *)snaplist, 763 error = vn_rdwr(UIO_WRITE, vp, (void *)snaplist,
764 snaplistsize * sizeof(daddr_t), lblktosize(fs, (off_t)numblks), 764 snaplistsize * sizeof(daddr_t), lblktosize(fs, (off_t)numblks),
765 UIO_SYSSPACE, IO_NODELOCKED | IO_JOURNALLOCKED | IO_UNIT, 765 UIO_SYSSPACE, IO_NODELOCKED | IO_JOURNALLOCKED | IO_UNIT,
766 l->l_cred, NULL, NULL); 766 l->l_cred, NULL, NULL);
767 for (i = 0; i < snaplistsize; i++) 767 for (i = 0; i < snaplistsize; i++)
768 snaplist[i] = ufs_rw64(snaplist[i], UFS_FSNEEDSWAP(fs)); 768 snaplist[i] = ufs_rw64(snaplist[i], UFS_FSNEEDSWAP(fs));
769out: 769out:
770 UFS_WAPBL_END(mp); 770 UFS_WAPBL_END(mp);
771 if (error && snaplist != NULL) { 771 if (error && snaplist != NULL) {
772 free(snaplist, M_UFSMNT); 772 free(snaplist, M_UFSMNT);
773 ip->i_snapblklist = NULL; 773 ip->i_snapblklist = NULL;
774 } 774 }
775 return error; 775 return error;
776} 776}
777 777
778/* 778/*
779 * Write the superblock and its summary information to the snapshot. 779 * Write the superblock and its summary information to the snapshot.
780 * Make sure, the first NDADDR blocks get copied to the snapshot. 780 * Make sure, the first NDADDR blocks get copied to the snapshot.
781 */ 781 */
782static int 782static int
783snapshot_writefs(struct mount *mp, struct vnode *vp, void *sbbuf) 783snapshot_writefs(struct mount *mp, struct vnode *vp, void *sbbuf)
784{ 784{
785 int error, len, loc; 785 int error, len, loc;
786 void *space; 786 void *space;
787 daddr_t blkno; 787 daddr_t blkno;
788 struct buf *bp; 788 struct buf *bp;
789 struct fs *copyfs, *fs = VFSTOUFS(mp)->um_fs; 789 struct fs *copyfs, *fs = VFSTOUFS(mp)->um_fs;
790 struct inode *ip = VTOI(vp); 790 struct inode *ip = VTOI(vp);
791 struct lwp *l = curlwp; 791 struct lwp *l = curlwp;
792 792
793 copyfs = (struct fs *)((char *)sbbuf + blkoff(fs, fs->fs_sblockloc)); 793 copyfs = (struct fs *)((char *)sbbuf + blkoff(fs, fs->fs_sblockloc));
794 794
795 /* 795 /*
796 * Write the superblock and its summary information 796 * Write the superblock and its summary information
797 * to the snapshot. 797 * to the snapshot.
798 */ 798 */
799 blkno = fragstoblks(fs, fs->fs_csaddr); 799 blkno = fragstoblks(fs, fs->fs_csaddr);
800 len = howmany(fs->fs_cssize, fs->fs_bsize); 800 len = howmany(fs->fs_cssize, fs->fs_bsize);
801 space = copyfs->fs_csp; 801 space = copyfs->fs_csp;
802#ifdef FFS_EI 802#ifdef FFS_EI
803 if (UFS_FSNEEDSWAP(fs)) { 803 if (UFS_FSNEEDSWAP(fs)) {
804 ffs_sb_swap(copyfs, copyfs); 804 ffs_sb_swap(copyfs, copyfs);
805 ffs_csum_swap(space, space, fs->fs_cssize); 805 ffs_csum_swap(space, space, fs->fs_cssize);
806 } 806 }
807#endif 807#endif
808 error = UFS_WAPBL_BEGIN(mp); 808 error = UFS_WAPBL_BEGIN(mp);
809 if (error) 809 if (error)
810 return error; 810 return error;
811 for (loc = 0; loc < len; loc++) { 811 for (loc = 0; loc < len; loc++) {
812 error = bread(vp, blkno + loc, fs->fs_bsize, l->l_cred, 812 error = bread(vp, blkno + loc, fs->fs_bsize, l->l_cred,
813 B_MODIFY, &bp); 813 B_MODIFY, &bp);
814 if (error) { 814 if (error) {
815 brelse(bp, 0); 815 brelse(bp, 0);
816 break; 816 break;
817 } 817 }
818 bcopy(space, bp->b_data, fs->fs_bsize); 818 bcopy(space, bp->b_data, fs->fs_bsize);
819 space = (char *)space + fs->fs_bsize; 819 space = (char *)space + fs->fs_bsize;
820 bawrite(bp); 820 bawrite(bp);
821 } 821 }
822 if (error) 822 if (error)
823 goto out; 823 goto out;
824 error = bread(vp, lblkno(fs, fs->fs_sblockloc), 824 error = bread(vp, lblkno(fs, fs->fs_sblockloc),
825 fs->fs_bsize, l->l_cred, B_MODIFY, &bp); 825 fs->fs_bsize, l->l_cred, B_MODIFY, &bp);
826 if (error) { 826 if (error) {
827 brelse(bp, 0); 827 brelse(bp, 0);
828 goto out; 828 goto out;
829 } else { 829 } else {
830 bcopy(sbbuf, bp->b_data, fs->fs_bsize); 830 bcopy(sbbuf, bp->b_data, fs->fs_bsize);
831 bawrite(bp); 831 bawrite(bp);
832 } 832 }
833 /* 833 /*
834 * Copy the first NDADDR blocks to the snapshot so ffs_copyonwrite() 834 * Copy the first NDADDR blocks to the snapshot so ffs_copyonwrite()
835 * and ffs_snapblkfree() will always work on indirect blocks. 835 * and ffs_snapblkfree() will always work on indirect blocks.
836 */ 836 */
837 for (loc = 0; loc < NDADDR; loc++) { 837 for (loc = 0; loc < NDADDR; loc++) {
838 if (db_get(ip, loc) != 0) 838 if (db_get(ip, loc) != 0)
839 continue; 839 continue;
840 error = ffs_balloc(vp, lblktosize(fs, (off_t)loc), 840 error = ffs_balloc(vp, lblktosize(fs, (off_t)loc),
841 fs->fs_bsize, l->l_cred, 0, &bp); 841 fs->fs_bsize, l->l_cred, 0, &bp);
842 if (error) 842 if (error)
843 break; 843 break;
844 error = rwfsblk(vp, B_READ, bp->b_data, loc); 844 error = rwfsblk(vp, B_READ, bp->b_data, loc);
845 if (error) { 845 if (error) {
846 brelse(bp, 0); 846 brelse(bp, 0);
847 break; 847 break;
848 } 848 }
849 bawrite(bp); 849 bawrite(bp);
850 } 850 }
851 851
852out: 852out:
853 UFS_WAPBL_END(mp); 853 UFS_WAPBL_END(mp);
854 return error; 854 return error;
855} 855}
856 856
857/* 857/*
858 * Copy all cylinder group maps. 858 * Copy all cylinder group maps.
859 */ 859 */
860static int 860static int
861cgaccount(struct vnode *vp, int passno, int *redo) 861cgaccount(struct vnode *vp, int passno, int *redo)
862{ 862{
863 int cg, error; 863 int cg, error;
864 struct buf *nbp; 864 struct buf *nbp;
865 struct fs *fs = VTOI(vp)->i_fs; 865 struct fs *fs = VTOI(vp)->i_fs;
866 866
867 error = UFS_WAPBL_BEGIN(vp->v_mount); 867 error = UFS_WAPBL_BEGIN(vp->v_mount);
868 if (error) 868 if (error)
869 return error; 869 return error;
870 if (redo != NULL) 870 if (redo != NULL)
871 *redo = 0; 871 *redo = 0;
872 if (passno == 1) 872 if (passno == 1)
873 fs->fs_active = malloc(howmany(fs->fs_ncg, NBBY), 873 fs->fs_active = malloc(howmany(fs->fs_ncg, NBBY),
874 M_DEVBUF, M_WAITOK | M_ZERO); 874 M_DEVBUF, M_WAITOK | M_ZERO);
875 for (cg = 0; cg < fs->fs_ncg; cg++) { 875 for (cg = 0; cg < fs->fs_ncg; cg++) {
876 if (passno == 2 && ACTIVECG_ISSET(fs, cg)) 876 if (passno == 2 && ACTIVECG_ISSET(fs, cg))
877 continue; 877 continue;
878 if (redo != NULL) 878 if (redo != NULL)
879 *redo += 1; 879 *redo += 1;
880 error = ffs_balloc(vp, lfragtosize(fs, cgtod(fs, cg)), 880 error = ffs_balloc(vp, lfragtosize(fs, cgtod(fs, cg)),
881 fs->fs_bsize, curlwp->l_cred, 0, &nbp); 881 fs->fs_bsize, curlwp->l_cred, 0, &nbp);
882 if (error) 882 if (error)
883 break; 883 break;
884 error = cgaccount1(cg, vp, nbp->b_data, passno); 884 error = cgaccount1(cg, vp, nbp->b_data, passno);
885 bawrite(nbp); 885 bawrite(nbp);
886 if (error) 886 if (error)
887 break; 887 break;
888 } 888 }
889 UFS_WAPBL_END(vp->v_mount); 889 UFS_WAPBL_END(vp->v_mount);
890 return error; 890 return error;
891} 891}
892 892
893/* 893/*
894 * Copy a cylinder group map. All the unallocated blocks are marked 894 * Copy a cylinder group map. All the unallocated blocks are marked
895 * BLK_NOCOPY so that the snapshot knows that it need not copy them 895 * BLK_NOCOPY so that the snapshot knows that it need not copy them
896 * if they are later written. If passno is one, then this is a first 896 * if they are later written. If passno is one, then this is a first
897 * pass, so only setting needs to be done. If passno is 2, then this 897 * pass, so only setting needs to be done. If passno is 2, then this
898 * is a revision to a previous pass which must be undone as the 898 * is a revision to a previous pass which must be undone as the
899 * replacement pass is done. 899 * replacement pass is done.
900 */ 900 */
901static int 901static int
902cgaccount1(int cg, struct vnode *vp, void *data, int passno) 902cgaccount1(int cg, struct vnode *vp, void *data, int passno)
903{ 903{
904 struct buf *bp, *ibp; 904 struct buf *bp, *ibp;
905 struct inode *ip; 905 struct inode *ip;
906 struct cg *cgp; 906 struct cg *cgp;
907 struct fs *fs; 907 struct fs *fs;
908 struct lwp *l = curlwp; 908 struct lwp *l = curlwp;
909 daddr_t base, numblks; 909 daddr_t base, numblks;
910 int error, len, loc, ns, indiroff; 910 int error, len, loc, ns, indiroff;
911 911
912 ip = VTOI(vp); 912 ip = VTOI(vp);
913 fs = ip->i_fs; 913 fs = ip->i_fs;
914 ns = UFS_FSNEEDSWAP(fs); 914 ns = UFS_FSNEEDSWAP(fs);
915 error = bread(ip->i_devvp, fsbtodb(fs, cgtod(fs, cg)), 915 error = bread(ip->i_devvp, fsbtodb(fs, cgtod(fs, cg)),
916 (int)fs->fs_cgsize, l->l_cred, 0, &bp); 916 (int)fs->fs_cgsize, l->l_cred, 0, &bp);
917 if (error) { 917 if (error) {
918 brelse(bp, 0); 918 brelse(bp, 0);
919 return (error); 919 return (error);
920 } 920 }
921 cgp = (struct cg *)bp->b_data; 921 cgp = (struct cg *)bp->b_data;
922 if (!cg_chkmagic(cgp, ns)) { 922 if (!cg_chkmagic(cgp, ns)) {
923 brelse(bp, 0); 923 brelse(bp, 0);
924 return (EIO); 924 return (EIO);
925 } 925 }
926 ACTIVECG_SET(fs, cg); 926 ACTIVECG_SET(fs, cg);
927 927
928 bcopy(bp->b_data, data, fs->fs_cgsize); 928 bcopy(bp->b_data, data, fs->fs_cgsize);
929 brelse(bp, 0); 929 brelse(bp, 0);
930 if (fs->fs_cgsize < fs->fs_bsize) 930 if (fs->fs_cgsize < fs->fs_bsize)
931 memset((char *)data + fs->fs_cgsize, 0, 931 memset((char *)data + fs->fs_cgsize, 0,
932 fs->fs_bsize - fs->fs_cgsize); 932 fs->fs_bsize - fs->fs_cgsize);
933 numblks = howmany(fs->fs_size, fs->fs_frag); 933 numblks = howmany(fs->fs_size, fs->fs_frag);
934 len = howmany(fs->fs_fpg, fs->fs_frag); 934 len = howmany(fs->fs_fpg, fs->fs_frag);
935 base = cg * fs->fs_fpg / fs->fs_frag; 935 base = cg * fs->fs_fpg / fs->fs_frag;
936 if (base + len >= numblks) 936 if (base + len >= numblks)
937 len = numblks - base - 1; 937 len = numblks - base - 1;
938 loc = 0; 938 loc = 0;
939 if (base < NDADDR) { 939 if (base < NDADDR) {
940 for ( ; loc < NDADDR; loc++) { 940 for ( ; loc < NDADDR; loc++) {
941 if (ffs_isblock(fs, cg_blksfree(cgp, ns), loc)) 941 if (ffs_isblock(fs, cg_blksfree(cgp, ns), loc))
942 db_assign(ip, loc, BLK_NOCOPY); 942 db_assign(ip, loc, BLK_NOCOPY);
943 else if (db_get(ip, loc) == BLK_NOCOPY) { 943 else if (db_get(ip, loc) == BLK_NOCOPY) {
944 if (passno == 2) 944 if (passno == 2)
945 db_assign(ip, loc, 0); 945 db_assign(ip, loc, 0);
946 else if (passno == 1) 946 else if (passno == 1)
947 panic("ffs_snapshot: lost direct block"); 947 panic("ffs_snapshot: lost direct block");
948 } 948 }
949 } 949 }
950 } 950 }
951 if ((error = ffs_balloc(vp, lblktosize(fs, (off_t)(base + loc)), 951 if ((error = ffs_balloc(vp, lblktosize(fs, (off_t)(base + loc)),
952 fs->fs_bsize, l->l_cred, B_METAONLY, &ibp)) != 0) 952 fs->fs_bsize, l->l_cred, B_METAONLY, &ibp)) != 0)
953 return (error); 953 return (error);
954 indiroff = (base + loc - NDADDR) % NINDIR(fs); 954 indiroff = (base + loc - NDADDR) % NINDIR(fs);
955 for ( ; loc < len; loc++, indiroff++) { 955 for ( ; loc < len; loc++, indiroff++) {
956 if (indiroff >= NINDIR(fs)) { 956 if (indiroff >= NINDIR(fs)) {
957 bawrite(ibp); 957 bawrite(ibp);
958 if ((error = ffs_balloc(vp, 958 if ((error = ffs_balloc(vp,
959 lblktosize(fs, (off_t)(base + loc)), 959 lblktosize(fs, (off_t)(base + loc)),
960 fs->fs_bsize, l->l_cred, B_METAONLY, &ibp)) != 0) 960 fs->fs_bsize, l->l_cred, B_METAONLY, &ibp)) != 0)
961 return (error); 961 return (error);
962 indiroff = 0; 962 indiroff = 0;
963 } 963 }
964 if (ffs_isblock(fs, cg_blksfree(cgp, ns), loc)) 964 if (ffs_isblock(fs, cg_blksfree(cgp, ns), loc))
965 idb_assign(ip, ibp->b_data, indiroff, BLK_NOCOPY); 965 idb_assign(ip, ibp->b_data, indiroff, BLK_NOCOPY);
966 else if (idb_get(ip, ibp->b_data, indiroff) == BLK_NOCOPY) { 966 else if (idb_get(ip, ibp->b_data, indiroff) == BLK_NOCOPY) {
967 if (passno == 2) 967 if (passno == 2)
968 idb_assign(ip, ibp->b_data, indiroff, 0); 968 idb_assign(ip, ibp->b_data, indiroff, 0);
969 else if (passno == 1) 969 else if (passno == 1)
970 panic("ffs_snapshot: lost indirect block"); 970 panic("ffs_snapshot: lost indirect block");
971 } 971 }
972 } 972 }
973 bdwrite(ibp); 973 bdwrite(ibp);
974 return (0); 974 return (0);
975} 975}
976 976
977/* 977/*
978 * Before expunging a snapshot inode, note all the 978 * Before expunging a snapshot inode, note all the
979 * blocks that it claims with BLK_SNAP so that fsck will 979 * blocks that it claims with BLK_SNAP so that fsck will
980 * be able to account for those blocks properly and so 980 * be able to account for those blocks properly and so
981 * that this snapshot knows that it need not copy them 981 * that this snapshot knows that it need not copy them
982 * if the other snapshot holding them is freed. 982 * if the other snapshot holding them is freed.
983 */ 983 */
984static int 984static int
985expunge(struct vnode *snapvp, struct inode *cancelip, struct fs *fs, 985expunge(struct vnode *snapvp, struct inode *cancelip, struct fs *fs,
986 acctfunc_t acctfunc, int expungetype) 986 acctfunc_t acctfunc, int expungetype)
987{ 987{
988 int i, error, ns; 988 int i, error, ns;
989 daddr_t lbn, rlbn; 989 daddr_t lbn, rlbn;
990 daddr_t len, blkno, numblks, blksperindir; 990 daddr_t len, blkno, numblks, blksperindir;
991 struct ufs1_dinode *dip1; 991 struct ufs1_dinode *dip1;
992 struct ufs2_dinode *dip2; 992 struct ufs2_dinode *dip2;
993 struct lwp *l = curlwp; 993 struct lwp *l = curlwp;
994 void *bap; 994 void *bap;
995 struct buf *bp; 995 struct buf *bp;
996 996
997 ns = UFS_FSNEEDSWAP(fs); 997 ns = UFS_FSNEEDSWAP(fs);
998 /* 998 /*
999 * Prepare to expunge the inode. If its inode block has not 999 * Prepare to expunge the inode. If its inode block has not
1000 * yet been copied, then allocate and fill the copy. 1000 * yet been copied, then allocate and fill the copy.
1001 */ 1001 */
1002 lbn = fragstoblks(fs, ino_to_fsba(fs, cancelip->i_number)); 1002 lbn = fragstoblks(fs, ino_to_fsba(fs, cancelip->i_number));
1003 error = snapblkaddr(snapvp, lbn, &blkno); 1003 error = snapblkaddr(snapvp, lbn, &blkno);
1004 if (error) 1004 if (error)
1005 return error; 1005 return error;
1006 if (blkno != 0) { 1006 if (blkno != 0) {
1007 error = bread(snapvp, lbn, fs->fs_bsize, l->l_cred, 1007 error = bread(snapvp, lbn, fs->fs_bsize, l->l_cred,
1008 B_MODIFY, &bp); 1008 B_MODIFY, &bp);
1009 } else { 1009 } else {
1010 error = ffs_balloc(snapvp, lblktosize(fs, (off_t)lbn), 1010 error = ffs_balloc(snapvp, lblktosize(fs, (off_t)lbn),
1011 fs->fs_bsize, l->l_cred, 0, &bp); 1011 fs->fs_bsize, l->l_cred, 0, &bp);
1012 if (! error) 1012 if (! error)
1013 error = rwfsblk(snapvp, B_READ, bp->b_data, lbn); 1013 error = rwfsblk(snapvp, B_READ, bp->b_data, lbn);
1014 } 1014 }
1015 if (error) 1015 if (error)
1016 return error; 1016 return error;
1017 /* 1017 /*
1018 * Set a snapshot inode to be a zero length file, regular files 1018 * Set a snapshot inode to be a zero length file, regular files
1019 * or unlinked snapshots to be completely unallocated. 1019 * or unlinked snapshots to be completely unallocated.
1020 */ 1020 */
1021 if (fs->fs_magic == FS_UFS1_MAGIC) { 1021 if (fs->fs_magic == FS_UFS1_MAGIC) {
1022 dip1 = (struct ufs1_dinode *)bp->b_data + 1022 dip1 = (struct ufs1_dinode *)bp->b_data +
1023 ino_to_fsbo(fs, cancelip->i_number); 1023 ino_to_fsbo(fs, cancelip->i_number);
1024 if (expungetype == BLK_NOCOPY || cancelip->i_ffs_effnlink == 0) 1024 if (expungetype == BLK_NOCOPY || cancelip->i_ffs_effnlink == 0)
1025 dip1->di_mode = 0; 1025 dip1->di_mode = 0;
1026 dip1->di_size = 0; 1026 dip1->di_size = 0;
1027 dip1->di_blocks = 0; 1027 dip1->di_blocks = 0;
1028 dip1->di_flags = 1028 dip1->di_flags =
1029 ufs_rw32(ufs_rw32(dip1->di_flags, ns) & ~SF_SNAPSHOT, ns); 1029 ufs_rw32(ufs_rw32(dip1->di_flags, ns) & ~SF_SNAPSHOT, ns);
1030 bzero(&dip1->di_db[0], (NDADDR + NIADDR) * sizeof(int32_t)); 1030 bzero(&dip1->di_db[0], (NDADDR + NIADDR) * sizeof(int32_t));
1031 } else { 1031 } else {
1032 dip2 = (struct ufs2_dinode *)bp->b_data + 1032 dip2 = (struct ufs2_dinode *)bp->b_data +
1033 ino_to_fsbo(fs, cancelip->i_number); 1033 ino_to_fsbo(fs, cancelip->i_number);
1034 if (expungetype == BLK_NOCOPY || cancelip->i_ffs_effnlink == 0) 1034 if (expungetype == BLK_NOCOPY || cancelip->i_ffs_effnlink == 0)
1035 dip2->di_mode = 0; 1035 dip2->di_mode = 0;
1036 dip2->di_size = 0; 1036 dip2->di_size = 0;
1037 dip2->di_blocks = 0; 1037 dip2->di_blocks = 0;
1038 dip2->di_flags = 1038 dip2->di_flags =
1039 ufs_rw32(ufs_rw32(dip2->di_flags, ns) & ~SF_SNAPSHOT, ns); 1039 ufs_rw32(ufs_rw32(dip2->di_flags, ns) & ~SF_SNAPSHOT, ns);
1040 bzero(&dip2->di_db[0], (NDADDR + NIADDR) * sizeof(int64_t)); 1040 bzero(&dip2->di_db[0], (NDADDR + NIADDR) * sizeof(int64_t));
1041 } 1041 }
1042 bdwrite(bp); 1042 bdwrite(bp);
1043 /* 1043 /*
1044 * Now go through and expunge all the blocks in the file 1044 * Now go through and expunge all the blocks in the file
1045 * using the function requested. 1045 * using the function requested.
1046 */ 1046 */
1047 numblks = howmany(cancelip->i_size, fs->fs_bsize); 1047 numblks = howmany(cancelip->i_size, fs->fs_bsize);
1048 if (fs->fs_magic == FS_UFS1_MAGIC) 1048 if (fs->fs_magic == FS_UFS1_MAGIC)
1049 bap = &cancelip->i_ffs1_db[0]; 1049 bap = &cancelip->i_ffs1_db[0];
1050 else 1050 else
1051 bap = &cancelip->i_ffs2_db[0]; 1051 bap = &cancelip->i_ffs2_db[0];
1052 if ((error = (*acctfunc)(snapvp, bap, 0, NDADDR, fs, 0, expungetype))) 1052 if ((error = (*acctfunc)(snapvp, bap, 0, NDADDR, fs, 0, expungetype)))
1053 return (error); 1053 return (error);
1054 if (fs->fs_magic == FS_UFS1_MAGIC) 1054 if (fs->fs_magic == FS_UFS1_MAGIC)
1055 bap = &cancelip->i_ffs1_ib[0]; 1055 bap = &cancelip->i_ffs1_ib[0];
1056 else 1056 else
1057 bap = &cancelip->i_ffs2_ib[0]; 1057 bap = &cancelip->i_ffs2_ib[0];
1058 if ((error = (*acctfunc)(snapvp, bap, 0, NIADDR, fs, -1, expungetype))) 1058 if ((error = (*acctfunc)(snapvp, bap, 0, NIADDR, fs, -1, expungetype)))
1059 return (error); 1059 return (error);
1060 blksperindir = 1; 1060 blksperindir = 1;
1061 lbn = -NDADDR; 1061 lbn = -NDADDR;
1062 len = numblks - NDADDR; 1062 len = numblks - NDADDR;
1063 rlbn = NDADDR; 1063 rlbn = NDADDR;
1064 for (i = 0; len > 0 && i < NIADDR; i++) { 1064 for (i = 0; len > 0 && i < NIADDR; i++) {
1065 error = indiracct(snapvp, ITOV(cancelip), i, 1065 error = indiracct(snapvp, ITOV(cancelip), i,
1066 ib_get(cancelip, i), lbn, rlbn, len, 1066 ib_get(cancelip, i), lbn, rlbn, len,
1067 blksperindir, fs, acctfunc, expungetype); 1067 blksperindir, fs, acctfunc, expungetype);
1068 if (error) 1068 if (error)
1069 return (error); 1069 return (error);
1070 blksperindir *= NINDIR(fs); 1070 blksperindir *= NINDIR(fs);
1071 lbn -= blksperindir + 1; 1071 lbn -= blksperindir + 1;
1072 len -= blksperindir; 1072 len -= blksperindir;
1073 rlbn += blksperindir; 1073 rlbn += blksperindir;
1074 } 1074 }
1075 return (0); 1075 return (0);
1076} 1076}
1077 1077
1078/* 1078/*
1079 * Descend an indirect block chain for vnode cancelvp accounting for all 1079 * Descend an indirect block chain for vnode cancelvp accounting for all
1080 * its indirect blocks in snapvp. 1080 * its indirect blocks in snapvp.
1081 */ 1081 */
1082static int 1082static int
1083indiracct(struct vnode *snapvp, struct vnode *cancelvp, int level, 1083indiracct(struct vnode *snapvp, struct vnode *cancelvp, int level,
1084 daddr_t blkno, daddr_t lbn, daddr_t rlbn, daddr_t remblks, 1084 daddr_t blkno, daddr_t lbn, daddr_t rlbn, daddr_t remblks,
1085 daddr_t blksperindir, struct fs *fs, acctfunc_t acctfunc, int expungetype) 1085 daddr_t blksperindir, struct fs *fs, acctfunc_t acctfunc, int expungetype)
1086{ 1086{
1087 int error, num, i; 1087 int error, num, i;
1088 daddr_t subblksperindir; 1088 daddr_t subblksperindir;
1089 struct indir indirs[NIADDR + 2]; 1089 struct indir indirs[NIADDR + 2];
1090 daddr_t last; 1090 daddr_t last;
1091 void *bap; 1091 void *bap;
1092 struct buf *bp; 1092 struct buf *bp;
1093 1093
1094 if (blkno == 0) { 1094 if (blkno == 0) {
1095 if (expungetype == BLK_NOCOPY) 1095 if (expungetype == BLK_NOCOPY)
1096 return (0); 1096 return (0);
1097 panic("indiracct: missing indir"); 1097 panic("indiracct: missing indir");
1098 } 1098 }
1099 if ((error = ufs_getlbns(cancelvp, rlbn, indirs, &num)) != 0) 1099 if ((error = ufs_getlbns(cancelvp, rlbn, indirs, &num)) != 0)
1100 return (error); 1100 return (error);
1101 if (lbn != indirs[num - 1 - level].in_lbn || num < 2) 1101 if (lbn != indirs[num - 1 - level].in_lbn || num < 2)
1102 panic("indiracct: botched params"); 1102 panic("indiracct: botched params");
1103 /* 1103 /*
1104 * We have to expand bread here since it will deadlock looking 1104 * We have to expand bread here since it will deadlock looking
1105 * up the block number for any blocks that are not in the cache. 1105 * up the block number for any blocks that are not in the cache.
1106 */ 1106 */
1107 error = ffs_getblk(cancelvp, lbn, fsbtodb(fs, blkno), fs->fs_bsize, 1107 error = ffs_getblk(cancelvp, lbn, fsbtodb(fs, blkno), fs->fs_bsize,
1108 false, &bp); 1108 false, &bp);
1109 if (error) 1109 if (error)
1110 return error; 1110 return error;
1111 if ((bp->b_oflags & (BO_DONE | BO_DELWRI)) == 0 && (error = 1111 if ((bp->b_oflags & (BO_DONE | BO_DELWRI)) == 0 && (error =
1112 rwfsblk(bp->b_vp, B_READ, bp->b_data, fragstoblks(fs, blkno)))) { 1112 rwfsblk(bp->b_vp, B_READ, bp->b_data, fragstoblks(fs, blkno)))) {
1113 brelse(bp, 0); 1113 brelse(bp, 0);
1114 return (error); 1114 return (error);
1115 } 1115 }
1116 /* 1116 /*
1117 * Account for the block pointers in this indirect block. 1117 * Account for the block pointers in this indirect block.
1118 */ 1118 */
1119 last = howmany(remblks, blksperindir); 1119 last = howmany(remblks, blksperindir);
1120 if (last > NINDIR(fs)) 1120 if (last > NINDIR(fs))
1121 last = NINDIR(fs); 1121 last = NINDIR(fs);
1122 bap = malloc(fs->fs_bsize, M_DEVBUF, M_WAITOK); 1122 bap = malloc(fs->fs_bsize, M_DEVBUF, M_WAITOK);
1123 bcopy(bp->b_data, (void *)bap, fs->fs_bsize); 1123 bcopy(bp->b_data, (void *)bap, fs->fs_bsize);
1124 brelse(bp, 0); 1124 brelse(bp, 0);
1125 error = (*acctfunc)(snapvp, bap, 0, last, 1125 error = (*acctfunc)(snapvp, bap, 0, last,
1126 fs, level == 0 ? rlbn : -1, expungetype); 1126 fs, level == 0 ? rlbn : -1, expungetype);
1127 if (error || level == 0) 1127 if (error || level == 0)
1128 goto out; 1128 goto out;
1129 /* 1129 /*
1130 * Account for the block pointers in each of the indirect blocks 1130 * Account for the block pointers in each of the indirect blocks
1131 * in the levels below us. 1131 * in the levels below us.
1132 */ 1132 */
1133 subblksperindir = blksperindir / NINDIR(fs); 1133 subblksperindir = blksperindir / NINDIR(fs);
1134 for (lbn++, level--, i = 0; i < last; i++) { 1134 for (lbn++, level--, i = 0; i < last; i++) {
1135 error = indiracct(snapvp, cancelvp, level, 1135 error = indiracct(snapvp, cancelvp, level,
1136 idb_get(VTOI(snapvp), bap, i), lbn, rlbn, remblks, 1136 idb_get(VTOI(snapvp), bap, i), lbn, rlbn, remblks,
1137 subblksperindir, fs, acctfunc, expungetype); 1137 subblksperindir, fs, acctfunc, expungetype);
1138 if (error) 1138 if (error)
1139 goto out; 1139 goto out;
1140 rlbn += blksperindir; 1140 rlbn += blksperindir;
1141 lbn -= blksperindir; 1141 lbn -= blksperindir;
1142 remblks -= blksperindir; 1142 remblks -= blksperindir;
1143 } 1143 }
1144out: 1144out:
1145 FREE(bap, M_DEVBUF); 1145 FREE(bap, M_DEVBUF);
1146 return (error); 1146 return (error);
1147} 1147}
1148 1148
1149/* 1149/*
1150 * Do both snap accounting and map accounting. 1150 * Do both snap accounting and map accounting.
1151 */ 1151 */
1152static int 1152static int
1153fullacct(struct vnode *vp, void *bap, int oldblkp, int lastblkp, 1153fullacct(struct vnode *vp, void *bap, int oldblkp, int lastblkp,
1154 struct fs *fs, daddr_t lblkno, 1154 struct fs *fs, daddr_t lblkno,
1155 int exptype /* BLK_SNAP or BLK_NOCOPY */) 1155 int exptype /* BLK_SNAP or BLK_NOCOPY */)
1156{ 1156{
1157 int error; 1157 int error;
1158 1158
1159 if ((error = snapacct(vp, bap, oldblkp, lastblkp, fs, lblkno, exptype))) 1159 if ((error = snapacct(vp, bap, oldblkp, lastblkp, fs, lblkno, exptype)))
1160 return (error); 1160 return (error);
1161 return (mapacct(vp, bap, oldblkp, lastblkp, fs, lblkno, exptype)); 1161 return (mapacct(vp, bap, oldblkp, lastblkp, fs, lblkno, exptype));
1162} 1162}
1163 1163
1164/* 1164/*
1165 * Identify a set of blocks allocated in a snapshot inode. 1165 * Identify a set of blocks allocated in a snapshot inode.
1166 */ 1166 */
1167static int 1167static int
1168snapacct(struct vnode *vp, void *bap, int oldblkp, int lastblkp, 1168snapacct(struct vnode *vp, void *bap, int oldblkp, int lastblkp,
1169 struct fs *fs, daddr_t lblkno, 1169 struct fs *fs, daddr_t lblkno,
1170 int expungetype /* BLK_SNAP or BLK_NOCOPY */) 1170 int expungetype /* BLK_SNAP or BLK_NOCOPY */)
1171{ 1171{
1172 struct inode *ip = VTOI(vp); 1172 struct inode *ip = VTOI(vp);
1173 struct lwp *l = curlwp; 1173 struct lwp *l = curlwp;
1174 daddr_t blkno; 1174 daddr_t blkno;
1175 daddr_t lbn; 1175 daddr_t lbn;
1176 struct buf *ibp; 1176 struct buf *ibp;
1177 int error; 1177 int error;
1178 1178
1179 for ( ; oldblkp < lastblkp; oldblkp++) { 1179 for ( ; oldblkp < lastblkp; oldblkp++) {