Bug Summary

File:ufs/ffs/ffs_softdep.c
Warning:line 3542, column 13
Value stored to 'fs' during its initialization is never read

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple amd64-unknown-openbsd7.0 -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name ffs_softdep.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model static -mframe-pointer=all -relaxed-aliasing -fno-rounding-math -mconstructor-aliases -ffreestanding -mcmodel=kernel -target-cpu x86-64 -target-feature +retpoline-indirect-calls -target-feature +retpoline-indirect-branches -target-feature -sse2 -target-feature -sse -target-feature -3dnow -target-feature -mmx -target-feature +save-args -disable-red-zone -no-implicit-float -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/usr/src/sys/arch/amd64/compile/GENERIC.MP/obj -nostdsysteminc -nobuiltininc -resource-dir /usr/local/lib/clang/13.0.0 -I /usr/src/sys -I /usr/src/sys/arch/amd64/compile/GENERIC.MP/obj -I /usr/src/sys/arch -I /usr/src/sys/dev/pci/drm/include -I /usr/src/sys/dev/pci/drm/include/uapi -I /usr/src/sys/dev/pci/drm/amd/include/asic_reg -I /usr/src/sys/dev/pci/drm/amd/include -I /usr/src/sys/dev/pci/drm/amd/amdgpu -I /usr/src/sys/dev/pci/drm/amd/display -I /usr/src/sys/dev/pci/drm/amd/display/include -I /usr/src/sys/dev/pci/drm/amd/display/dc -I /usr/src/sys/dev/pci/drm/amd/display/amdgpu_dm -I /usr/src/sys/dev/pci/drm/amd/pm/inc -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu/smu11 -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu/smu12 -I /usr/src/sys/dev/pci/drm/amd/pm/powerplay -I /usr/src/sys/dev/pci/drm/amd/pm/powerplay/hwmgr -I /usr/src/sys/dev/pci/drm/amd/pm/powerplay/smumgr -I /usr/src/sys/dev/pci/drm/amd/display/dc/inc -I /usr/src/sys/dev/pci/drm/amd/display/dc/inc/hw -I /usr/src/sys/dev/pci/drm/amd/display/dc/clk_mgr -I /usr/src/sys/dev/pci/drm/amd/display/modules/inc -I /usr/src/sys/dev/pci/drm/amd/display/modules/hdcp -I /usr/src/sys/dev/pci/drm/amd/display/dmub/inc -I /usr/src/sys/dev/pci/drm/i915 -D DDB -D DIAGNOSTIC -D KTRACE -D ACCOUNTING -D KMEMSTATS -D PTRACE -D POOL_DEBUG -D CRYPTO -D SYSVMSG -D SYSVSEM -D SYSVSHM -D UVM_SWAP_ENCRYPT -D FFS -D FFS2 -D FFS_SOFTUPDATES -D UFS_DIRHASH -D QUOTA -D EXT2FS -D MFS -D NFSCLIENT -D NFSSERVER -D CD9660 -D UDF -D MSDOSFS -D FIFO -D FUSE -D SOCKET_SPLICE -D TCP_ECN -D TCP_SIGNATURE -D INET6 -D IPSEC -D PPP_BSDCOMP -D PPP_DEFLATE -D PIPEX -D MROUTING -D MPLS -D BOOT_CONFIG -D USER_PCICONF -D APERTURE -D MTRR -D NTFS -D HIBERNATE -D PCIVERBOSE -D USBVERBOSE -D WSDISPLAY_COMPAT_USL -D WSDISPLAY_COMPAT_RAWKBD -D WSDISPLAY_DEFAULTSCREENS=6 -D X86EMU -D ONEWIREVERBOSE -D MULTIPROCESSOR -D MAXUSERS=80 -D _KERNEL -D CONFIG_DRM_AMD_DC_DCN3_0 -O2 -Wno-pointer-sign -Wno-address-of-packed-member -Wno-constant-conversion -Wno-unused-but-set-variable -Wno-gnu-folding-constant -fdebug-compilation-dir=/usr/src/sys/arch/amd64/compile/GENERIC.MP/obj -ferror-limit 19 -fwrapv -D_RET_PROTECTOR -ret-protector -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-valloc -fno-builtin-free -fno-builtin-strdup -fno-builtin-strndup -analyzer-output=html -faddrsig -o /usr/obj/sys/arch/amd64/compile/GENERIC.MP/scan-build/2022-01-12-131800-47421-1 -x c /usr/src/sys/ufs/ffs/ffs_softdep.c
1/* $OpenBSD: ffs_softdep.c,v 1.150 2021/04/28 09:53:53 claudio Exp $ */
2
3/*
4 * Copyright 1998, 2000 Marshall Kirk McKusick. All Rights Reserved.
5 *
6 * The soft updates code is derived from the appendix of a University
7 * of Michigan technical report (Gregory R. Ganger and Yale N. Patt,
8 * "Soft Updates: A Solution to the Metadata Update Problem in File
9 * Systems", CSE-TR-254-95, August 1995).
10 *
11 * Further information about soft updates can be obtained from:
12 *
13 * Marshall Kirk McKusick http://www.mckusick.com/softdep/
14 * 1614 Oxford Street mckusick@mckusick.com
15 * Berkeley, CA 94709-1608 +1-510-843-9542
16 * USA
17 *
18 * Redistribution and use in source and binary forms, with or without
19 * modification, are permitted provided that the following conditions
20 * are met:
21 *
22 * 1. Redistributions of source code must retain the above copyright
23 * notice, this list of conditions and the following disclaimer.
24 * 2. Redistributions in binary form must reproduce the above copyright
25 * notice, this list of conditions and the following disclaimer in the
26 * documentation and/or other materials provided with the distribution.
27 *
28 * THIS SOFTWARE IS PROVIDED BY MARSHALL KIRK MCKUSICK ``AS IS'' AND ANY
29 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
30 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
31 * DISCLAIMED. IN NO EVENT SHALL MARSHALL KIRK MCKUSICK BE LIABLE FOR
32 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
33 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
34 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
35 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
36 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
37 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
38 * SUCH DAMAGE.
39 *
40 * from: @(#)ffs_softdep.c 9.59 (McKusick) 6/21/00
41 * $FreeBSD: src/sys/ufs/ffs/ffs_softdep.c,v 1.86 2001/02/04 16:08:18 phk Exp $
42 */
43
44#include <sys/param.h>
45#include <sys/buf.h>
46#include <sys/kernel.h>
47#include <sys/malloc.h>
48#include <sys/mount.h>
49#include <sys/proc.h>
50#include <sys/pool.h>
51#include <sys/syslog.h>
52#include <sys/systm.h>
53#include <sys/vnode.h>
54#include <sys/specdev.h>
55#include <crypto/siphash.h>
56#include <ufs/ufs/dir.h>
57#include <ufs/ufs/quota.h>
58#include <ufs/ufs/inode.h>
59#include <ufs/ufs/ufsmount.h>
60#include <ufs/ffs/fs.h>
61#include <ufs/ffs/softdep.h>
62#include <ufs/ffs/ffs_extern.h>
63#include <ufs/ufs/ufs_extern.h>
64
65#define STATIC
66
67/*
68 * Mapping of dependency structure types to malloc types.
69 */
70#define D_PAGEDEP0 0
71#define D_INODEDEP1 1
72#define D_NEWBLK2 2
73#define D_BMSAFEMAP3 3
74#define D_ALLOCDIRECT4 4
75#define D_INDIRDEP5 5
76#define D_ALLOCINDIR6 6
77#define D_FREEFRAG7 7
78#define D_FREEBLKS8 8
79#define D_FREEFILE9 9
80#define D_DIRADD10 10
81#define D_MKDIR11 11
82#define D_DIRREM12 12
83#define D_NEWDIRBLK13 13
84#define D_LAST13 13
85/*
86 * Names of softdep types.
87 */
88const char *softdep_typenames[] = {
89 "pagedep",
90 "inodedep",
91 "newblk",
92 "bmsafemap",
93 "allocdirect",
94 "indirdep",
95 "allocindir",
96 "freefrag",
97 "freeblks",
98 "freefile",
99 "diradd",
100 "mkdir",
101 "dirrem",
102 "newdirblk",
103};
104#define TYPENAME(type)((unsigned)(type) <= 13 ? softdep_typenames[type] : "???") \
105 ((unsigned)(type) <= D_LAST13 ? softdep_typenames[type] : "???")
106/*
107 * Finding the current process.
108 */
109#define CURPROC({struct cpu_info *__ci; asm volatile("movq %%gs:%P1,%0" : "=r"
(__ci) :"n" (__builtin_offsetof(struct cpu_info, ci_self)));
__ci;})->ci_curproc
curproc({struct cpu_info *__ci; asm volatile("movq %%gs:%P1,%0" : "=r"
(__ci) :"n" (__builtin_offsetof(struct cpu_info, ci_self)));
__ci;})->ci_curproc
110/*
111 * End system adaptation definitions.
112 */
113
114/*
115 * Internal function prototypes.
116 */
117STATIC void softdep_error(char *, int);
118STATIC void drain_output(struct vnode *, int);
119STATIC int getdirtybuf(struct buf *, int);
120STATIC void clear_remove(struct proc *);
121STATIC void clear_inodedeps(struct proc *);
122STATIC int flush_pagedep_deps(struct vnode *, struct mount *,
123 struct diraddhd *);
124STATIC int flush_inodedep_deps(struct fs *, ufsino_t);
125STATIC int handle_written_filepage(struct pagedep *, struct buf *);
126STATIC void diradd_inode_written(struct diradd *, struct inodedep *);
127STATIC int handle_written_inodeblock(struct inodedep *, struct buf *);
128STATIC void handle_allocdirect_partdone(struct allocdirect *);
129STATIC void handle_allocindir_partdone(struct allocindir *);
130STATIC void initiate_write_filepage(struct pagedep *, struct buf *);
131STATIC void handle_written_mkdir(struct mkdir *, int);
132STATIC void initiate_write_inodeblock_ufs1(struct inodedep *, struct buf *);
133#ifdef FFS21
134STATIC void initiate_write_inodeblock_ufs2(struct inodedep *, struct buf *);
135#endif
136STATIC void handle_workitem_freefile(struct freefile *);
137STATIC void handle_workitem_remove(struct dirrem *);
138STATIC struct dirrem *newdirrem(struct buf *, struct inode *,
139 struct inode *, int, struct dirrem **);
140STATIC void free_diradd(struct diradd *);
141STATIC void free_allocindir(struct allocindir *, struct inodedep *);
142STATIC void free_newdirblk(struct newdirblk *);
143STATIC int indir_trunc(struct inode *, daddr_t, int, daddr_t, long *);
144STATIC void deallocate_dependencies(struct buf *, struct inodedep *);
145STATIC void free_allocdirect(struct allocdirectlst *,
146 struct allocdirect *, int);
147STATIC int check_inode_unwritten(struct inodedep *);
148STATIC int free_inodedep(struct inodedep *);
149STATIC void handle_workitem_freeblocks(struct freeblks *);
150STATIC void merge_inode_lists(struct inodedep *);
151STATIC void setup_allocindir_phase2(struct buf *, struct inode *,
152 struct allocindir *);
153STATIC struct allocindir *newallocindir(struct inode *, int, daddr_t,
154 daddr_t);
155STATIC void handle_workitem_freefrag(struct freefrag *);
156STATIC struct freefrag *newfreefrag(struct inode *, daddr_t, long);
157STATIC void allocdirect_merge(struct allocdirectlst *,
158 struct allocdirect *, struct allocdirect *);
159STATIC struct bmsafemap *bmsafemap_lookup(struct buf *);
160STATIC int newblk_lookup(struct fs *, daddr_t, int,
161 struct newblk **);
162STATIC int inodedep_lookup(struct fs *, ufsino_t, int, struct inodedep **);
163STATIC int pagedep_lookup(struct inode *, daddr_t, int, struct pagedep **);
164STATIC void pause_timer(void *);
165STATIC int request_cleanup(int, int);
166STATIC int process_worklist_item(struct mount *, int *, int);
167STATIC void add_to_worklist(struct worklist *);
168
169/*
170 * Exported softdep operations.
171 */
172void softdep_disk_io_initiation(struct buf *);
173void softdep_disk_write_complete(struct buf *);
174void softdep_deallocate_dependencies(struct buf *);
175void softdep_move_dependencies(struct buf *, struct buf *);
176int softdep_count_dependencies(struct buf *bp, int, int);
177
178/*
179 * Locking primitives.
180 *
181 * For a uniprocessor, all we need to do is protect against disk
182 * interrupts. For a multiprocessor, this lock would have to be
183 * a mutex. A single mutex is used throughout this file, though
184 * finer grain locking could be used if contention warranted it.
185 *
186 * For a multiprocessor, the sleep call would accept a lock and
187 * release it after the sleep processing was complete. In a uniprocessor
188 * implementation there is no such interlock, so we simple mark
189 * the places where it needs to be done with the `interlocked' form
190 * of the lock calls. Since the uniprocessor sleep already interlocks
191 * the spl, there is nothing that really needs to be done.
192 */
193#ifndef /* NOT */ DEBUG
194STATIC struct lockit {
195 int lkt_spl;
196} lk = { 0 };
197#define ACQUIRE_LOCK(lk)(lk)->lkt_spl = splraise(0x6) (lk)->lkt_spl = splbio()splraise(0x6)
198#define FREE_LOCK(lk)spllower((lk)->lkt_spl) splx((lk)->lkt_spl)spllower((lk)->lkt_spl)
199#define ACQUIRE_LOCK_INTERLOCKED(lk,s)(lk)->lkt_spl = (s) (lk)->lkt_spl = (s)
200#define FREE_LOCK_INTERLOCKED(lk)((lk)->lkt_spl) ((lk)->lkt_spl)
201
202#else /* DEBUG */
203STATIC struct lockit {
204 int lkt_spl;
205 pid_t lkt_held;
206 int lkt_line;
207} lk = { 0, -1 };
208STATIC int lockcnt;
209
210STATIC void acquire_lock(struct lockit *, int);
211STATIC void free_lock(struct lockit *, int);
212STATIC void acquire_lock_interlocked(struct lockit *, int, int);
213STATIC int free_lock_interlocked(struct lockit *, int);
214
215#define ACQUIRE_LOCK(lk)(lk)->lkt_spl = splraise(0x6) acquire_lock(lk, __LINE__215)
216#define FREE_LOCK(lk)spllower((lk)->lkt_spl) free_lock(lk, __LINE__216)
217#define ACQUIRE_LOCK_INTERLOCKED(lk,s)(lk)->lkt_spl = (s) acquire_lock_interlocked(lk, (s), __LINE__217)
218#define FREE_LOCK_INTERLOCKED(lk)((lk)->lkt_spl) free_lock_interlocked(lk, __LINE__218)
219
220STATIC void
221acquire_lock(struct lockit *lk, int line)
222{
223 pid_t holder;
224 int original_line;
225
226 if (lk->lkt_held != -1) {
227 holder = lk->lkt_held;
228 original_line = lk->lkt_line;
229 FREE_LOCK(lk)spllower((lk)->lkt_spl);
230 if (holder == CURPROC({struct cpu_info *__ci; asm volatile("movq %%gs:%P1,%0" : "=r"
(__ci) :"n" (__builtin_offsetof(struct cpu_info, ci_self)));
__ci;})->ci_curproc
->p_tid)
231 panic("softdep_lock: locking against myself, acquired at line %d, relocked at line %d", original_line, line);
232 else
233 panic("softdep_lock: lock held by %d, acquired at line %d, relocked at line %d", holder, original_line, line);
234 }
235 lk->lkt_spl = splbio()splraise(0x6);
236 lk->lkt_held = CURPROC({struct cpu_info *__ci; asm volatile("movq %%gs:%P1,%0" : "=r"
(__ci) :"n" (__builtin_offsetof(struct cpu_info, ci_self)));
__ci;})->ci_curproc
->p_tid;
237 lk->lkt_line = line;
238 lockcnt++;
239}
240
241STATIC void
242free_lock(struct lockit *lk, int line)
243{
244
245 if (lk->lkt_held == -1)
246 panic("softdep_unlock: lock not held at line %d", line);
247 lk->lkt_held = -1;
248 splx(lk->lkt_spl)spllower(lk->lkt_spl);
249}
250
251STATIC void
252acquire_lock_interlocked(struct lockit *lk, int s, int line)
253{
254 pid_t holder;
255 int original_line;
256
257 if (lk->lkt_held != -1) {
258 holder = lk->lkt_held;
259 original_line = lk->lkt_line;
260 FREE_LOCK_INTERLOCKED(lk)((lk)->lkt_spl);
261 if (holder == CURPROC({struct cpu_info *__ci; asm volatile("movq %%gs:%P1,%0" : "=r"
(__ci) :"n" (__builtin_offsetof(struct cpu_info, ci_self)));
__ci;})->ci_curproc
->p_tid)
262 panic("softdep_lock: locking against myself, acquired at line %d, relocked at line %d", original_line, line);
263 else
264 panic("softdep_lock: lock held by %d, acquired at line %d, relocked at line %d", holder, original_line, line);
265 }
266 lk->lkt_held = CURPROC({struct cpu_info *__ci; asm volatile("movq %%gs:%P1,%0" : "=r"
(__ci) :"n" (__builtin_offsetof(struct cpu_info, ci_self)));
__ci;})->ci_curproc
->p_tid;
267 lk->lkt_line = line;
268 lk->lkt_spl = s;
269 lockcnt++;
270}
271
272STATIC int
273free_lock_interlocked(struct lockit *lk, int line)
274{
275
276 if (lk->lkt_held == -1)
277 panic("softdep_unlock_interlocked: lock not held at line %d", line);
278 lk->lkt_held = -1;
279
280 return (lk->lkt_spl);
281}
282#endif /* DEBUG */
283
284/*
285 * Place holder for real semaphores.
286 */
287struct sema {
288 int value;
289 pid_t holder;
290 char *name;
291 int prio;
292};
293STATIC void sema_init(struct sema *, char *, int);
294STATIC int sema_get(struct sema *, struct lockit *);
295STATIC void sema_release(struct sema *);
296
297STATIC void
298sema_init(struct sema *semap, char *name, int prio)
299{
300
301 semap->holder = -1;
302 semap->value = 0;
303 semap->name = name;
304 semap->prio = prio;
305}
306
307STATIC int
308sema_get(struct sema *semap, struct lockit *interlock)
309{
310 int s;
311
312 if (semap->value++ > 0) {
313 if (interlock != NULL((void *)0))
314 s = FREE_LOCK_INTERLOCKED(interlock)((interlock)->lkt_spl);
315 tsleep_nsec(semap, semap->prio, semap->name, INFSLP0xffffffffffffffffULL);
316 if (interlock != NULL((void *)0)) {
317 ACQUIRE_LOCK_INTERLOCKED(interlock, s)(interlock)->lkt_spl = (s);
318 FREE_LOCK(interlock)spllower((interlock)->lkt_spl);
319 }
320 return (0);
321 }
322 semap->holder = CURPROC({struct cpu_info *__ci; asm volatile("movq %%gs:%P1,%0" : "=r"
(__ci) :"n" (__builtin_offsetof(struct cpu_info, ci_self)));
__ci;})->ci_curproc
->p_tid;
323 if (interlock != NULL((void *)0))
324 FREE_LOCK(interlock)spllower((interlock)->lkt_spl);
325 return (1);
326}
327
328STATIC void
329sema_release(struct sema *semap)
330{
331
332 if (semap->value <= 0 || semap->holder != CURPROC({struct cpu_info *__ci; asm volatile("movq %%gs:%P1,%0" : "=r"
(__ci) :"n" (__builtin_offsetof(struct cpu_info, ci_self)));
__ci;})->ci_curproc
->p_tid) {
333#ifdef DEBUG
334 if (lk.lkt_held != -1)
335 FREE_LOCK(&lk)spllower((&lk)->lkt_spl);
336#endif
337 panic("sema_release: not held");
338 }
339 if (--semap->value > 0) {
340 semap->value = 0;
341 wakeup(semap);
342 }
343 semap->holder = -1;
344}
345
346/*
347 * Memory management.
348 */
349STATIC struct pool pagedep_pool;
350STATIC struct pool inodedep_pool;
351STATIC struct pool newblk_pool;
352STATIC struct pool bmsafemap_pool;
353STATIC struct pool allocdirect_pool;
354STATIC struct pool indirdep_pool;
355STATIC struct pool allocindir_pool;
356STATIC struct pool freefrag_pool;
357STATIC struct pool freeblks_pool;
358STATIC struct pool freefile_pool;
359STATIC struct pool diradd_pool;
360STATIC struct pool mkdir_pool;
361STATIC struct pool dirrem_pool;
362STATIC struct pool newdirblk_pool;
363
364static __inline void
365softdep_free(struct worklist *item, int type)
366{
367
368 switch (type) {
369 case D_PAGEDEP0:
370 pool_put(&pagedep_pool, item);
371 break;
372
373 case D_INODEDEP1:
374 pool_put(&inodedep_pool, item);
375 break;
376
377 case D_BMSAFEMAP3:
378 pool_put(&bmsafemap_pool, item);
379 break;
380
381 case D_ALLOCDIRECT4:
382 pool_put(&allocdirect_pool, item);
383 break;
384
385 case D_INDIRDEP5:
386 pool_put(&indirdep_pool, item);
387 break;
388
389 case D_ALLOCINDIR6:
390 pool_put(&allocindir_pool, item);
391 break;
392
393 case D_FREEFRAG7:
394 pool_put(&freefrag_pool, item);
395 break;
396
397 case D_FREEBLKS8:
398 pool_put(&freeblks_pool, item);
399 break;
400
401 case D_FREEFILE9:
402 pool_put(&freefile_pool, item);
403 break;
404
405 case D_DIRADD10:
406 pool_put(&diradd_pool, item);
407 break;
408
409 case D_MKDIR11:
410 pool_put(&mkdir_pool, item);
411 break;
412
413 case D_DIRREM12:
414 pool_put(&dirrem_pool, item);
415 break;
416
417 case D_NEWDIRBLK13:
418 pool_put(&newdirblk_pool, item);
419 break;
420
421 default:
422#ifdef DEBUG
423 if (lk.lkt_held != -1)
424 FREE_LOCK(&lk)spllower((&lk)->lkt_spl);
425#endif
426 panic("softdep_free: unknown type %d", type);
427 }
428}
429
430struct workhead softdep_freequeue;
431
432static __inline void
433softdep_freequeue_add(struct worklist *item)
434{
435 int s;
436
437 s = splbio()splraise(0x6);
438 LIST_INSERT_HEAD(&softdep_freequeue, item, wk_list)do { if (((item)->wk_list.le_next = (&softdep_freequeue
)->lh_first) != ((void *)0)) (&softdep_freequeue)->
lh_first->wk_list.le_prev = &(item)->wk_list.le_next
; (&softdep_freequeue)->lh_first = (item); (item)->
wk_list.le_prev = &(&softdep_freequeue)->lh_first;
} while (0)
;
439 splx(s)spllower(s);
440}
441
442static __inline void
443softdep_freequeue_process(void)
444{
445 struct worklist *wk;
446
447 splassert(IPL_BIO)do { if (splassert_ctl > 0) { splassert_check(0x6, __func__
); } } while (0)
;
448
449 while ((wk = LIST_FIRST(&softdep_freequeue)((&softdep_freequeue)->lh_first)) != NULL((void *)0)) {
450 LIST_REMOVE(wk, wk_list)do { if ((wk)->wk_list.le_next != ((void *)0)) (wk)->wk_list
.le_next->wk_list.le_prev = (wk)->wk_list.le_prev; *(wk
)->wk_list.le_prev = (wk)->wk_list.le_next; ((wk)->wk_list
.le_prev) = ((void *)-1); ((wk)->wk_list.le_next) = ((void
*)-1); } while (0)
;
451 FREE_LOCK(&lk)spllower((&lk)->lkt_spl);
452 softdep_free(wk, wk->wk_type);
453 ACQUIRE_LOCK(&lk)(&lk)->lkt_spl = splraise(0x6);
454 }
455}
456
457/*
458 * Worklist queue management.
459 * These routines require that the lock be held.
460 */
461#ifndef /* NOT */ DEBUG
462#define WORKLIST_INSERT(head, item)do { (item)->wk_state |= 0x8000; do { if (((item)->wk_list
.le_next = (head)->lh_first) != ((void *)0)) (head)->lh_first
->wk_list.le_prev = &(item)->wk_list.le_next; (head
)->lh_first = (item); (item)->wk_list.le_prev = &(head
)->lh_first; } while (0); } while (0)
do { \
463 (item)->wk_state |= ONWORKLIST0x8000; \
464 LIST_INSERT_HEAD(head, item, wk_list)do { if (((item)->wk_list.le_next = (head)->lh_first) !=
((void *)0)) (head)->lh_first->wk_list.le_prev = &
(item)->wk_list.le_next; (head)->lh_first = (item); (item
)->wk_list.le_prev = &(head)->lh_first; } while (0)
; \
465} while (0)
466#define WORKLIST_REMOVE(item)do { (item)->wk_state &= ~0x8000; do { if ((item)->
wk_list.le_next != ((void *)0)) (item)->wk_list.le_next->
wk_list.le_prev = (item)->wk_list.le_prev; *(item)->wk_list
.le_prev = (item)->wk_list.le_next; ((item)->wk_list.le_prev
) = ((void *)-1); ((item)->wk_list.le_next) = ((void *)-1)
; } while (0); } while (0)
do { \
467 (item)->wk_state &= ~ONWORKLIST0x8000; \
468 LIST_REMOVE(item, wk_list)do { if ((item)->wk_list.le_next != ((void *)0)) (item)->
wk_list.le_next->wk_list.le_prev = (item)->wk_list.le_prev
; *(item)->wk_list.le_prev = (item)->wk_list.le_next; (
(item)->wk_list.le_prev) = ((void *)-1); ((item)->wk_list
.le_next) = ((void *)-1); } while (0)
; \
469} while (0)
470#define WORKITEM_FREE(item, type)softdep_freequeue_add((struct worklist *)item) softdep_freequeue_add((struct worklist *)item)
471
472#else /* DEBUG */
473STATIC void worklist_insert(struct workhead *, struct worklist *);
474STATIC void worklist_remove(struct worklist *);
475STATIC void workitem_free(struct worklist *);
476
477#define WORKLIST_INSERT(head, item)do { (item)->wk_state |= 0x8000; do { if (((item)->wk_list
.le_next = (head)->lh_first) != ((void *)0)) (head)->lh_first
->wk_list.le_prev = &(item)->wk_list.le_next; (head
)->lh_first = (item); (item)->wk_list.le_prev = &(head
)->lh_first; } while (0); } while (0)
worklist_insert(head, item)
478#define WORKLIST_REMOVE(item)do { (item)->wk_state &= ~0x8000; do { if ((item)->
wk_list.le_next != ((void *)0)) (item)->wk_list.le_next->
wk_list.le_prev = (item)->wk_list.le_prev; *(item)->wk_list
.le_prev = (item)->wk_list.le_next; ((item)->wk_list.le_prev
) = ((void *)-1); ((item)->wk_list.le_next) = ((void *)-1)
; } while (0); } while (0)
worklist_remove(item)
479#define WORKITEM_FREE(item, type)softdep_freequeue_add((struct worklist *)item) workitem_free((struct worklist *)item)
480
481STATIC void
482worklist_insert(struct workhead *head, struct worklist *item)
483{
484
485 if (lk.lkt_held == -1)
486 panic("worklist_insert: lock not held");
487 if (item->wk_state & ONWORKLIST0x8000) {
488 FREE_LOCK(&lk)spllower((&lk)->lkt_spl);
489 panic("worklist_insert: already on list");
490 }
491 item->wk_state |= ONWORKLIST0x8000;
492 LIST_INSERT_HEAD(head, item, wk_list)do { if (((item)->wk_list.le_next = (head)->lh_first) !=
((void *)0)) (head)->lh_first->wk_list.le_prev = &
(item)->wk_list.le_next; (head)->lh_first = (item); (item
)->wk_list.le_prev = &(head)->lh_first; } while (0)
;
493}
494
495STATIC void
496worklist_remove(struct worklist *item)
497{
498
499 if (lk.lkt_held == -1)
500 panic("worklist_remove: lock not held");
501 if ((item->wk_state & ONWORKLIST0x8000) == 0) {
502 FREE_LOCK(&lk)spllower((&lk)->lkt_spl);
503 panic("worklist_remove: not on list");
504 }
505 item->wk_state &= ~ONWORKLIST0x8000;
506 LIST_REMOVE(item, wk_list)do { if ((item)->wk_list.le_next != ((void *)0)) (item)->
wk_list.le_next->wk_list.le_prev = (item)->wk_list.le_prev
; *(item)->wk_list.le_prev = (item)->wk_list.le_next; (
(item)->wk_list.le_prev) = ((void *)-1); ((item)->wk_list
.le_next) = ((void *)-1); } while (0)
;
507}
508
509STATIC void
510workitem_free(struct worklist *item)
511{
512
513 if (item->wk_state & ONWORKLIST0x8000) {
514 if (lk.lkt_held != -1)
515 FREE_LOCK(&lk)spllower((&lk)->lkt_spl);
516 panic("workitem_free: still on list");
517 }
518 softdep_freequeue_add(item);
519}
520#endif /* DEBUG */
521
522/*
523 * Workitem queue management
524 */
525STATIC struct workhead softdep_workitem_pending;
526STATIC struct worklist *worklist_tail;
527STATIC int num_on_worklist; /* number of worklist items to be processed */
528STATIC int softdep_worklist_busy; /* 1 => trying to do unmount */
529STATIC int softdep_worklist_req; /* serialized waiters */
530STATIC int max_softdeps; /* maximum number of structs before slowdown */
531STATIC int tickdelay = 2; /* number of ticks to pause during slowdown */
532STATIC int proc_waiting; /* tracks whether we have a timeout posted */
533STATIC int *stat_countp; /* statistic to count in proc_waiting timeout */
534STATIC struct timeout proc_waiting_timeout;
535STATIC struct proc *filesys_syncer; /* proc of filesystem syncer process */
536STATIC int req_clear_inodedeps; /* syncer process flush some inodedeps */
537#define FLUSH_INODES1 1
538STATIC int req_clear_remove; /* syncer process flush some freeblks */
539#define FLUSH_REMOVE2 2
540/*
541 * runtime statistics
542 */
543STATIC int stat_worklist_push; /* number of worklist cleanups */
544STATIC int stat_blk_limit_push; /* number of times block limit neared */
545STATIC int stat_ino_limit_push; /* number of times inode limit neared */
546STATIC int stat_blk_limit_hit; /* number of times block slowdown imposed */
547STATIC int stat_ino_limit_hit; /* number of times inode slowdown imposed */
548STATIC int stat_sync_limit_hit; /* number of synchronous slowdowns imposed */
549STATIC int stat_indir_blk_ptrs; /* bufs redirtied as indir ptrs not written */
550STATIC int stat_inode_bitmap; /* bufs redirtied as inode bitmap not written */
551STATIC int stat_direct_blk_ptrs;/* bufs redirtied as direct ptrs not written */
552STATIC int stat_dir_entry; /* bufs redirtied as dir entry cannot write */
553
554/*
555 * Add an item to the end of the work queue.
556 * This routine requires that the lock be held.
557 * This is the only routine that adds items to the list.
558 * The following routine is the only one that removes items
559 * and does so in order from first to last.
560 */
561STATIC void
562add_to_worklist(struct worklist *wk)
563{
564
565 if (wk->wk_state & ONWORKLIST0x8000) {
566#ifdef DEBUG
567 if (lk.lkt_held != -1)
568 FREE_LOCK(&lk)spllower((&lk)->lkt_spl);
569#endif
570 panic("add_to_worklist: already on list");
571 }
572 wk->wk_state |= ONWORKLIST0x8000;
573 if (LIST_FIRST(&softdep_workitem_pending)((&softdep_workitem_pending)->lh_first) == NULL((void *)0))
574 LIST_INSERT_HEAD(&softdep_workitem_pending, wk, wk_list)do { if (((wk)->wk_list.le_next = (&softdep_workitem_pending
)->lh_first) != ((void *)0)) (&softdep_workitem_pending
)->lh_first->wk_list.le_prev = &(wk)->wk_list.le_next
; (&softdep_workitem_pending)->lh_first = (wk); (wk)->
wk_list.le_prev = &(&softdep_workitem_pending)->lh_first
; } while (0)
;
575 else
576 LIST_INSERT_AFTER(worklist_tail, wk, wk_list)do { if (((wk)->wk_list.le_next = (worklist_tail)->wk_list
.le_next) != ((void *)0)) (worklist_tail)->wk_list.le_next
->wk_list.le_prev = &(wk)->wk_list.le_next; (worklist_tail
)->wk_list.le_next = (wk); (wk)->wk_list.le_prev = &
(worklist_tail)->wk_list.le_next; } while (0)
;
577 worklist_tail = wk;
578 num_on_worklist += 1;
579}
580
581/*
582 * Process that runs once per second to handle items in the background queue.
583 *
584 * Note that we ensure that everything is done in the order in which they
585 * appear in the queue. The code below depends on this property to ensure
586 * that blocks of a file are freed before the inode itself is freed. This
587 * ordering ensures that no new <vfsid, inum, lbn> triples will be generated
588 * until all the old ones have been purged from the dependency lists.
589 */
590int
591softdep_process_worklist(struct mount *matchmnt)
592{
593 struct proc *p = CURPROC({struct cpu_info *__ci; asm volatile("movq %%gs:%P1,%0" : "=r"
(__ci) :"n" (__builtin_offsetof(struct cpu_info, ci_self)));
__ci;})->ci_curproc
;
594 int matchcnt, loopcount;
595 struct timeval starttime;
596
597 /*
598 * First process any items on the delayed-free queue.
599 */
600 ACQUIRE_LOCK(&lk)(&lk)->lkt_spl = splraise(0x6);
601 softdep_freequeue_process();
602 FREE_LOCK(&lk)spllower((&lk)->lkt_spl);
603
604 /*
605 * Record the process identifier of our caller so that we can give
606 * this process preferential treatment in request_cleanup below.
607 * We can't do this in softdep_initialize, because the syncer doesn't
608 * have to run then.
609 * NOTE! This function _could_ be called with a curproc != syncerproc.
610 */
611 filesys_syncer = syncerproc;
612 matchcnt = 0;
613
614 /*
615 * There is no danger of having multiple processes run this
616 * code, but we have to single-thread it when softdep_flushfiles()
617 * is in operation to get an accurate count of the number of items
618 * related to its mount point that are in the list.
619 */
620 if (matchmnt == NULL((void *)0)) {
621 if (softdep_worklist_busy < 0)
622 return(-1);
623 softdep_worklist_busy += 1;
624 }
625
626 /*
627 * If requested, try removing inode or removal dependencies.
628 */
629 if (req_clear_inodedeps) {
630 clear_inodedeps(p);
631 req_clear_inodedeps -= 1;
632 wakeup_one(&proc_waiting)wakeup_n((&proc_waiting), 1);
633 }
634 if (req_clear_remove) {
635 clear_remove(p);
636 req_clear_remove -= 1;
637 wakeup_one(&proc_waiting)wakeup_n((&proc_waiting), 1);
638 }
639 loopcount = 1;
640 getmicrouptime(&starttime);
641 while (num_on_worklist > 0) {
642 if (process_worklist_item(matchmnt, &matchcnt, LK_NOWAIT0x0040UL) == 0)
643 break;
644
645 /*
646 * If a umount operation wants to run the worklist
647 * accurately, abort.
648 */
649 if (softdep_worklist_req && matchmnt == NULL((void *)0)) {
650 matchcnt = -1;
651 break;
652 }
653
654 /*
655 * If requested, try removing inode or removal dependencies.
656 */
657 if (req_clear_inodedeps) {
658 clear_inodedeps(p);
659 req_clear_inodedeps -= 1;
660 wakeup_one(&proc_waiting)wakeup_n((&proc_waiting), 1);
661 }
662 if (req_clear_remove) {
663 clear_remove(p);
664 req_clear_remove -= 1;
665 wakeup_one(&proc_waiting)wakeup_n((&proc_waiting), 1);
666 }
667 /*
668 * We do not generally want to stop for buffer space, but if
669 * we are really being a buffer hog, we will stop and wait.
670 */
671#if 0
672 if (loopcount++ % 128 == 0)
673 bwillwrite();
674#endif
675 /*
676 * Never allow processing to run for more than one
677 * second. Otherwise the other syncer tasks may get
678 * excessively backlogged.
679 */
680 {
681 struct timeval diff;
682 struct timeval tv;
683
684 getmicrouptime(&tv);
685 timersub(&tv, &starttime, &diff)do { (&diff)->tv_sec = (&tv)->tv_sec - (&starttime
)->tv_sec; (&diff)->tv_usec = (&tv)->tv_usec
- (&starttime)->tv_usec; if ((&diff)->tv_usec <
0) { (&diff)->tv_sec--; (&diff)->tv_usec += 1000000
; } } while (0)
;
686 if (diff.tv_sec != 0 && matchmnt == NULL((void *)0)) {
687 matchcnt = -1;
688 break;
689 }
690 }
691
692 /*
693 * Process any new items on the delayed-free queue.
694 */
695 ACQUIRE_LOCK(&lk)(&lk)->lkt_spl = splraise(0x6);
696 softdep_freequeue_process();
697 FREE_LOCK(&lk)spllower((&lk)->lkt_spl);
698 }
699 if (matchmnt == NULL((void *)0)) {
700 softdep_worklist_busy -= 1;
701 if (softdep_worklist_req && softdep_worklist_busy == 0)
702 wakeup(&softdep_worklist_req);
703 }
704 return (matchcnt);
705}
706
707/*
708 * Process one item on the worklist.
709 */
710STATIC int
711process_worklist_item(struct mount *matchmnt, int *matchcnt, int flags)
712{
713 struct worklist *wk, *wkend;
714 struct dirrem *dirrem;
715 struct mount *mp;
716 struct vnode *vp;
717
718 ACQUIRE_LOCK(&lk)(&lk)->lkt_spl = splraise(0x6);
719 /*
720 * Normally we just process each item on the worklist in order.
721 * However, if we are in a situation where we cannot lock any
722 * inodes, we have to skip over any dirrem requests whose
723 * vnodes are resident and locked.
724 */
725 LIST_FOREACH(wk, &softdep_workitem_pending, wk_list)for((wk) = ((&softdep_workitem_pending)->lh_first); (wk
)!= ((void *)0); (wk) = ((wk)->wk_list.le_next))
{
726 if ((flags & LK_NOWAIT0x0040UL) == 0 || wk->wk_type != D_DIRREM12)
727 break;
728 dirrem = WK_DIRREM(wk)((struct dirrem *)(wk));
729 vp = ufs_ihashlookup(VFSTOUFS(dirrem->dm_mnt)((struct ufsmount *)((dirrem->dm_mnt)->mnt_data))->um_dev,
730 dirrem->dm_oldinum);
731 if (vp == NULL((void *)0) || !VOP_ISLOCKED(vp))
732 break;
733 }
734 if (wk == NULL((void *)0)) {
735 FREE_LOCK(&lk)spllower((&lk)->lkt_spl);
736 return (0);
737 }
738 /*
739 * Remove the item to be processed. If we are removing the last
740 * item on the list, we need to recalculate the tail pointer.
741 * As this happens rarely and usually when the list is short,
742 * we just run down the list to find it rather than tracking it
743 * in the above loop.
744 */
745 WORKLIST_REMOVE(wk)do { (wk)->wk_state &= ~0x8000; do { if ((wk)->wk_list
.le_next != ((void *)0)) (wk)->wk_list.le_next->wk_list
.le_prev = (wk)->wk_list.le_prev; *(wk)->wk_list.le_prev
= (wk)->wk_list.le_next; ((wk)->wk_list.le_prev) = ((void
*)-1); ((wk)->wk_list.le_next) = ((void *)-1); } while (0
); } while (0)
;
746 if (wk == worklist_tail) {
747 LIST_FOREACH(wkend, &softdep_workitem_pending, wk_list)for((wkend) = ((&softdep_workitem_pending)->lh_first);
(wkend)!= ((void *)0); (wkend) = ((wkend)->wk_list.le_next
))
748 if (LIST_NEXT(wkend, wk_list)((wkend)->wk_list.le_next) == NULL((void *)0))
749 break;
750 worklist_tail = wkend;
751 }
752 num_on_worklist -= 1;
753 FREE_LOCK(&lk)spllower((&lk)->lkt_spl);
754 switch (wk->wk_type) {
755
756 case D_DIRREM12:
757 /* removal of a directory entry */
758 mp = WK_DIRREM(wk)((struct dirrem *)(wk))->dm_mnt;
759#if 0
760 if (vn_write_suspend_wait(NULL((void *)0), mp, V_NOWAIT))
761 panic("%s: dirrem on suspended filesystem",
762 "process_worklist_item");
763#endif
764 if (matchmnt != NULL((void *)0) && mp == matchmnt)
765 *matchcnt += 1;
766 handle_workitem_remove(WK_DIRREM(wk)((struct dirrem *)(wk)));
767 break;
768
769 case D_FREEBLKS8:
770 /* releasing blocks and/or fragments from a file */
771 mp = WK_FREEBLKS(wk)((struct freeblks *)(wk))->fb_mnt;
772#if 0
773 if (vn_write_suspend_wait(NULL((void *)0), mp, V_NOWAIT))
774 panic("%s: freeblks on suspended filesystem",
775 "process_worklist_item");
776#endif
777 if (matchmnt != NULL((void *)0) && mp == matchmnt)
778 *matchcnt += 1;
779 handle_workitem_freeblocks(WK_FREEBLKS(wk)((struct freeblks *)(wk)));
780 break;
781
782 case D_FREEFRAG7:
783 /* releasing a fragment when replaced as a file grows */
784 mp = WK_FREEFRAG(wk)((struct freefrag *)(wk))->ff_mnt;
785#if 0
786 if (vn_write_suspend_wait(NULL((void *)0), mp, V_NOWAIT))
787 panic("%s: freefrag on suspended filesystem",
788 "process_worklist_item");
789#endif
790 if (matchmnt != NULL((void *)0) && mp == matchmnt)
791 *matchcnt += 1;
792 handle_workitem_freefrag(WK_FREEFRAG(wk)((struct freefrag *)(wk)));
793 break;
794
795 case D_FREEFILE9:
796 /* releasing an inode when its link count drops to 0 */
797 mp = WK_FREEFILE(wk)((struct freefile *)(wk))->fx_mnt;
798#if 0
799 if (vn_write_suspend_wait(NULL((void *)0), mp, V_NOWAIT))
800 panic("%s: freefile on suspended filesystem",
801 "process_worklist_item");
802#endif
803 if (matchmnt != NULL((void *)0) && mp == matchmnt)
804 *matchcnt += 1;
805 handle_workitem_freefile(WK_FREEFILE(wk)((struct freefile *)(wk)));
806 break;
807
808 default:
809 panic("%s_process_worklist: Unknown type %s",
810 "softdep", TYPENAME(wk->wk_type)((unsigned)(wk->wk_type) <= 13 ? softdep_typenames[wk->
wk_type] : "???")
);
811 /* NOTREACHED */
812 }
813 return (1);
814}
815
816/*
817 * Move dependencies from one buffer to another.
818 */
819void
820softdep_move_dependencies(struct buf *oldbp, struct buf *newbp)
821{
822 struct worklist *wk, *wktail;
823
824 if (LIST_FIRST(&newbp->b_dep)((&newbp->b_dep)->lh_first) != NULL((void *)0))
825 panic("softdep_move_dependencies: need merge code");
826 wktail = NULL((void *)0);
827 ACQUIRE_LOCK(&lk)(&lk)->lkt_spl = splraise(0x6);
828 while ((wk = LIST_FIRST(&oldbp->b_dep)((&oldbp->b_dep)->lh_first)) != NULL((void *)0)) {
829 LIST_REMOVE(wk, wk_list)do { if ((wk)->wk_list.le_next != ((void *)0)) (wk)->wk_list
.le_next->wk_list.le_prev = (wk)->wk_list.le_prev; *(wk
)->wk_list.le_prev = (wk)->wk_list.le_next; ((wk)->wk_list
.le_prev) = ((void *)-1); ((wk)->wk_list.le_next) = ((void
*)-1); } while (0)
;
830 if (wktail == NULL((void *)0))
831 LIST_INSERT_HEAD(&newbp->b_dep, wk, wk_list)do { if (((wk)->wk_list.le_next = (&newbp->b_dep)->
lh_first) != ((void *)0)) (&newbp->b_dep)->lh_first
->wk_list.le_prev = &(wk)->wk_list.le_next; (&newbp
->b_dep)->lh_first = (wk); (wk)->wk_list.le_prev = &
(&newbp->b_dep)->lh_first; } while (0)
;
832 else
833 LIST_INSERT_AFTER(wktail, wk, wk_list)do { if (((wk)->wk_list.le_next = (wktail)->wk_list.le_next
) != ((void *)0)) (wktail)->wk_list.le_next->wk_list.le_prev
= &(wk)->wk_list.le_next; (wktail)->wk_list.le_next
= (wk); (wk)->wk_list.le_prev = &(wktail)->wk_list
.le_next; } while (0)
;
834 wktail = wk;
835 }
836 FREE_LOCK(&lk)spllower((&lk)->lkt_spl);
837}
838
839/*
840 * Purge the work list of all items associated with a particular mount point.
841 */
842int
843softdep_flushworklist(struct mount *oldmnt, int *countp, struct proc *p)
844{
845 struct vnode *devvp;
846 int count, error = 0;
847
848 /*
849 * Await our turn to clear out the queue, then serialize access.
850 */
851 while (softdep_worklist_busy) {
852 softdep_worklist_req += 1;
853 tsleep_nsec(&softdep_worklist_req, PRIBIO16, "softflush", INFSLP0xffffffffffffffffULL);
854 softdep_worklist_req -= 1;
855 }
856 softdep_worklist_busy = -1;
857 /*
858 * Alternately flush the block device associated with the mount
859 * point and process any dependencies that the flushing
860 * creates. We continue until no more worklist dependencies
861 * are found.
862 */
863 *countp = 0;
864 devvp = VFSTOUFS(oldmnt)((struct ufsmount *)((oldmnt)->mnt_data))->um_devvp;
865 while ((count = softdep_process_worklist(oldmnt)) > 0) {
866 *countp += count;
867 vn_lock(devvp, LK_EXCLUSIVE0x0001UL | LK_RETRY0x2000UL);
868 error = VOP_FSYNC(devvp, p->p_ucred, MNT_WAIT1, p);
869 VOP_UNLOCK(devvp);
870 if (error)
871 break;
872 }
873 softdep_worklist_busy = 0;
874 if (softdep_worklist_req)
875 wakeup(&softdep_worklist_req);
876 return (error);
877}
878
879/*
880 * Flush all vnodes and worklist items associated with a specified mount point.
881 */
882int
883softdep_flushfiles(struct mount *oldmnt, int flags, struct proc *p)
884{
885 int error, count, loopcnt;
886
887 /*
888 * Alternately flush the vnodes associated with the mount
889 * point and process any dependencies that the flushing
890 * creates. In theory, this loop can happen at most twice,
891 * but we give it a few extra just to be sure.
892 */
893 for (loopcnt = 10; loopcnt > 0; loopcnt--) {
894 /*
895 * Do another flush in case any vnodes were brought in
896 * as part of the cleanup operations.
897 */
898 if ((error = ffs_flushfiles(oldmnt, flags, p)) != 0)
899 break;
900 if ((error = softdep_flushworklist(oldmnt, &count, p)) != 0 ||
901 count == 0)
902 break;
903 }
904 /*
905 * If the reboot process sleeps during the loop, the update
906 * process may call softdep_process_worklist() and create
907 * new dirty vnodes at the mount point. Call ffs_flushfiles()
908 * again after the loop has flushed all soft dependencies.
909 */
910 if (error == 0)
911 error = ffs_flushfiles(oldmnt, flags, p);
912 /*
913 * If we are unmounting then it is an error to fail. If we
914 * are simply trying to downgrade to read-only, then filesystem
915 * activity can keep us busy forever, so we just fail with EBUSY.
916 */
917 if (loopcnt == 0) {
918 error = EBUSY16;
919 }
920 return (error);
921}
922
923/*
924 * Structure hashing.
925 *
926 * There are three types of structures that can be looked up:
927 * 1) pagedep structures identified by mount point, inode number,
928 * and logical block.
929 * 2) inodedep structures identified by mount point and inode number.
930 * 3) newblk structures identified by mount point and
931 * physical block number.
932 *
933 * The "pagedep" and "inodedep" dependency structures are hashed
934 * separately from the file blocks and inodes to which they correspond.
935 * This separation helps when the in-memory copy of an inode or
936 * file block must be replaced. It also obviates the need to access
937 * an inode or file page when simply updating (or de-allocating)
938 * dependency structures. Lookup of newblk structures is needed to
939 * find newly allocated blocks when trying to associate them with
940 * their allocdirect or allocindir structure.
941 *
942 * The lookup routines optionally create and hash a new instance when
943 * an existing entry is not found.
944 */
945#define DEPALLOC0x0001 0x0001 /* allocate structure if lookup fails */
946#define NODELAY0x0002 0x0002 /* cannot do background work */
947
948SIPHASH_KEY softdep_hashkey;
949
950/*
951 * Structures and routines associated with pagedep caching.
952 */
953LIST_HEAD(pagedep_hashhead, pagedep)struct pagedep_hashhead { struct pagedep *lh_first; } *pagedep_hashtbl;
954u_long pagedep_hash; /* size of hash table - 1 */
955STATIC struct sema pagedep_in_progress;
956
957/*
958 * Look up a pagedep. Return 1 if found, 0 if not found or found
959 * when asked to allocate but not associated with any buffer.
960 * If not found, allocate if DEPALLOC flag is passed.
961 * Found or allocated entry is returned in pagedeppp.
962 * This routine must be called with splbio interrupts blocked.
963 */
964STATIC int
965pagedep_lookup(struct inode *ip, daddr_t lbn, int flags,
966 struct pagedep **pagedeppp)
967{
968 SIPHASH_CTX ctx;
969 struct pagedep *pagedep;
970 struct pagedep_hashhead *pagedephd;
971 struct mount *mp;
972 int i;
973
974 splassert(IPL_BIO)do { if (splassert_ctl > 0) { splassert_check(0x6, __func__
); } } while (0)
;
975
976#ifdef DEBUG
977 if (lk.lkt_held == -1)
978 panic("pagedep_lookup: lock not held");
979#endif
980 mp = ITOV(ip)((ip)->i_vnode)->v_mount;
981
982 SipHash24_Init(&ctx, &softdep_hashkey)SipHash_Init((&ctx), (&softdep_hashkey));
983 SipHash24_Update(&ctx, &mp, sizeof(mp))SipHash_Update((&ctx), 2, 4, (&mp), (sizeof(mp)));
984 SipHash24_Update(&ctx, &ip->i_number, sizeof(ip->i_number))SipHash_Update((&ctx), 2, 4, (&ip->i_number), (sizeof
(ip->i_number)))
;
985 SipHash24_Update(&ctx, &lbn, sizeof(lbn))SipHash_Update((&ctx), 2, 4, (&lbn), (sizeof(lbn)));
986 pagedephd = &pagedep_hashtbl[SipHash24_End(&ctx)SipHash_End((&ctx), 2, 4) & pagedep_hash];
987top:
988 LIST_FOREACH(pagedep, pagedephd, pd_hash)for((pagedep) = ((pagedephd)->lh_first); (pagedep)!= ((void
*)0); (pagedep) = ((pagedep)->pd_hash.le_next))
989 if (ip->i_number == pagedep->pd_ino &&
990 lbn == pagedep->pd_lbn &&
991 mp == pagedep->pd_mnt)
992 break;
993 if (pagedep) {
994 *pagedeppp = pagedep;
995 if ((flags & DEPALLOC0x0001) != 0 &&
996 (pagedep->pd_statepd_list.wk_state & ONWORKLIST0x8000) == 0)
997 return (0);
998 return (1);
999 }
1000 if ((flags & DEPALLOC0x0001) == 0) {
1001 *pagedeppp = NULL((void *)0);
1002 return (0);
1003 }
1004 if (sema_get(&pagedep_in_progress, &lk) == 0) {
1005 ACQUIRE_LOCK(&lk)(&lk)->lkt_spl = splraise(0x6);
1006 goto top;
1007 }
1008 pagedep = pool_get(&pagedep_pool, PR_WAITOK0x0001 | PR_ZERO0x0008);
1009 pagedep->pd_list.wk_type = D_PAGEDEP0;
1010 pagedep->pd_mnt = mp;
1011 pagedep->pd_ino = ip->i_number;
1012 pagedep->pd_lbn = lbn;
1013 LIST_INIT(&pagedep->pd_dirremhd)do { ((&pagedep->pd_dirremhd)->lh_first) = ((void *
)0); } while (0)
;
1014 LIST_INIT(&pagedep->pd_pendinghd)do { ((&pagedep->pd_pendinghd)->lh_first) = ((void *
)0); } while (0)
;
1015 for (i = 0; i < DAHASHSZ6; i++)
1016 LIST_INIT(&pagedep->pd_diraddhd[i])do { ((&pagedep->pd_diraddhd[i])->lh_first) = ((void
*)0); } while (0)
;
1017 ACQUIRE_LOCK(&lk)(&lk)->lkt_spl = splraise(0x6);
1018 LIST_INSERT_HEAD(pagedephd, pagedep, pd_hash)do { if (((pagedep)->pd_hash.le_next = (pagedephd)->lh_first
) != ((void *)0)) (pagedephd)->lh_first->pd_hash.le_prev
= &(pagedep)->pd_hash.le_next; (pagedephd)->lh_first
= (pagedep); (pagedep)->pd_hash.le_prev = &(pagedephd
)->lh_first; } while (0)
;
1019 sema_release(&pagedep_in_progress);
1020 *pagedeppp = pagedep;
1021 return (0);
1022}
1023
1024/*
1025 * Structures and routines associated with inodedep caching.
1026 */
1027LIST_HEAD(inodedep_hashhead, inodedep)struct inodedep_hashhead { struct inodedep *lh_first; } *inodedep_hashtbl;
1028STATIC u_long inodedep_hash; /* size of hash table - 1 */
1029STATIC long num_inodedep; /* number of inodedep allocated */
1030STATIC struct sema inodedep_in_progress;
1031
1032/*
1033 * Look up a inodedep. Return 1 if found, 0 if not found.
1034 * If not found, allocate if DEPALLOC flag is passed.
1035 * Found or allocated entry is returned in inodedeppp.
1036 * This routine must be called with splbio interrupts blocked.
1037 */
1038STATIC int
1039inodedep_lookup(struct fs *fs, ufsino_t inum, int flags,
1040 struct inodedep **inodedeppp)
1041{
1042 SIPHASH_CTX ctx;
1043 struct inodedep *inodedep;
1044 struct inodedep_hashhead *inodedephd;
1045 int firsttry;
1046
1047 splassert(IPL_BIO)do { if (splassert_ctl > 0) { splassert_check(0x6, __func__
); } } while (0)
;
1048
1049#ifdef DEBUG
1050 if (lk.lkt_held == -1)
1051 panic("inodedep_lookup: lock not held");
1052#endif
1053 firsttry = 1;
1054 SipHash24_Init(&ctx, &softdep_hashkey)SipHash_Init((&ctx), (&softdep_hashkey));
1055 SipHash24_Update(&ctx, &fs, sizeof(fs))SipHash_Update((&ctx), 2, 4, (&fs), (sizeof(fs)));
1056 SipHash24_Update(&ctx, &inum, sizeof(inum))SipHash_Update((&ctx), 2, 4, (&inum), (sizeof(inum)));
1057 inodedephd = &inodedep_hashtbl[SipHash24_End(&ctx)SipHash_End((&ctx), 2, 4) & inodedep_hash];
1058top:
1059 LIST_FOREACH(inodedep, inodedephd, id_hash)for((inodedep) = ((inodedephd)->lh_first); (inodedep)!= ((
void *)0); (inodedep) = ((inodedep)->id_hash.le_next))
1060 if (inum == inodedep->id_ino && fs == inodedep->id_fs)
1061 break;
1062 if (inodedep) {
1063 *inodedeppp = inodedep;
1064 return (1);
1065 }
1066 if ((flags & DEPALLOC0x0001) == 0) {
1067 *inodedeppp = NULL((void *)0);
1068 return (0);
1069 }
1070 /*
1071 * If we are over our limit, try to improve the situation.
1072 */
1073 if (num_inodedep > max_softdeps && firsttry && (flags & NODELAY0x0002) == 0 &&
1074 request_cleanup(FLUSH_INODES1, 1)) {
1075 firsttry = 0;
1076 goto top;
1077 }
1078 if (sema_get(&inodedep_in_progress, &lk) == 0) {
1079 ACQUIRE_LOCK(&lk)(&lk)->lkt_spl = splraise(0x6);
1080 goto top;
1081 }
1082 num_inodedep += 1;
1083 inodedep = pool_get(&inodedep_pool, PR_WAITOK0x0001);
1084 inodedep->id_list.wk_type = D_INODEDEP1;
1085 inodedep->id_fs = fs;
1086 inodedep->id_ino = inum;
1087 inodedep->id_stateid_list.wk_state = ALLCOMPLETE(0x0001 | 0x0004 | 0x0008);
1088 inodedep->id_nlinkdelta = 0;
1089 inodedep->id_savedino1id_un.idu_savedino1 = NULL((void *)0);
1090 inodedep->id_savedsize = -1;
1091 inodedep->id_buf = NULL((void *)0);
1092 LIST_INIT(&inodedep->id_pendinghd)do { ((&inodedep->id_pendinghd)->lh_first) = ((void
*)0); } while (0)
;
1093 LIST_INIT(&inodedep->id_inowait)do { ((&inodedep->id_inowait)->lh_first) = ((void *
)0); } while (0)
;
1094 LIST_INIT(&inodedep->id_bufwait)do { ((&inodedep->id_bufwait)->lh_first) = ((void *
)0); } while (0)
;
1095 TAILQ_INIT(&inodedep->id_inoupdt)do { (&inodedep->id_inoupdt)->tqh_first = ((void *)
0); (&inodedep->id_inoupdt)->tqh_last = &(&
inodedep->id_inoupdt)->tqh_first; } while (0)
;
1096 TAILQ_INIT(&inodedep->id_newinoupdt)do { (&inodedep->id_newinoupdt)->tqh_first = ((void
*)0); (&inodedep->id_newinoupdt)->tqh_last = &
(&inodedep->id_newinoupdt)->tqh_first; } while (0)
;
1097 ACQUIRE_LOCK(&lk)(&lk)->lkt_spl = splraise(0x6);
1098 LIST_INSERT_HEAD(inodedephd, inodedep, id_hash)do { if (((inodedep)->id_hash.le_next = (inodedephd)->lh_first
) != ((void *)0)) (inodedephd)->lh_first->id_hash.le_prev
= &(inodedep)->id_hash.le_next; (inodedephd)->lh_first
= (inodedep); (inodedep)->id_hash.le_prev = &(inodedephd
)->lh_first; } while (0)
;
1099 sema_release(&inodedep_in_progress);
1100 *inodedeppp = inodedep;
1101 return (0);
1102}
1103
1104/*
1105 * Structures and routines associated with newblk caching.
1106 */
1107LIST_HEAD(newblk_hashhead, newblk)struct newblk_hashhead { struct newblk *lh_first; } *newblk_hashtbl;
1108u_long newblk_hash; /* size of hash table - 1 */
1109STATIC struct sema newblk_in_progress;
1110
1111/*
1112 * Look up a newblk. Return 1 if found, 0 if not found.
1113 * If not found, allocate if DEPALLOC flag is passed.
1114 * Found or allocated entry is returned in newblkpp.
1115 */
1116STATIC int
1117newblk_lookup(struct fs *fs, daddr_t newblkno, int flags,
1118 struct newblk **newblkpp)
1119{
1120 SIPHASH_CTX ctx;
1121 struct newblk *newblk;
1122 struct newblk_hashhead *newblkhd;
1123
1124 SipHash24_Init(&ctx, &softdep_hashkey)SipHash_Init((&ctx), (&softdep_hashkey));
1125 SipHash24_Update(&ctx, &fs, sizeof(fs))SipHash_Update((&ctx), 2, 4, (&fs), (sizeof(fs)));
1126 SipHash24_Update(&ctx, &newblkno, sizeof(newblkno))SipHash_Update((&ctx), 2, 4, (&newblkno), (sizeof(newblkno
)))
;
1127 newblkhd = &newblk_hashtbl[SipHash24_End(&ctx)SipHash_End((&ctx), 2, 4) & newblk_hash];
1128top:
1129 LIST_FOREACH(newblk, newblkhd, nb_hash)for((newblk) = ((newblkhd)->lh_first); (newblk)!= ((void *
)0); (newblk) = ((newblk)->nb_hash.le_next))
1130 if (newblkno == newblk->nb_newblkno && fs == newblk->nb_fs)
1131 break;
1132 if (newblk) {
1133 *newblkpp = newblk;
1134 return (1);
1135 }
1136 if ((flags & DEPALLOC0x0001) == 0) {
1137 *newblkpp = NULL((void *)0);
1138 return (0);
1139 }
1140 if (sema_get(&newblk_in_progress, NULL((void *)0)) == 0)
1141 goto top;
1142 newblk = pool_get(&newblk_pool, PR_WAITOK0x0001);
1143 newblk->nb_state = 0;
1144 newblk->nb_fs = fs;
1145 newblk->nb_newblkno = newblkno;
1146 LIST_INSERT_HEAD(newblkhd, newblk, nb_hash)do { if (((newblk)->nb_hash.le_next = (newblkhd)->lh_first
) != ((void *)0)) (newblkhd)->lh_first->nb_hash.le_prev
= &(newblk)->nb_hash.le_next; (newblkhd)->lh_first
= (newblk); (newblk)->nb_hash.le_prev = &(newblkhd)->
lh_first; } while (0)
;
1147 sema_release(&newblk_in_progress);
1148 *newblkpp = newblk;
1149 return (0);
1150}
1151
1152/*
1153 * Executed during filesystem system initialization before
1154 * mounting any file systems.
1155 */
1156void
1157softdep_initialize(void)
1158{
1159
1160 bioops.io_start = softdep_disk_io_initiation;
1161 bioops.io_complete = softdep_disk_write_complete;
1162 bioops.io_deallocate = softdep_deallocate_dependencies;
1163 bioops.io_movedeps = softdep_move_dependencies;
1164 bioops.io_countdeps = softdep_count_dependencies;
1165
1166 LIST_INIT(&mkdirlisthd)do { ((&mkdirlisthd)->lh_first) = ((void *)0); } while
(0)
;
1167 LIST_INIT(&softdep_workitem_pending)do { ((&softdep_workitem_pending)->lh_first) = ((void *
)0); } while (0)
;
1168#ifdef KMEMSTATS1
1169 max_softdeps = min (initialvnodes * 8,
1170 kmemstats[M_INODEDEP79].ks_limit / (2 * sizeof(struct inodedep)));
1171#else
1172 max_softdeps = initialvnodes * 4;
1173#endif
1174 arc4random_buf(&softdep_hashkey, sizeof(softdep_hashkey));
1175 pagedep_hashtbl = hashinit(initialvnodes / 5, M_PAGEDEP78, M_WAITOK0x0001,
1176 &pagedep_hash);
1177 sema_init(&pagedep_in_progress, "pagedep", PRIBIO16);
1178 inodedep_hashtbl = hashinit(initialvnodes, M_INODEDEP79, M_WAITOK0x0001,
1179 &inodedep_hash);
1180 sema_init(&inodedep_in_progress, "inodedep", PRIBIO16);
1181 newblk_hashtbl = hashinit(64, M_NEWBLK80, M_WAITOK0x0001, &newblk_hash);
1182 sema_init(&newblk_in_progress, "newblk", PRIBIO16);
1183 timeout_set(&proc_waiting_timeout, pause_timer, NULL((void *)0));
1184 pool_init(&pagedep_pool, sizeof(struct pagedep), 0, IPL_NONE0x0,
1185 PR_WAITOK0x0001, "pagedep", NULL((void *)0));
1186 pool_init(&inodedep_pool, sizeof(struct inodedep), 0, IPL_NONE0x0,
1187 PR_WAITOK0x0001, "inodedep", NULL((void *)0));
1188 pool_init(&newblk_pool, sizeof(struct newblk), 0, IPL_NONE0x0,
1189 PR_WAITOK0x0001, "newblk", NULL((void *)0));
1190 pool_init(&bmsafemap_pool, sizeof(struct bmsafemap), 0, IPL_NONE0x0,
1191 PR_WAITOK0x0001, "bmsafemap", NULL((void *)0));
1192 pool_init(&allocdirect_pool, sizeof(struct allocdirect), 0, IPL_NONE0x0,
1193 PR_WAITOK0x0001, "allocdir", NULL((void *)0));
1194 pool_init(&indirdep_pool, sizeof(struct indirdep), 0, IPL_NONE0x0,
1195 PR_WAITOK0x0001, "indirdep", NULL((void *)0));
1196 pool_init(&allocindir_pool, sizeof(struct allocindir), 0, IPL_NONE0x0,
1197 PR_WAITOK0x0001, "allocindir", NULL((void *)0));
1198 pool_init(&freefrag_pool, sizeof(struct freefrag), 0, IPL_NONE0x0,
1199 PR_WAITOK0x0001, "freefrag", NULL((void *)0));
1200 pool_init(&freeblks_pool, sizeof(struct freeblks), 0, IPL_NONE0x0,
1201 PR_WAITOK0x0001, "freeblks", NULL((void *)0));
1202 pool_init(&freefile_pool, sizeof(struct freefile), 0, IPL_NONE0x0,
1203 PR_WAITOK0x0001, "freefile", NULL((void *)0));
1204 pool_init(&diradd_pool, sizeof(struct diradd), 0, IPL_NONE0x0,
1205 PR_WAITOK0x0001, "diradd", NULL((void *)0));
1206 pool_init(&mkdir_pool, sizeof(struct mkdir), 0, IPL_NONE0x0,
1207 PR_WAITOK0x0001, "mkdir", NULL((void *)0));
1208 pool_init(&dirrem_pool, sizeof(struct dirrem), 0, IPL_NONE0x0,
1209 PR_WAITOK0x0001, "dirrem", NULL((void *)0));
1210 pool_init(&newdirblk_pool, sizeof(struct newdirblk), 0, IPL_NONE0x0,
1211 PR_WAITOK0x0001, "newdirblk", NULL((void *)0));
1212}
1213
1214/*
1215 * Called at mount time to notify the dependency code that a
1216 * filesystem wishes to use it.
1217 */
1218int
1219softdep_mount(struct vnode *devvp, struct mount *mp, struct fs *fs,
1220 struct ucred *cred)
1221{
1222 struct csum_total cstotal;
1223 struct cg *cgp;
1224 struct buf *bp;
1225 int error, cyl;
1226
1227 /*
1228 * When doing soft updates, the counters in the
1229 * superblock may have gotten out of sync, so we have
1230 * to scan the cylinder groups and recalculate them.
1231 */
1232 if ((fs->fs_flags & FS_UNCLEAN0x01) == 0)
1233 return (0);
1234 memset(&cstotal, 0, sizeof(cstotal))__builtin_memset((&cstotal), (0), (sizeof(cstotal)));
1235 for (cyl = 0; cyl < fs->fs_ncg; cyl++) {
1236 if ((error = bread(devvp, fsbtodb(fs, cgtod(fs, cyl))((((((daddr_t)(fs)->fs_fpg * (cyl)) + (fs)->fs_cgoffset
* ((cyl) & ~((fs)->fs_cgmask))) + (fs)->fs_cblkno)
) << (fs)->fs_fsbtodb)
,
1237 fs->fs_cgsize, &bp)) != 0) {
1238 brelse(bp);
1239 return (error);
1240 }
1241 cgp = (struct cg *)bp->b_data;
1242 cstotal.cs_nffree += cgp->cg_cs.cs_nffree;
1243 cstotal.cs_nbfree += cgp->cg_cs.cs_nbfree;
1244 cstotal.cs_nifree += cgp->cg_cs.cs_nifree;
1245 cstotal.cs_ndir += cgp->cg_cs.cs_ndir;
1246 fs->fs_cs(fs, cyl)fs_csp[cyl] = cgp->cg_cs;
1247 brelse(bp);
1248 }
1249#ifdef DEBUG
1250 if (memcmp(&cstotal, &fs->fs_cstotal, sizeof(cstotal))__builtin_memcmp((&cstotal), (&fs->fs_cstotal), (sizeof
(cstotal)))
)
1251 printf("ffs_mountfs: superblock updated for soft updates\n");
1252#endif
1253 memcpy(&fs->fs_cstotal, &cstotal, sizeof(cstotal))__builtin_memcpy((&fs->fs_cstotal), (&cstotal), (sizeof
(cstotal)))
;
1254 return (0);
1255}
1256
1257/*
1258 * Protecting the freemaps (or bitmaps).
1259 *
1260 * To eliminate the need to execute fsck before mounting a file system
1261 * after a power failure, one must (conservatively) guarantee that the
1262 * on-disk copy of the bitmaps never indicate that a live inode or block is
1263 * free. So, when a block or inode is allocated, the bitmap should be
1264 * updated (on disk) before any new pointers. When a block or inode is
1265 * freed, the bitmap should not be updated until all pointers have been
1266 * reset. The latter dependency is handled by the delayed de-allocation
1267 * approach described below for block and inode de-allocation. The former
1268 * dependency is handled by calling the following procedure when a block or
1269 * inode is allocated. When an inode is allocated an "inodedep" is created
1270 * with its DEPCOMPLETE flag cleared until its bitmap is written to disk.
1271 * Each "inodedep" is also inserted into the hash indexing structure so
1272 * that any additional link additions can be made dependent on the inode
1273 * allocation.
1274 *
1275 * The ufs file system maintains a number of free block counts (e.g., per
1276 * cylinder group, per cylinder and per <cylinder, rotational position> pair)
1277 * in addition to the bitmaps. These counts are used to improve efficiency
1278 * during allocation and therefore must be consistent with the bitmaps.
1279 * There is no convenient way to guarantee post-crash consistency of these
1280 * counts with simple update ordering, for two main reasons: (1) The counts
1281 * and bitmaps for a single cylinder group block are not in the same disk
1282 * sector. If a disk write is interrupted (e.g., by power failure), one may
1283 * be written and the other not. (2) Some of the counts are located in the
1284 * superblock rather than the cylinder group block. So, we focus our soft
1285 * updates implementation on protecting the bitmaps. When mounting a
1286 * filesystem, we recompute the auxiliary counts from the bitmaps.
1287 */
1288
1289/*
1290 * Called just after updating the cylinder group block to allocate an inode.
1291 */
1292/* buffer for cylgroup block with inode map */
1293/* inode related to allocation */
1294/* new inode number being allocated */
1295void
1296softdep_setup_inomapdep(struct buf *bp, struct inode *ip, ufsino_t newinum)
1297{
1298 struct inodedep *inodedep;
1299 struct bmsafemap *bmsafemap;
1300
1301 /*
1302 * Create a dependency for the newly allocated inode.
1303 * Panic if it already exists as something is seriously wrong.
1304 * Otherwise add it to the dependency list for the buffer holding
1305 * the cylinder group map from which it was allocated.
1306 */
1307 ACQUIRE_LOCK(&lk)(&lk)->lkt_spl = splraise(0x6);
1308 if (inodedep_lookup(ip->i_fsinode_u.fs, newinum, DEPALLOC0x0001 | NODELAY0x0002, &inodedep)
1309 != 0) {
1310 FREE_LOCK(&lk)spllower((&lk)->lkt_spl);
1311 panic("softdep_setup_inomapdep: found inode");
1312 }
1313 inodedep->id_buf = bp;
1314 inodedep->id_stateid_list.wk_state &= ~DEPCOMPLETE0x0008;
1315 bmsafemap = bmsafemap_lookup(bp);
1316 LIST_INSERT_HEAD(&bmsafemap->sm_inodedephd, inodedep, id_deps)do { if (((inodedep)->id_deps.le_next = (&bmsafemap->
sm_inodedephd)->lh_first) != ((void *)0)) (&bmsafemap->
sm_inodedephd)->lh_first->id_deps.le_prev = &(inodedep
)->id_deps.le_next; (&bmsafemap->sm_inodedephd)->
lh_first = (inodedep); (inodedep)->id_deps.le_prev = &
(&bmsafemap->sm_inodedephd)->lh_first; } while (0)
;
1317 FREE_LOCK(&lk)spllower((&lk)->lkt_spl);
1318}
1319
1320/*
1321 * Called just after updating the cylinder group block to
1322 * allocate block or fragment.
1323 */
1324/* buffer for cylgroup block with block map */
1325/* filesystem doing allocation */
1326/* number of newly allocated block */
1327void
1328softdep_setup_blkmapdep(struct buf *bp, struct fs *fs, daddr_t newblkno)
1329{
1330 struct newblk *newblk;
1331 struct bmsafemap *bmsafemap;
1332
1333 /*
1334 * Create a dependency for the newly allocated block.
1335 * Add it to the dependency list for the buffer holding
1336 * the cylinder group map from which it was allocated.
1337 */
1338 if (newblk_lookup(fs, newblkno, DEPALLOC0x0001, &newblk) != 0)
1339 panic("softdep_setup_blkmapdep: found block");
1340 ACQUIRE_LOCK(&lk)(&lk)->lkt_spl = splraise(0x6);
1341 newblk->nb_bmsafemap = bmsafemap = bmsafemap_lookup(bp);
1342 LIST_INSERT_HEAD(&bmsafemap->sm_newblkhd, newblk, nb_deps)do { if (((newblk)->nb_deps.le_next = (&bmsafemap->
sm_newblkhd)->lh_first) != ((void *)0)) (&bmsafemap->
sm_newblkhd)->lh_first->nb_deps.le_prev = &(newblk)
->nb_deps.le_next; (&bmsafemap->sm_newblkhd)->lh_first
= (newblk); (newblk)->nb_deps.le_prev = &(&bmsafemap
->sm_newblkhd)->lh_first; } while (0)
;
1343 FREE_LOCK(&lk)spllower((&lk)->lkt_spl);
1344}
1345
1346/*
1347 * Find the bmsafemap associated with a cylinder group buffer.
1348 * If none exists, create one. The buffer must be locked when
1349 * this routine is called and this routine must be called with
1350 * splbio interrupts blocked.
1351 */
1352STATIC struct bmsafemap *
1353bmsafemap_lookup(struct buf *bp)
1354{
1355 struct bmsafemap *bmsafemap;
1356 struct worklist *wk;
1357
1358 splassert(IPL_BIO)do { if (splassert_ctl > 0) { splassert_check(0x6, __func__
); } } while (0)
;
1359
1360#ifdef DEBUG
1361 if (lk.lkt_held == -1)
1362 panic("bmsafemap_lookup: lock not held");
1363#endif
1364 LIST_FOREACH(wk, &bp->b_dep, wk_list)for((wk) = ((&bp->b_dep)->lh_first); (wk)!= ((void *
)0); (wk) = ((wk)->wk_list.le_next))
1365 if (wk->wk_type == D_BMSAFEMAP3)
1366 return (WK_BMSAFEMAP(wk)((struct bmsafemap *)(wk)));
1367 FREE_LOCK(&lk)spllower((&lk)->lkt_spl);
1368 bmsafemap = pool_get(&bmsafemap_pool, PR_WAITOK0x0001);
1369 bmsafemap->sm_list.wk_type = D_BMSAFEMAP3;
1370 bmsafemap->sm_list.wk_state = 0;
1371 bmsafemap->sm_buf = bp;
1372 LIST_INIT(&bmsafemap->sm_allocdirecthd)do { ((&bmsafemap->sm_allocdirecthd)->lh_first) = (
(void *)0); } while (0)
;
1373 LIST_INIT(&bmsafemap->sm_allocindirhd)do { ((&bmsafemap->sm_allocindirhd)->lh_first) = ((
void *)0); } while (0)
;
1374 LIST_INIT(&bmsafemap->sm_inodedephd)do { ((&bmsafemap->sm_inodedephd)->lh_first) = ((void
*)0); } while (0)
;
1375 LIST_INIT(&bmsafemap->sm_newblkhd)do { ((&bmsafemap->sm_newblkhd)->lh_first) = ((void
*)0); } while (0)
;
1376 ACQUIRE_LOCK(&lk)(&lk)->lkt_spl = splraise(0x6);
1377 WORKLIST_INSERT(&bp->b_dep, &bmsafemap->sm_list)do { (&bmsafemap->sm_list)->wk_state |= 0x8000; do {
if (((&bmsafemap->sm_list)->wk_list.le_next = (&
bp->b_dep)->lh_first) != ((void *)0)) (&bp->b_dep
)->lh_first->wk_list.le_prev = &(&bmsafemap->
sm_list)->wk_list.le_next; (&bp->b_dep)->lh_first
= (&bmsafemap->sm_list); (&bmsafemap->sm_list)
->wk_list.le_prev = &(&bp->b_dep)->lh_first;
} while (0); } while (0)
;
1378 return (bmsafemap);
1379}
1380
1381/*
1382 * Direct block allocation dependencies.
1383 *
1384 * When a new block is allocated, the corresponding disk locations must be
1385 * initialized (with zeros or new data) before the on-disk inode points to
1386 * them. Also, the freemap from which the block was allocated must be
1387 * updated (on disk) before the inode's pointer. These two dependencies are
1388 * independent of each other and are needed for all file blocks and indirect
1389 * blocks that are pointed to directly by the inode. Just before the
1390 * "in-core" version of the inode is updated with a newly allocated block
1391 * number, a procedure (below) is called to setup allocation dependency
1392 * structures. These structures are removed when the corresponding
1393 * dependencies are satisfied or when the block allocation becomes obsolete
1394 * (i.e., the file is deleted, the block is de-allocated, or the block is a
1395 * fragment that gets upgraded). All of these cases are handled in
1396 * procedures described later.
1397 *
1398 * When a file extension causes a fragment to be upgraded, either to a larger
1399 * fragment or to a full block, the on-disk location may change (if the
1400 * previous fragment could not simply be extended). In this case, the old
1401 * fragment must be de-allocated, but not until after the inode's pointer has
1402 * been updated. In most cases, this is handled by later procedures, which
1403 * will construct a "freefrag" structure to be added to the workitem queue
1404 * when the inode update is complete (or obsolete). The main exception to
1405 * this is when an allocation occurs while a pending allocation dependency
1406 * (for the same block pointer) remains. This case is handled in the main
1407 * allocation dependency setup procedure by immediately freeing the
1408 * unreferenced fragments.
1409 */
1410/* inode to which block is being added */
1411/* block pointer within inode */
1412/* disk block number being added */
1413/* previous block number, 0 unless frag */
1414/* size of new block */
1415/* size of new block */
1416/* bp for allocated block */
1417void
1418softdep_setup_allocdirect(struct inode *ip, daddr_t lbn, daddr_t newblkno,
1419 daddr_t oldblkno, long newsize, long oldsize, struct buf *bp)
1420{
1421 struct allocdirect *adp, *oldadp;
1422 struct allocdirectlst *adphead;
1423 struct bmsafemap *bmsafemap;
1424 struct inodedep *inodedep;
1425 struct pagedep *pagedep;
1426 struct newblk *newblk;
1427
1428 adp = pool_get(&allocdirect_pool, PR_WAITOK0x0001 | PR_ZERO0x0008);
1429 adp->ad_list.wk_type = D_ALLOCDIRECT4;
1430 adp->ad_lbn = lbn;
1431 adp->ad_newblkno = newblkno;
1432 adp->ad_oldblkno = oldblkno;
1433 adp->ad_newsize = newsize;
1434 adp->ad_oldsize = oldsize;
1435 adp->ad_statead_list.wk_state = ATTACHED0x0001;
1436 LIST_INIT(&adp->ad_newdirblk)do { ((&adp->ad_newdirblk)->lh_first) = ((void *)0)
; } while (0)
;
1437 if (newblkno == oldblkno)
1438 adp->ad_freefrag = NULL((void *)0);
1439 else
1440 adp->ad_freefrag = newfreefrag(ip, oldblkno, oldsize);
1441
1442 if (newblk_lookup(ip->i_fsinode_u.fs, newblkno, 0, &newblk) == 0)
1443 panic("softdep_setup_allocdirect: lost block");
1444
1445 ACQUIRE_LOCK(&lk)(&lk)->lkt_spl = splraise(0x6);
1446 inodedep_lookup(ip->i_fsinode_u.fs, ip->i_number, DEPALLOC0x0001 | NODELAY0x0002, &inodedep);
1447 adp->ad_inodedep = inodedep;
1448
1449 if (newblk->nb_state == DEPCOMPLETE0x0008) {
1450 adp->ad_statead_list.wk_state |= DEPCOMPLETE0x0008;
1451 adp->ad_buf = NULL((void *)0);
1452 } else {
1453 bmsafemap = newblk->nb_bmsafemap;
1454 adp->ad_buf = bmsafemap->sm_buf;
1455 LIST_REMOVE(newblk, nb_deps)do { if ((newblk)->nb_deps.le_next != ((void *)0)) (newblk
)->nb_deps.le_next->nb_deps.le_prev = (newblk)->nb_deps
.le_prev; *(newblk)->nb_deps.le_prev = (newblk)->nb_deps
.le_next; ((newblk)->nb_deps.le_prev) = ((void *)-1); ((newblk
)->nb_deps.le_next) = ((void *)-1); } while (0)
;
1456 LIST_INSERT_HEAD(&bmsafemap->sm_allocdirecthd, adp, ad_deps)do { if (((adp)->ad_deps.le_next = (&bmsafemap->sm_allocdirecthd
)->lh_first) != ((void *)0)) (&bmsafemap->sm_allocdirecthd
)->lh_first->ad_deps.le_prev = &(adp)->ad_deps.le_next
; (&bmsafemap->sm_allocdirecthd)->lh_first = (adp);
(adp)->ad_deps.le_prev = &(&bmsafemap->sm_allocdirecthd
)->lh_first; } while (0)
;
1457 }
1458 LIST_REMOVE(newblk, nb_hash)do { if ((newblk)->nb_hash.le_next != ((void *)0)) (newblk
)->nb_hash.le_next->nb_hash.le_prev = (newblk)->nb_hash
.le_prev; *(newblk)->nb_hash.le_prev = (newblk)->nb_hash
.le_next; ((newblk)->nb_hash.le_prev) = ((void *)-1); ((newblk
)->nb_hash.le_next) = ((void *)-1); } while (0)
;
1459 pool_put(&newblk_pool, newblk);
1460
1461 if (bp == NULL((void *)0)) {
1462 /*
1463 * XXXUBC - Yes, I know how to fix this, but not right now.
1464 */
1465 panic("softdep_setup_allocdirect: Bonk art in the head");
1466 }
1467 WORKLIST_INSERT(&bp->b_dep, &adp->ad_list)do { (&adp->ad_list)->wk_state |= 0x8000; do { if (
((&adp->ad_list)->wk_list.le_next = (&bp->b_dep
)->lh_first) != ((void *)0)) (&bp->b_dep)->lh_first
->wk_list.le_prev = &(&adp->ad_list)->wk_list
.le_next; (&bp->b_dep)->lh_first = (&adp->ad_list
); (&adp->ad_list)->wk_list.le_prev = &(&bp
->b_dep)->lh_first; } while (0); } while (0)
;
1468 if (lbn >= NDADDR12) {
1469 /* allocating an indirect block */
1470 if (oldblkno != 0) {
1471 FREE_LOCK(&lk)spllower((&lk)->lkt_spl);
1472 panic("softdep_setup_allocdirect: non-zero indir");
1473 }
1474 } else {
1475 /*
1476 * Allocating a direct block.
1477 *
1478 * If we are allocating a directory block, then we must
1479 * allocate an associated pagedep to track additions and
1480 * deletions.
1481 */
1482 if ((DIP(ip, mode)(((ip)->i_ump->um_fstype == 1) ? (ip)->dinode_u.ffs1_din
->di_mode : (ip)->dinode_u.ffs2_din->di_mode)
& IFMT0170000) == IFDIR0040000 &&
1483 pagedep_lookup(ip, lbn, DEPALLOC0x0001, &pagedep) == 0)
1484 WORKLIST_INSERT(&bp->b_dep, &pagedep->pd_list)do { (&pagedep->pd_list)->wk_state |= 0x8000; do { if
(((&pagedep->pd_list)->wk_list.le_next = (&bp->
b_dep)->lh_first) != ((void *)0)) (&bp->b_dep)->
lh_first->wk_list.le_prev = &(&pagedep->pd_list
)->wk_list.le_next; (&bp->b_dep)->lh_first = (&
pagedep->pd_list); (&pagedep->pd_list)->wk_list.
le_prev = &(&bp->b_dep)->lh_first; } while (0);
} while (0)
;
1485 }
1486 /*
1487 * The list of allocdirects must be kept in sorted and ascending
1488 * order so that the rollback routines can quickly determine the
1489 * first uncommitted block (the size of the file stored on disk
1490 * ends at the end of the lowest committed fragment, or if there
1491 * are no fragments, at the end of the highest committed block).
1492 * Since files generally grow, the typical case is that the new
1493 * block is to be added at the end of the list. We speed this
1494 * special case by checking against the last allocdirect in the
1495 * list before laboriously traversing the list looking for the
1496 * insertion point.
1497 */
1498 adphead = &inodedep->id_newinoupdt;
1499 oldadp = TAILQ_LAST(adphead, allocdirectlst)(*(((struct allocdirectlst *)((adphead)->tqh_last))->tqh_last
))
;
1500 if (oldadp == NULL((void *)0) || oldadp->ad_lbn <= lbn) {
1501 /* insert at end of list */
1502 TAILQ_INSERT_TAIL(adphead, adp, ad_next)do { (adp)->ad_next.tqe_next = ((void *)0); (adp)->ad_next
.tqe_prev = (adphead)->tqh_last; *(adphead)->tqh_last =
(adp); (adphead)->tqh_last = &(adp)->ad_next.tqe_next
; } while (0)
;
1503 if (oldadp != NULL((void *)0) && oldadp->ad_lbn == lbn)
1504 allocdirect_merge(adphead, adp, oldadp);
1505 FREE_LOCK(&lk)spllower((&lk)->lkt_spl);
1506 return;
1507 }
1508 TAILQ_FOREACH(oldadp, adphead, ad_next)for((oldadp) = ((adphead)->tqh_first); (oldadp) != ((void *
)0); (oldadp) = ((oldadp)->ad_next.tqe_next))
{
1509 if (oldadp->ad_lbn >= lbn)
1510 break;
1511 }
1512 if (oldadp == NULL((void *)0)) {
1513 FREE_LOCK(&lk)spllower((&lk)->lkt_spl);
1514 panic("softdep_setup_allocdirect: lost entry");
1515 }
1516 /* insert in middle of list */
1517 TAILQ_INSERT_BEFORE(oldadp, adp, ad_next)do { (adp)->ad_next.tqe_prev = (oldadp)->ad_next.tqe_prev
; (adp)->ad_next.tqe_next = (oldadp); *(oldadp)->ad_next
.tqe_prev = (adp); (oldadp)->ad_next.tqe_prev = &(adp)
->ad_next.tqe_next; } while (0)
;
1518 if (oldadp->ad_lbn == lbn)
1519 allocdirect_merge(adphead, adp, oldadp);
1520 FREE_LOCK(&lk)spllower((&lk)->lkt_spl);
1521}
1522
1523/*
1524 * Replace an old allocdirect dependency with a newer one.
1525 * This routine must be called with splbio interrupts blocked.
1526 */
1527/* head of list holding allocdirects */
1528/* allocdirect being added */
1529/* existing allocdirect being checked */
1530STATIC void
1531allocdirect_merge(struct allocdirectlst *adphead, struct allocdirect *newadp,
1532 struct allocdirect *oldadp)
1533{
1534 struct worklist *wk;
1535 struct freefrag *freefrag;
1536 struct newdirblk *newdirblk;
1537
1538 splassert(IPL_BIO)do { if (splassert_ctl > 0) { splassert_check(0x6, __func__
); } } while (0)
;
1539
1540#ifdef DEBUG
1541 if (lk.lkt_held == -1)
1542 panic("allocdirect_merge: lock not held");
1543#endif
1544 if (newadp->ad_oldblkno != oldadp->ad_newblkno ||
1545 newadp->ad_oldsize != oldadp->ad_newsize ||
1546 newadp->ad_lbn >= NDADDR12) {
1547 FREE_LOCK(&lk)spllower((&lk)->lkt_spl);
1548 panic("allocdirect_merge: old %lld != new %lld || lbn %lld >= "
1549 "%d", (long long)newadp->ad_oldblkno,
1550 (long long)oldadp->ad_newblkno, (long long)newadp->ad_lbn,
1551 NDADDR12);
1552 }
1553 newadp->ad_oldblkno = oldadp->ad_oldblkno;
1554 newadp->ad_oldsize = oldadp->ad_oldsize;
1555 /*
1556 * If the old dependency had a fragment to free or had never
1557 * previously had a block allocated, then the new dependency
1558 * can immediately post its freefrag and adopt the old freefrag.
1559 * This action is done by swapping the freefrag dependencies.
1560 * The new dependency gains the old one's freefrag, and the
1561 * old one gets the new one and then immediately puts it on
1562 * the worklist when it is freed by free_allocdirect. It is
1563 * not possible to do this swap when the old dependency had a
1564 * non-zero size but no previous fragment to free. This condition
1565 * arises when the new block is an extension of the old block.
1566 * Here, the first part of the fragment allocated to the new
1567 * dependency is part of the block currently claimed on disk by
1568 * the old dependency, so cannot legitimately be freed until the
1569 * conditions for the new dependency are fulfilled.
1570 */
1571 if (oldadp->ad_freefrag != NULL((void *)0) || oldadp->ad_oldblkno == 0) {
1572 freefrag = newadp->ad_freefrag;
1573 newadp->ad_freefrag = oldadp->ad_freefrag;
1574 oldadp->ad_freefrag = freefrag;
1575 }
1576 /*
1577 * If we are tracking a new directory-block allocation,
1578 * move it from the old allocdirect to the new allocdirect.
1579 */
1580 if ((wk = LIST_FIRST(&oldadp->ad_newdirblk)((&oldadp->ad_newdirblk)->lh_first)) != NULL((void *)0)) {
1581 newdirblk = WK_NEWDIRBLK(wk)((struct newdirblk *)(wk));
1582 WORKLIST_REMOVE(&newdirblk->db_list)do { (&newdirblk->db_list)->wk_state &= ~0x8000
; do { if ((&newdirblk->db_list)->wk_list.le_next !=
((void *)0)) (&newdirblk->db_list)->wk_list.le_next
->wk_list.le_prev = (&newdirblk->db_list)->wk_list
.le_prev; *(&newdirblk->db_list)->wk_list.le_prev =
(&newdirblk->db_list)->wk_list.le_next; ((&newdirblk
->db_list)->wk_list.le_prev) = ((void *)-1); ((&newdirblk
->db_list)->wk_list.le_next) = ((void *)-1); } while (0
); } while (0)
;
1583 if (LIST_FIRST(&oldadp->ad_newdirblk)((&oldadp->ad_newdirblk)->lh_first) != NULL((void *)0))
1584 panic("allocdirect_merge: extra newdirblk");
1585 WORKLIST_INSERT(&newadp->ad_newdirblk, &newdirblk->db_list)do { (&newdirblk->db_list)->wk_state |= 0x8000; do {
if (((&newdirblk->db_list)->wk_list.le_next = (&
newadp->ad_newdirblk)->lh_first) != ((void *)0)) (&
newadp->ad_newdirblk)->lh_first->wk_list.le_prev = &
(&newdirblk->db_list)->wk_list.le_next; (&newadp
->ad_newdirblk)->lh_first = (&newdirblk->db_list
); (&newdirblk->db_list)->wk_list.le_prev = &(&
newadp->ad_newdirblk)->lh_first; } while (0); } while (
0)
;
1586 }
1587 free_allocdirect(adphead, oldadp, 0);
1588}
1589
1590/*
1591 * Allocate a new freefrag structure if needed.
1592 */
1593STATIC struct freefrag *
1594newfreefrag(struct inode *ip, daddr_t blkno, long size)
1595{
1596 struct freefrag *freefrag;
1597 struct fs *fs;
1598
1599 if (blkno == 0)
1600 return (NULL((void *)0));
1601 fs = ip->i_fsinode_u.fs;
1602 if (fragnum(fs, blkno)((blkno) & ((fs)->fs_frag - 1)) + numfrags(fs, size)((size) >> (fs)->fs_fshift) > fs->fs_frag)
1603 panic("newfreefrag: frag size");
1604 freefrag = pool_get(&freefrag_pool, PR_WAITOK0x0001);
1605 freefrag->ff_list.wk_type = D_FREEFRAG7;
1606 freefrag->ff_stateff_list.wk_state = DIP(ip, uid)(((ip)->i_ump->um_fstype == 1) ? (ip)->dinode_u.ffs1_din
->di_uid : (ip)->dinode_u.ffs2_din->di_uid)
& ~ONWORKLIST0x8000; /* used below */
1607 freefrag->ff_inum = ip->i_number;
1608 freefrag->ff_mnt = ITOV(ip)((ip)->i_vnode)->v_mount;
1609 freefrag->ff_devvp = ip->i_devvpi_ump->um_devvp;
1610 freefrag->ff_blkno = blkno;
1611 freefrag->ff_fragsize = size;
1612 return (freefrag);
1613}
1614
1615/*
1616 * This workitem de-allocates fragments that were replaced during
1617 * file block allocation.
1618 */
1619STATIC void
1620handle_workitem_freefrag(struct freefrag *freefrag)
1621{
1622 struct inode tip;
1623 struct ufs1_dinode dtip1;
1624
1625 tip.i_vnode = NULL((void *)0);
1626 tip.i_din1dinode_u.ffs1_din = &dtip1;
1627 tip.i_fsinode_u.fs = VFSTOUFS(freefrag->ff_mnt)((struct ufsmount *)((freefrag->ff_mnt)->mnt_data))->um_fsufsmount_u.fs;
1628 tip.i_ump = VFSTOUFS(freefrag->ff_mnt)((struct ufsmount *)((freefrag->ff_mnt)->mnt_data));
1629 tip.i_dev = freefrag->ff_devvp->v_rdevv_un.vu_specinfo->si_rdev;
1630 tip.i_number = freefrag->ff_inum;
1631 tip.i_ffs1_uiddinode_u.ffs1_din->di_uid = freefrag->ff_stateff_list.wk_state & ~ONWORKLIST0x8000; /* set above */
1632 ffs_blkfree(&tip, freefrag->ff_blkno, freefrag->ff_fragsize);
1633 pool_put(&freefrag_pool, freefrag);
1634}
1635
1636/*
1637 * Indirect block allocation dependencies.
1638 *
1639 * The same dependencies that exist for a direct block also exist when
1640 * a new block is allocated and pointed to by an entry in a block of
1641 * indirect pointers. The undo/redo states described above are also
1642 * used here. Because an indirect block contains many pointers that
1643 * may have dependencies, a second copy of the entire in-memory indirect
1644 * block is kept. The buffer cache copy is always completely up-to-date.
1645 * The second copy, which is used only as a source for disk writes,
1646 * contains only the safe pointers (i.e., those that have no remaining
1647 * update dependencies). The second copy is freed when all pointers
1648 * are safe. The cache is not allowed to replace indirect blocks with
1649 * pending update dependencies. If a buffer containing an indirect
1650 * block with dependencies is written, these routines will mark it
1651 * dirty again. It can only be successfully written once all the
1652 * dependencies are removed. The ffs_fsync routine in conjunction with
1653 * softdep_sync_metadata work together to get all the dependencies
1654 * removed so that a file can be successfully written to disk. Three
1655 * procedures are used when setting up indirect block pointer
1656 * dependencies. The division is necessary because of the organization
1657 * of the "balloc" routine and because of the distinction between file
1658 * pages and file metadata blocks.
1659 */
1660
1661/*
1662 * Allocate a new allocindir structure.
1663 */
1664/* inode for file being extended */
1665/* offset of pointer in indirect block */
1666/* disk block number being added */
1667/* previous block number, 0 if none */
1668STATIC struct allocindir *
1669newallocindir(struct inode *ip, int ptrno, daddr_t newblkno,
1670 daddr_t oldblkno)
1671{
1672 struct allocindir *aip;
1673
1674 aip = pool_get(&allocindir_pool, PR_WAITOK0x0001 | PR_ZERO0x0008);
1675 aip->ai_list.wk_type = D_ALLOCINDIR6;
1676 aip->ai_stateai_list.wk_state = ATTACHED0x0001;
1677 aip->ai_offset = ptrno;
1678 aip->ai_newblkno = newblkno;
1679 aip->ai_oldblkno = oldblkno;
1680 aip->ai_freefrag = newfreefrag(ip, oldblkno, ip->i_fsinode_u.fs->fs_bsize);
1681 return (aip);
1682}
1683
1684/*
1685 * Called just before setting an indirect block pointer
1686 * to a newly allocated file page.
1687 */
1688/* inode for file being extended */
1689/* allocated block number within file */
1690/* buffer with indirect blk referencing page */
1691/* offset of pointer in indirect block */
1692/* disk block number being added */
1693/* previous block number, 0 if none */
1694/* buffer holding allocated page */
1695void
1696softdep_setup_allocindir_page(struct inode *ip, daddr_t lbn, struct buf *bp,
1697 int ptrno, daddr_t newblkno, daddr_t oldblkno, struct buf *nbp)
1698{
1699 struct allocindir *aip;
1700 struct pagedep *pagedep;
1701
1702 aip = newallocindir(ip, ptrno, newblkno, oldblkno);
1703 ACQUIRE_LOCK(&lk)(&lk)->lkt_spl = splraise(0x6);
1704 /*
1705 * If we are allocating a directory page, then we must
1706 * allocate an associated pagedep to track additions and
1707 * deletions.
1708 */
1709 if ((DIP(ip, mode)(((ip)->i_ump->um_fstype == 1) ? (ip)->dinode_u.ffs1_din
->di_mode : (ip)->dinode_u.ffs2_din->di_mode)
& IFMT0170000) == IFDIR0040000 &&
1710 pagedep_lookup(ip, lbn, DEPALLOC0x0001, &pagedep) == 0)
1711 WORKLIST_INSERT(&nbp->b_dep, &pagedep->pd_list)do { (&pagedep->pd_list)->wk_state |= 0x8000; do { if
(((&pagedep->pd_list)->wk_list.le_next = (&nbp
->b_dep)->lh_first) != ((void *)0)) (&nbp->b_dep
)->lh_first->wk_list.le_prev = &(&pagedep->pd_list
)->wk_list.le_next; (&nbp->b_dep)->lh_first = (&
pagedep->pd_list); (&pagedep->pd_list)->wk_list.
le_prev = &(&nbp->b_dep)->lh_first; } while (0)
; } while (0)
;
1712 if (nbp == NULL((void *)0)) {
1713 /*
1714 * XXXUBC - Yes, I know how to fix this, but not right now.
1715 */
1716 panic("softdep_setup_allocindir_page: Bonk art in the head");
1717 }
1718 WORKLIST_INSERT(&nbp->b_dep, &aip->ai_list)do { (&aip->ai_list)->wk_state |= 0x8000; do { if (
((&aip->ai_list)->wk_list.le_next = (&nbp->b_dep
)->lh_first) != ((void *)0)) (&nbp->b_dep)->lh_first
->wk_list.le_prev = &(&aip->ai_list)->wk_list
.le_next; (&nbp->b_dep)->lh_first = (&aip->ai_list
); (&aip->ai_list)->wk_list.le_prev = &(&nbp
->b_dep)->lh_first; } while (0); } while (0)
;
1719 FREE_LOCK(&lk)spllower((&lk)->lkt_spl);
1720 setup_allocindir_phase2(bp, ip, aip);
1721}
1722
1723/*
1724 * Called just before setting an indirect block pointer to a
1725 * newly allocated indirect block.
1726 */
1727/* newly allocated indirect block */
1728/* inode for file being extended */
1729/* indirect block referencing allocated block */
1730/* offset of pointer in indirect block */
1731/* disk block number being added */
1732void
1733softdep_setup_allocindir_meta(struct buf *nbp, struct inode *ip,
1734 struct buf *bp, int ptrno, daddr_t newblkno)
1735{
1736 struct allocindir *aip;
1737
1738 aip = newallocindir(ip, ptrno, newblkno, 0);
1739 ACQUIRE_LOCK(&lk)(&lk)->lkt_spl = splraise(0x6);
1740 WORKLIST_INSERT(&nbp->b_dep, &aip->ai_list)do { (&aip->ai_list)->wk_state |= 0x8000; do { if (
((&aip->ai_list)->wk_list.le_next = (&nbp->b_dep
)->lh_first) != ((void *)0)) (&nbp->b_dep)->lh_first
->wk_list.le_prev = &(&aip->ai_list)->wk_list
.le_next; (&nbp->b_dep)->lh_first = (&aip->ai_list
); (&aip->ai_list)->wk_list.le_prev = &(&nbp
->b_dep)->lh_first; } while (0); } while (0)
;
1741 FREE_LOCK(&lk)spllower((&lk)->lkt_spl);
1742 setup_allocindir_phase2(bp, ip, aip);
1743}
1744
1745/*
1746 * Called to finish the allocation of the "aip" allocated
1747 * by one of the two routines above.
1748 */
1749/* in-memory copy of the indirect block */
1750/* inode for file being extended */
1751/* allocindir allocated by the above routines */
1752STATIC void
1753setup_allocindir_phase2(struct buf *bp, struct inode *ip,
1754 struct allocindir *aip)
1755{
1756 struct worklist *wk;
1757 struct indirdep *indirdep, *newindirdep;
1758 struct bmsafemap *bmsafemap;
1759 struct allocindir *oldaip;
1760 struct freefrag *freefrag;
1761 struct newblk *newblk;
1762
1763 if (bp->b_lblkno >= 0)
1764 panic("setup_allocindir_phase2: not indir blk");
1765 for (indirdep = NULL((void *)0), newindirdep = NULL((void *)0); ; ) {
1766 ACQUIRE_LOCK(&lk)(&lk)->lkt_spl = splraise(0x6);
1767 LIST_FOREACH(wk, &bp->b_dep, wk_list)for((wk) = ((&bp->b_dep)->lh_first); (wk)!= ((void *
)0); (wk) = ((wk)->wk_list.le_next))
{
1768 if (wk->wk_type != D_INDIRDEP5)
1769 continue;
1770 indirdep = WK_INDIRDEP(wk)((struct indirdep *)(wk));
1771 break;
1772 }
1773 if (indirdep == NULL((void *)0) && newindirdep) {
1774 indirdep = newindirdep;
1775 WORKLIST_INSERT(&bp->b_dep, &indirdep->ir_list)do { (&indirdep->ir_list)->wk_state |= 0x8000; do {
if (((&indirdep->ir_list)->wk_list.le_next = (&
bp->b_dep)->lh_first) != ((void *)0)) (&bp->b_dep
)->lh_first->wk_list.le_prev = &(&indirdep->
ir_list)->wk_list.le_next; (&bp->b_dep)->lh_first
= (&indirdep->ir_list); (&indirdep->ir_list)->
wk_list.le_prev = &(&bp->b_dep)->lh_first; } while
(0); } while (0)
;
1776 newindirdep = NULL((void *)0);
1777 }
1778 FREE_LOCK(&lk)spllower((&lk)->lkt_spl);
1779 if (indirdep) {
1780 if (newblk_lookup(ip->i_fsinode_u.fs, aip->ai_newblkno, 0,
1781 &newblk) == 0)
1782 panic("setup_allocindir: lost block");
1783 ACQUIRE_LOCK(&lk)(&lk)->lkt_spl = splraise(0x6);
1784 if (newblk->nb_state == DEPCOMPLETE0x0008) {
1785 aip->ai_stateai_list.wk_state |= DEPCOMPLETE0x0008;
1786 aip->ai_buf = NULL((void *)0);
1787 } else {
1788 bmsafemap = newblk->nb_bmsafemap;
1789 aip->ai_buf = bmsafemap->sm_buf;
1790 LIST_REMOVE(newblk, nb_deps)do { if ((newblk)->nb_deps.le_next != ((void *)0)) (newblk
)->nb_deps.le_next->nb_deps.le_prev = (newblk)->nb_deps
.le_prev; *(newblk)->nb_deps.le_prev = (newblk)->nb_deps
.le_next; ((newblk)->nb_deps.le_prev) = ((void *)-1); ((newblk
)->nb_deps.le_next) = ((void *)-1); } while (0)
;
1791 LIST_INSERT_HEAD(&bmsafemap->sm_allocindirhd,do { if (((aip)->ai_deps.le_next = (&bmsafemap->sm_allocindirhd
)->lh_first) != ((void *)0)) (&bmsafemap->sm_allocindirhd
)->lh_first->ai_deps.le_prev = &(aip)->ai_deps.le_next
; (&bmsafemap->sm_allocindirhd)->lh_first = (aip); (
aip)->ai_deps.le_prev = &(&bmsafemap->sm_allocindirhd
)->lh_first; } while (0)
1792 aip, ai_deps)do { if (((aip)->ai_deps.le_next = (&bmsafemap->sm_allocindirhd
)->lh_first) != ((void *)0)) (&bmsafemap->sm_allocindirhd
)->lh_first->ai_deps.le_prev = &(aip)->ai_deps.le_next
; (&bmsafemap->sm_allocindirhd)->lh_first = (aip); (
aip)->ai_deps.le_prev = &(&bmsafemap->sm_allocindirhd
)->lh_first; } while (0)
;
1793 }
1794 LIST_REMOVE(newblk, nb_hash)do { if ((newblk)->nb_hash.le_next != ((void *)0)) (newblk
)->nb_hash.le_next->nb_hash.le_prev = (newblk)->nb_hash
.le_prev; *(newblk)->nb_hash.le_prev = (newblk)->nb_hash
.le_next; ((newblk)->nb_hash.le_prev) = ((void *)-1); ((newblk
)->nb_hash.le_next) = ((void *)-1); } while (0)
;
1795 pool_put(&newblk_pool, newblk);
1796 aip->ai_indirdep = indirdep;
1797 /*
1798 * Check to see if there is an existing dependency
1799 * for this block. If there is, merge the old
1800 * dependency into the new one.
1801 */
1802 if (aip->ai_oldblkno == 0)
1803 oldaip = NULL((void *)0);
1804 else
1805
1806 LIST_FOREACH(oldaip, &indirdep->ir_deplisthd, ai_next)for((oldaip) = ((&indirdep->ir_deplisthd)->lh_first
); (oldaip)!= ((void *)0); (oldaip) = ((oldaip)->ai_next.le_next
))
1807 if (oldaip->ai_offset == aip->ai_offset)
1808 break;
1809 freefrag = NULL((void *)0);
1810 if (oldaip != NULL((void *)0)) {
1811 if (oldaip->ai_newblkno != aip->ai_oldblkno) {
1812 FREE_LOCK(&lk)spllower((&lk)->lkt_spl);
1813 panic("setup_allocindir_phase2: blkno");
1814 }
1815 aip->ai_oldblkno = oldaip->ai_oldblkno;
1816 freefrag = aip->ai_freefrag;
1817 aip->ai_freefrag = oldaip->ai_freefrag;
1818 oldaip->ai_freefrag = NULL((void *)0);
1819 free_allocindir(oldaip, NULL((void *)0));
1820 }
1821 LIST_INSERT_HEAD(&indirdep->ir_deplisthd, aip, ai_next)do { if (((aip)->ai_next.le_next = (&indirdep->ir_deplisthd
)->lh_first) != ((void *)0)) (&indirdep->ir_deplisthd
)->lh_first->ai_next.le_prev = &(aip)->ai_next.le_next
; (&indirdep->ir_deplisthd)->lh_first = (aip); (aip
)->ai_next.le_prev = &(&indirdep->ir_deplisthd)
->lh_first; } while (0)
;
1822 if (ip->i_ump->um_fstype == UM_UFS11)
1823 ((int32_t *)indirdep->ir_savebp->b_data)
1824 [aip->ai_offset] = aip->ai_oldblkno;
1825 else
1826 ((int64_t *)indirdep->ir_savebp->b_data)
1827 [aip->ai_offset] = aip->ai_oldblkno;
1828 FREE_LOCK(&lk)spllower((&lk)->lkt_spl);
1829 if (freefrag != NULL((void *)0))
1830 handle_workitem_freefrag(freefrag);
1831 }
1832 if (newindirdep) {
1833 if (indirdep->ir_savebp != NULL((void *)0))
1834 brelse(newindirdep->ir_savebp);
1835 WORKITEM_FREE(newindirdep, D_INDIRDEP)softdep_freequeue_add((struct worklist *)newindirdep);
1836 }
1837 if (indirdep)
1838 break;
1839 newindirdep = pool_get(&indirdep_pool, PR_WAITOK0x0001);
1840 newindirdep->ir_list.wk_type = D_INDIRDEP5;
1841 newindirdep->ir_stateir_list.wk_state = ATTACHED0x0001;
1842 if (ip->i_ump->um_fstype == UM_UFS11)
1843 newindirdep->ir_stateir_list.wk_state |= UFS1FMT0x2000;
1844 LIST_INIT(&newindirdep->ir_deplisthd)do { ((&newindirdep->ir_deplisthd)->lh_first) = ((void
*)0); } while (0)
;
1845 LIST_INIT(&newindirdep->ir_donehd)do { ((&newindirdep->ir_donehd)->lh_first) = ((void
*)0); } while (0)
;
1846 if (bp->b_blkno == bp->b_lblkno) {
1847 VOP_BMAP(bp->b_vp, bp->b_lblkno, NULL((void *)0), &bp->b_blkno,
1848 NULL((void *)0));
1849 }
1850 newindirdep->ir_savebp =
1851 getblk(ip->i_devvpi_ump->um_devvp, bp->b_blkno, bp->b_bcount, 0, INFSLP0xffffffffffffffffULL);
1852#if 0
1853 BUF_KERNPROC(newindirdep->ir_savebp);
1854#endif
1855 memcpy(newindirdep->ir_savebp->b_data, bp->b_data, bp->b_bcount)__builtin_memcpy((newindirdep->ir_savebp->b_data), (bp->
b_data), (bp->b_bcount))
;
1856 }
1857}
1858
1859/*
1860 * Block de-allocation dependencies.
1861 *
1862 * When blocks are de-allocated, the on-disk pointers must be nullified before
1863 * the blocks are made available for use by other files. (The true
1864 * requirement is that old pointers must be nullified before new on-disk
1865 * pointers are set. We chose this slightly more stringent requirement to
1866 * reduce complexity.) Our implementation handles this dependency by updating
1867 * the inode (or indirect block) appropriately but delaying the actual block
1868 * de-allocation (i.e., freemap and free space count manipulation) until
1869 * after the updated versions reach stable storage. After the disk is
1870 * updated, the blocks can be safely de-allocated whenever it is convenient.
1871 * This implementation handles only the common case of reducing a file's
1872 * length to zero. Other cases are handled by the conventional synchronous
1873 * write approach.
1874 *
1875 * The ffs implementation with which we worked double-checks
1876 * the state of the block pointers and file size as it reduces
1877 * a file's length. Some of this code is replicated here in our
1878 * soft updates implementation. The freeblks->fb_chkcnt field is
1879 * used to transfer a part of this information to the procedure
1880 * that eventually de-allocates the blocks.
1881 *
1882 * This routine should be called from the routine that shortens
1883 * a file's length, before the inode's size or block pointers
1884 * are modified. It will save the block pointer information for
1885 * later release and zero the inode so that the calling routine
1886 * can release it.
1887 */
1888/* The inode whose length is to be reduced */
1889/* The new length for the file */
1890void
1891softdep_setup_freeblocks(struct inode *ip, off_t length)
1892{
1893 struct freeblks *freeblks;
1894 struct inodedep *inodedep;
1895 struct allocdirect *adp;
1896 struct vnode *vp;
1897 struct buf *bp;
1898 struct fs *fs;
1899 int i, delay, error;
1900
1901 fs = ip->i_fsinode_u.fs;
1902 if (length != 0)
1903 panic("softdep_setup_freeblocks: non-zero length");
1904 freeblks = pool_get(&freeblks_pool, PR_WAITOK0x0001 | PR_ZERO0x0008);
1905 freeblks->fb_list.wk_type = D_FREEBLKS8;
1906 freeblks->fb_statefb_list.wk_state = ATTACHED0x0001;
1907 freeblks->fb_uid = DIP(ip, uid)(((ip)->i_ump->um_fstype == 1) ? (ip)->dinode_u.ffs1_din
->di_uid : (ip)->dinode_u.ffs2_din->di_uid)
;
1908 freeblks->fb_previousinum = ip->i_number;
1909 freeblks->fb_devvp = ip->i_devvpi_ump->um_devvp;
1910 freeblks->fb_mnt = ITOV(ip)((ip)->i_vnode)->v_mount;
1911 freeblks->fb_oldsize = DIP(ip, size)(((ip)->i_ump->um_fstype == 1) ? (ip)->dinode_u.ffs1_din
->di_size : (ip)->dinode_u.ffs2_din->di_size)
;
1912 freeblks->fb_newsize = length;
1913 freeblks->fb_chkcnt = DIP(ip, blocks)(((ip)->i_ump->um_fstype == 1) ? (ip)->dinode_u.ffs1_din
->di_blocks : (ip)->dinode_u.ffs2_din->di_blocks)
;
1914
1915 for (i = 0; i < NDADDR12; i++) {
1916 freeblks->fb_dblks[i] = DIP(ip, db[i])(((ip)->i_ump->um_fstype == 1) ? (ip)->dinode_u.ffs1_din
->di_db[i] : (ip)->dinode_u.ffs2_din->di_db[i])
;
1917 DIP_ASSIGN(ip, db[i], 0)do { if ((ip)->i_ump->um_fstype == 1) (ip)->dinode_u
.ffs1_din->di_db[i] = (0); else (ip)->dinode_u.ffs2_din
->di_db[i] = (0); } while (0)
;
1918 }
1919
1920 for (i = 0; i < NIADDR3; i++) {
1921 freeblks->fb_iblks[i] = DIP(ip, ib[i])(((ip)->i_ump->um_fstype == 1) ? (ip)->dinode_u.ffs1_din
->di_ib[i] : (ip)->dinode_u.ffs2_din->di_ib[i])
;
1922 DIP_ASSIGN(ip, ib[i], 0)do { if ((ip)->i_ump->um_fstype == 1) (ip)->dinode_u
.ffs1_din->di_ib[i] = (0); else (ip)->dinode_u.ffs2_din
->di_ib[i] = (0); } while (0)
;
1923 }
1924
1925 DIP_ASSIGN(ip, blocks, 0)do { if ((ip)->i_ump->um_fstype == 1) (ip)->dinode_u
.ffs1_din->di_blocks = (0); else (ip)->dinode_u.ffs2_din
->di_blocks = (0); } while (0)
;
1926 DIP_ASSIGN(ip, size, 0)do { if ((ip)->i_ump->um_fstype == 1) (ip)->dinode_u
.ffs1_din->di_size = (0); else (ip)->dinode_u.ffs2_din->
di_size = (0); } while (0)
;
1927
1928 /*
1929 * Push the zero'ed inode to to its disk buffer so that we are free
1930 * to delete its dependencies below. Once the dependencies are gone
1931 * the buffer can be safely released.
1932 */
1933 if ((error = bread(ip->i_devvpi_ump->um_devvp,
1934 fsbtodb(fs, ino_to_fsba(fs, ip->i_number))((((daddr_t)(((((daddr_t)(fs)->fs_fpg * (((ip->i_number
) / (fs)->fs_ipg))) + (fs)->fs_cgoffset * ((((ip->i_number
) / (fs)->fs_ipg)) & ~((fs)->fs_cgmask))) + (fs)->
fs_iblkno) + ((((((ip->i_number) % (fs)->fs_ipg) / ((fs
)->fs_inopb))) << ((fs))->fs_fragshift))))) <<
(fs)->fs_fsbtodb)
,
1935 (int)fs->fs_bsize, &bp)) != 0)
1936 softdep_error("softdep_setup_freeblocks", error);
1937
1938 if (ip->i_ump->um_fstype == UM_UFS11)
1939 *((struct ufs1_dinode *) bp->b_data +
1940 ino_to_fsbo(fs, ip->i_number)((ip->i_number) % ((fs)->fs_inopb))) = *ip->i_din1dinode_u.ffs1_din;
1941 else
1942 *((struct ufs2_dinode *) bp->b_data +
1943 ino_to_fsbo(fs, ip->i_number)((ip->i_number) % ((fs)->fs_inopb))) = *ip->i_din2dinode_u.ffs2_din;
1944
1945 /*
1946 * Find and eliminate any inode dependencies.
1947 */
1948 ACQUIRE_LOCK(&lk)(&lk)->lkt_spl = splraise(0x6);
1949 (void) inodedep_lookup(fs, ip->i_number, DEPALLOC0x0001, &inodedep);
1950 if ((inodedep->id_stateid_list.wk_state & IOSTARTED0x0200) != 0) {
1951 FREE_LOCK(&lk)spllower((&lk)->lkt_spl);
1952 panic("softdep_setup_freeblocks: inode busy");
1953 }
1954 /*
1955 * Add the freeblks structure to the list of operations that
1956 * must await the zero'ed inode being written to disk. If we
1957 * still have a bitmap dependency (delay == 0), then the inode
1958 * has never been written to disk, so we can process the
1959 * freeblks below once we have deleted the dependencies.
1960 */
1961 delay = (inodedep->id_stateid_list.wk_state & DEPCOMPLETE0x0008);
1962 if (delay)
1963 WORKLIST_INSERT(&inodedep->id_bufwait, &freeblks->fb_list)do { (&freeblks->fb_list)->wk_state |= 0x8000; do {
if (((&freeblks->fb_list)->wk_list.le_next = (&
inodedep->id_bufwait)->lh_first) != ((void *)0)) (&
inodedep->id_bufwait)->lh_first->wk_list.le_prev = &
(&freeblks->fb_list)->wk_list.le_next; (&inodedep
->id_bufwait)->lh_first = (&freeblks->fb_list); (
&freeblks->fb_list)->wk_list.le_prev = &(&inodedep
->id_bufwait)->lh_first; } while (0); } while (0)
;
1964 /*
1965 * Because the file length has been truncated to zero, any
1966 * pending block allocation dependency structures associated
1967 * with this inode are obsolete and can simply be de-allocated.
1968 * We must first merge the two dependency lists to get rid of
1969 * any duplicate freefrag structures, then purge the merged list.
1970 * If we still have a bitmap dependency, then the inode has never
1971 * been written to disk, so we can free any fragments without delay.
1972 */
1973 merge_inode_lists(inodedep);
1974 while ((adp = TAILQ_FIRST(&inodedep->id_inoupdt)((&inodedep->id_inoupdt)->tqh_first)) != NULL((void *)0))
1975 free_allocdirect(&inodedep->id_inoupdt, adp, delay);
1976 FREE_LOCK(&lk)spllower((&lk)->lkt_spl);
1977 bdwrite(bp);
1978 /*
1979 * We must wait for any I/O in progress to finish so that
1980 * all potential buffers on the dirty list will be visible.
1981 * Once they are all there, walk the list and get rid of
1982 * any dependencies.
1983 */
1984 vp = ITOV(ip)((ip)->i_vnode);
1985 ACQUIRE_LOCK(&lk)(&lk)->lkt_spl = splraise(0x6);
1986 drain_output(vp, 1);
1987 while ((bp = LIST_FIRST(&vp->v_dirtyblkhd)((&vp->v_dirtyblkhd)->lh_first))) {
1988 if (getdirtybuf(bp, MNT_WAIT1) <= 0)
1989 break;
1990 (void) inodedep_lookup(fs, ip->i_number, 0, &inodedep);
1991 deallocate_dependencies(bp, inodedep);
1992 bp->b_flags |= B_INVAL0x00000800 | B_NOCACHE0x00001000;
1993 FREE_LOCK(&lk)spllower((&lk)->lkt_spl);
1994 brelse(bp);
1995 ACQUIRE_LOCK(&lk)(&lk)->lkt_spl = splraise(0x6);
1996 }
1997 if (inodedep_lookup(fs, ip->i_number, 0, &inodedep) != 0)
1998 (void) free_inodedep(inodedep);
1999
2000 if (delay) {
2001 freeblks->fb_statefb_list.wk_state |= DEPCOMPLETE0x0008;
2002 /*
2003 * If the inode with zeroed block pointers is now on disk we
2004 * can start freeing blocks. Add freeblks to the worklist
2005 * instead of calling handle_workitem_freeblocks() directly as
2006 * it is more likely that additional IO is needed to complete
2007 * the request than in the !delay case.
2008 */
2009 if ((freeblks->fb_statefb_list.wk_state & ALLCOMPLETE(0x0001 | 0x0004 | 0x0008)) == ALLCOMPLETE(0x0001 | 0x0004 | 0x0008))
2010 add_to_worklist(&freeblks->fb_list);
2011 }
2012
2013 FREE_LOCK(&lk)spllower((&lk)->lkt_spl);
2014 /*
2015 * If the inode has never been written to disk (delay == 0),
2016 * then we can process the freeblks now that we have deleted
2017 * the dependencies.
2018 */
2019 if (!delay)
2020 handle_workitem_freeblocks(freeblks);
2021}
2022
2023/*
2024 * Reclaim any dependency structures from a buffer that is about to
2025 * be reallocated to a new vnode. The buffer must be locked, thus,
2026 * no I/O completion operations can occur while we are manipulating
2027 * its associated dependencies. The mutex is held so that other I/O's
2028 * associated with related dependencies do not occur.
2029 */
2030STATIC void
2031deallocate_dependencies(struct buf *bp, struct inodedep *inodedep)
2032{
2033 struct worklist *wk;
2034 struct indirdep *indirdep;
2035 struct allocindir *aip;
2036 struct pagedep *pagedep;
2037 struct dirrem *dirrem;
2038 struct diradd *dap;
2039 int i;
2040
2041 while ((wk = LIST_FIRST(&bp->b_dep)((&bp->b_dep)->lh_first)) != NULL((void *)0)) {
2042 switch (wk->wk_type) {
2043
2044 case D_INDIRDEP5:
2045 indirdep = WK_INDIRDEP(wk)((struct indirdep *)(wk));
2046 /*
2047 * None of the indirect pointers will ever be visible,
2048 * so they can simply be tossed. GOINGAWAY ensures
2049 * that allocated pointers will be saved in the buffer
2050 * cache until they are freed. Note that they will
2051 * only be able to be found by their physical address
2052 * since the inode mapping the logical address will
2053 * be gone. The save buffer used for the safe copy
2054 * was allocated in setup_allocindir_phase2 using
2055 * the physical address so it could be used for this
2056 * purpose. Hence we swap the safe copy with the real
2057 * copy, allowing the safe copy to be freed and holding
2058 * on to the real copy for later use in indir_trunc.
2059 */
2060 if (indirdep->ir_stateir_list.wk_state & GOINGAWAY0x0100) {
2061 FREE_LOCK(&lk)spllower((&lk)->lkt_spl);
2062 panic("deallocate_dependencies: already gone");
2063 }
2064 indirdep->ir_stateir_list.wk_state |= GOINGAWAY0x0100;
2065 while ((aip = LIST_FIRST(&indirdep->ir_deplisthd)((&indirdep->ir_deplisthd)->lh_first)))
2066 free_allocindir(aip, inodedep);
2067 if (bp->b_lblkno >= 0 ||
2068 bp->b_blkno != indirdep->ir_savebp->b_lblkno) {
2069 FREE_LOCK(&lk)spllower((&lk)->lkt_spl);
2070 panic("deallocate_dependencies: not indir");
2071 }
2072 memcpy(indirdep->ir_savebp->b_data, bp->b_data,__builtin_memcpy((indirdep->ir_savebp->b_data), (bp->
b_data), (bp->b_bcount))
2073 bp->b_bcount)__builtin_memcpy((indirdep->ir_savebp->b_data), (bp->
b_data), (bp->b_bcount))
;
2074 WORKLIST_REMOVE(wk)do { (wk)->wk_state &= ~0x8000; do { if ((wk)->wk_list
.le_next != ((void *)0)) (wk)->wk_list.le_next->wk_list
.le_prev = (wk)->wk_list.le_prev; *(wk)->wk_list.le_prev
= (wk)->wk_list.le_next; ((wk)->wk_list.le_prev) = ((void
*)-1); ((wk)->wk_list.le_next) = ((void *)-1); } while (0
); } while (0)
;
2075 WORKLIST_INSERT(&indirdep->ir_savebp->b_dep, wk)do { (wk)->wk_state |= 0x8000; do { if (((wk)->wk_list.
le_next = (&indirdep->ir_savebp->b_dep)->lh_first
) != ((void *)0)) (&indirdep->ir_savebp->b_dep)->
lh_first->wk_list.le_prev = &(wk)->wk_list.le_next;
(&indirdep->ir_savebp->b_dep)->lh_first = (wk);
(wk)->wk_list.le_prev = &(&indirdep->ir_savebp
->b_dep)->lh_first; } while (0); } while (0)
;
2076 continue;
2077
2078 case D_PAGEDEP0:
2079 pagedep = WK_PAGEDEP(wk)((struct pagedep *)(wk));
2080 /*
2081 * None of the directory additions will ever be
2082 * visible, so they can simply be tossed.
2083 */
2084 for (i = 0; i < DAHASHSZ6; i++)
2085 while ((dap =
2086 LIST_FIRST(&pagedep->pd_diraddhd[i])((&pagedep->pd_diraddhd[i])->lh_first)))
2087 free_diradd(dap);
2088 while ((dap = LIST_FIRST(&pagedep->pd_pendinghd)((&pagedep->pd_pendinghd)->lh_first)))
2089 free_diradd(dap);
2090 /*
2091 * Copy any directory remove dependencies to the list
2092 * to be processed after the zero'ed inode is written.
2093 * If the inode has already been written, then they
2094 * can be dumped directly onto the work list.
2095 */
2096 while ((dirrem = LIST_FIRST(&pagedep->pd_dirremhd)((&pagedep->pd_dirremhd)->lh_first))) {
2097 LIST_REMOVE(dirrem, dm_next)do { if ((dirrem)->dm_next.le_next != ((void *)0)) (dirrem
)->dm_next.le_next->dm_next.le_prev = (dirrem)->dm_next
.le_prev; *(dirrem)->dm_next.le_prev = (dirrem)->dm_next
.le_next; ((dirrem)->dm_next.le_prev) = ((void *)-1); ((dirrem
)->dm_next.le_next) = ((void *)-1); } while (0)
;
2098 dirrem->dm_dirinumdm_un.dmu_dirinum = pagedep->pd_ino;
2099 if (inodedep == NULL((void *)0) ||
2100 (inodedep->id_stateid_list.wk_state & ALLCOMPLETE(0x0001 | 0x0004 | 0x0008)) ==
2101 ALLCOMPLETE(0x0001 | 0x0004 | 0x0008))
2102 add_to_worklist(&dirrem->dm_list);
2103 else
2104 WORKLIST_INSERT(&inodedep->id_bufwait,do { (&dirrem->dm_list)->wk_state |= 0x8000; do { if
(((&dirrem->dm_list)->wk_list.le_next = (&inodedep
->id_bufwait)->lh_first) != ((void *)0)) (&inodedep
->id_bufwait)->lh_first->wk_list.le_prev = &(&
dirrem->dm_list)->wk_list.le_next; (&inodedep->id_bufwait
)->lh_first = (&dirrem->dm_list); (&dirrem->
dm_list)->wk_list.le_prev = &(&inodedep->id_bufwait
)->lh_first; } while (0); } while (0)
2105 &dirrem->dm_list)do { (&dirrem->dm_list)->wk_state |= 0x8000; do { if
(((&dirrem->dm_list)->wk_list.le_next = (&inodedep
->id_bufwait)->lh_first) != ((void *)0)) (&inodedep
->id_bufwait)->lh_first->wk_list.le_prev = &(&
dirrem->dm_list)->wk_list.le_next; (&inodedep->id_bufwait
)->lh_first = (&dirrem->dm_list); (&dirrem->
dm_list)->wk_list.le_prev = &(&inodedep->id_bufwait
)->lh_first; } while (0); } while (0)
;
2106 }
2107 if ((pagedep->pd_statepd_list.wk_state & NEWBLOCK0x0800) != 0) {
2108 LIST_FOREACH(wk, &inodedep->id_bufwait, wk_list)for((wk) = ((&inodedep->id_bufwait)->lh_first); (wk
)!= ((void *)0); (wk) = ((wk)->wk_list.le_next))
2109 if (wk->wk_type == D_NEWDIRBLK13 &&
2110 WK_NEWDIRBLK(wk)((struct newdirblk *)(wk))->db_pagedep ==
2111 pagedep)
2112 break;
2113 if (wk != NULL((void *)0)) {
2114 WORKLIST_REMOVE(wk)do { (wk)->wk_state &= ~0x8000; do { if ((wk)->wk_list
.le_next != ((void *)0)) (wk)->wk_list.le_next->wk_list
.le_prev = (wk)->wk_list.le_prev; *(wk)->wk_list.le_prev
= (wk)->wk_list.le_next; ((wk)->wk_list.le_prev) = ((void
*)-1); ((wk)->wk_list.le_next) = ((void *)-1); } while (0
); } while (0)
;
2115 free_newdirblk(WK_NEWDIRBLK(wk)((struct newdirblk *)(wk)));
2116 } else {
2117 FREE_LOCK(&lk)spllower((&lk)->lkt_spl);
2118 panic("deallocate_dependencies: "
2119 "lost pagedep");
2120 }
2121 }
2122 WORKLIST_REMOVE(&pagedep->pd_list)do { (&pagedep->pd_list)->wk_state &= ~0x8000; do
{ if ((&pagedep->pd_list)->wk_list.le_next != ((void
*)0)) (&pagedep->pd_list)->wk_list.le_next->wk_list
.le_prev = (&pagedep->pd_list)->wk_list.le_prev; *(
&pagedep->pd_list)->wk_list.le_prev = (&pagedep
->pd_list)->wk_list.le_next; ((&pagedep->pd_list
)->wk_list.le_prev) = ((void *)-1); ((&pagedep->pd_list
)->wk_list.le_next) = ((void *)-1); } while (0); } while (
0)
;
2123 LIST_REMOVE(pagedep, pd_hash)do { if ((pagedep)->pd_hash.le_next != ((void *)0)) (pagedep
)->pd_hash.le_next->pd_hash.le_prev = (pagedep)->pd_hash
.le_prev; *(pagedep)->pd_hash.le_prev = (pagedep)->pd_hash
.le_next; ((pagedep)->pd_hash.le_prev) = ((void *)-1); ((pagedep
)->pd_hash.le_next) = ((void *)-1); } while (0)
;
2124 WORKITEM_FREE(pagedep, D_PAGEDEP)softdep_freequeue_add((struct worklist *)pagedep);
2125 continue;
2126
2127 case D_ALLOCINDIR6:
2128 free_allocindir(WK_ALLOCINDIR(wk)((struct allocindir *)(wk)), inodedep);
2129 continue;
2130
2131 case D_ALLOCDIRECT4:
2132 case D_INODEDEP1:
2133 FREE_LOCK(&lk)spllower((&lk)->lkt_spl);
2134 panic("deallocate_dependencies: Unexpected type %s",
2135 TYPENAME(wk->wk_type)((unsigned)(wk->wk_type) <= 13 ? softdep_typenames[wk->
wk_type] : "???")
);
2136 /* NOTREACHED */
2137
2138 default:
2139 FREE_LOCK(&lk)spllower((&lk)->lkt_spl);
2140 panic("deallocate_dependencies: Unknown type %s",
2141 TYPENAME(wk->wk_type)((unsigned)(wk->wk_type) <= 13 ? softdep_typenames[wk->
wk_type] : "???")
);
2142 /* NOTREACHED */
2143 }
2144 }
2145}
2146
2147/*
2148 * Free an allocdirect. Generate a new freefrag work request if appropriate.
2149 * This routine must be called with splbio interrupts blocked.
2150 */
2151STATIC void
2152free_allocdirect(struct allocdirectlst *adphead, struct allocdirect *adp,
2153 int delay)
2154{
2155 struct newdirblk *newdirblk;
2156 struct worklist *wk;
2157
2158 splassert(IPL_BIO)do { if (splassert_ctl > 0) { splassert_check(0x6, __func__
); } } while (0)
;
2159
2160#ifdef DEBUG
2161 if (lk.lkt_held == -1)
2162 panic("free_allocdirect: lock not held");
2163#endif
2164 if ((adp->ad_statead_list.wk_state & DEPCOMPLETE0x0008) == 0)
2165 LIST_REMOVE(adp, ad_deps)do { if ((adp)->ad_deps.le_next != ((void *)0)) (adp)->
ad_deps.le_next->ad_deps.le_prev = (adp)->ad_deps.le_prev
; *(adp)->ad_deps.le_prev = (adp)->ad_deps.le_next; ((adp
)->ad_deps.le_prev) = ((void *)-1); ((adp)->ad_deps.le_next
) = ((void *)-1); } while (0)
;
2166 TAILQ_REMOVE(adphead, adp, ad_next)do { if (((adp)->ad_next.tqe_next) != ((void *)0)) (adp)->
ad_next.tqe_next->ad_next.tqe_prev = (adp)->ad_next.tqe_prev
; else (adphead)->tqh_last = (adp)->ad_next.tqe_prev; *
(adp)->ad_next.tqe_prev = (adp)->ad_next.tqe_next; ((adp
)->ad_next.tqe_prev) = ((void *)-1); ((adp)->ad_next.tqe_next
) = ((void *)-1); } while (0)
;
2167 if ((adp->ad_statead_list.wk_state & COMPLETE0x0004) == 0)
2168 WORKLIST_REMOVE(&adp->ad_list)do { (&adp->ad_list)->wk_state &= ~0x8000; do {
if ((&adp->ad_list)->wk_list.le_next != ((void *)0
)) (&adp->ad_list)->wk_list.le_next->wk_list.le_prev
= (&adp->ad_list)->wk_list.le_prev; *(&adp->
ad_list)->wk_list.le_prev = (&adp->ad_list)->wk_list
.le_next; ((&adp->ad_list)->wk_list.le_prev) = ((void
*)-1); ((&adp->ad_list)->wk_list.le_next) = ((void
*)-1); } while (0); } while (0)
;
2169 if (adp->ad_freefrag != NULL((void *)0)) {
2170 if (delay)
2171 WORKLIST_INSERT(&adp->ad_inodedep->id_bufwait,do { (&adp->ad_freefrag->ff_list)->wk_state |= 0x8000
; do { if (((&adp->ad_freefrag->ff_list)->wk_list
.le_next = (&adp->ad_inodedep->id_bufwait)->lh_first
) != ((void *)0)) (&adp->ad_inodedep->id_bufwait)->
lh_first->wk_list.le_prev = &(&adp->ad_freefrag
->ff_list)->wk_list.le_next; (&adp->ad_inodedep->
id_bufwait)->lh_first = (&adp->ad_freefrag->ff_list
); (&adp->ad_freefrag->ff_list)->wk_list.le_prev
= &(&adp->ad_inodedep->id_bufwait)->lh_first
; } while (0); } while (0)
2172 &adp->ad_freefrag->ff_list)do { (&adp->ad_freefrag->ff_list)->wk_state |= 0x8000
; do { if (((&adp->ad_freefrag->ff_list)->wk_list
.le_next = (&adp->ad_inodedep->id_bufwait)->lh_first
) != ((void *)0)) (&adp->ad_inodedep->id_bufwait)->
lh_first->wk_list.le_prev = &(&adp->ad_freefrag
->ff_list)->wk_list.le_next; (&adp->ad_inodedep->
id_bufwait)->lh_first = (&adp->ad_freefrag->ff_list
); (&adp->ad_freefrag->ff_list)->wk_list.le_prev
= &(&adp->ad_inodedep->id_bufwait)->lh_first
; } while (0); } while (0)
;
2173 else
2174 add_to_worklist(&adp->ad_freefrag->ff_list);
2175 }
2176 if ((wk = LIST_FIRST(&adp->ad_newdirblk)((&adp->ad_newdirblk)->lh_first)) != NULL((void *)0)) {
2177 newdirblk = WK_NEWDIRBLK(wk)((struct newdirblk *)(wk));
2178 WORKLIST_REMOVE(&newdirblk->db_list)do { (&newdirblk->db_list)->wk_state &= ~0x8000
; do { if ((&newdirblk->db_list)->wk_list.le_next !=
((void *)0)) (&newdirblk->db_list)->wk_list.le_next
->wk_list.le_prev = (&newdirblk->db_list)->wk_list
.le_prev; *(&newdirblk->db_list)->wk_list.le_prev =
(&newdirblk->db_list)->wk_list.le_next; ((&newdirblk
->db_list)->wk_list.le_prev) = ((void *)-1); ((&newdirblk
->db_list)->wk_list.le_next) = ((void *)-1); } while (0
); } while (0)
;
2179 if (LIST_FIRST(&adp->ad_newdirblk)((&adp->ad_newdirblk)->lh_first) != NULL((void *)0))
2180 panic("free_allocdirect: extra newdirblk");
2181 if (delay)
2182 WORKLIST_INSERT(&adp->ad_inodedep->id_bufwait,do { (&newdirblk->db_list)->wk_state |= 0x8000; do {
if (((&newdirblk->db_list)->wk_list.le_next = (&
adp->ad_inodedep->id_bufwait)->lh_first) != ((void *
)0)) (&adp->ad_inodedep->id_bufwait)->lh_first->
wk_list.le_prev = &(&newdirblk->db_list)->wk_list
.le_next; (&adp->ad_inodedep->id_bufwait)->lh_first
= (&newdirblk->db_list); (&newdirblk->db_list)
->wk_list.le_prev = &(&adp->ad_inodedep->id_bufwait
)->lh_first; } while (0); } while (0)
2183 &newdirblk->db_list)do { (&newdirblk->db_list)->wk_state |= 0x8000; do {
if (((&newdirblk->db_list)->wk_list.le_next = (&
adp->ad_inodedep->id_bufwait)->lh_first) != ((void *
)0)) (&adp->ad_inodedep->id_bufwait)->lh_first->
wk_list.le_prev = &(&newdirblk->db_list)->wk_list
.le_next; (&adp->ad_inodedep->id_bufwait)->lh_first
= (&newdirblk->db_list); (&newdirblk->db_list)
->wk_list.le_prev = &(&adp->ad_inodedep->id_bufwait
)->lh_first; } while (0); } while (0)
;
2184 else
2185 free_newdirblk(newdirblk);
2186 }
2187 WORKITEM_FREE(adp, D_ALLOCDIRECT)softdep_freequeue_add((struct worklist *)adp);
2188}
2189
2190/*
2191 * Free a newdirblk. Clear the NEWBLOCK flag on its associated pagedep.
2192 * This routine must be called with splbio interrupts blocked.
2193 */
2194void
2195free_newdirblk(struct newdirblk *newdirblk)
2196{
2197 struct pagedep *pagedep;
2198 struct diradd *dap;
2199 int i;
2200
2201 splassert(IPL_BIO)do { if (splassert_ctl > 0) { splassert_check(0x6, __func__
); } } while (0)
;
2202
2203#ifdef DEBUG
2204 if (lk.lkt_held == -1)
2205 panic("free_newdirblk: lock not held");
2206#endif
2207 /*
2208 * If the pagedep is still linked onto the directory buffer
2209 * dependency chain, then some of the entries on the
2210 * pd_pendinghd list may not be committed to disk yet. In
2211 * this case, we will simply clear the NEWBLOCK flag and
2212 * let the pd_pendinghd list be processed when the pagedep
2213 * is next written. If the pagedep is no longer on the buffer
2214 * dependency chain, then all the entries on the pd_pending
2215 * list are committed to disk and we can free them here.
2216 */
2217 pagedep = newdirblk->db_pagedep;
2218 pagedep->pd_statepd_list.wk_state &= ~NEWBLOCK0x0800;
2219 if ((pagedep->pd_statepd_list.wk_state & ONWORKLIST0x8000) == 0)
2220 while ((dap = LIST_FIRST(&pagedep->pd_pendinghd)((&pagedep->pd_pendinghd)->lh_first)) != NULL((void *)0))
2221 free_diradd(dap);
2222 /*
2223 * If no dependencies remain, the pagedep will be freed.
2224 */
2225 for (i = 0; i < DAHASHSZ6; i++)
2226 if (LIST_FIRST(&pagedep->pd_diraddhd[i])((&pagedep->pd_diraddhd[i])->lh_first) != NULL((void *)0))
2227 break;
2228 if (i == DAHASHSZ6 && (pagedep->pd_statepd_list.wk_state & ONWORKLIST0x8000) == 0) {
2229 LIST_REMOVE(pagedep, pd_hash)do { if ((pagedep)->pd_hash.le_next != ((void *)0)) (pagedep
)->pd_hash.le_next->pd_hash.le_prev = (pagedep)->pd_hash
.le_prev; *(pagedep)->pd_hash.le_prev = (pagedep)->pd_hash
.le_next; ((pagedep)->pd_hash.le_prev) = ((void *)-1); ((pagedep
)->pd_hash.le_next) = ((void *)-1); } while (0)
;
2230 WORKITEM_FREE(pagedep, D_PAGEDEP)softdep_freequeue_add((struct worklist *)pagedep);
2231 }
2232 WORKITEM_FREE(newdirblk, D_NEWDIRBLK)softdep_freequeue_add((struct worklist *)newdirblk);
2233}
2234
2235/*
2236 * Prepare an inode to be freed. The actual free operation is not
2237 * done until the zero'ed inode has been written to disk.
2238 */
2239void
2240softdep_freefile(struct vnode *pvp, ufsino_t ino, mode_t mode)
2241{
2242 struct inode *ip = VTOI(pvp)((struct inode *)(pvp)->v_data);
2243 struct inodedep *inodedep;
2244 struct freefile *freefile;
2245
2246 /*
2247 * This sets up the inode de-allocation dependency.
2248 */
2249 freefile = pool_get(&freefile_pool, PR_WAITOK0x0001);
2250 freefile->fx_list.wk_type = D_FREEFILE9;
2251 freefile->fx_list.wk_state = 0;
2252 freefile->fx_mode = mode;
2253 freefile->fx_oldinum = ino;
2254 freefile->fx_devvp = ip->i_devvpi_ump->um_devvp;
2255 freefile->fx_mnt = ITOV(ip)((ip)->i_vnode)->v_mount;
2256
2257 /*
2258 * If the inodedep does not exist, then the zero'ed inode has
2259 * been written to disk. If the allocated inode has never been
2260 * written to disk, then the on-disk inode is zero'ed. In either
2261 * case we can free the file immediately.
2262 */
2263 ACQUIRE_LOCK(&lk)(&lk)->lkt_spl = splraise(0x6);
2264 if (inodedep_lookup(ip->i_fsinode_u.fs, ino, 0, &inodedep) == 0 ||
2265 check_inode_unwritten(inodedep)) {
2266 FREE_LOCK(&lk)spllower((&lk)->lkt_spl);
2267 handle_workitem_freefile(freefile);
2268 return;
2269 }
2270 WORKLIST_INSERT(&inodedep->id_inowait, &freefile->fx_list)do { (&freefile->fx_list)->wk_state |= 0x8000; do {
if (((&freefile->fx_list)->wk_list.le_next = (&
inodedep->id_inowait)->lh_first) != ((void *)0)) (&
inodedep->id_inowait)->lh_first->wk_list.le_prev = &
(&freefile->fx_list)->wk_list.le_next; (&inodedep
->id_inowait)->lh_first = (&freefile->fx_list); (
&freefile->fx_list)->wk_list.le_prev = &(&inodedep
->id_inowait)->lh_first; } while (0); } while (0)
;
2271 FREE_LOCK(&lk)spllower((&lk)->lkt_spl);
2272}
2273
2274/*
2275 * Check to see if an inode has never been written to disk. If
2276 * so free the inodedep and return success, otherwise return failure.
2277 * This routine must be called with splbio interrupts blocked.
2278 *
2279 * If we still have a bitmap dependency, then the inode has never
2280 * been written to disk. Drop the dependency as it is no longer
2281 * necessary since the inode is being deallocated. We set the
2282 * ALLCOMPLETE flags since the bitmap now properly shows that the
2283 * inode is not allocated. Even if the inode is actively being
2284 * written, it has been rolled back to its zero'ed state, so we
2285 * are ensured that a zero inode is what is on the disk. For short
2286 * lived files, this change will usually result in removing all the
2287 * dependencies from the inode so that it can be freed immediately.
2288 */
2289STATIC int
2290check_inode_unwritten(struct inodedep *inodedep)
2291{
2292 splassert(IPL_BIO)do { if (splassert_ctl > 0) { splassert_check(0x6, __func__
); } } while (0)
;
2293
2294 if ((inodedep->id_stateid_list.wk_state & DEPCOMPLETE0x0008) != 0 ||
2295 LIST_FIRST(&inodedep->id_pendinghd)((&inodedep->id_pendinghd)->lh_first) != NULL((void *)0) ||
2296 LIST_FIRST(&inodedep->id_bufwait)((&inodedep->id_bufwait)->lh_first) != NULL((void *)0) ||
2297 LIST_FIRST(&inodedep->id_inowait)((&inodedep->id_inowait)->lh_first) != NULL((void *)0) ||
2298 TAILQ_FIRST(&inodedep->id_inoupdt)((&inodedep->id_inoupdt)->tqh_first) != NULL((void *)0) ||
2299 TAILQ_FIRST(&inodedep->id_newinoupdt)((&inodedep->id_newinoupdt)->tqh_first) != NULL((void *)0) ||
2300 inodedep->id_nlinkdelta != 0)
2301 return (0);
2302 inodedep->id_stateid_list.wk_state |= ALLCOMPLETE(0x0001 | 0x0004 | 0x0008);
2303 LIST_REMOVE(inodedep, id_deps)do { if ((inodedep)->id_deps.le_next != ((void *)0)) (inodedep
)->id_deps.le_next->id_deps.le_prev = (inodedep)->id_deps
.le_prev; *(inodedep)->id_deps.le_prev = (inodedep)->id_deps
.le_next; ((inodedep)->id_deps.le_prev) = ((void *)-1); ((
inodedep)->id_deps.le_next) = ((void *)-1); } while (0)
;
2304 inodedep->id_buf = NULL((void *)0);
2305 if (inodedep->id_stateid_list.wk_state & ONWORKLIST0x8000)
2306 WORKLIST_REMOVE(&inodedep->id_list)do { (&inodedep->id_list)->wk_state &= ~0x8000;
do { if ((&inodedep->id_list)->wk_list.le_next != (
(void *)0)) (&inodedep->id_list)->wk_list.le_next->
wk_list.le_prev = (&inodedep->id_list)->wk_list.le_prev
; *(&inodedep->id_list)->wk_list.le_prev = (&inodedep
->id_list)->wk_list.le_next; ((&inodedep->id_list
)->wk_list.le_prev) = ((void *)-1); ((&inodedep->id_list
)->wk_list.le_next) = ((void *)-1); } while (0); } while (
0)
;
2307 if (inodedep->id_savedino1id_un.idu_savedino1 != NULL((void *)0)) {
2308 free(inodedep->id_savedino1id_un.idu_savedino1, M_INODEDEP79, inodedep->id_unsize);
2309 inodedep->id_savedino1id_un.idu_savedino1 = NULL((void *)0);
2310 }
2311 if (free_inodedep(inodedep) == 0) {
2312 FREE_LOCK(&lk)spllower((&lk)->lkt_spl);
2313 panic("check_inode_unwritten: busy inode");
2314 }
2315 return (1);
2316}
2317
2318/*
2319 * Try to free an inodedep structure. Return 1 if it could be freed.
2320 */
2321STATIC int
2322free_inodedep(struct inodedep *inodedep)
2323{
2324
2325 if ((inodedep->id_stateid_list.wk_state & ONWORKLIST0x8000) != 0 ||
2326 (inodedep->id_stateid_list.wk_state & ALLCOMPLETE(0x0001 | 0x0004 | 0x0008)) != ALLCOMPLETE(0x0001 | 0x0004 | 0x0008) ||
2327 LIST_FIRST(&inodedep->id_pendinghd)((&inodedep->id_pendinghd)->lh_first) != NULL((void *)0) ||
2328 LIST_FIRST(&inodedep->id_bufwait)((&inodedep->id_bufwait)->lh_first) != NULL((void *)0) ||
2329 LIST_FIRST(&inodedep->id_inowait)((&inodedep->id_inowait)->lh_first) != NULL((void *)0) ||
2330 TAILQ_FIRST(&inodedep->id_inoupdt)((&inodedep->id_inoupdt)->tqh_first) != NULL((void *)0) ||
2331 TAILQ_FIRST(&inodedep->id_newinoupdt)((&inodedep->id_newinoupdt)->tqh_first) != NULL((void *)0) ||
2332 inodedep->id_nlinkdelta != 0 || inodedep->id_savedino1id_un.idu_savedino1 != NULL((void *)0))
2333 return (0);
2334 LIST_REMOVE(inodedep, id_hash)do { if ((inodedep)->id_hash.le_next != ((void *)0)) (inodedep
)->id_hash.le_next->id_hash.le_prev = (inodedep)->id_hash
.le_prev; *(inodedep)->id_hash.le_prev = (inodedep)->id_hash
.le_next; ((inodedep)->id_hash.le_prev) = ((void *)-1); ((
inodedep)->id_hash.le_next) = ((void *)-1); } while (0)
;
2335 WORKITEM_FREE(inodedep, D_INODEDEP)softdep_freequeue_add((struct worklist *)inodedep);
2336 num_inodedep -= 1;
2337 return (1);
2338}
2339
2340/*
2341 * This workitem routine performs the block de-allocation.
2342 * The workitem is added to the pending list after the updated
2343 * inode block has been written to disk. As mentioned above,
2344 * checks regarding the number of blocks de-allocated (compared
2345 * to the number of blocks allocated for the file) are also
2346 * performed in this function.
2347 */
2348STATIC void
2349handle_workitem_freeblocks(struct freeblks *freeblks)
2350{
2351 struct inode tip;
2352 daddr_t bn;
2353 union {
2354 struct ufs1_dinode di1;
2355 struct ufs2_dinode di2;
2356 } di;
2357 struct fs *fs;
2358 int i, level, bsize;
2359 long nblocks, blocksreleased = 0;
2360 int error, allerror = 0;
2361 daddr_t baselbns[NIADDR3], tmpval;
2362
2363 if (VFSTOUFS(freeblks->fb_mnt)((struct ufsmount *)((freeblks->fb_mnt)->mnt_data))->um_fstype == UM_UFS11)
2364 tip.i_din1dinode_u.ffs1_din = &di.di1;
2365 else
2366 tip.i_din2dinode_u.ffs2_din = &di.di2;
2367
2368 tip.i_fsinode_u.fs = fs = VFSTOUFS(freeblks->fb_mnt)((struct ufsmount *)((freeblks->fb_mnt)->mnt_data))->um_fsufsmount_u.fs;
2369 tip.i_number = freeblks->fb_previousinum;
2370 tip.i_ump = VFSTOUFS(freeblks->fb_mnt)((struct ufsmount *)((freeblks->fb_mnt)->mnt_data));
2371 tip.i_dev = freeblks->fb_devvp->v_rdevv_un.vu_specinfo->si_rdev;
2372 DIP_ASSIGN(&tip, size, freeblks->fb_oldsize)do { if ((&tip)->i_ump->um_fstype == 1) (&tip)->
dinode_u.ffs1_din->di_size = (freeblks->fb_oldsize); else
(&tip)->dinode_u.ffs2_din->di_size = (freeblks->
fb_oldsize); } while (0)
;
2373 DIP_ASSIGN(&tip, uid, freeblks->fb_uid)do { if ((&tip)->i_ump->um_fstype == 1) (&tip)->
dinode_u.ffs1_din->di_uid = (freeblks->fb_uid); else (&
tip)->dinode_u.ffs2_din->di_uid = (freeblks->fb_uid)
; } while (0)
;
2374 tip.i_vnode = NULL((void *)0);
2375 tmpval = 1;
2376 baselbns[0] = NDADDR12;
2377 for (i = 1; i < NIADDR3; i++) {
2378 tmpval *= NINDIR(fs)((fs)->fs_nindir);
2379 baselbns[i] = baselbns[i - 1] + tmpval;
2380 }
2381 nblocks = btodb(fs->fs_bsize)((fs->fs_bsize) >> 9);
2382 blocksreleased = 0;
2383 /*
2384 * Indirect blocks first.
2385 */
2386 for (level = (NIADDR3 - 1); level >= 0; level--) {
2387 if ((bn = freeblks->fb_iblks[level]) == 0)
2388 continue;
2389 if ((error = indir_trunc(&tip, fsbtodb(fs, bn)((bn) << (fs)->fs_fsbtodb), level,
2390 baselbns[level], &blocksreleased)) != 0)
2391 allerror = error;
2392 ffs_blkfree(&tip, bn, fs->fs_bsize);
2393 blocksreleased += nblocks;
2394 }
2395 /*
2396 * All direct blocks or frags.
2397 */
2398 for (i = (NDADDR12 - 1); i >= 0; i--) {
2399 if ((bn = freeblks->fb_dblks[i]) == 0)
2400 continue;
2401 bsize = blksize(fs, &tip, i)(((i) >= 12 || ((((&tip))->i_ump->um_fstype == 1
) ? ((&tip))->dinode_u.ffs1_din->di_size : ((&tip
))->dinode_u.ffs2_din->di_size) >= ((i) + 1) <<
(fs)->fs_bshift) ? (u_int64_t)(fs)->fs_bsize : (((((((
(((&tip))->i_ump->um_fstype == 1) ? ((&tip))->
dinode_u.ffs1_din->di_size : ((&tip))->dinode_u.ffs2_din
->di_size)) & (fs)->fs_qbmask)) + (fs)->fs_qfmask
) & (fs)->fs_fmask)))
;
2402 ffs_blkfree(&tip, bn, bsize);
2403 blocksreleased += btodb(bsize)((bsize) >> 9);
2404 }
2405
2406#ifdef DIAGNOSTIC1
2407 if (freeblks->fb_chkcnt != blocksreleased)
2408 printf("handle_workitem_freeblocks: block count\n");
2409 if (allerror)
2410 softdep_error("handle_workitem_freeblks", allerror);
2411#endif /* DIAGNOSTIC */
2412 WORKITEM_FREE(freeblks, D_FREEBLKS)softdep_freequeue_add((struct worklist *)freeblks);
2413}
2414
2415/*
2416 * Release blocks associated with the inode ip and stored in the indirect
2417 * block dbn. If level is greater than SINGLE, the block is an indirect block
2418 * and recursive calls to indirtrunc must be used to cleanse other indirect
2419 * blocks.
2420 */
2421STATIC int
2422indir_trunc(struct inode *ip, daddr_t dbn, int level, daddr_t lbn,
2423 long *countp)
2424{
2425 struct buf *bp;
2426 int32_t *bap1 = NULL((void *)0);
2427 int64_t nb, *bap2 = NULL((void *)0);
2428 struct fs *fs;
2429 struct worklist *wk;
2430 struct indirdep *indirdep;
2431 int i, lbnadd, nblocks, ufs1fmt;
2432 int error, allerror = 0;
2433
2434 fs = ip->i_fsinode_u.fs;
2435 lbnadd = 1;
2436 for (i = level; i > 0; i--)
2437 lbnadd *= NINDIR(fs)((fs)->fs_nindir);
2438 /*
2439 * Get buffer of block pointers to be freed. This routine is not
2440 * called until the zero'ed inode has been written, so it is safe
2441 * to free blocks as they are encountered. Because the inode has
2442 * been zero'ed, calls to bmap on these blocks will fail. So, we
2443 * have to use the on-disk address and the block device for the
2444 * filesystem to look them up. If the file was deleted before its
2445 * indirect blocks were all written to disk, the routine that set
2446 * us up (deallocate_dependencies) will have arranged to leave
2447 * a complete copy of the indirect block in memory for our use.
2448 * Otherwise we have to read the blocks in from the disk.
2449 */
2450 ACQUIRE_LOCK(&lk)(&lk)->lkt_spl = splraise(0x6);
2451 if ((bp = incore(ip->i_devvpi_ump->um_devvp, dbn)) != NULL((void *)0) &&
2452 (wk = LIST_FIRST(&bp->b_dep)((&bp->b_dep)->lh_first)) != NULL((void *)0)) {
2453 if (wk->wk_type != D_INDIRDEP5 ||
2454 (indirdep = WK_INDIRDEP(wk)((struct indirdep *)(wk)))->ir_savebp != bp ||
2455 (indirdep->ir_stateir_list.wk_state & GOINGAWAY0x0100) == 0) {
2456 FREE_LOCK(&lk)spllower((&lk)->lkt_spl);
2457 panic("indir_trunc: lost indirdep");
2458 }
2459 WORKLIST_REMOVE(wk)do { (wk)->wk_state &= ~0x8000; do { if ((wk)->wk_list
.le_next != ((void *)0)) (wk)->wk_list.le_next->wk_list
.le_prev = (wk)->wk_list.le_prev; *(wk)->wk_list.le_prev
= (wk)->wk_list.le_next; ((wk)->wk_list.le_prev) = ((void
*)-1); ((wk)->wk_list.le_next) = ((void *)-1); } while (0
); } while (0)
;
2460 WORKITEM_FREE(indirdep, D_INDIRDEP)softdep_freequeue_add((struct worklist *)indirdep);
2461 if (LIST_FIRST(&bp->b_dep)((&bp->b_dep)->lh_first) != NULL((void *)0)) {
2462 FREE_LOCK(&lk)spllower((&lk)->lkt_spl);
2463 panic("indir_trunc: dangling dep");
2464 }
2465 FREE_LOCK(&lk)spllower((&lk)->lkt_spl);
2466 } else {
2467 FREE_LOCK(&lk)spllower((&lk)->lkt_spl);
2468 error = bread(ip->i_devvpi_ump->um_devvp, dbn, (int)fs->fs_bsize, &bp);
2469 if (error)
2470 return (error);
2471 }
2472 /*
2473 * Recursively free indirect blocks.
2474 */
2475 if (ip->i_ump->um_fstype == UM_UFS11) {
2476 ufs1fmt = 1;
2477 bap1 = (int32_t *)bp->b_data;
2478 } else {
2479 ufs1fmt = 0;
2480 bap2 = (int64_t *)bp->b_data;
2481 }
2482 nblocks = btodb(fs->fs_bsize)((fs->fs_bsize) >> 9);
2483 for (i = NINDIR(fs)((fs)->fs_nindir) - 1; i >= 0; i--) {
2484 if (ufs1fmt)
2485 nb = bap1[i];
2486 else
2487 nb = bap2[i];
2488 if (nb == 0)
2489 continue;
2490 if (level != 0) {
2491 if ((error = indir_trunc(ip, fsbtodb(fs, nb)((nb) << (fs)->fs_fsbtodb),
2492 level - 1, lbn + (i * lbnadd), countp)) != 0)
2493 allerror = error;
2494 }
2495 ffs_blkfree(ip, nb, fs->fs_bsize);
2496 *countp += nblocks;
2497 }
2498 bp->b_flags |= B_INVAL0x00000800 | B_NOCACHE0x00001000;
2499 brelse(bp);
2500 return (allerror);
2501}
2502
2503/*
2504 * Free an allocindir.
2505 * This routine must be called with splbio interrupts blocked.
2506 */
2507STATIC void
2508free_allocindir(struct allocindir *aip, struct inodedep *inodedep)
2509{
2510 struct freefrag *freefrag;
2511
2512 splassert(IPL_BIO)do { if (splassert_ctl > 0) { splassert_check(0x6, __func__
); } } while (0)
;
2513
2514#ifdef DEBUG
2515 if (lk.lkt_held == -1)
2516 panic("free_allocindir: lock not held");
2517#endif
2518 if ((aip->ai_stateai_list.wk_state & DEPCOMPLETE0x0008) == 0)
2519 LIST_REMOVE(aip, ai_deps)do { if ((aip)->ai_deps.le_next != ((void *)0)) (aip)->
ai_deps.le_next->ai_deps.le_prev = (aip)->ai_deps.le_prev
; *(aip)->ai_deps.le_prev = (aip)->ai_deps.le_next; ((aip
)->ai_deps.le_prev) = ((void *)-1); ((aip)->ai_deps.le_next
) = ((void *)-1); } while (0)
;
2520 if (aip->ai_stateai_list.wk_state & ONWORKLIST0x8000)
2521 WORKLIST_REMOVE(&aip->ai_list)do { (&aip->ai_list)->wk_state &= ~0x8000; do {
if ((&aip->ai_list)->wk_list.le_next != ((void *)0
)) (&aip->ai_list)->wk_list.le_next->wk_list.le_prev
= (&aip->ai_list)->wk_list.le_prev; *(&aip->
ai_list)->wk_list.le_prev = (&aip->ai_list)->wk_list
.le_next; ((&aip->ai_list)->wk_list.le_prev) = ((void
*)-1); ((&aip->ai_list)->wk_list.le_next) = ((void
*)-1); } while (0); } while (0)
;
2522 LIST_REMOVE(aip, ai_next)do { if ((aip)->ai_next.le_next != ((void *)0)) (aip)->
ai_next.le_next->ai_next.le_prev = (aip)->ai_next.le_prev
; *(aip)->ai_next.le_prev = (aip)->ai_next.le_next; ((aip
)->ai_next.le_prev) = ((void *)-1); ((aip)->ai_next.le_next
) = ((void *)-1); } while (0)
;
2523 if ((freefrag = aip->ai_freefrag) != NULL((void *)0)) {
2524 if (inodedep == NULL((void *)0))
2525 add_to_worklist(&freefrag->ff_list);
2526 else
2527 WORKLIST_INSERT(&inodedep->id_bufwait,do { (&freefrag->ff_list)->wk_state |= 0x8000; do {
if (((&freefrag->ff_list)->wk_list.le_next = (&
inodedep->id_bufwait)->lh_first) != ((void *)0)) (&
inodedep->id_bufwait)->lh_first->wk_list.le_prev = &
(&freefrag->ff_list)->wk_list.le_next; (&inodedep
->id_bufwait)->lh_first = (&freefrag->ff_list); (
&freefrag->ff_list)->wk_list.le_prev = &(&inodedep
->id_bufwait)->lh_first; } while (0); } while (0)
2528 &freefrag->ff_list)do { (&freefrag->ff_list)->wk_state |= 0x8000; do {
if (((&freefrag->ff_list)->wk_list.le_next = (&
inodedep->id_bufwait)->lh_first) != ((void *)0)) (&
inodedep->id_bufwait)->lh_first->wk_list.le_prev = &
(&freefrag->ff_list)->wk_list.le_next; (&inodedep
->id_bufwait)->lh_first = (&freefrag->ff_list); (
&freefrag->ff_list)->wk_list.le_prev = &(&inodedep
->id_bufwait)->lh_first; } while (0); } while (0)
;
2529 }
2530 WORKITEM_FREE(aip, D_ALLOCINDIR)softdep_freequeue_add((struct worklist *)aip);
2531}
2532
2533/*
2534 * Directory entry addition dependencies.
2535 *
2536 * When adding a new directory entry, the inode (with its incremented link
2537 * count) must be written to disk before the directory entry's pointer to it.
2538 * Also, if the inode is newly allocated, the corresponding freemap must be
2539 * updated (on disk) before the directory entry's pointer. These requirements
2540 * are met via undo/redo on the directory entry's pointer, which consists
2541 * simply of the inode number.
2542 *
2543 * As directory entries are added and deleted, the free space within a
2544 * directory block can become fragmented. The ufs file system will compact
2545 * a fragmented directory block to make space for a new entry. When this
2546 * occurs, the offsets of previously added entries change. Any "diradd"
2547 * dependency structures corresponding to these entries must be updated with
2548 * the new offsets.
2549 */
2550
2551/*
2552 * This routine is called after the in-memory inode's link
2553 * count has been incremented, but before the directory entry's
2554 * pointer to the inode has been set.
2555 */
2556/* buffer containing directory block */
2557/* inode for directory */
2558/* offset of new entry in directory */
2559/* inode referenced by new directory entry */
2560/* non-NULL => contents of new mkdir */
2561/* entry is in a newly allocated block */
2562int
2563softdep_setup_directory_add(struct buf *bp, struct inode *dp, off_t diroffset,
2564 long newinum, struct buf *newdirbp, int isnewblk)
2565{
2566 int offset; /* offset of new entry within directory block */
2567 daddr_t lbn; /* block in directory containing new entry */
2568 struct fs *fs;
2569 struct diradd *dap;
2570 struct allocdirect *adp;
2571 struct pagedep *pagedep;
2572 struct inodedep *inodedep;
2573 struct newdirblk *newdirblk = NULL((void *)0);
2574 struct mkdir *mkdir1, *mkdir2;
2575
2576
2577 fs = dp->i_fsinode_u.fs;
2578 lbn = lblkno(fs, diroffset)((diroffset) >> (fs)->fs_bshift);
2579 offset = blkoff(fs, diroffset)((diroffset) & (fs)->fs_qbmask);
2580 dap = pool_get(&diradd_pool, PR_WAITOK0x0001 | PR_ZERO0x0008);
2581 dap->da_list.wk_type = D_DIRADD10;
2582 dap->da_offset = offset;
2583 dap->da_newinum = newinum;
2584 dap->da_stateda_list.wk_state = ATTACHED0x0001;
2585 if (isnewblk && lbn < NDADDR12 && fragoff(fs, diroffset)((diroffset) & (fs)->fs_qfmask) == 0) {
2586 newdirblk = pool_get(&newdirblk_pool, PR_WAITOK0x0001);
2587 newdirblk->db_list.wk_type = D_NEWDIRBLK13;
2588 newdirblk->db_statedb_list.wk_state = 0;
2589 }
2590 if (newdirbp == NULL((void *)0)) {
2591 dap->da_stateda_list.wk_state |= DEPCOMPLETE0x0008;
2592 ACQUIRE_LOCK(&lk)(&lk)->lkt_spl = splraise(0x6);
2593 } else {
2594 dap->da_stateda_list.wk_state |= MKDIR_BODY0x0020 | MKDIR_PARENT0x0010;
2595 mkdir1 = pool_get(&mkdir_pool, PR_WAITOK0x0001);
2596 mkdir1->md_list.wk_type = D_MKDIR11;
2597 mkdir1->md_statemd_list.wk_state = MKDIR_BODY0x0020;
2598 mkdir1->md_diradd = dap;
2599 mkdir2 = pool_get(&mkdir_pool, PR_WAITOK0x0001);
2600 mkdir2->md_list.wk_type = D_MKDIR11;
2601 mkdir2->md_statemd_list.wk_state = MKDIR_PARENT0x0010;
2602 mkdir2->md_diradd = dap;
2603 /*
2604 * Dependency on "." and ".." being written to disk.
2605 */
2606 mkdir1->md_buf = newdirbp;
2607 ACQUIRE_LOCK(&lk)(&lk)->lkt_spl = splraise(0x6);
2608 LIST_INSERT_HEAD(&mkdirlisthd, mkdir1, md_mkdirs)do { if (((mkdir1)->md_mkdirs.le_next = (&mkdirlisthd)
->lh_first) != ((void *)0)) (&mkdirlisthd)->lh_first
->md_mkdirs.le_prev = &(mkdir1)->md_mkdirs.le_next;
(&mkdirlisthd)->lh_first = (mkdir1); (mkdir1)->md_mkdirs
.le_prev = &(&mkdirlisthd)->lh_first; } while (0)
;
2609 WORKLIST_INSERT(&newdirbp->b_dep, &mkdir1->md_list)do { (&mkdir1->md_list)->wk_state |= 0x8000; do { if
(((&mkdir1->md_list)->wk_list.le_next = (&newdirbp
->b_dep)->lh_first) != ((void *)0)) (&newdirbp->
b_dep)->lh_first->wk_list.le_prev = &(&mkdir1->
md_list)->wk_list.le_next; (&newdirbp->b_dep)->lh_first
= (&mkdir1->md_list); (&mkdir1->md_list)->wk_list
.le_prev = &(&newdirbp->b_dep)->lh_first; } while
(0); } while (0)
;
2610 FREE_LOCK(&lk)spllower((&lk)->lkt_spl);
2611 bdwrite(newdirbp);
2612 /*
2613 * Dependency on link count increase for parent directory
2614 */
2615 ACQUIRE_LOCK(&lk)(&lk)->lkt_spl = splraise(0x6);
2616 if (inodedep_lookup(fs, dp->i_number, 0, &inodedep) == 0
2617 || (inodedep->id_stateid_list.wk_state & ALLCOMPLETE(0x0001 | 0x0004 | 0x0008)) == ALLCOMPLETE(0x0001 | 0x0004 | 0x0008)) {
2618 dap->da_stateda_list.wk_state &= ~MKDIR_PARENT0x0010;
2619 WORKITEM_FREE(mkdir2, D_MKDIR)softdep_freequeue_add((struct worklist *)mkdir2);
2620 } else {
2621 LIST_INSERT_HEAD(&mkdirlisthd, mkdir2, md_mkdirs)do { if (((mkdir2)->md_mkdirs.le_next = (&mkdirlisthd)
->lh_first) != ((void *)0)) (&mkdirlisthd)->lh_first
->md_mkdirs.le_prev = &(mkdir2)->md_mkdirs.le_next;
(&mkdirlisthd)->lh_first = (mkdir2); (mkdir2)->md_mkdirs
.le_prev = &(&mkdirlisthd)->lh_first; } while (0)
;
2622 WORKLIST_INSERT(&inodedep->id_bufwait,&mkdir2->md_list)do { (&mkdir2->md_list)->wk_state |= 0x8000; do { if
(((&mkdir2->md_list)->wk_list.le_next = (&inodedep
->id_bufwait)->lh_first) != ((void *)0)) (&inodedep
->id_bufwait)->lh_first->wk_list.le_prev = &(&
mkdir2->md_list)->wk_list.le_next; (&inodedep->id_bufwait
)->lh_first = (&mkdir2->md_list); (&mkdir2->
md_list)->wk_list.le_prev = &(&inodedep->id_bufwait
)->lh_first; } while (0); } while (0)
;
2623 }
2624 }
2625 /*
2626 * Link into parent directory pagedep to await its being written.
2627 */
2628 if (pagedep_lookup(dp, lbn, DEPALLOC0x0001, &pagedep) == 0)
2629 WORKLIST_INSERT(&bp->b_dep, &pagedep->pd_list)do { (&pagedep->pd_list)->wk_state |= 0x8000; do { if
(((&pagedep->pd_list)->wk_list.le_next = (&bp->
b_dep)->lh_first) != ((void *)0)) (&bp->b_dep)->
lh_first->wk_list.le_prev = &(&pagedep->pd_list
)->wk_list.le_next; (&bp->b_dep)->lh_first = (&
pagedep->pd_list); (&pagedep->pd_list)->wk_list.
le_prev = &(&bp->b_dep)->lh_first; } while (0);
} while (0)
;
2630 dap->da_pagedepda_un.dau_pagedep = pagedep;
2631 LIST_INSERT_HEAD(&pagedep->pd_diraddhd[DIRADDHASH(offset)], dap,do { if (((dap)->da_pdlist.le_next = (&pagedep->pd_diraddhd
[(((offset) >> 2) % 6)])->lh_first) != ((void *)0)) (
&pagedep->pd_diraddhd[(((offset) >> 2) % 6)])->
lh_first->da_pdlist.le_prev = &(dap)->da_pdlist.le_next
; (&pagedep->pd_diraddhd[(((offset) >> 2) % 6)])
->lh_first = (dap); (dap)->da_pdlist.le_prev = &(&
pagedep->pd_diraddhd[(((offset) >> 2) % 6)])->lh_first
; } while (0)
2632 da_pdlist)do { if (((dap)->da_pdlist.le_next = (&pagedep->pd_diraddhd
[(((offset) >> 2) % 6)])->lh_first) != ((void *)0)) (
&pagedep->pd_diraddhd[(((offset) >> 2) % 6)])->
lh_first->da_pdlist.le_prev = &(dap)->da_pdlist.le_next
; (&pagedep->pd_diraddhd[(((offset) >> 2) % 6)])
->lh_first = (dap); (dap)->da_pdlist.le_prev = &(&
pagedep->pd_diraddhd[(((offset) >> 2) % 6)])->lh_first
; } while (0)
;
2633 /*
2634 * Link into its inodedep. Put it on the id_bufwait list if the inode
2635 * is not yet written. If it is written, do the post-inode write
2636 * processing to put it on the id_pendinghd list.
2637 */
2638 (void) inodedep_lookup(fs, newinum, DEPALLOC0x0001, &inodedep);
2639 if ((inodedep->id_stateid_list.wk_state & ALLCOMPLETE(0x0001 | 0x0004 | 0x0008)) == ALLCOMPLETE(0x0001 | 0x0004 | 0x0008))
2640 diradd_inode_written(dap, inodedep);
2641 else
2642 WORKLIST_INSERT(&inodedep->id_bufwait, &dap->da_list)do { (&dap->da_list)->wk_state |= 0x8000; do { if (
((&dap->da_list)->wk_list.le_next = (&inodedep->
id_bufwait)->lh_first) != ((void *)0)) (&inodedep->
id_bufwait)->lh_first->wk_list.le_prev = &(&dap
->da_list)->wk_list.le_next; (&inodedep->id_bufwait
)->lh_first = (&dap->da_list); (&dap->da_list
)->wk_list.le_prev = &(&inodedep->id_bufwait)->
lh_first; } while (0); } while (0)
;
2643 if (isnewblk) {
2644 /*
2645 * Directories growing into indirect blocks are rare
2646 * enough and the frequency of new block allocation
2647 * in those cases even more rare, that we choose not
2648 * to bother tracking them. Rather we simply force the
2649 * new directory entry to disk.
2650 */
2651 if (lbn >= NDADDR12) {
2652 FREE_LOCK(&lk)spllower((&lk)->lkt_spl);
2653 /*
2654 * We only have a new allocation when at the
2655 * beginning of a new block, not when we are
2656 * expanding into an existing block.
2657 */
2658 if (blkoff(fs, diroffset)((diroffset) & (fs)->fs_qbmask) == 0)
2659 return (1);
2660 return (0);
2661 }
2662 /*
2663 * We only have a new allocation when at the beginning
2664 * of a new fragment, not when we are expanding into an
2665 * existing fragment. Also, there is nothing to do if we
2666 * are already tracking this block.
2667 */
2668 if (fragoff(fs, diroffset)((diroffset) & (fs)->fs_qfmask) != 0) {
2669 FREE_LOCK(&lk)spllower((&lk)->lkt_spl);
2670 return (0);
2671 }
2672
2673 if ((pagedep->pd_statepd_list.wk_state & NEWBLOCK0x0800) != 0) {
2674 WORKITEM_FREE(newdirblk, D_NEWDIRBLK)softdep_freequeue_add((struct worklist *)newdirblk);
2675 FREE_LOCK(&lk)spllower((&lk)->lkt_spl);
2676 return (0);
2677 }
2678 /*
2679 * Find our associated allocdirect and have it track us.
2680 */
2681 if (inodedep_lookup(fs, dp->i_number, 0, &inodedep) == 0)
2682 panic("softdep_setup_directory_add: lost inodedep");
2683 adp = TAILQ_LAST(&inodedep->id_newinoupdt, allocdirectlst)(*(((struct allocdirectlst *)((&inodedep->id_newinoupdt
)->tqh_last))->tqh_last))
;
2684 if (adp == NULL((void *)0) || adp->ad_lbn != lbn) {
2685 FREE_LOCK(&lk)spllower((&lk)->lkt_spl);
2686 panic("softdep_setup_directory_add: lost entry");
2687 }
2688 pagedep->pd_statepd_list.wk_state |= NEWBLOCK0x0800;
2689 newdirblk->db_pagedep = pagedep;
2690 WORKLIST_INSERT(&adp->ad_newdirblk, &newdirblk->db_list)do { (&newdirblk->db_list)->wk_state |= 0x8000; do {
if (((&newdirblk->db_list)->wk_list.le_next = (&
adp->ad_newdirblk)->lh_first) != ((void *)0)) (&adp
->ad_newdirblk)->lh_first->wk_list.le_prev = &(&
newdirblk->db_list)->wk_list.le_next; (&adp->ad_newdirblk
)->lh_first = (&newdirblk->db_list); (&newdirblk
->db_list)->wk_list.le_prev = &(&adp->ad_newdirblk
)->lh_first; } while (0); } while (0)
;
2691 }
2692 FREE_LOCK(&lk)spllower((&lk)->lkt_spl);
2693 return (0);
2694}
2695
2696/*
2697 * This procedure is called to change the offset of a directory
2698 * entry when compacting a directory block which must be owned
2699 * exclusively by the caller. Note that the actual entry movement
2700 * must be done in this procedure to ensure that no I/O completions
2701 * occur while the move is in progress.
2702 */
2703/* inode for directory */
2704/* address of dp->i_offset */
2705/* address of old directory location */
2706/* address of new directory location */
2707/* size of directory entry */
2708void
2709softdep_change_directoryentry_offset(struct inode *dp, caddr_t base,
2710 caddr_t oldloc, caddr_t newloc, int entrysize)
2711{
2712 int offset, oldoffset, newoffset;
2713 struct pagedep *pagedep;
2714 struct diradd *dap;
2715 daddr_t lbn;
2716
2717 ACQUIRE_LOCK(&lk)(&lk)->lkt_spl = splraise(0x6);
2718 lbn = lblkno(dp->i_fs, dp->i_offset)((dp->i_offset) >> (dp->inode_u.fs)->fs_bshift
)
;
2719 offset = blkoff(dp->i_fs, dp->i_offset)((dp->i_offset) & (dp->inode_u.fs)->fs_qbmask);
2720 if (pagedep_lookup(dp, lbn, 0, &pagedep) == 0)
2721 goto done;
2722 oldoffset = offset + (oldloc - base);
2723 newoffset = offset + (newloc - base);
2724
2725 LIST_FOREACH(dap, &pagedep->pd_diraddhd[DIRADDHASH(oldoffset)], da_pdlist)for((dap) = ((&pagedep->pd_diraddhd[(((oldoffset) >>
2) % 6)])->lh_first); (dap)!= ((void *)0); (dap) = ((dap)
->da_pdlist.le_next))
{
2726 if (dap->da_offset != oldoffset)
2727 continue;
2728 dap->da_offset = newoffset;
2729 if (DIRADDHASH(newoffset)(((newoffset) >> 2) % 6) == DIRADDHASH(oldoffset)(((oldoffset) >> 2) % 6))
2730 break;
2731 LIST_REMOVE(dap, da_pdlist)do { if ((dap)->da_pdlist.le_next != ((void *)0)) (dap)->
da_pdlist.le_next->da_pdlist.le_prev = (dap)->da_pdlist
.le_prev; *(dap)->da_pdlist.le_prev = (dap)->da_pdlist.
le_next; ((dap)->da_pdlist.le_prev) = ((void *)-1); ((dap)
->da_pdlist.le_next) = ((void *)-1); } while (0)
;
2732 LIST_INSERT_HEAD(&pagedep->pd_diraddhd[DIRADDHASH(newoffset)],do { if (((dap)->da_pdlist.le_next = (&pagedep->pd_diraddhd
[(((newoffset) >> 2) % 6)])->lh_first) != ((void *)0
)) (&pagedep->pd_diraddhd[(((newoffset) >> 2) % 6
)])->lh_first->da_pdlist.le_prev = &(dap)->da_pdlist
.le_next; (&pagedep->pd_diraddhd[(((newoffset) >>
2) % 6)])->lh_first = (dap); (dap)->da_pdlist.le_prev =
&(&pagedep->pd_diraddhd[(((newoffset) >> 2)
% 6)])->lh_first; } while (0)
2733 dap, da_pdlist)do { if (((dap)->da_pdlist.le_next = (&pagedep->pd_diraddhd
[(((newoffset) >> 2) % 6)])->lh_first) != ((void *)0
)) (&pagedep->pd_diraddhd[(((newoffset) >> 2) % 6
)])->lh_first->da_pdlist.le_prev = &(dap)->da_pdlist
.le_next; (&pagedep->pd_diraddhd[(((newoffset) >>
2) % 6)])->lh_first = (dap); (dap)->da_pdlist.le_prev =
&(&pagedep->pd_diraddhd[(((newoffset) >> 2)
% 6)])->lh_first; } while (0)
;
2734 break;
2735 }
2736 if (dap == NULL((void *)0)) {
2737
2738 LIST_FOREACH(dap, &pagedep->pd_pendinghd, da_pdlist)for((dap) = ((&pagedep->pd_pendinghd)->lh_first); (
dap)!= ((void *)0); (dap) = ((dap)->da_pdlist.le_next))
{
2739 if (dap->da_offset == oldoffset) {
2740 dap->da_offset = newoffset;
2741 break;
2742 }
2743 }
2744 }
2745done:
2746 memmove(newloc, oldloc, entrysize)__builtin_memmove((newloc), (oldloc), (entrysize));
2747 FREE_LOCK(&lk)spllower((&lk)->lkt_spl);
2748}
2749
2750/*
2751 * Free a diradd dependency structure. This routine must be called
2752 * with splbio interrupts blocked.
2753 */
2754STATIC void
2755free_diradd(struct diradd *dap)
2756{
2757 struct dirrem *dirrem;
2758 struct pagedep *pagedep;
2759 struct inodedep *inodedep;
2760 struct mkdir *mkdir, *nextmd;
2761
2762 splassert(IPL_BIO)do { if (splassert_ctl > 0) { splassert_check(0x6, __func__
); } } while (0)
;
2763
2764#ifdef DEBUG
2765 if (lk.lkt_held == -1)
2766 panic("free_diradd: lock not held");
2767#endif
2768 WORKLIST_REMOVE(&dap->da_list)do { (&dap->da_list)->wk_state &= ~0x8000; do {
if ((&dap->da_list)->wk_list.le_next != ((void *)0
)) (&dap->da_list)->wk_list.le_next->wk_list.le_prev
= (&dap->da_list)->wk_list.le_prev; *(&dap->
da_list)->wk_list.le_prev = (&dap->da_list)->wk_list
.le_next; ((&dap->da_list)->wk_list.le_prev) = ((void
*)-1); ((&dap->da_list)->wk_list.le_next) = ((void
*)-1); } while (0); } while (0)
;
2769 LIST_REMOVE(dap, da_pdlist)do { if ((dap)->da_pdlist.le_next != ((void *)0)) (dap)->
da_pdlist.le_next->da_pdlist.le_prev = (dap)->da_pdlist
.le_prev; *(dap)->da_pdlist.le_prev = (dap)->da_pdlist.
le_next; ((dap)->da_pdlist.le_prev) = ((void *)-1); ((dap)
->da_pdlist.le_next) = ((void *)-1); } while (0)
;
2770 if ((dap->da_stateda_list.wk_state & DIRCHG0x0080) == 0) {
2771 pagedep = dap->da_pagedepda_un.dau_pagedep;
2772 } else {
2773 dirrem = dap->da_previousda_un.dau_previous;
2774 pagedep = dirrem->dm_pagedepdm_un.dmu_pagedep;
2775 dirrem->dm_dirinumdm_un.dmu_dirinum = pagedep->pd_ino;
2776 add_to_worklist(&dirrem->dm_list);
2777 }
2778 if (inodedep_lookup(VFSTOUFS(pagedep->pd_mnt)((struct ufsmount *)((pagedep->pd_mnt)->mnt_data))->um_fsufsmount_u.fs, dap->da_newinum,
2779 0, &inodedep) != 0)
2780 (void) free_inodedep(inodedep);
2781 if ((dap->da_stateda_list.wk_state & (MKDIR_PARENT0x0010 | MKDIR_BODY0x0020)) != 0) {
2782 for (mkdir = LIST_FIRST(&mkdirlisthd)((&mkdirlisthd)->lh_first); mkdir; mkdir = nextmd) {
2783 nextmd = LIST_NEXT(mkdir, md_mkdirs)((mkdir)->md_mkdirs.le_next);
2784 if (mkdir->md_diradd != dap)
2785 continue;
2786 dap->da_stateda_list.wk_state &= ~mkdir->md_statemd_list.wk_state;
2787 WORKLIST_REMOVE(&mkdir->md_list)do { (&mkdir->md_list)->wk_state &= ~0x8000; do
{ if ((&mkdir->md_list)->wk_list.le_next != ((void
*)0)) (&mkdir->md_list)->wk_list.le_next->wk_list
.le_prev = (&mkdir->md_list)->wk_list.le_prev; *(&
mkdir->md_list)->wk_list.le_prev = (&mkdir->md_list
)->wk_list.le_next; ((&mkdir->md_list)->wk_list.
le_prev) = ((void *)-1); ((&mkdir->md_list)->wk_list
.le_next) = ((void *)-1); } while (0); } while (0)
;
2788 LIST_REMOVE(mkdir, md_mkdirs)do { if ((mkdir)->md_mkdirs.le_next != ((void *)0)) (mkdir
)->md_mkdirs.le_next->md_mkdirs.le_prev = (mkdir)->md_mkdirs
.le_prev; *(mkdir)->md_mkdirs.le_prev = (mkdir)->md_mkdirs
.le_next; ((mkdir)->md_mkdirs.le_prev) = ((void *)-1); ((mkdir
)->md_mkdirs.le_next) = ((void *)-1); } while (0)
;
2789 WORKITEM_FREE(mkdir, D_MKDIR)softdep_freequeue_add((struct worklist *)mkdir);
2790 }
2791 if ((dap->da_stateda_list.wk_state & (MKDIR_PARENT0x0010 | MKDIR_BODY0x0020)) != 0) {
2792 FREE_LOCK(&lk)spllower((&lk)->lkt_spl);
2793 panic("free_diradd: unfound ref");
2794 }
2795 }
2796 WORKITEM_FREE(dap, D_DIRADD)softdep_freequeue_add((struct worklist *)dap);
2797}
2798
2799/*
2800 * Directory entry removal dependencies.
2801 *
2802 * When removing a directory entry, the entry's inode pointer must be
2803 * zero'ed on disk before the corresponding inode's link count is decremented
2804 * (possibly freeing the inode for re-use). This dependency is handled by
2805 * updating the directory entry but delaying the inode count reduction until
2806 * after the directory block has been written to disk. After this point, the
2807 * inode count can be decremented whenever it is convenient.
2808 */
2809
2810/*
2811 * This routine should be called immediately after removing
2812 * a directory entry. The inode's link count should not be
2813 * decremented by the calling procedure -- the soft updates
2814 * code will do this task when it is safe.
2815 */
2816/* buffer containing directory block */
2817/* inode for the directory being modified */
2818/* inode for directory entry being removed */
2819/* indicates if doing RMDIR */
2820void
2821softdep_setup_remove(struct buf *bp, struct inode *dp, struct inode *ip,
2822 int isrmdir)
2823{
2824 struct dirrem *dirrem, *prevdirrem;
2825
2826 /*
2827 * Allocate a new dirrem if appropriate and ACQUIRE_LOCK.
2828 */
2829 dirrem = newdirrem(bp, dp, ip, isrmdir, &prevdirrem);
2830
2831 /*
2832 * If the COMPLETE flag is clear, then there were no active
2833 * entries and we want to roll back to a zeroed entry until
2834 * the new inode is committed to disk. If the COMPLETE flag is
2835 * set then we have deleted an entry that never made it to
2836 * disk. If the entry we deleted resulted from a name change,
2837 * then the old name still resides on disk. We cannot delete
2838 * its inode (returned to us in prevdirrem) until the zeroed
2839 * directory entry gets to disk. The new inode has never been
2840 * referenced on the disk, so can be deleted immediately.
2841 */
2842 if ((dirrem->dm_statedm_list.wk_state & COMPLETE0x0004) == 0) {
2843 LIST_INSERT_HEAD(&dirrem->dm_pagedep->pd_dirremhd, dirrem,do { if (((dirrem)->dm_next.le_next = (&dirrem->dm_un
.dmu_pagedep->pd_dirremhd)->lh_first) != ((void *)0)) (
&dirrem->dm_un.dmu_pagedep->pd_dirremhd)->lh_first
->dm_next.le_prev = &(dirrem)->dm_next.le_next; (&
dirrem->dm_un.dmu_pagedep->pd_dirremhd)->lh_first = (
dirrem); (dirrem)->dm_next.le_prev = &(&dirrem->
dm_un.dmu_pagedep->pd_dirremhd)->lh_first; } while (0)
2844 dm_next)do { if (((dirrem)->dm_next.le_next = (&dirrem->dm_un
.dmu_pagedep->pd_dirremhd)->lh_first) != ((void *)0)) (
&dirrem->dm_un.dmu_pagedep->pd_dirremhd)->lh_first
->dm_next.le_prev = &(dirrem)->dm_next.le_next; (&
dirrem->dm_un.dmu_pagedep->pd_dirremhd)->lh_first = (
dirrem); (dirrem)->dm_next.le_prev = &(&dirrem->
dm_un.dmu_pagedep->pd_dirremhd)->lh_first; } while (0)
;
2845 FREE_LOCK(&lk)spllower((&lk)->lkt_spl);
2846 } else {
2847 if (prevdirrem != NULL((void *)0))
2848 LIST_INSERT_HEAD(&dirrem->dm_pagedep->pd_dirremhd,do { if (((prevdirrem)->dm_next.le_next = (&dirrem->
dm_un.dmu_pagedep->pd_dirremhd)->lh_first) != ((void *)
0)) (&dirrem->dm_un.dmu_pagedep->pd_dirremhd)->lh_first
->dm_next.le_prev = &(prevdirrem)->dm_next.le_next;
(&dirrem->dm_un.dmu_pagedep->pd_dirremhd)->lh_first
= (prevdirrem); (prevdirrem)->dm_next.le_prev = &(&
dirrem->dm_un.dmu_pagedep->pd_dirremhd)->lh_first; }
while (0)
2849 prevdirrem, dm_next)do { if (((prevdirrem)->dm_next.le_next = (&dirrem->
dm_un.dmu_pagedep->pd_dirremhd)->lh_first) != ((void *)
0)) (&dirrem->dm_un.dmu_pagedep->pd_dirremhd)->lh_first
->dm_next.le_prev = &(prevdirrem)->dm_next.le_next;
(&dirrem->dm_un.dmu_pagedep->pd_dirremhd)->lh_first
= (prevdirrem); (prevdirrem)->dm_next.le_prev = &(&
dirrem->dm_un.dmu_pagedep->pd_dirremhd)->lh_first; }
while (0)
;
2850 dirrem->dm_dirinumdm_un.dmu_dirinum = dirrem->dm_pagedepdm_un.dmu_pagedep->pd_ino;
2851 FREE_LOCK(&lk)spllower((&lk)->lkt_spl);
2852 handle_workitem_remove(dirrem);
2853 }
2854}
2855
2856STATIC long num_dirrem; /* number of dirrem allocated */
2857/*
2858 * Allocate a new dirrem if appropriate and return it along with
2859 * its associated pagedep. Called without a lock, returns with lock.
2860 */
2861/* buffer containing directory block */
2862/* inode for the directory being modified */
2863/* inode for directory entry being removed */
2864/* indicates if doing RMDIR */
2865/* previously referenced inode, if any */
2866STATIC struct dirrem *
2867newdirrem(struct buf *bp, struct inode *dp, struct inode *ip, int isrmdir,
2868 struct dirrem **prevdirremp)
2869{
2870 int offset;
2871 daddr_t lbn;
2872 struct diradd *dap;
2873 struct dirrem *dirrem;
2874 struct pagedep *pagedep;
2875
2876 /*
2877 * Whiteouts have no deletion dependencies.
2878 */
2879 if (ip == NULL((void *)0))
2880 panic("newdirrem: whiteout");
2881 /*
2882 * If we are over our limit, try to improve the situation.
2883 * Limiting the number of dirrem structures will also limit
2884 * the number of freefile and freeblks structures.
2885 */
2886 if (num_dirrem > max_softdeps / 2)
2887 (void) request_cleanup(FLUSH_REMOVE2, 0);
2888 num_dirrem += 1;
2889 dirrem = pool_get(&dirrem_pool, PR_WAITOK0x0001 | PR_ZERO0x0008);
2890 dirrem->dm_list.wk_type = D_DIRREM12;
2891 dirrem->dm_statedm_list.wk_state = isrmdir ? RMDIR0x0040 : 0;
2892 dirrem->dm_mnt = ITOV(ip)((ip)->i_vnode)->v_mount;
2893 dirrem->dm_oldinum = ip->i_number;
2894 *prevdirremp = NULL((void *)0);
2895
2896 ACQUIRE_LOCK(&lk)(&lk)->lkt_spl = splraise(0x6);
2897 lbn = lblkno(dp->i_fs, dp->i_offset)((dp->i_offset) >> (dp->inode_u.fs)->fs_bshift
)
;
2898 offset = blkoff(dp->i_fs, dp->i_offset)((dp->i_offset) & (dp->inode_u.fs)->fs_qbmask);
2899 if (pagedep_lookup(dp, lbn, DEPALLOC0x0001, &pagedep) == 0)
2900 WORKLIST_INSERT(&bp->b_dep, &pagedep->pd_list)do { (&pagedep->pd_list)->wk_state |= 0x8000; do { if
(((&pagedep->pd_list)->wk_list.le_next = (&bp->
b_dep)->lh_first) != ((void *)0)) (&bp->b_dep)->
lh_first->wk_list.le_prev = &(&pagedep->pd_list
)->wk_list.le_next; (&bp->b_dep)->lh_first = (&
pagedep->pd_list); (&pagedep->pd_list)->wk_list.
le_prev = &(&bp->b_dep)->lh_first; } while (0);
} while (0)
;
2901 dirrem->dm_pagedepdm_un.dmu_pagedep = pagedep;
2902 /*
2903 * Check for a diradd dependency for the same directory entry.
2904 * If present, then both dependencies become obsolete and can
2905 * be de-allocated. Check for an entry on both the pd_dirraddhd
2906 * list and the pd_pendinghd list.
2907 */
2908
2909 LIST_FOREACH(dap, &pagedep->pd_diraddhd[DIRADDHASH(offset)], da_pdlist)for((dap) = ((&pagedep->pd_diraddhd[(((offset) >>
2) % 6)])->lh_first); (dap)!= ((void *)0); (dap) = ((dap)
->da_pdlist.le_next))
2910 if (dap->da_offset == offset)
2911 break;
2912 if (dap == NULL((void *)0)) {
2913
2914 LIST_FOREACH(dap, &pagedep->pd_pendinghd, da_pdlist)for((dap) = ((&pagedep->pd_pendinghd)->lh_first); (
dap)!= ((void *)0); (dap) = ((dap)->da_pdlist.le_next))
2915 if (dap->da_offset == offset)
2916 break;
2917 if (dap == NULL((void *)0))
2918 return (dirrem);
2919 }
2920 /*
2921 * Must be ATTACHED at this point.
2922 */
2923 if ((dap->da_stateda_list.wk_state & ATTACHED0x0001) == 0) {
2924 FREE_LOCK(&lk)spllower((&lk)->lkt_spl);
2925 panic("newdirrem: not ATTACHED");
2926 }
2927 if (dap->da_newinum != ip->i_number) {
2928 FREE_LOCK(&lk)spllower((&lk)->lkt_spl);
2929 panic("newdirrem: inum %u should be %u",
2930 ip->i_number, dap->da_newinum);
2931 }
2932 /*
2933 * If we are deleting a changed name that never made it to disk,
2934 * then return the dirrem describing the previous inode (which
2935 * represents the inode currently referenced from this entry on disk).
2936 */
2937 if ((dap->da_stateda_list.wk_state & DIRCHG0x0080) != 0) {
2938 *prevdirremp = dap->da_previousda_un.dau_previous;
2939 dap->da_stateda_list.wk_state &= ~DIRCHG0x0080;
2940 dap->da_pagedepda_un.dau_pagedep = pagedep;
2941 }
2942 /*
2943 * We are deleting an entry that never made it to disk.
2944 * Mark it COMPLETE so we can delete its inode immediately.
2945 */
2946 dirrem->dm_statedm_list.wk_state |= COMPLETE0x0004;
2947 free_diradd(dap);
2948 return (dirrem);
2949}
2950
2951/*
2952 * Directory entry change dependencies.
2953 *
2954 * Changing an existing directory entry requires that an add operation
2955 * be completed first followed by a deletion. The semantics for the addition
2956 * are identical to the description of adding a new entry above except
2957 * that the rollback is to the old inode number rather than zero. Once
2958 * the addition dependency is completed, the removal is done as described
2959 * in the removal routine above.
2960 */
2961
2962/*
2963 * This routine should be called immediately after changing
2964 * a directory entry. The inode's link count should not be
2965 * decremented by the calling procedure -- the soft updates
2966 * code will perform this task when it is safe.
2967 */
2968/* buffer containing directory block */
2969/* inode for the directory being modified */
2970/* inode for directory entry being removed */
2971/* new inode number for changed entry */
2972/* indicates if doing RMDIR */
2973void
2974softdep_setup_directory_change(struct buf *bp, struct inode *dp,
2975 struct inode *ip, long newinum, int isrmdir)
2976{
2977 int offset;
2978 struct diradd *dap;
2979 struct dirrem *dirrem, *prevdirrem;
2980 struct pagedep *pagedep;
2981 struct inodedep *inodedep;
2982
2983 offset = blkoff(dp->i_fs, dp->i_offset)((dp->i_offset) & (dp->inode_u.fs)->fs_qbmask);
2984 dap = pool_get(&diradd_pool, PR_WAITOK0x0001 | PR_ZERO0x0008);
2985 dap->da_list.wk_type = D_DIRADD10;
2986 dap->da_stateda_list.wk_state = DIRCHG0x0080 | ATTACHED0x0001 | DEPCOMPLETE0x0008;
2987 dap->da_offset = offset;
2988 dap->da_newinum = newinum;
2989
2990 /*
2991 * Allocate a new dirrem and ACQUIRE_LOCK.
2992 */
2993 dirrem = newdirrem(bp, dp, ip, isrmdir, &prevdirrem);
2994 pagedep = dirrem->dm_pagedepdm_un.dmu_pagedep;
2995 /*
2996 * The possible values for isrmdir:
2997 * 0 - non-directory file rename
2998 * 1 - directory rename within same directory
2999 * inum - directory rename to new directory of given inode number
3000 * When renaming to a new directory, we are both deleting and
3001 * creating a new directory entry, so the link count on the new
3002 * directory should not change. Thus we do not need the followup
3003 * dirrem which is usually done in handle_workitem_remove. We set
3004 * the DIRCHG flag to tell handle_workitem_remove to skip the
3005 * followup dirrem.
3006 */
3007 if (isrmdir > 1)
3008 dirrem->dm_statedm_list.wk_state |= DIRCHG0x0080;
3009
3010 /*
3011 * If the COMPLETE flag is clear, then there were no active
3012 * entries and we want to roll back to the previous inode until
3013 * the new inode is committed to disk. If the COMPLETE flag is
3014 * set, then we have deleted an entry that never made it to disk.
3015 * If the entry we deleted resulted from a name change, then the old
3016 * inode reference still resides on disk. Any rollback that we do
3017 * needs to be to that old inode (returned to us in prevdirrem). If
3018 * the entry we deleted resulted from a create, then there is
3019 * no entry on the disk, so we want to roll back to zero rather
3020 * than the uncommitted inode. In either of the COMPLETE cases we
3021 * want to immediately free the unwritten and unreferenced inode.
3022 */
3023 if ((dirrem->dm_statedm_list.wk_state & COMPLETE0x0004) == 0) {
3024 dap->da_previousda_un.dau_previous = dirrem;
3025 } else {
3026 if (prevdirrem != NULL((void *)0)) {
3027 dap->da_previousda_un.dau_previous = prevdirrem;
3028 } else {
3029 dap->da_stateda_list.wk_state &= ~DIRCHG0x0080;
3030 dap->da_pagedepda_un.dau_pagedep = pagedep;
3031 }
3032 dirrem->dm_dirinumdm_un.dmu_dirinum = pagedep->pd_ino;
3033 add_to_worklist(&dirrem->dm_list);
3034 }
3035 /*
3036 * Link into its inodedep. Put it on the id_bufwait list if the inode
3037 * is not yet written. If it is written, do the post-inode write
3038 * processing to put it on the id_pendinghd list.
3039 */
3040 if (inodedep_lookup(dp->i_fsinode_u.fs, newinum, DEPALLOC0x0001, &inodedep) == 0 ||
3041 (inodedep->id_stateid_list.wk_state & ALLCOMPLETE(0x0001 | 0x0004 | 0x0008)) == ALLCOMPLETE(0x0001 | 0x0004 | 0x0008)) {
3042 dap->da_stateda_list.wk_state |= COMPLETE0x0004;
3043 LIST_INSERT_HEAD(&pagedep->pd_pendinghd, dap, da_pdlist)do { if (((dap)->da_pdlist.le_next = (&pagedep->pd_pendinghd
)->lh_first) != ((void *)0)) (&pagedep->pd_pendinghd
)->lh_first->da_pdlist.le_prev = &(dap)->da_pdlist
.le_next; (&pagedep->pd_pendinghd)->lh_first = (dap
); (dap)->da_pdlist.le_prev = &(&pagedep->pd_pendinghd
)->lh_first; } while (0)
;
3044 WORKLIST_INSERT(&inodedep->id_pendinghd, &dap->da_list)do { (&dap->da_list)->wk_state |= 0x8000; do { if (
((&dap->da_list)->wk_list.le_next = (&inodedep->
id_pendinghd)->lh_first) != ((void *)0)) (&inodedep->
id_pendinghd)->lh_first->wk_list.le_prev = &(&dap
->da_list)->wk_list.le_next; (&inodedep->id_pendinghd
)->lh_first = (&dap->da_list); (&dap->da_list
)->wk_list.le_prev = &(&inodedep->id_pendinghd)
->lh_first; } while (0); } while (0)
;
3045 } else {
3046 LIST_INSERT_HEAD(&pagedep->pd_diraddhd[DIRADDHASH(offset)],do { if (((dap)->da_pdlist.le_next = (&pagedep->pd_diraddhd
[(((offset) >> 2) % 6)])->lh_first) != ((void *)0)) (
&pagedep->pd_diraddhd[(((offset) >> 2) % 6)])->
lh_first->da_pdlist.le_prev = &(dap)->da_pdlist.le_next
; (&pagedep->pd_diraddhd[(((offset) >> 2) % 6)])
->lh_first = (dap); (dap)->da_pdlist.le_prev = &(&
pagedep->pd_diraddhd[(((offset) >> 2) % 6)])->lh_first
; } while (0)
3047 dap, da_pdlist)do { if (((dap)->da_pdlist.le_next = (&pagedep->pd_diraddhd
[(((offset) >> 2) % 6)])->lh_first) != ((void *)0)) (
&pagedep->pd_diraddhd[(((offset) >> 2) % 6)])->
lh_first->da_pdlist.le_prev = &(dap)->da_pdlist.le_next
; (&pagedep->pd_diraddhd[(((offset) >> 2) % 6)])
->lh_first = (dap); (dap)->da_pdlist.le_prev = &(&
pagedep->pd_diraddhd[(((offset) >> 2) % 6)])->lh_first
; } while (0)
;
3048 WORKLIST_INSERT(&inodedep->id_bufwait, &dap->da_list)do { (&dap->da_list)->wk_state |= 0x8000; do { if (
((&dap->da_list)->wk_list.le_next = (&inodedep->
id_bufwait)->lh_first) != ((void *)0)) (&inodedep->
id_bufwait)->lh_first->wk_list.le_prev = &(&dap
->da_list)->wk_list.le_next; (&inodedep->id_bufwait
)->lh_first = (&dap->da_list); (&dap->da_list
)->wk_list.le_prev = &(&inodedep->id_bufwait)->
lh_first; } while (0); } while (0)
;
3049 }
3050 FREE_LOCK(&lk)spllower((&lk)->lkt_spl);
3051}
3052
3053/*
3054 * Called whenever the link count on an inode is changed.
3055 * It creates an inode dependency so that the new reference(s)
3056 * to the inode cannot be committed to disk until the updated
3057 * inode has been written.
3058 */
3059/* the inode with the increased link count */
3060/* do background work or not */
3061void
3062softdep_change_linkcnt(struct inode *ip, int nodelay)
3063{
3064 struct inodedep *inodedep;
3065 int flags;
3066
3067 /*
3068 * If requested, do not allow background work to happen.
3069 */
3070 flags = DEPALLOC0x0001;
3071 if (nodelay)
3072 flags |= NODELAY0x0002;
3073
3074 ACQUIRE_LOCK(&lk)(&lk)->lkt_spl = splraise(0x6);
3075
3076 (void) inodedep_lookup(ip->i_fsinode_u.fs, ip->i_number, flags, &inodedep);
3077 if (DIP(ip, nlink)(((ip)->i_ump->um_fstype == 1) ? (ip)->dinode_u.ffs1_din
->di_nlink : (ip)->dinode_u.ffs2_din->di_nlink)
< ip->i_effnlink) {
3078 FREE_LOCK(&lk)spllower((&lk)->lkt_spl);
3079 panic("softdep_change_linkcnt: bad delta");
3080 }
3081
3082 inodedep->id_nlinkdelta = DIP(ip, nlink)(((ip)->i_ump->um_fstype == 1) ? (ip)->dinode_u.ffs1_din
->di_nlink : (ip)->dinode_u.ffs2_din->di_nlink)
- ip->i_effnlink;
3083
3084 FREE_LOCK(&lk)spllower((&lk)->lkt_spl);
3085}
3086
3087/*
3088 * This workitem decrements the inode's link count.
3089 * If the link count reaches zero, the file is removed.
3090 */
3091STATIC void
3092handle_workitem_remove(struct dirrem *dirrem)
3093{
3094 struct proc *p = CURPROC({struct cpu_info *__ci; asm volatile("movq %%gs:%P1,%0" : "=r"
(__ci) :"n" (__builtin_offsetof(struct cpu_info, ci_self)));
__ci;})->ci_curproc
; /* XXX */
3095 struct inodedep *inodedep;
3096 struct vnode *vp;
3097 struct inode *ip;
3098 ufsino_t oldinum;
3099 int error;
3100
3101 if ((error = VFS_VGET(dirrem->dm_mnt, dirrem->dm_oldinum, &vp)(*(dirrem->dm_mnt)->mnt_op->vfs_vget)(dirrem->dm_mnt
, dirrem->dm_oldinum, &vp)
) != 0) {
3102 softdep_error("handle_workitem_remove: vget", error);
3103 return;
3104 }
3105 ip = VTOI(vp)((struct inode *)(vp)->v_data);
3106 ACQUIRE_LOCK(&lk)(&lk)->lkt_spl = splraise(0x6);
3107 if ((inodedep_lookup(ip->i_fsinode_u.fs, dirrem->dm_oldinum, 0, &inodedep))
3108 == 0) {
3109 FREE_LOCK(&lk)spllower((&lk)->lkt_spl);
3110 panic("handle_workitem_remove: lost inodedep");
3111 }
3112 /*
3113 * Normal file deletion.
3114 */
3115 if ((dirrem->dm_statedm_list.wk_state & RMDIR0x0040) == 0) {
3116 DIP_ADD(ip, nlink, -1)do { if ((ip)->i_ump->um_fstype == 1) (ip)->dinode_u
.ffs1_din->di_nlink += (-1); else (ip)->dinode_u.ffs2_din
->di_nlink += (-1); } while (0)
;
3117 ip->i_flag |= IN_CHANGE0x0002;
3118 if (DIP(ip, nlink)(((ip)->i_ump->um_fstype == 1) ? (ip)->dinode_u.ffs1_din
->di_nlink : (ip)->dinode_u.ffs2_din->di_nlink)
< ip->i_effnlink) {
3119 FREE_LOCK(&lk)spllower((&lk)->lkt_spl);
3120 panic("handle_workitem_remove: bad file delta");
3121 }
3122 inodedep->id_nlinkdelta = DIP(ip, nlink)(((ip)->i_ump->um_fstype == 1) ? (ip)->dinode_u.ffs1_din
->di_nlink : (ip)->dinode_u.ffs2_din->di_nlink)
- ip->i_effnlink;
3123 FREE_LOCK(&lk)spllower((&lk)->lkt_spl);
3124 vput(vp);
3125 num_dirrem -= 1;
3126 WORKITEM_FREE(dirrem, D_DIRREM)softdep_freequeue_add((struct worklist *)dirrem);
3127 return;
3128 }
3129 /*
3130 * Directory deletion. Decrement reference count for both the
3131 * just deleted parent directory entry and the reference for ".".
3132 * Next truncate the directory to length zero. When the
3133 * truncation completes, arrange to have the reference count on
3134 * the parent decremented to account for the loss of "..".
3135 */
3136 DIP_ADD(ip, nlink, -2)do { if ((ip)->i_ump->um_fstype == 1) (ip)->dinode_u
.ffs1_din->di_nlink += (-2); else (ip)->dinode_u.ffs2_din
->di_nlink += (-2); } while (0)
;
3137 ip->i_flag |= IN_CHANGE0x0002;
3138 if (DIP(ip, nlink)(((ip)->i_ump->um_fstype == 1) ? (ip)->dinode_u.ffs1_din
->di_nlink : (ip)->dinode_u.ffs2_din->di_nlink)
< ip->i_effnlink)
3139 panic("handle_workitem_remove: bad dir delta");
3140 inodedep->id_nlinkdelta = DIP(ip, nlink)(((ip)->i_ump->um_fstype == 1) ? (ip)->dinode_u.ffs1_din
->di_nlink : (ip)->dinode_u.ffs2_din->di_nlink)
- ip->i_effnlink;
3141 FREE_LOCK(&lk)spllower((&lk)->lkt_spl);
3142 if ((error = UFS_TRUNCATE(ip, (off_t)0, 0, p->p_ucred)((ip)->i_vtbl->iv_truncate)((ip), ((off_t)0), (0), (p->
p_ucred))
) != 0)
3143 softdep_error("handle_workitem_remove: truncate", error);
3144 /*
3145 * Rename a directory to a new parent. Since, we are both deleting
3146 * and creating a new directory entry, the link count on the new
3147 * directory should not change. Thus we skip the followup dirrem.
3148 */
3149 if (dirrem->dm_statedm_list.wk_state & DIRCHG0x0080) {
3150 vput(vp);
3151 num_dirrem -= 1;
3152 WORKITEM_FREE(dirrem, D_DIRREM)softdep_freequeue_add((struct worklist *)dirrem);
3153 return;
3154 }
3155 /*
3156 * If the inodedep does not exist, then the zero'ed inode has
3157 * been written to disk. If the allocated inode has never been
3158 * written to disk, then the on-disk inode is zero'ed. In either
3159 * case we can remove the file immediately.
3160 */
3161 ACQUIRE_LOCK(&lk)(&lk)->lkt_spl = splraise(0x6);
3162 dirrem->dm_statedm_list.wk_state = 0;
3163 oldinum = dirrem->dm_oldinum;
3164 dirrem->dm_oldinum = dirrem->dm_dirinumdm_un.dmu_dirinum;
3165 if (inodedep_lookup(ip->i_fsinode_u.fs, oldinum, 0, &inodedep) == 0 ||
3166 check_inode_unwritten(inodedep)) {
3167 FREE_LOCK(&lk)spllower((&lk)->lkt_spl);
3168 vput(vp);
3169 handle_workitem_remove(dirrem);
3170 return;
3171 }
3172 WORKLIST_INSERT(&inodedep->id_inowait, &dirrem->dm_list)do { (&dirrem->dm_list)->wk_state |= 0x8000; do { if
(((&dirrem->dm_list)->wk_list.le_next = (&inodedep
->id_inowait)->lh_first) != ((void *)0)) (&inodedep
->id_inowait)->lh_first->wk_list.le_prev = &(&
dirrem->dm_list)->wk_list.le_next; (&inodedep->id_inowait
)->lh_first = (&dirrem->dm_list); (&dirrem->
dm_list)->wk_list.le_prev = &(&inodedep->id_inowait
)->lh_first; } while (0); } while (0)
;
3173 FREE_LOCK(&lk)spllower((&lk)->lkt_spl);
3174 ip->i_flag |= IN_CHANGE0x0002;
3175 UFS_UPDATE(VTOI(vp), 0)((((struct inode *)(vp)->v_data))->i_vtbl->iv_update
)((((struct inode *)(vp)->v_data)), (0))
;
3176 vput(vp);
3177}
3178
3179/*
3180 * Inode de-allocation dependencies.
3181 *
3182 * When an inode's link count is reduced to zero, it can be de-allocated. We
3183 * found it convenient to postpone de-allocation until after the inode is
3184 * written to disk with its new link count (zero). At this point, all of the
3185 * on-disk inode's block pointers are nullified and, with careful dependency
3186 * list ordering, all dependencies related to the inode will be satisfied and
3187 * the corresponding dependency structures de-allocated. So, if/when the
3188 * inode is reused, there will be no mixing of old dependencies with new
3189 * ones. This artificial dependency is set up by the block de-allocation
3190 * procedure above (softdep_setup_freeblocks) and completed by the
3191 * following procedure.
3192 */
3193STATIC void
3194handle_workitem_freefile(struct freefile *freefile)
3195{
3196 struct fs *fs;
3197 struct vnode vp;
3198 struct inode tip;
3199#ifdef DEBUG
3200 struct inodedep *idp;
3201#endif
3202 int error;
3203
3204 fs = VFSTOUFS(freefile->fx_mnt)((struct ufsmount *)((freefile->fx_mnt)->mnt_data))->um_fsufsmount_u.fs;
3205#ifdef DEBUG
3206 ACQUIRE_LOCK(&lk)(&lk)->lkt_spl = splraise(0x6);
3207 error = inodedep_lookup(fs, freefile->fx_oldinum, 0, &idp);
3208 FREE_LOCK(&lk)spllower((&lk)->lkt_spl);
3209 if (error)
3210 panic("handle_workitem_freefile: inodedep survived");
3211#endif
3212 tip.i_ump = VFSTOUFS(freefile->fx_mnt)((struct ufsmount *)((freefile->fx_mnt)->mnt_data));
3213 tip.i_dev = freefile->fx_devvp->v_rdevv_un.vu_specinfo->si_rdev;
3214 tip.i_fsinode_u.fs = fs;
3215 tip.i_vnode = &vp;
3216 vp.v_data = &tip;
3217
3218 if ((error = ffs_freefile(&tip, freefile->fx_oldinum,
3219 freefile->fx_mode)) != 0) {
3220 softdep_error("handle_workitem_freefile", error);
3221 }
3222 WORKITEM_FREE(freefile, D_FREEFILE)softdep_freequeue_add((struct worklist *)freefile);
3223}
3224
3225/*
3226 * Disk writes.
3227 *
3228 * The dependency structures constructed above are most actively used when file
3229 * system blocks are written to disk. No constraints are placed on when a
3230 * block can be written, but unsatisfied update dependencies are made safe by
3231 * modifying (or replacing) the source memory for the duration of the disk
3232 * write. When the disk write completes, the memory block is again brought
3233 * up-to-date.
3234 *
3235 * In-core inode structure reclamation.
3236 *
3237 * Because there are a finite number of "in-core" inode structures, they are
3238 * reused regularly. By transferring all inode-related dependencies to the
3239 * in-memory inode block and indexing them separately (via "inodedep"s), we
3240 * can allow "in-core" inode structures to be reused at any time and avoid
3241 * any increase in contention.
3242 *
3243 * Called just before entering the device driver to initiate a new disk I/O.
3244 * The buffer must be locked, thus, no I/O completion operations can occur
3245 * while we are manipulating its associated dependencies.
3246 */
3247/* structure describing disk write to occur */
3248void
3249softdep_disk_io_initiation(struct buf *bp)
3250{
3251 struct worklist *wk, *nextwk;
3252 struct indirdep *indirdep;
3253 struct inodedep *inodedep;
3254 struct buf *sbp;
3255
3256 /*
3257 * We only care about write operations. There should never
3258 * be dependencies for reads.
3259 */
3260 if (bp->b_flags & B_READ0x00008000)
3261 panic("softdep_disk_io_initiation: read");
3262
3263 ACQUIRE_LOCK(&lk)(&lk)->lkt_spl = splraise(0x6);
3264
3265 /*
3266 * Do any necessary pre-I/O processing.
3267 */
3268 for (wk = LIST_FIRST(&bp->b_dep)((&bp->b_dep)->lh_first); wk; wk = nextwk) {
3269 nextwk = LIST_NEXT(wk, wk_list)((wk)->wk_list.le_next);
3270 switch (wk->wk_type) {
3271
3272 case D_PAGEDEP0:
3273 initiate_write_filepage(WK_PAGEDEP(wk)((struct pagedep *)(wk)), bp);
3274 continue;
3275
3276 case D_INODEDEP1:
3277 inodedep = WK_INODEDEP(wk)((struct inodedep *)(wk));
3278 if (inodedep->id_fs->fs_magic == FS_UFS1_MAGIC0x011954)
3279 initiate_write_inodeblock_ufs1(inodedep, bp);
3280#ifdef FFS21
3281 else
3282 initiate_write_inodeblock_ufs2(inodedep, bp);
3283#endif
3284 continue;
3285
3286 case D_INDIRDEP5:
3287 indirdep = WK_INDIRDEP(wk)((struct indirdep *)(wk));
3288 if (indirdep->ir_stateir_list.wk_state & GOINGAWAY0x0100)
3289 panic("disk_io_initiation: indirdep gone");
3290 /*
3291 * If there are no remaining dependencies, this
3292 * will be writing the real pointers, so the
3293 * dependency can be freed.
3294 */
3295 if (LIST_FIRST(&indirdep->ir_deplisthd)((&indirdep->ir_deplisthd)->lh_first) == NULL((void *)0)) {
3296 sbp = indirdep->ir_savebp;
3297 sbp->b_flags |= B_INVAL0x00000800 | B_NOCACHE0x00001000;
3298 /* inline expand WORKLIST_REMOVE(wk); */
3299 wk->wk_state &= ~ONWORKLIST0x8000;
3300 LIST_REMOVE(wk, wk_list)do { if ((wk)->wk_list.le_next != ((void *)0)) (wk)->wk_list
.le_next->wk_list.le_prev = (wk)->wk_list.le_prev; *(wk
)->wk_list.le_prev = (wk)->wk_list.le_next; ((wk)->wk_list
.le_prev) = ((void *)-1); ((wk)->wk_list.le_next) = ((void
*)-1); } while (0)
;
3301 WORKITEM_FREE(indirdep, D_INDIRDEP)softdep_freequeue_add((struct worklist *)indirdep);
3302 FREE_LOCK(&lk)spllower((&lk)->lkt_spl);
3303 brelse(sbp);
3304 ACQUIRE_LOCK(&lk)(&lk)->lkt_spl = splraise(0x6);
3305 continue;
3306 }
3307 /*
3308 * Replace up-to-date version with safe version.
3309 */
3310 FREE_LOCK(&lk)spllower((&lk)->lkt_spl);
3311 indirdep->ir_saveddata = malloc(bp->b_bcount,
3312 M_INDIRDEP83, M_WAITOK0x0001);
3313 ACQUIRE_LOCK(&lk)(&lk)->lkt_spl = splraise(0x6);
3314 indirdep->ir_stateir_list.wk_state &= ~ATTACHED0x0001;
3315 indirdep->ir_stateir_list.wk_state |= UNDONE0x0002;
3316 memcpy(indirdep->ir_saveddata, bp->b_data, bp->b_bcount)__builtin_memcpy((indirdep->ir_saveddata), (bp->b_data)
, (bp->b_bcount))
;
3317 memcpy(bp->b_data, indirdep->ir_savebp->b_data,__builtin_memcpy((bp->b_data), (indirdep->ir_savebp->
b_data), (bp->b_bcount))
3318 bp->b_bcount)__builtin_memcpy((bp->b_data), (indirdep->ir_savebp->
b_data), (bp->b_bcount))
;
3319 continue;
3320
3321 case D_MKDIR11:
3322 case D_BMSAFEMAP3:
3323 case D_ALLOCDIRECT4:
3324 case D_ALLOCINDIR6:
3325 continue;
3326
3327 default:
3328 FREE_LOCK(&lk)spllower((&lk)->lkt_spl);
3329 panic("handle_disk_io_initiation: Unexpected type %s",
3330 TYPENAME(wk->wk_type)((unsigned)(wk->wk_type) <= 13 ? softdep_typenames[wk->
wk_type] : "???")
);
3331 /* NOTREACHED */
3332 }
3333 }
3334
3335 FREE_LOCK(&lk)spllower((&lk)->lkt_spl);
3336}
3337
3338/*
3339 * Called from within the procedure above to deal with unsatisfied
3340 * allocation dependencies in a directory. The buffer must be locked,
3341 * thus, no I/O completion operations can occur while we are
3342 * manipulating its associated dependencies.
3343 */
3344STATIC void
3345initiate_write_filepage(struct pagedep *pagedep, struct buf *bp)
3346{
3347 struct diradd *dap;
3348 struct direct *ep;
3349 int i;
3350
3351 if (pagedep->pd_statepd_list.wk_state & IOSTARTED0x0200) {
3352 /*
3353 * This can only happen if there is a driver that does not
3354 * understand chaining. Here biodone will reissue the call
3355 * to strategy for the incomplete buffers.
3356 */
3357 printf("initiate_write_filepage: already started\n");
3358 return;
3359 }
3360 pagedep->pd_statepd_list.wk_state |= IOSTARTED0x0200;
3361 for (i = 0; i < DAHASHSZ6; i++) {
3362 LIST_FOREACH(dap, &pagedep->pd_diraddhd[i], da_pdlist)for((dap) = ((&pagedep->pd_diraddhd[i])->lh_first);
(dap)!= ((void *)0); (dap) = ((dap)->da_pdlist.le_next))
{
3363 ep = (struct direct *)
3364 ((char *)bp->b_data + dap->da_offset);
3365 if (ep->d_ino != dap->da_newinum) {
3366 FREE_LOCK(&lk)spllower((&lk)->lkt_spl);
3367 panic("%s: dir inum %u != new %u",
3368 "initiate_write_filepage",
3369 ep->d_ino, dap->da_newinum);
3370 }
3371 if (dap->da_stateda_list.wk_state & DIRCHG0x0080)
3372 ep->d_ino = dap->da_previousda_un.dau_previous->dm_oldinum;
3373 else
3374 ep->d_ino = 0;
3375 dap->da_stateda_list.wk_state &= ~ATTACHED0x0001;
3376 dap->da_stateda_list.wk_state |= UNDONE0x0002;
3377 }
3378 }
3379}
3380
3381/*
3382 * Called from within the procedure above to deal with unsatisfied
3383 * allocation dependencies in an inodeblock. The buffer must be
3384 * locked, thus, no I/O completion operations can occur while we
3385 * are manipulating its associated dependencies.
3386 */
3387/* The inode block */
3388STATIC void
3389initiate_write_inodeblock_ufs1(struct inodedep *inodedep, struct buf *bp)
3390{
3391 struct allocdirect *adp, *lastadp;
3392 struct ufs1_dinode *dp;
3393 struct fs *fs;
3394#ifdef DIAGNOSTIC1
3395 daddr_t prevlbn = 0;
3396 int32_t d1, d2;
3397#endif
3398 int i, deplist;
3399
3400 if (inodedep->id_stateid_list.wk_state & IOSTARTED0x0200) {
3401 FREE_LOCK(&lk)spllower((&lk)->lkt_spl);
3402 panic("initiate_write_inodeblock: already started");
3403 }
3404 inodedep->id_stateid_list.wk_state |= IOSTARTED0x0200;
3405 fs = inodedep->id_fs;
3406 dp = (struct ufs1_dinode *)bp->b_data +
3407 ino_to_fsbo(fs, inodedep->id_ino)((inodedep->id_ino) % ((fs)->fs_inopb));
3408 /*
3409 * If the bitmap is not yet written, then the allocated
3410 * inode cannot be written to disk.
3411 */
3412 if ((inodedep->id_stateid_list.wk_state & DEPCOMPLETE0x0008) == 0) {
3413 if (inodedep->id_savedino1id_un.idu_savedino1 != NULL((void *)0)) {
3414 FREE_LOCK(&lk)spllower((&lk)->lkt_spl);
3415 panic("initiate_write_inodeblock: already doing I/O");
3416 }
3417 FREE_LOCK(&lk)spllower((&lk)->lkt_spl);
3418 inodedep->id_savedino1id_un.idu_savedino1 = malloc(sizeof(struct ufs1_dinode),
3419 M_INODEDEP79, M_WAITOK0x0001);
3420 inodedep->id_unsize = sizeof(struct ufs1_dinode);
3421 ACQUIRE_LOCK(&lk)(&lk)->lkt_spl = splraise(0x6);
3422 *inodedep->id_savedino1id_un.idu_savedino1 = *dp;
3423 memset(dp, 0, sizeof(struct ufs1_dinode))__builtin_memset((dp), (0), (sizeof(struct ufs1_dinode)));
3424 return;
3425 }
3426 /*
3427 * If no dependencies, then there is nothing to roll back.
3428 */
3429 inodedep->id_savedsize = dp->di_size;
3430 if (TAILQ_FIRST(&inodedep->id_inoupdt)((&inodedep->id_inoupdt)->tqh_first) == NULL((void *)0))
3431 return;
3432 /*
3433 * Set the dependencies to busy.
3434 */
3435 for (deplist = 0, adp = TAILQ_FIRST(&inodedep->id_inoupdt)((&inodedep->id_inoupdt)->tqh_first); adp;
3436 adp = TAILQ_NEXT(adp, ad_next)((adp)->ad_next.tqe_next)) {
3437#ifdef DIAGNOSTIC1
3438 if (deplist != 0 && prevlbn >= adp->ad_lbn) {
3439 FREE_LOCK(&lk)spllower((&lk)->lkt_spl);
3440 panic("softdep_write_inodeblock: lbn order");
3441 }
3442 prevlbn = adp->ad_lbn;
3443 if (adp->ad_lbn < NDADDR12 &&
3444 (d1 = dp->di_db[adp->ad_lbn]) != (d2 = adp->ad_newblkno)) {
3445 FREE_LOCK(&lk)spllower((&lk)->lkt_spl);
3446 panic("%s: direct pointer #%lld mismatch %d != %d",
3447 "softdep_write_inodeblock", (long long)adp->ad_lbn,
3448 d1, d2);
3449 }
3450 if (adp->ad_lbn >= NDADDR12 &&
3451 (d1 = dp->di_ib[adp->ad_lbn - NDADDR12]) !=
3452 (d2 = adp->ad_newblkno)) {
3453 FREE_LOCK(&lk)spllower((&lk)->lkt_spl);
3454 panic("%s: indirect pointer #%lld mismatch %d != %d",
3455 "softdep_write_inodeblock", (long long)(adp->ad_lbn -
3456 NDADDR12), d1, d2);
3457 }
3458 deplist |= 1 << adp->ad_lbn;
3459 if ((adp->ad_statead_list.wk_state & ATTACHED0x0001) == 0) {
3460 FREE_LOCK(&lk)spllower((&lk)->lkt_spl);
3461 panic("softdep_write_inodeblock: Unknown state 0x%x",
3462 adp->ad_statead_list.wk_state);
3463 }
3464#endif /* DIAGNOSTIC */
3465 adp->ad_statead_list.wk_state &= ~ATTACHED0x0001;
3466 adp->ad_statead_list.wk_state |= UNDONE0x0002;
3467 }
3468 /*
3469 * The on-disk inode cannot claim to be any larger than the last
3470 * fragment that has been written. Otherwise, the on-disk inode
3471 * might have fragments that were not the last block in the file
3472 * which would corrupt the filesystem.
3473 */
3474 for (lastadp = NULL((void *)0), adp = TAILQ_FIRST(&inodedep->id_inoupdt)((&inodedep->id_inoupdt)->tqh_first); adp;
3475 lastadp = adp, adp = TAILQ_NEXT(adp, ad_next)((adp)->ad_next.tqe_next)) {
3476 if (adp->ad_lbn >= NDADDR12)
3477 break;
3478 dp->di_db[adp->ad_lbn] = adp->ad_oldblkno;
3479 /* keep going until hitting a rollback to a frag */
3480 if (adp->ad_oldsize == 0 || adp->ad_oldsize == fs->fs_bsize)
3481 continue;
3482 dp->di_size = fs->fs_bsize * adp->ad_lbn + adp->ad_oldsize;
3483 for (i = adp->ad_lbn + 1; i < NDADDR12; i++) {
3484#ifdef DIAGNOSTIC1
3485 if (dp->di_db[i] != 0 && (deplist & (1 << i)) == 0) {
3486 FREE_LOCK(&lk)spllower((&lk)->lkt_spl);
3487 panic("softdep_write_inodeblock: lost dep1");
3488 }
3489#endif /* DIAGNOSTIC */
3490 dp->di_db[i] = 0;
3491 }
3492 for (i = 0; i < NIADDR3; i++) {
3493#ifdef DIAGNOSTIC1
3494 if (dp->di_ib[i] != 0 &&
3495 (deplist & ((1 << NDADDR12) << i)) == 0) {
3496 FREE_LOCK(&lk)spllower((&lk)->lkt_spl);
3497 panic("softdep_write_inodeblock: lost dep2");
3498 }
3499#endif /* DIAGNOSTIC */
3500 dp->di_ib[i] = 0;
3501 }
3502 return;
3503 }
3504 /*
3505 * If we have zero'ed out the last allocated block of the file,
3506 * roll back the size to the last currently allocated block.
3507 * We know that this last allocated block is a full-sized as
3508 * we already checked for fragments in the loop above.
3509 */
3510 if (lastadp != NULL((void *)0) &&
3511 dp->di_size <= (lastadp->ad_lbn + 1) * fs->fs_bsize) {
3512 for (i = lastadp->ad_lbn; i >= 0; i--)
3513 if (dp->di_db[i] != 0)
3514 break;
3515 dp->di_size = (i + 1) * fs->fs_bsize;
3516 }
3517 /*
3518 * The only dependencies are for indirect blocks.
3519 *
3520 * The file size for indirect block additions is not guaranteed.
3521 * Such a guarantee would be non-trivial to achieve. The conventional
3522 * synchronous write implementation also does not make this guarantee.
3523 * Fsck should catch and fix discrepancies. Arguably, the file size
3524 * can be over-estimated without destroying integrity when the file
3525 * moves into the indirect blocks (i.e., is large). If we want to
3526 * postpone fsck, we are stuck with this argument.
3527 */
3528 for (; adp; adp = TAILQ_NEXT(adp, ad_next)((adp)->ad_next.tqe_next))
3529 dp->di_ib[adp->ad_lbn - NDADDR12] = 0;
3530}
3531
3532#ifdef FFS21
3533/*
3534 * Version of initiate_write_inodeblock that handles FFS2 dinodes.
3535 */
3536/* The inode block */
3537STATIC void
3538initiate_write_inodeblock_ufs2(struct inodedep *inodedep, struct buf *bp)
3539{
3540 struct allocdirect *adp, *lastadp;
3541 struct ufs2_dinode *dp;
3542 struct fs *fs = inodedep->id_fs;
Value stored to 'fs' during its initialization is never read
3543#ifdef DIAGNOSTIC1
3544 daddr_t prevlbn = -1, d1, d2;
3545#endif
3546 int deplist, i;
3547
3548 if (inodedep->id_stateid_list.wk_state & IOSTARTED0x0200)
3549 panic("initiate_write_inodeblock_ufs2: already started");
3550 inodedep->id_stateid_list.wk_state |= IOSTARTED0x0200;
3551 fs = inodedep->id_fs;
3552 dp = (struct ufs2_dinode *)bp->b_data +
3553 ino_to_fsbo(fs, inodedep->id_ino)((inodedep->id_ino) % ((fs)->fs_inopb));
3554 /*
3555 * If the bitmap is not yet written, then the allocated
3556 * inode cannot be written to disk.
3557 */
3558 if ((inodedep->id_stateid_list.wk_state & DEPCOMPLETE0x0008) == 0) {
3559 if (inodedep->id_savedino2id_un.idu_savedino2 != NULL((void *)0))
3560 panic("initiate_write_inodeblock_ufs2: I/O underway");
3561 inodedep->id_savedino2id_un.idu_savedino2 = malloc(sizeof(struct ufs2_dinode),
3562 M_INODEDEP79, M_WAITOK0x0001);
3563 inodedep->id_unsize = sizeof(struct ufs2_dinode);
3564 *inodedep->id_savedino2id_un.idu_savedino2 = *dp;
3565 memset(dp, 0, sizeof(struct ufs2_dinode))__builtin_memset((dp), (0), (sizeof(struct ufs2_dinode)));
3566 return;
3567 }
3568 /*
3569 * If no dependencies, then there is nothing to roll back.
3570 */
3571 inodedep->id_savedsize = dp->di_size;
3572 if (TAILQ_FIRST(&inodedep->id_inoupdt)((&inodedep->id_inoupdt)->tqh_first) == NULL((void *)0))
3573 return;
3574
3575#ifdef notyet
3576 inodedep->id_savedextsize = dp->di_extsize;
3577 if (TAILQ_FIRST(&inodedep->id_inoupdt)((&inodedep->id_inoupdt)->tqh_first) == NULL((void *)0) &&
3578 TAILQ_FIRST(&inodedep->id_extupdt)((&inodedep->id_extupdt)->tqh_first) == NULL((void *)0))
3579 return;
3580 /*
3581 * Set the ext data dependencies to busy.
3582 */
3583 for (deplist = 0, adp = TAILQ_FIRST(&inodedep->id_extupdt)((&inodedep->id_extupdt)->tqh_first); adp;
3584 adp = TAILQ_NEXT(adp, ad_next)((adp)->ad_next.tqe_next)) {
3585#ifdef DIAGNOSTIC1
3586 if (deplist != 0 && prevlbn >= adp->ad_lbn) {
3587 FREE_LOCK(&lk)spllower((&lk)->lkt_spl);
3588 panic("softdep_write_inodeblock: lbn order");
3589 }
3590 prevlbn = adp->ad_lbn;
3591 if ((d1 = dp->di_extb[adp->ad_lbn]) !=
3592 (d2 = adp->ad_newblkno)) {
3593 FREE_LOCK(&lk)spllower((&lk)->lkt_spl);
3594 panic("%s: direct pointer #%lld mismatch %lld != %lld",
3595 "softdep_write_inodeblock", (long long)adp->ad_lbn,
3596 d1, d2);
3597 }
3598 deplist |= 1 << adp->ad_lbn;
3599 if ((adp->ad_statead_list.wk_state & ATTACHED0x0001) == 0) {
3600 FREE_LOCK(&lk)spllower((&lk)->lkt_spl);
3601 panic("softdep_write_inodeblock: Unknown state 0x%x",
3602 adp->ad_statead_list.wk_state);
3603 }
3604#endif /* DIAGNOSTIC */
3605 adp->ad_statead_list.wk_state &= ~ATTACHED0x0001;
3606 adp->ad_statead_list.wk_state |= UNDONE0x0002;
3607 }
3608 /*
3609 * The on-disk inode cannot claim to be any larger than the last
3610 * fragment that has been written. Otherwise, the on-disk inode
3611 * might have fragments that were not the last block in the ext
3612 * data which would corrupt the filesystem.
3613 */
3614 for (lastadp = NULL((void *)0), adp = TAILQ_FIRST(&inodedep->id_extupdt)((&inodedep->id_extupdt)->tqh_first); adp;
3615 lastadp = adp, adp = TAILQ_NEXT(adp, ad_next)((adp)->ad_next.tqe_next)) {
3616 dp->di_extb[adp->ad_lbn] = adp->ad_oldblkno;
3617 /* keep going until hitting a rollback to a frag */
3618 if (adp->ad_oldsize == 0 || adp->ad_oldsize == fs->fs_bsize)
3619 continue;
3620 dp->di_extsize = fs->fs_bsize * adp->ad_lbn + adp->ad_oldsize;
3621 for (i = adp->ad_lbn + 1; i < NXADDR2; i++) {
3622#ifdef DIAGNOSTIC1
3623 if (dp->di_extb[i] != 0 && (deplist & (1 << i)) == 0) {
3624 FREE_LOCK(&lk)spllower((&lk)->lkt_spl);
3625 panic("softdep_write_inodeblock: lost dep1");
3626 }
3627#endif /* DIAGNOSTIC */
3628 dp->di_extb[i] = 0;
3629 }
3630 lastadp = NULL((void *)0);
3631 break;
3632 }
3633 /*
3634 * If we have zero'ed out the last allocated block of the ext
3635 * data, roll back the size to the last currently allocated block.
3636 * We know that this last allocated block is a full-sized as
3637 * we already checked for fragments in the loop above.
3638 */
3639 if (lastadp != NULL((void *)0) &&
3640 dp->di_extsize <= (lastadp->ad_lbn + 1) * fs->fs_bsize) {
3641 for (i = lastadp->ad_lbn; i >= 0; i--)
3642 if (dp->di_extb[i] != 0)
3643 break;
3644 dp->di_extsize = (i + 1) * fs->fs_bsize;
3645 }
3646#endif /* notyet */
3647
3648 /*
3649 * Set the file data dependencies to busy.
3650 */
3651 for (deplist = 0, adp = TAILQ_FIRST(&inodedep->id_inoupdt)((&inodedep->id_inoupdt)->tqh_first); adp;
3652 adp = TAILQ_NEXT(adp, ad_next)((adp)->ad_next.tqe_next)) {
3653#ifdef DIAGNOSTIC1
3654 if (deplist != 0 && prevlbn >= adp->ad_lbn) {
3655 FREE_LOCK(&lk)spllower((&lk)->lkt_spl);
3656 panic("softdep_write_inodeblock: lbn order");
3657 }
3658 prevlbn = adp->ad_lbn;
3659 if (adp->ad_lbn < NDADDR12 &&
3660 (d1 = dp->di_db[adp->ad_lbn]) != (d2 = adp->ad_newblkno)) {
3661 FREE_LOCK(&lk)spllower((&lk)->lkt_spl);
3662 panic("%s: direct pointer #%lld mismatch %lld != %lld",
3663 "softdep_write_inodeblock", (long long)adp->ad_lbn,
3664 d1, d2);
3665 }
3666 if (adp->ad_lbn >= NDADDR12 &&
3667 (d1 = dp->di_ib[adp->ad_lbn - NDADDR12]) !=
3668 (d2 = adp->ad_newblkno)) {
3669 FREE_LOCK(&lk)spllower((&lk)->lkt_spl);
3670 panic("%s: indirect pointer #%lld mismatch %lld != %lld",
3671 "softdep_write_inodeblock", (long long)(adp->ad_lbn -
3672 NDADDR12), d1, d2);
3673 }
3674 deplist |= 1 << adp->ad_lbn;
3675 if ((adp->ad_statead_list.wk_state & ATTACHED0x0001) == 0) {
3676 FREE_LOCK(&lk)spllower((&lk)->lkt_spl);
3677 panic("softdep_write_inodeblock: Unknown state 0x%x",
3678 adp->ad_statead_list.wk_state);
3679 }
3680#endif /* DIAGNOSTIC */
3681 adp->ad_statead_list.wk_state &= ~ATTACHED0x0001;
3682 adp->ad_statead_list.wk_state |= UNDONE0x0002;
3683 }
3684 /*
3685 * The on-disk inode cannot claim to be any larger than the last
3686 * fragment that has been written. Otherwise, the on-disk inode
3687 * might have fragments that were not the last block in the file
3688 * which would corrupt the filesystem.
3689 */
3690 for (lastadp = NULL((void *)0), adp = TAILQ_FIRST(&inodedep->id_inoupdt)((&inodedep->id_inoupdt)->tqh_first); adp;
3691 lastadp = adp, adp = TAILQ_NEXT(adp, ad_next)((adp)->ad_next.tqe_next)) {
3692 if (adp->ad_lbn >= NDADDR12)
3693 break;
3694 dp->di_db[adp->ad_lbn] = adp->ad_oldblkno;
3695 /* keep going until hitting a rollback to a frag */
3696 if (adp->ad_oldsize == 0 || adp->ad_oldsize == fs->fs_bsize)
3697 continue;
3698 dp->di_size = fs->fs_bsize * adp->ad_lbn + adp->ad_oldsize;
3699 for (i = adp->ad_lbn + 1; i < NDADDR12; i++) {
3700#ifdef DIAGNOSTIC1
3701 if (dp->di_db[i] != 0 && (deplist & (1 << i)) == 0) {
3702 FREE_LOCK(&lk)spllower((&lk)->lkt_spl);
3703 panic("softdep_write_inodeblock: lost dep2");
3704 }
3705#endif /* DIAGNOSTIC */
3706 dp->di_db[i] = 0;
3707 }
3708 for (i = 0; i < NIADDR3; i++) {
3709#ifdef DIAGNOSTIC1
3710 if (dp->di_ib[i] != 0 &&
3711 (deplist & ((1 << NDADDR12) << i)) == 0) {
3712 FREE_LOCK(&lk)spllower((&lk)->lkt_spl);
3713 panic("softdep_write_inodeblock: lost dep3");
3714 }
3715#endif /* DIAGNOSTIC */
3716 dp->di_ib[i] = 0;
3717 }
3718 return;
3719 }
3720 /*
3721 * If we have zero'ed out the last allocated block of the file,
3722 * roll back the size to the last currently allocated block.
3723 * We know that this last allocated block is a full-sized as
3724 * we already checked for fragments in the loop above.
3725 */
3726 if (lastadp != NULL((void *)0) &&
3727 dp->di_size <= (lastadp->ad_lbn + 1) * fs->fs_bsize) {
3728 for (i = lastadp->ad_lbn; i >= 0; i--)
3729 if (dp->di_db[i] != 0)
3730 break;
3731 dp->di_size = (i + 1) * fs->fs_bsize;
3732 }
3733 /*
3734 * The only dependencies are for indirect blocks.
3735 *
3736 * The file size for indirect block additions is not guaranteed.
3737 * Such a guarantee would be non-trivial to achieve. The conventional
3738 * synchronous write implementation also does not make this guarantee.
3739 * Fsck should catch and fix discrepancies. Arguably, the file size
3740 * can be over-estimated without destroying integrity when the file
3741 * moves into the indirect blocks (i.e., is large). If we want to
3742 * postpone fsck, we are stuck with this argument.
3743 */
3744 for (; adp; adp = TAILQ_NEXT(adp, ad_next)((adp)->ad_next.tqe_next))
3745 dp->di_ib[adp->ad_lbn - NDADDR12] = 0;
3746}
3747#endif /* FFS2 */
3748
3749/*
3750 * This routine is called during the completion interrupt
3751 * service routine for a disk write (from the procedure called
3752 * by the device driver to inform the file system caches of
3753 * a request completion). It should be called early in this
3754 * procedure, before the block is made available to other
3755 * processes or other routines are called.
3756 */
3757/* describes the completed disk write */
3758void
3759softdep_disk_write_complete(struct buf *bp)
3760{
3761 struct worklist *wk;
3762 struct workhead reattach;
3763 struct newblk *newblk;
3764 struct allocindir *aip;
3765 struct allocdirect *adp;
3766 struct indirdep *indirdep;
3767 struct inodedep *inodedep;
3768 struct bmsafemap *bmsafemap;
3769
3770 /*
3771 * If an error occurred while doing the write, then the data
3772 * has not hit the disk and the dependencies cannot be unrolled.
3773 */
3774 if ((bp->b_flags & B_ERROR0x00000400) && !(bp->b_flags & B_INVAL0x00000800))
3775 return;
3776
3777#ifdef DEBUG
3778 if (lk.lkt_held != -1)
3779 panic("softdep_disk_write_complete: lock is held");
3780 lk.lkt_held = -2;
3781#endif
3782 LIST_INIT(&reattach)do { ((&reattach)->lh_first) = ((void *)0); } while (0
)
;
3783 while ((wk = LIST_FIRST(&bp->b_dep)((&bp->b_dep)->lh_first)) != NULL((void *)0)) {
3784 WORKLIST_REMOVE(wk)do { (wk)->wk_state &= ~0x8000; do { if ((wk)->wk_list
.le_next != ((void *)0)) (wk)->wk_list.le_next->wk_list
.le_prev = (wk)->wk_list.le_prev; *(wk)->wk_list.le_prev
= (wk)->wk_list.le_next; ((wk)->wk_list.le_prev) = ((void
*)-1); ((wk)->wk_list.le_next) = ((void *)-1); } while (0
); } while (0)
;
3785 switch (wk->wk_type) {
3786
3787 case D_PAGEDEP0:
3788 if (handle_written_filepage(WK_PAGEDEP(wk)((struct pagedep *)(wk)), bp))
3789 WORKLIST_INSERT(&reattach, wk)do { (wk)->wk_state |= 0x8000; do { if (((wk)->wk_list.
le_next = (&reattach)->lh_first) != ((void *)0)) (&
reattach)->lh_first->wk_list.le_prev = &(wk)->wk_list
.le_next; (&reattach)->lh_first = (wk); (wk)->wk_list
.le_prev = &(&reattach)->lh_first; } while (0); } while
(0)
;
3790 continue;
3791
3792 case D_INODEDEP1:
3793 if (handle_written_inodeblock(WK_INODEDEP(wk)((struct inodedep *)(wk)), bp))
3794 WORKLIST_INSERT(&reattach, wk)do { (wk)->wk_state |= 0x8000; do { if (((wk)->wk_list.
le_next = (&reattach)->lh_first) != ((void *)0)) (&
reattach)->lh_first->wk_list.le_prev = &(wk)->wk_list
.le_next; (&reattach)->lh_first = (wk); (wk)->wk_list
.le_prev = &(&reattach)->lh_first; } while (0); } while
(0)
;
3795 continue;
3796
3797 case D_BMSAFEMAP3:
3798 bmsafemap = WK_BMSAFEMAP(wk)((struct bmsafemap *)(wk));
3799 while ((newblk = LIST_FIRST(&bmsafemap->sm_newblkhd)((&bmsafemap->sm_newblkhd)->lh_first))) {
3800 newblk->nb_state |= DEPCOMPLETE0x0008;
3801 newblk->nb_bmsafemap = NULL((void *)0);
3802 LIST_REMOVE(newblk, nb_deps)do { if ((newblk)->nb_deps.le_next != ((void *)0)) (newblk
)->nb_deps.le_next->nb_deps.le_prev = (newblk)->nb_deps
.le_prev; *(newblk)->nb_deps.le_prev = (newblk)->nb_deps
.le_next; ((newblk)->nb_deps.le_prev) = ((void *)-1); ((newblk
)->nb_deps.le_next) = ((void *)-1); } while (0)
;
3803 }
3804 while ((adp =
3805 LIST_FIRST(&bmsafemap->sm_allocdirecthd)((&bmsafemap->sm_allocdirecthd)->lh_first))) {
3806 adp->ad_statead_list.wk_state |= DEPCOMPLETE0x0008;
3807 adp->ad_buf = NULL((void *)0);
3808 LIST_REMOVE(adp, ad_deps)do { if ((adp)->ad_deps.le_next != ((void *)0)) (adp)->
ad_deps.le_next->ad_deps.le_prev = (adp)->ad_deps.le_prev
; *(adp)->ad_deps.le_prev = (adp)->ad_deps.le_next; ((adp
)->ad_deps.le_prev) = ((void *)-1); ((adp)->ad_deps.le_next
) = ((void *)-1); } while (0)
;
3809 handle_allocdirect_partdone(adp);
3810 }
3811 while ((aip =
3812 LIST_FIRST(&bmsafemap->sm_allocindirhd)((&bmsafemap->sm_allocindirhd)->lh_first))) {
3813 aip->ai_stateai_list.wk_state |= DEPCOMPLETE0x0008;
3814 aip->ai_buf = NULL((void *)0);
3815 LIST_REMOVE(aip, ai_deps)do { if ((aip)->ai_deps.le_next != ((void *)0)) (aip)->
ai_deps.le_next->ai_deps.le_prev = (aip)->ai_deps.le_prev
; *(aip)->ai_deps.le_prev = (aip)->ai_deps.le_next; ((aip
)->ai_deps.le_prev) = ((void *)-1); ((aip)->ai_deps.le_next
) = ((void *)-1); } while (0)
;
3816 handle_allocindir_partdone(aip);
3817 }
3818 while ((inodedep =
3819 LIST_FIRST(&bmsafemap->sm_inodedephd)((&bmsafemap->sm_inodedephd)->lh_first)) != NULL((void *)0)) {
3820 inodedep->id_stateid_list.wk_state |= DEPCOMPLETE0x0008;
3821 LIST_REMOVE(inodedep, id_deps)do { if ((inodedep)->id_deps.le_next != ((void *)0)) (inodedep
)->id_deps.le_next->id_deps.le_prev = (inodedep)->id_deps
.le_prev; *(inodedep)->id_deps.le_prev = (inodedep)->id_deps
.le_next; ((inodedep)->id_deps.le_prev) = ((void *)-1); ((
inodedep)->id_deps.le_next) = ((void *)-1); } while (0)
;
3822 inodedep->id_buf = NULL((void *)0);
3823 }
3824 WORKITEM_FREE(bmsafemap, D_BMSAFEMAP)softdep_freequeue_add((struct worklist *)bmsafemap);
3825 continue;
3826
3827 case D_MKDIR11:
3828 handle_written_mkdir(WK_MKDIR(wk)((struct mkdir *)(wk)), MKDIR_BODY0x0020);
3829 continue;
3830
3831 case D_ALLOCDIRECT4:
3832 adp = WK_ALLOCDIRECT(wk)((struct allocdirect *)(wk));
3833 adp->ad_statead_list.wk_state |= COMPLETE0x0004;
3834 handle_allocdirect_partdone(adp);
3835 continue;
3836
3837 case D_ALLOCINDIR6:
3838 aip = WK_ALLOCINDIR(wk)((struct allocindir *)(wk));
3839 aip->ai_stateai_list.wk_state |= COMPLETE0x0004;
3840 handle_allocindir_partdone(aip);
3841 continue;
3842
3843 case D_INDIRDEP5:
3844 indirdep = WK_INDIRDEP(wk)((struct indirdep *)(wk));
3845 if (indirdep->ir_stateir_list.wk_state & GOINGAWAY0x0100)
3846 panic("disk_write_complete: indirdep gone");
3847 memcpy(bp->b_data, indirdep->ir_saveddata, bp->b_bcount)__builtin_memcpy((bp->b_data), (indirdep->ir_saveddata)
, (bp->b_bcount))
;
3848 free(indirdep->ir_saveddata, M_INDIRDEP83, bp->b_bcount);
3849 indirdep->ir_saveddata = NULL((void *)0);
3850 indirdep->ir_stateir_list.wk_state &= ~UNDONE0x0002;
3851 indirdep->ir_stateir_list.wk_state |= ATTACHED0x0001;
3852 while ((aip = LIST_FIRST(&indirdep->ir_donehd)((&indirdep->ir_donehd)->lh_first))) {
3853 handle_allocindir_partdone(aip);
3854 if (aip == LIST_FIRST(&indirdep->ir_donehd)((&indirdep->ir_donehd)->lh_first))
3855 panic("disk_write_complete: not gone");
3856 }
3857 WORKLIST_INSERT(&reattach, wk)do { (wk)->wk_state |= 0x8000; do { if (((wk)->wk_list.
le_next = (&reattach)->lh_first) != ((void *)0)) (&
reattach)->lh_first->wk_list.le_prev = &(wk)->wk_list
.le_next; (&reattach)->lh_first = (wk); (wk)->wk_list
.le_prev = &(&reattach)->lh_first; } while (0); } while
(0)
;
3858 if ((bp->b_flags & B_DELWRI0x00000080) == 0)
3859 stat_indir_blk_ptrs++;
3860 buf_dirty(bp);
3861 continue;
3862
3863 default:
3864 panic("handle_disk_write_complete: Unknown type %s",
3865 TYPENAME(wk->wk_type)((unsigned)(wk->wk_type) <= 13 ? softdep_typenames[wk->
wk_type] : "???")
);
3866 /* NOTREACHED */
3867 }
3868 }
3869 /*
3870 * Reattach any requests that must be redone.
3871 */
3872 while ((wk = LIST_FIRST(&reattach)((&reattach)->lh_first)) != NULL((void *)0)) {
3873 WORKLIST_REMOVE(wk)do { (wk)->wk_state &= ~0x8000; do { if ((wk)->wk_list
.le_next != ((void *)0)) (wk)->wk_list.le_next->wk_list
.le_prev = (wk)->wk_list.le_prev; *(wk)->wk_list.le_prev
= (wk)->wk_list.le_next; ((wk)->wk_list.le_prev) = ((void
*)-1); ((wk)->wk_list.le_next) = ((void *)-1); } while (0
); } while (0)
;
3874 WORKLIST_INSERT(&bp->b_dep, wk)do { (wk)->wk_state |= 0x8000; do { if (((wk)->wk_list.
le_next = (&bp->b_dep)->lh_first) != ((void *)0)) (
&bp->b_dep)->lh_first->wk_list.le_prev = &(wk
)->wk_list.le_next; (&bp->b_dep)->lh_first = (wk
); (wk)->wk_list.le_prev = &(&bp->b_dep)->lh_first
; } while (0); } while (0)
;
3875 }
3876#ifdef DEBUG
3877 if (lk.lkt_held != -2)
3878 panic("softdep_disk_write_complete: lock lost");
3879 lk.lkt_held = -1;
3880#endif
3881}
3882
3883/*
3884 * Called from within softdep_disk_write_complete above. Note that
3885 * this routine is always called from interrupt level with further
3886 * splbio interrupts blocked.
3887 */
3888/* the completed allocdirect */
3889STATIC void
3890handle_allocdirect_partdone(struct allocdirect *adp)
3891{
3892 struct allocdirect *listadp;
3893 struct inodedep *inodedep;
3894 long bsize, delay;
3895
3896 splassert(IPL_BIO)do { if (splassert_ctl > 0) { splassert_check(0x6, __func__
); } } while (0)
;
3897
3898 if ((adp->ad_statead_list.wk_state & ALLCOMPLETE(0x0001 | 0x0004 | 0x0008)) != ALLCOMPLETE(0x0001 | 0x0004 | 0x0008))
3899 return;
3900 if (adp->ad_buf != NULL((void *)0))
3901 panic("handle_allocdirect_partdone: dangling dep");
3902
3903 /*
3904 * The on-disk inode cannot claim to be any larger than the last
3905 * fragment that has been written. Otherwise, the on-disk inode
3906 * might have fragments that were not the last block in the file
3907 * which would corrupt the filesystem. Thus, we cannot free any
3908 * allocdirects after one whose ad_oldblkno claims a fragment as
3909 * these blocks must be rolled back to zero before writing the inode.
3910 * We check the currently active set of allocdirects in id_inoupdt.
3911 */
3912 inodedep = adp->ad_inodedep;
3913 bsize = inodedep->id_fs->fs_bsize;
3914 TAILQ_FOREACH(listadp, &inodedep->id_inoupdt, ad_next)for((listadp) = ((&inodedep->id_inoupdt)->tqh_first
); (listadp) != ((void *)0); (listadp) = ((listadp)->ad_next
.tqe_next))
{
3915 /* found our block */
3916 if (listadp == adp)
3917 break;
3918 /* continue if ad_oldlbn is not a fragment */
3919 if (listadp->ad_oldsize == 0 ||
3920 listadp->ad_oldsize == bsize)
3921 continue;
3922 /* hit a fragment */
3923 return;
3924 }
3925 /*
3926 * If we have reached the end of the current list without
3927 * finding the just finished dependency, then it must be
3928 * on the future dependency list. Future dependencies cannot
3929 * be freed until they are moved to the current list.
3930 */
3931 if (listadp == NULL((void *)0)) {
3932#ifdef DEBUG
3933 TAILQ_FOREACH(listadp, &inodedep->id_newinoupdt, ad_next)for((listadp) = ((&inodedep->id_newinoupdt)->tqh_first
); (listadp) != ((void *)0); (listadp) = ((listadp)->ad_next
.tqe_next))
3934 /* found our block */
3935 if (listadp == adp)
3936 break;
3937 if (listadp == NULL((void *)0))
3938 panic("handle_allocdirect_partdone: lost dep");
3939#endif /* DEBUG */
3940 return;
3941 }
3942 /*
3943 * If we have found the just finished dependency, then free
3944 * it along with anything that follows it that is complete.
3945 * If the inode still has a bitmap dependency, then it has
3946 * never been written to disk, hence the on-disk inode cannot
3947 * reference the old fragment so we can free it without delay.
3948 */
3949 delay = (inodedep->id_stateid_list.wk_state & DEPCOMPLETE0x0008);
3950 for (; adp; adp = listadp) {
3951 listadp = TAILQ_NEXT(adp, ad_next)((adp)->ad_next.tqe_next);
3952 if ((adp->ad_statead_list.wk_state & ALLCOMPLETE(0x0001 | 0x0004 | 0x0008)) != ALLCOMPLETE(0x0001 | 0x0004 | 0x0008))
3953 return;
3954 free_allocdirect(&inodedep->id_inoupdt, adp, delay);
3955 }
3956}
3957
3958/*
3959 * Called from within softdep_disk_write_complete above. Note that
3960 * this routine is always called from interrupt level with further
3961 * splbio interrupts blocked.
3962 */
3963/* the completed allocindir */
3964STATIC void
3965handle_allocindir_partdone(struct allocindir *aip)
3966{
3967 struct indirdep *indirdep;
3968
3969 splassert(IPL_BIO)do { if (splassert_ctl > 0) { splassert_check(0x6, __func__
); } } while (0)
;
3970
3971 if ((aip->ai_stateai_list.wk_state & ALLCOMPLETE(0x0001 | 0x0004 | 0x0008)) != ALLCOMPLETE(0x0001 | 0x0004 | 0x0008))
3972 return;
3973 if (aip->ai_buf != NULL((void *)0))
3974 panic("handle_allocindir_partdone: dangling dependency");
3975 indirdep = aip->ai_indirdep;
3976 if (indirdep->ir_stateir_list.wk_state & UNDONE0x0002) {
3977 LIST_REMOVE(aip, ai_next)do { if ((aip)->ai_next.le_next != ((void *)0)) (aip)->
ai_next.le_next->ai_next.le_prev = (aip)->ai_next.le_prev
; *(aip)->ai_next.le_prev = (aip)->ai_next.le_next; ((aip
)->ai_next.le_prev) = ((void *)-1); ((aip)->ai_next.le_next
) = ((void *)-1); } while (0)
;
3978 LIST_INSERT_HEAD(&indirdep->ir_donehd, aip, ai_next)do { if (((aip)->ai_next.le_next = (&indirdep->ir_donehd
)->lh_first) != ((void *)0)) (&indirdep->ir_donehd)
->lh_first->ai_next.le_prev = &(aip)->ai_next.le_next
; (&indirdep->ir_donehd)->lh_first = (aip); (aip)->
ai_next.le_prev = &(&indirdep->ir_donehd)->lh_first
; } while (0)
;
3979 return;
3980 }
3981 if (indirdep->ir_stateir_list.wk_state & UFS1FMT0x2000)
3982 ((int32_t *)indirdep->ir_savebp->b_data)[aip->ai_offset] =
3983 aip->ai_newblkno;
3984 else
3985 ((int64_t *)indirdep->ir_savebp->b_data)[aip->ai_offset] =
3986 aip->ai_newblkno;
3987 LIST_REMOVE(aip, ai_next)do { if ((aip)->ai_next.le_next != ((void *)0)) (aip)->
ai_next.le_next->ai_next.le_prev = (aip)->ai_next.le_prev
; *(aip)->ai_next.le_prev = (aip)->ai_next.le_next; ((aip
)->ai_next.le_prev) = ((void *)-1); ((aip)->ai_next.le_next
) = ((void *)-1); } while (0)
;
3988 if (aip->ai_freefrag != NULL((void *)0))
3989 add_to_worklist(&aip->ai_freefrag->ff_list);
3990 WORKITEM_FREE(aip, D_ALLOCINDIR)softdep_freequeue_add((struct worklist *)aip);
3991}
3992
3993/*
3994 * Called from within softdep_disk_write_complete above to restore
3995 * in-memory inode block contents to their most up-to-date state. Note
3996 * that this routine is always called from interrupt level with further
3997 * splbio interrupts blocked.
3998 */
3999/* buffer containing the inode block */
4000STATIC int
4001handle_written_inodeblock(struct inodedep *inodedep, struct buf *bp)
4002{
4003 struct worklist *wk, *filefree;
4004 struct allocdirect *adp, *nextadp;
4005 struct ufs1_dinode *dp1 = NULL((void *)0);
4006 struct ufs2_dinode *dp2 = NULL((void *)0);
4007 int hadchanges, fstype;
4008
4009 splassert(IPL_BIO)do { if (splassert_ctl > 0) { splassert_check(0x6, __func__
); } } while (0)
;
4010
4011 if ((inodedep->id_stateid_list.wk_state & IOSTARTED0x0200) == 0)
4012 panic("handle_written_inodeblock: not started");
4013 inodedep->id_stateid_list.wk_state &= ~IOSTARTED0x0200;
4014
4015 if (inodedep->id_fs->fs_magic == FS_UFS1_MAGIC0x011954) {
4016 fstype = UM_UFS11;
4017 dp1 = (struct ufs1_dinode *) bp->b_data +
4018 ino_to_fsbo(inodedep->id_fs, inodedep->id_ino)((inodedep->id_ino) % ((inodedep->id_fs)->fs_inopb));
4019 } else {
4020 fstype = UM_UFS22;
4021 dp2 = (struct ufs2_dinode *) bp->b_data +
4022 ino_to_fsbo(inodedep->id_fs, inodedep->id_ino)((inodedep->id_ino) % ((inodedep->id_fs)->fs_inopb));
4023 }
4024
4025 /*
4026 * If we had to rollback the inode allocation because of
4027 * bitmaps being incomplete, then simply restore it.
4028 * Keep the block dirty so that it will not be reclaimed until
4029 * all associated dependencies have been cleared and the
4030 * corresponding updates written to disk.
4031 */
4032 if (inodedep->id_savedino1id_un.idu_savedino1 != NULL((void *)0)) {
4033 if (fstype == UM_UFS11)
4034 *dp1 = *inodedep->id_savedino1id_un.idu_savedino1;
4035 else
4036 *dp2 = *inodedep->id_savedino2id_un.idu_savedino2;
4037 free(inodedep->id_savedino1id_un.idu_savedino1, M_INODEDEP79, inodedep->id_unsize);
4038 inodedep->id_savedino1id_un.idu_savedino1 = NULL((void *)0);
4039 if ((bp->b_flags & B_DELWRI0x00000080) == 0)
4040 stat_inode_bitmap++;
4041 buf_dirty(bp);
4042 return (1);
4043 }
4044 inodedep->id_stateid_list.wk_state |= COMPLETE0x0004;
4045 /*
4046 * Roll forward anything that had to be rolled back before
4047 * the inode could be updated.
4048 */
4049 hadchanges = 0;
4050 for (adp = TAILQ_FIRST(&inodedep->id_inoupdt)((&inodedep->id_inoupdt)->tqh_first); adp; adp = nextadp) {
4051 nextadp = TAILQ_NEXT(adp, ad_next)((adp)->ad_next.tqe_next);
4052 if (adp->ad_statead_list.wk_state & ATTACHED0x0001)
4053 panic("handle_written_inodeblock: new entry");
4054 if (fstype == UM_UFS11) {
4055 if (adp->ad_lbn < NDADDR12) {
4056 if (dp1->di_db[adp->ad_lbn] != adp->ad_oldblkno)
4057 panic("%s: %s #%lld mismatch %d != "
4058 "%lld",
4059 "handle_written_inodeblock",
4060 "direct pointer",
4061 (long long)adp->ad_lbn,
4062 dp1->di_db[adp->ad_lbn],
4063 (long long)adp->ad_oldblkno);
4064 dp1->di_db[adp->ad_lbn] = adp->ad_newblkno;
4065 } else {
4066 if (dp1->di_ib[adp->ad_lbn - NDADDR12] != 0)
4067 panic("%s: %s #%lld allocated as %d",
4068 "handle_written_inodeblock",
4069 "indirect pointer",
4070 (long long)(adp->ad_lbn - NDADDR12),
4071 dp1->di_ib[adp->ad_lbn - NDADDR12]);
4072 dp1->di_ib[adp->ad_lbn - NDADDR12] =
4073 adp->ad_newblkno;
4074 }
4075 } else {
4076 if (adp->ad_lbn < NDADDR12) {
4077 if (dp2->di_db[adp->ad_lbn] != adp->ad_oldblkno)
4078 panic("%s: %s #%lld mismatch %lld != "
4079 "%lld", "handle_written_inodeblock",
4080 "direct pointer",
4081 (long long)adp->ad_lbn,
4082 dp2->di_db[adp->ad_lbn],
4083 (long long)adp->ad_oldblkno);
4084 dp2->di_db[adp->ad_lbn] = adp->ad_newblkno;
4085 } else {
4086 if (dp2->di_ib[adp->ad_lbn - NDADDR12] != 0)
4087 panic("%s: %s #%lld allocated as %lld",
4088 "handle_written_inodeblock",
4089 "indirect pointer",
4090 (long long)(adp->ad_lbn - NDADDR12),
4091 dp2->di_ib[adp->ad_lbn - NDADDR12]);
4092 dp2->di_ib[adp->ad_lbn - NDADDR12] =
4093 adp->ad_newblkno;
4094 }
4095 }
4096 adp->ad_statead_list.wk_state &= ~UNDONE0x0002;
4097 adp->ad_statead_list.wk_state |= ATTACHED0x0001;
4098 hadchanges = 1;
4099 }
4100 if (hadchanges && (bp->b_flags & B_DELWRI0x00000080) == 0)
4101 stat_direct_blk_ptrs++;
4102 /*
4103 * Reset the file size to its most up-to-date value.
4104 */
4105 if (inodedep->id_savedsize == -1)
4106 panic("handle_written_inodeblock: bad size");
4107
4108 if (fstype == UM_UFS11) {
4109 if (dp1->di_size != inodedep->id_savedsize) {
4110 dp1->di_size = inodedep->id_savedsize;
4111 hadchanges = 1;
4112 }
4113 } else {
4114 if (dp2->di_size != inodedep->id_savedsize) {
4115 dp2->di_size = inodedep->id_savedsize;
4116 hadchanges = 1;
4117 }
4118 }
4119 inodedep->id_savedsize = -1;
4120 /*
4121 * If there were any rollbacks in the inode block, then it must be
4122 * marked dirty so that its will eventually get written back in
4123 * its correct form.
4124 */
4125 if (hadchanges)
4126 buf_dirty(bp);
4127 /*
4128 * Process any allocdirects that completed during the update.
4129 */
4130 if ((adp = TAILQ_FIRST(&inodedep->id_inoupdt)((&inodedep->id_inoupdt)->tqh_first)) != NULL((void *)0))
4131 handle_allocdirect_partdone(adp);
4132 /*
4133 * Process deallocations that were held pending until the
4134 * inode had been written to disk. Freeing of the inode
4135 * is delayed until after all blocks have been freed to
4136 * avoid creation of new <vfsid, inum, lbn> triples
4137 * before the old ones have been deleted.
4138 */
4139 filefree = NULL((void *)0);
4140 while ((wk = LIST_FIRST(&inodedep->id_bufwait)((&inodedep->id_bufwait)->lh_first)) != NULL((void *)0)) {
4141 WORKLIST_REMOVE(wk)do { (wk)->wk_state &= ~0x8000; do { if ((wk)->wk_list
.le_next != ((void *)0)) (wk)->wk_list.le_next->wk_list
.le_prev = (wk)->wk_list.le_prev; *(wk)->wk_list.le_prev
= (wk)->wk_list.le_next; ((wk)->wk_list.le_prev) = ((void
*)-1); ((wk)->wk_list.le_next) = ((void *)-1); } while (0
); } while (0)
;
4142 switch (wk->wk_type) {
4143
4144 case D_FREEFILE9:
4145 /*
4146 * We defer adding filefree to the worklist until
4147 * all other additions have been made to ensure
4148 * that it will be done after all the old blocks
4149 * have been freed.
4150 */
4151 if (filefree != NULL((void *)0))
4152 panic("handle_written_inodeblock: filefree");
4153 filefree = wk;
4154 continue;
4155
4156 case D_MKDIR11:
4157 handle_written_mkdir(WK_MKDIR(wk)((struct mkdir *)(wk)), MKDIR_PARENT0x0010);
4158 continue;
4159
4160 case D_DIRADD10:
4161 diradd_inode_written(WK_DIRADD(wk)((struct diradd *)(wk)), inodedep);
4162 continue;
4163
4164 case D_FREEBLKS8:
4165 wk->wk_state |= COMPLETE0x0004;
4166 if ((wk->wk_state & ALLCOMPLETE(0x0001 | 0x0004 | 0x0008)) != ALLCOMPLETE(0x0001 | 0x0004 | 0x0008))
4167 continue;
4168 /* FALLTHROUGH */
4169 case D_FREEFRAG7:
4170 case D_DIRREM12:
4171 add_to_worklist(wk);
4172 continue;
4173
4174 case D_NEWDIRBLK13:
4175 free_newdirblk(WK_NEWDIRBLK(wk)((struct newdirblk *)(wk)));
4176 continue;
4177
4178 default:
4179 panic("handle_written_inodeblock: Unknown type %s",
4180 TYPENAME(wk->wk_type)((unsigned)(wk->wk_type) <= 13 ? softdep_typenames[wk->
wk_type] : "???")
);
4181 /* NOTREACHED */
4182 }
4183 }
4184 if (filefree != NULL((void *)0)) {
4185 if (free_inodedep(inodedep) == 0)
4186 panic("handle_written_inodeblock: live inodedep");
4187 add_to_worklist(filefree);
4188 return (0);
4189 }
4190
4191 /*
4192 * If no outstanding dependencies, free it.
4193 */
4194 if (free_inodedep(inodedep) ||
4195 TAILQ_FIRST(&inodedep->id_inoupdt)((&inodedep->id_inoupdt)->tqh_first) == NULL((void *)0))
4196 return (0);
4197 return (hadchanges);
4198}
4199
4200/*
4201 * Process a diradd entry after its dependent inode has been written.
4202 * This routine must be called with splbio interrupts blocked.
4203 */
4204STATIC void
4205diradd_inode_written(struct diradd *dap, struct inodedep *inodedep)
4206{
4207 struct pagedep *pagedep;
4208
4209 splassert(IPL_BIO)do { if (splassert_ctl > 0) { splassert_check(0x6, __func__
); } } while (0)
;
4210
4211 dap->da_stateda_list.wk_state |= COMPLETE0x0004;
4212 if ((dap->da_stateda_list.wk_state & ALLCOMPLETE(0x0001 | 0x0004 | 0x0008)) == ALLCOMPLETE(0x0001 | 0x0004 | 0x0008)) {
4213 if (dap->da_stateda_list.wk_state & DIRCHG0x0080)
4214 pagedep = dap->da_previousda_un.dau_previous->dm_pagedepdm_un.dmu_pagedep;
4215 else
4216 pagedep = dap->da_pagedepda_un.dau_pagedep;
4217 LIST_REMOVE(dap, da_pdlist)do { if ((dap)->da_pdlist.le_next != ((void *)0)) (dap)->
da_pdlist.le_next->da_pdlist.le_prev = (dap)->da_pdlist
.le_prev; *(dap)->da_pdlist.le_prev = (dap)->da_pdlist.
le_next; ((dap)->da_pdlist.le_prev) = ((void *)-1); ((dap)
->da_pdlist.le_next) = ((void *)-1); } while (0)
;
4218 LIST_INSERT_HEAD(&pagedep->pd_pendinghd, dap, da_pdlist)do { if (((dap)->da_pdlist.le_next = (&pagedep->pd_pendinghd
)->lh_first) != ((void *)0)) (&pagedep->pd_pendinghd
)->lh_first->da_pdlist.le_prev = &(dap)->da_pdlist
.le_next; (&pagedep->pd_pendinghd)->lh_first = (dap
); (dap)->da_pdlist.le_prev = &(&pagedep->pd_pendinghd
)->lh_first; } while (0)
;
4219 }
4220 WORKLIST_INSERT(&inodedep->id_pendinghd, &dap->da_list)do { (&dap->da_list)->wk_state |= 0x8000; do { if (
((&dap->da_list)->wk_list.le_next = (&inodedep->
id_pendinghd)->lh_first) != ((void *)0)) (&inodedep->
id_pendinghd)->lh_first->wk_list.le_prev = &(&dap
->da_list)->wk_list.le_next; (&inodedep->id_pendinghd
)->lh_first = (&dap->da_list); (&dap->da_list
)->wk_list.le_prev = &(&inodedep->id_pendinghd)
->lh_first; } while (0); } while (0)
;
4221}
4222
4223/*
4224 * Handle the completion of a mkdir dependency.
4225 */
4226STATIC void
4227handle_written_mkdir(struct mkdir *mkdir, int type)
4228{
4229 struct diradd *dap;
4230 struct pagedep *pagedep;
4231
4232 splassert(IPL_BIO)do { if (splassert_ctl > 0) { splassert_check(0x6, __func__
); } } while (0)
;
4233
4234 if (mkdir->md_statemd_list.wk_state != type)
4235 panic("handle_written_mkdir: bad type");
4236 dap = mkdir->md_diradd;
4237 dap->da_stateda_list.wk_state &= ~type;
4238 if ((dap->da_stateda_list.wk_state & (MKDIR_PARENT0x0010 | MKDIR_BODY0x0020)) == 0)
4239 dap->da_stateda_list.wk_state |= DEPCOMPLETE0x0008;
4240 if ((dap->da_stateda_list.wk_state & ALLCOMPLETE(0x0001 | 0x0004 | 0x0008)) == ALLCOMPLETE(0x0001 | 0x0004 | 0x0008)) {
4241 if (dap->da_stateda_list.wk_state & DIRCHG0x0080)
4242 pagedep = dap->da_previousda_un.dau_previous->dm_pagedepdm_un.dmu_pagedep;
4243 else
4244 pagedep = dap->da_pagedepda_un.dau_pagedep;
4245 LIST_REMOVE(dap, da_pdlist)do { if ((dap)->da_pdlist.le_next != ((void *)0)) (dap)->
da_pdlist.le_next->da_pdlist.le_prev = (dap)->da_pdlist
.le_prev; *(dap)->da_pdlist.le_prev = (dap)->da_pdlist.
le_next; ((dap)->da_pdlist.le_prev) = ((void *)-1); ((dap)
->da_pdlist.le_next) = ((void *)-1); } while (0)
;
4246 LIST_INSERT_HEAD(&pagedep->pd_pendinghd, dap, da_pdlist)do { if (((dap)->da_pdlist.le_next = (&pagedep->pd_pendinghd
)->lh_first) != ((void *)0)) (&pagedep->pd_pendinghd
)->lh_first->da_pdlist.le_prev = &(dap)->da_pdlist
.le_next; (&pagedep->pd_pendinghd)->lh_first = (dap
); (dap)->da_pdlist.le_prev = &(&pagedep->pd_pendinghd
)->lh_first; } while (0)
;
4247 }
4248 LIST_REMOVE(mkdir, md_mkdirs)do { if ((mkdir)->md_mkdirs.le_next != ((void *)0)) (mkdir
)->md_mkdirs.le_next->md_mkdirs.le_prev = (mkdir)->md_mkdirs
.le_prev; *(mkdir)->md_mkdirs.le_prev = (mkdir)->md_mkdirs
.le_next; ((mkdir)->md_mkdirs.le_prev) = ((void *)-1); ((mkdir
)->md_mkdirs.le_next) = ((void *)-1); } while (0)
;
4249 WORKITEM_FREE(mkdir, D_MKDIR)softdep_freequeue_add((struct worklist *)mkdir);
4250}
4251
4252/*
4253 * Called from within softdep_disk_write_complete above.
4254 * A write operation was just completed. Removed inodes can
4255 * now be freed and associated block pointers may be committed.
4256 * Note that this routine is always called from interrupt level
4257 * with further splbio interrupts blocked.
4258 */
4259/* buffer containing the written page */
4260STATIC int
4261handle_written_filepage(struct pagedep *pagedep, struct buf *bp)
4262{
4263 struct dirrem *dirrem;
4264 struct diradd *dap, *nextdap;
4265 struct direct *ep;
4266 int i, chgs;
4267
4268 splassert(IPL_BIO)do { if (splassert_ctl > 0) { splassert_check(0x6, __func__
); } } while (0)
;
4269
4270 if ((pagedep->pd_statepd_list.wk_state & IOSTARTED0x0200) == 0)
4271 panic("handle_written_filepage: not started");
4272 pagedep->pd_statepd_list.wk_state &= ~IOSTARTED0x0200;
4273 /*
4274 * Process any directory removals that have been committed.
4275 */
4276 while ((dirrem = LIST_FIRST(&pagedep->pd_dirremhd)((&pagedep->pd_dirremhd)->lh_first)) != NULL((void *)0)) {
4277 LIST_REMOVE(dirrem, dm_next)do { if ((dirrem)->dm_next.le_next != ((void *)0)) (dirrem
)->dm_next.le_next->dm_next.le_prev = (dirrem)->dm_next
.le_prev; *(dirrem)->dm_next.le_prev = (dirrem)->dm_next
.le_next; ((dirrem)->dm_next.le_prev) = ((void *)-1); ((dirrem
)->dm_next.le_next) = ((void *)-1); } while (0)
;
4278 dirrem->dm_dirinumdm_un.dmu_dirinum = pagedep->pd_ino;
4279 add_to_worklist(&dirrem->dm_list);
4280 }
4281 /*
4282 * Free any directory additions that have been committed.
4283 * If it is a newly allocated block, we have to wait until
4284 * the on-disk directory inode claims the new block.
4285 */
4286 if ((pagedep->pd_statepd_list.wk_state & NEWBLOCK0x0800) == 0)
4287 while ((dap = LIST_FIRST(&pagedep->pd_pendinghd)((&pagedep->pd_pendinghd)->lh_first)) != NULL((void *)0))
4288 free_diradd(dap);
4289 /*
4290 * Uncommitted directory entries must be restored.
4291 */
4292 for (chgs = 0, i = 0; i < DAHASHSZ6; i++) {
4293 for (dap = LIST_FIRST(&pagedep->pd_diraddhd[i])((&pagedep->pd_diraddhd[i])->lh_first); dap;
4294 dap = nextdap) {
4295 nextdap = LIST_NEXT(dap, da_pdlist)((dap)->da_pdlist.le_next);
4296 if (dap->da_stateda_list.wk_state & ATTACHED0x0001)
4297 panic("handle_written_filepage: attached");
4298 ep = (struct direct *)
4299 ((char *)bp->b_data + dap->da_offset);
4300 ep->d_ino = dap->da_newinum;
4301 dap->da_stateda_list.wk_state &= ~UNDONE0x0002;
4302 dap->da_stateda_list.wk_state |= ATTACHED0x0001;
4303 chgs = 1;
4304 /*
4305 * If the inode referenced by the directory has
4306 * been written out, then the dependency can be
4307 * moved to the pending list.
4308 */
4309 if ((dap->da_stateda_list.wk_state & ALLCOMPLETE(0x0001 | 0x0004 | 0x0008)) == ALLCOMPLETE(0x0001 | 0x0004 | 0x0008)) {
4310 LIST_REMOVE(dap, da_pdlist)do { if ((dap)->da_pdlist.le_next != ((void *)0)) (dap)->
da_pdlist.le_next->da_pdlist.le_prev = (dap)->da_pdlist
.le_prev; *(dap)->da_pdlist.le_prev = (dap)->da_pdlist.
le_next; ((dap)->da_pdlist.le_prev) = ((void *)-1); ((dap)
->da_pdlist.le_next) = ((void *)-1); } while (0)
;
4311 LIST_INSERT_HEAD(&pagedep->pd_pendinghd, dap,do { if (((dap)->da_pdlist.le_next = (&pagedep->pd_pendinghd
)->lh_first) != ((void *)0)) (&pagedep->pd_pendinghd
)->lh_first->da_pdlist.le_prev = &(dap)->da_pdlist
.le_next; (&pagedep->pd_pendinghd)->lh_first = (dap
); (dap)->da_pdlist.le_prev = &(&pagedep->pd_pendinghd
)->lh_first; } while (0)
4312 da_pdlist)do { if (((dap)->da_pdlist.le_next = (&pagedep->pd_pendinghd
)->lh_first) != ((void *)0)) (&pagedep->pd_pendinghd
)->lh_first->da_pdlist.le_prev = &(dap)->da_pdlist
.le_next; (&pagedep->pd_pendinghd)->lh_first = (dap
); (dap)->da_pdlist.le_prev = &(&pagedep->pd_pendinghd
)->lh_first; } while (0)
;
4313 }
4314 }
4315 }
4316 /*
4317 * If there were any rollbacks in the directory, then it must be
4318 * marked dirty so that its will eventually get written back in
4319 * its correct form.
4320 */
4321 if (chgs) {
4322 if ((bp->b_flags & B_DELWRI0x00000080) == 0)
4323 stat_dir_entry++;
4324 buf_dirty(bp);
4325 return (1);
4326 }
4327 /*
4328 * If we are not waiting for a new directory block to be
4329 * claimed by its inode, then the pagedep will be freed.
4330 * Otherwise it will remain to track any new entries on
4331 * the page in case they are fsync'ed.
4332 */
4333 if ((pagedep->pd_statepd_list.wk_state & NEWBLOCK0x0800) == 0) {
4334 LIST_REMOVE(pagedep, pd_hash)do { if ((pagedep)->pd_hash.le_next != ((void *)0)) (pagedep
)->pd_hash.le_next->pd_hash.le_prev = (pagedep)->pd_hash
.le_prev; *(pagedep)->pd_hash.le_prev = (pagedep)->pd_hash
.le_next; ((pagedep)->pd_hash.le_prev) = ((void *)-1); ((pagedep
)->pd_hash.le_next) = ((void *)-1); } while (0)
;
4335 WORKITEM_FREE(pagedep, D_PAGEDEP)softdep_freequeue_add((struct worklist *)pagedep);
4336 }
4337 return (0);
4338}
4339
4340/*
4341 * Writing back in-core inode structures.
4342 *
4343 * The file system only accesses an inode's contents when it occupies an
4344 * "in-core" inode structure. These "in-core" structures are separate from
4345 * the page frames used to cache inode blocks. Only the latter are
4346 * transferred to/from the disk. So, when the updated contents of the
4347 * "in-core" inode structure are copied to the corresponding in-memory inode
4348 * block, the dependencies are also transferred. The following procedure is
4349 * called when copying a dirty "in-core" inode to a cached inode block.
4350 */
4351
4352/*
4353 * Called when an inode is loaded from disk. If the effective link count
4354 * differed from the actual link count when it was last flushed, then we
4355 * need to ensure that the correct effective link count is put back.
4356 */
4357/* the "in_core" copy of the inode */
4358void
4359softdep_load_inodeblock(struct inode *ip)
4360{
4361 struct inodedep *inodedep;
4362
4363 /*
4364 * Check for alternate nlink count.
4365 */
4366 ip->i_effnlink = DIP(ip, nlink)(((ip)->i_ump->um_fstype == 1) ? (ip)->dinode_u.ffs1_din
->di_nlink : (ip)->dinode_u.ffs2_din->di_nlink)
;
4367 ACQUIRE_LOCK(&lk)(&lk)->lkt_spl = splraise(0x6);
4368 if (inodedep_lookup(ip->i_fsinode_u.fs, ip->i_number, 0, &inodedep) == 0) {
4369 FREE_LOCK(&lk)spllower((&lk)->lkt_spl);
4370 return;
4371 }
4372 ip->i_effnlink -= inodedep->id_nlinkdelta;
4373 FREE_LOCK(&lk)spllower((&lk)->lkt_spl);
4374}
4375
4376/*
4377 * This routine is called just before the "in-core" inode
4378 * information is to be copied to the in-memory inode block.
4379 * Recall that an inode block contains several inodes. If
4380 * the force flag is set, then the dependencies will be
4381 * cleared so that the update can always be made. Note that
4382 * the buffer is locked when this routine is called, so we
4383 * will never be in the middle of writing the inode block
4384 * to disk.
4385 */
4386/* the "in_core" copy of the inode */
4387/* the buffer containing the inode block */
4388/* nonzero => update must be allowed */
4389void
4390softdep_update_inodeblock(struct inode *ip, struct buf *bp, int waitfor)
4391{
4392 struct inodedep *inodedep;
4393 struct worklist *wk;
4394 int error, gotit;
4395
4396 /*
4397 * If the effective link count is not equal to the actual link
4398 * count, then we must track the difference in an inodedep while
4399 * the inode is (potentially) tossed out of the cache. Otherwise,
4400 * if there is no existing inodedep, then there are no dependencies
4401 * to track.
4402 */
4403 ACQUIRE_LOCK(&lk)(&lk)->lkt_spl = splraise(0x6);
4404 if (inodedep_lookup(ip->i_fsinode_u.fs, ip->i_number, 0, &inodedep) == 0) {
4405 FREE_LOCK(&lk)spllower((&lk)->lkt_spl);
4406 if (ip->i_effnlink != DIP(ip, nlink)(((ip)->i_ump->um_fstype == 1) ? (ip)->dinode_u.ffs1_din
->di_nlink : (ip)->dinode_u.ffs2_din->di_nlink)
)
4407 panic("softdep_update_inodeblock: bad link count");
4408 return;
4409 }
4410 if (inodedep->id_nlinkdelta != DIP(ip, nlink)(((ip)->i_ump->um_fstype == 1) ? (ip)->dinode_u.ffs1_din
->di_nlink : (ip)->dinode_u.ffs2_din->di_nlink)
- ip->i_effnlink) {
4411 FREE_LOCK(&lk)spllower((&lk)->lkt_spl);
4412 panic("softdep_update_inodeblock: bad delta");
4413 }
4414 /*
4415 * Changes have been initiated. Anything depending on these
4416 * changes cannot occur until this inode has been written.
4417 */
4418 inodedep->id_stateid_list.wk_state &= ~COMPLETE0x0004;
4419 if ((inodedep->id_stateid_list.wk_state & ONWORKLIST0x8000) == 0)
4420 WORKLIST_INSERT(&bp->b_dep, &inodedep->id_list)do { (&inodedep->id_list)->wk_state |= 0x8000; do {
if (((&inodedep->id_list)->wk_list.le_next = (&
bp->b_dep)->lh_first) != ((void *)0)) (&bp->b_dep
)->lh_first->wk_list.le_prev = &(&inodedep->
id_list)->wk_list.le_next; (&bp->b_dep)->lh_first
= (&inodedep->id_list); (&inodedep->id_list)->
wk_list.le_prev = &(&bp->b_dep)->lh_first; } while
(0); } while (0)
;
4421 /*
4422 * Any new dependencies associated with the incore inode must
4423 * now be moved to the list associated with the buffer holding
4424 * the in-memory copy of the inode. Once merged process any
4425 * allocdirects that are completed by the merger.
4426 */
4427 merge_inode_lists(inodedep);
4428 if (TAILQ_FIRST(&inodedep->id_inoupdt)((&inodedep->id_inoupdt)->tqh_first) != NULL((void *)0))
4429 handle_allocdirect_partdone(TAILQ_FIRST(&inodedep->id_inoupdt)((&inodedep->id_inoupdt)->tqh_first));
4430 /*
4431 * Now that the inode has been pushed into the buffer, the
4432 * operations dependent on the inode being written to disk
4433 * can be moved to the id_bufwait so that they will be
4434 * processed when the buffer I/O completes.
4435 */
4436 while ((wk = LIST_FIRST(&inodedep->id_inowait)((&inodedep->id_inowait)->lh_first)) != NULL((void *)0)) {
4437 WORKLIST_REMOVE(wk)do { (wk)->wk_state &= ~0x8000; do { if ((wk)->wk_list
.le_next != ((void *)0)) (wk)->wk_list.le_next->wk_list
.le_prev = (wk)->wk_list.le_prev; *(wk)->wk_list.le_prev
= (wk)->wk_list.le_next; ((wk)->wk_list.le_prev) = ((void
*)-1); ((wk)->wk_list.le_next) = ((void *)-1); } while (0
); } while (0)
;
4438 WORKLIST_INSERT(&inodedep->id_bufwait, wk)do { (wk)->wk_state |= 0x8000; do { if (((wk)->wk_list.
le_next = (&inodedep->id_bufwait)->lh_first) != ((void
*)0)) (&inodedep->id_bufwait)->lh_first->wk_list
.le_prev = &(wk)->wk_list.le_next; (&inodedep->
id_bufwait)->lh_first = (wk); (wk)->wk_list.le_prev = &
(&inodedep->id_bufwait)->lh_first; } while (0); } while
(0)
;
4439 }
4440 /*
4441 * Newly allocated inodes cannot be written until the bitmap
4442 * that allocates them have been written (indicated by
4443 * DEPCOMPLETE being set in id_state). If we are doing a
4444 * forced sync (e.g., an fsync on a file), we force the bitmap
4445 * to be written so that the update can be done.
4446 */
4447 do {
4448 if ((inodedep->id_stateid_list.wk_state & DEPCOMPLETE0x0008) != 0 || waitfor == 0) {
4449 FREE_LOCK(&lk)spllower((&lk)->lkt_spl);
4450 return;
4451 }
4452 bp = inodedep->id_buf;
4453 gotit = getdirtybuf(bp, MNT_WAIT1);
4454 } while (gotit == -1);
4455 FREE_LOCK(&lk)spllower((&lk)->lkt_spl);
4456 if (gotit && (error = bwrite(bp)) != 0)
4457 softdep_error("softdep_update_inodeblock: bwrite", error);
4458 if ((inodedep->id_stateid_list.wk_state & DEPCOMPLETE0x0008) == 0)
4459 panic("softdep_update_inodeblock: update failed");
4460}
4461
4462/*
4463 * Merge the new inode dependency list (id_newinoupdt) into the old
4464 * inode dependency list (id_inoupdt). This routine must be called
4465 * with splbio interrupts blocked.
4466 */
4467STATIC void
4468merge_inode_lists(struct inodedep *inodedep)
4469{
4470 struct allocdirect *listadp, *newadp;
4471
4472 splassert(IPL_BIO)do { if (splassert_ctl > 0) { splassert_check(0x6, __func__
); } } while (0)
;
4473
4474 newadp = TAILQ_FIRST(&inodedep->id_newinoupdt)((&inodedep->id_newinoupdt)->tqh_first);
4475 for (listadp = TAILQ_FIRST(&inodedep->id_inoupdt)((&inodedep->id_inoupdt)->tqh_first); listadp && newadp;) {
4476 if (listadp->ad_lbn < newadp->ad_lbn) {
4477 listadp = TAILQ_NEXT(listadp, ad_next)((listadp)->ad_next.tqe_next);
4478 continue;
4479 }
4480 TAILQ_REMOVE(&inodedep->id_newinoupdt, newadp, ad_next)do { if (((newadp)->ad_next.tqe_next) != ((void *)0)) (newadp
)->ad_next.tqe_next->ad_next.tqe_prev = (newadp)->ad_next
.tqe_prev; else (&inodedep->id_newinoupdt)->tqh_last
= (newadp)->ad_next.tqe_prev; *(newadp)->ad_next.tqe_prev
= (newadp)->ad_next.tqe_next; ((newadp)->ad_next.tqe_prev
) = ((void *)-1); ((newadp)->ad_next.tqe_next) = ((void *)
-1); } while (0)
;
4481 TAILQ_INSERT_BEFORE(listadp, newadp, ad_next)do { (newadp)->ad_next.tqe_prev = (listadp)->ad_next.tqe_prev
; (newadp)->ad_next.tqe_next = (listadp); *(listadp)->ad_next
.tqe_prev = (newadp); (listadp)->ad_next.tqe_prev = &(
newadp)->ad_next.tqe_next; } while (0)
;
4482 if (listadp->ad_lbn == newadp->ad_lbn) {
4483 allocdirect_merge(&inodedep->id_inoupdt, newadp,
4484 listadp);
4485 listadp = newadp;
4486 }
4487 newadp = TAILQ_FIRST(&inodedep->id_newinoupdt)((&inodedep->id_newinoupdt)->tqh_first);
4488 }
4489 TAILQ_CONCAT(&inodedep->id_inoupdt, &inodedep->id_newinoupdt, ad_next)do { if (!(((&inodedep->id_newinoupdt)->tqh_first) ==
((void *)0))) { *(&inodedep->id_inoupdt)->tqh_last
= (&inodedep->id_newinoupdt)->tqh_first; (&inodedep
->id_newinoupdt)->tqh_first->ad_next.tqe_prev = (&
inodedep->id_inoupdt)->tqh_last; (&inodedep->id_inoupdt
)->tqh_last = (&inodedep->id_newinoupdt)->tqh_last
; do { ((&inodedep->id_newinoupdt))->tqh_first = ((
void *)0); ((&inodedep->id_newinoupdt))->tqh_last =
&((&inodedep->id_newinoupdt))->tqh_first; } while
(0); } } while (0)
;
4490}
4491
4492/*
4493 * If we are doing an fsync, then we must ensure that any directory
4494 * entries for the inode have been written after the inode gets to disk.
4495 */
4496/* the "in_core" copy of the inode */
4497int
4498softdep_fsync(struct vnode *vp)
4499{
4500 struct inodedep *inodedep;
4501 struct pagedep *pagedep;
4502 struct worklist *wk;
4503 struct diradd *dap;
4504 struct mount *mnt;
4505 struct vnode *pvp;
4506 struct inode *ip;
4507 struct inode *pip;
4508 struct buf *bp;
4509 struct fs *fs;
4510 struct proc *p = CURPROC({struct cpu_info *__ci; asm volatile("movq %%gs:%P1,%0" : "=r"
(__ci) :"n" (__builtin_offsetof(struct cpu_info, ci_self)));
__ci;})->ci_curproc
; /* XXX */
4511 int error, flushparent;
4512 ufsino_t parentino;
4513 daddr_t lbn;
4514
4515 ip = VTOI(vp)((struct inode *)(vp)->v_data);
4516 fs = ip->i_fsinode_u.fs;
4517 ACQUIRE_LOCK(&lk)(&lk)->lkt_spl = splraise(0x6);
4518 if (inodedep_lookup(fs, ip->i_number, 0, &inodedep) == 0) {
4519 FREE_LOCK(&lk)spllower((&lk)->lkt_spl);
4520 return (0);
4521 }
4522 if (LIST_FIRST(&inodedep->id_inowait)((&inodedep->id_inowait)->lh_first) != NULL((void *)0) ||
4523 LIST_FIRST(&inodedep->id_bufwait)((&inodedep->id_bufwait)->lh_first) != NULL((void *)0) ||
4524 TAILQ_FIRST(&inodedep->id_inoupdt)((&inodedep->id_inoupdt)->tqh_first) != NULL((void *)0) ||
4525 TAILQ_FIRST(&inodedep->id_newinoupdt)((&inodedep->id_newinoupdt)->tqh_first) != NULL((void *)0)) {
4526 FREE_LOCK(&lk)spllower((&lk)->lkt_spl);
4527 panic("softdep_fsync: pending ops");
4528 }
4529 for (error = 0, flushparent = 0; ; ) {
4530 if ((wk = LIST_FIRST(&inodedep->id_pendinghd)((&inodedep->id_pendinghd)->lh_first)) == NULL((void *)0))
4531 break;
4532 if (wk->wk_type != D_DIRADD10) {
4533 FREE_LOCK(&lk)spllower((&lk)->lkt_spl);
4534 panic("softdep_fsync: Unexpected type %s",
4535 TYPENAME(wk->wk_type)((unsigned)(wk->wk_type) <= 13 ? softdep_typenames[wk->
wk_type] : "???")
);
4536 }
4537 dap = WK_DIRADD(wk)((struct diradd *)(wk));
4538 /*
4539 * Flush our parent if this directory entry has a MKDIR_PARENT
4540 * dependency or is contained in a newly allocated block.
4541 */
4542 if (dap->da_stateda_list.wk_state & DIRCHG0x0080)
4543 pagedep = dap->da_previousda_un.dau_previous->dm_pagedepdm_un.dmu_pagedep;
4544 else
4545 pagedep = dap->da_pagedepda_un.dau_pagedep;
4546 mnt = pagedep->pd_mnt;
4547 parentino = pagedep->pd_ino;
4548 lbn = pagedep->pd_lbn;
4549 if ((dap->da_stateda_list.wk_state & (MKDIR_BODY0x0020 | COMPLETE0x0004)) != COMPLETE0x0004) {
4550 FREE_LOCK(&lk)spllower((&lk)->lkt_spl);
4551 panic("softdep_fsync: dirty");
4552 }
4553 if ((dap->da_stateda_list.wk_state & MKDIR_PARENT0x0010) ||
4554 (pagedep->pd_statepd_list.wk_state & NEWBLOCK0x0800))
4555 flushparent = 1;
4556 else
4557 flushparent = 0;
4558 /*
4559 * If we are being fsync'ed as part of vgone'ing this vnode,
4560 * then we will not be able to release and recover the
4561 * vnode below, so we just have to give up on writing its
4562 * directory entry out. It will eventually be written, just
4563 * not now, but then the user was not asking to have it
4564 * written, so we are not breaking any promises.
4565 */
4566 mtx_enter(&vnode_mtx);
4567 if (vp->v_lflag & VXLOCK0x0100) {
4568 mtx_leave(&vnode_mtx);
4569 break;
4570 }
4571 mtx_leave(&vnode_mtx);
4572 /*
4573 * We prevent deadlock by always fetching inodes from the
4574 * root, moving down the directory tree. Thus, when fetching
4575 * our parent directory, we must unlock ourselves before
4576 * requesting the lock on our parent. See the comment in
4577 * ufs_lookup for details on possible races.
4578 */
4579 FREE_LOCK(&lk)spllower((&lk)->lkt_spl);
4580 VOP_UNLOCK(vp);
4581 error = VFS_VGET(mnt, parentino, &pvp)(*(mnt)->mnt_op->vfs_vget)(mnt, parentino, &pvp);
4582 vn_lock(vp, LK_EXCLUSIVE0x0001UL | LK_RETRY0x2000UL);
4583 if (error != 0)
4584 return (error);
4585 /*
4586 * All MKDIR_PARENT dependencies and all the NEWBLOCK pagedeps
4587 * that are contained in direct blocks will be resolved by
4588 * doing a UFS_UPDATE. Pagedeps contained in indirect blocks
4589 * may require a complete sync'ing of the directory. So, we
4590 * try the cheap and fast UFS_UPDATE first, and if that fails,
4591 * then we do the slower VOP_FSYNC of the directory.
4592 */
4593 pip = VTOI(pvp)((struct inode *)(pvp)->v_data);
4594 if (flushparent) {
4595 error = UFS_UPDATE(pip, 1)((pip)->i_vtbl->iv_update)((pip), (1));
4596 if (error) {
4597 vput(pvp);
4598 return (error);
4599 }
4600 if (pagedep->pd_statepd_list.wk_state & NEWBLOCK0x0800) {
4601 error = VOP_FSYNC(pvp, p->p_ucred, MNT_WAIT1, p);
4602 if (error) {
4603 vput(pvp);
4604 return (error);
4605 }
4606 }
4607 }
4608 /*
4609 * Flush directory page containing the inode's name.
4610 */
4611 error = bread(pvp, lbn, fs->fs_bsize, &bp);
4612 if (error == 0) {
4613 bp->b_bcount = blksize(fs, pip, lbn)(((lbn) >= 12 || ((((pip))->i_ump->um_fstype == 1) ?
((pip))->dinode_u.ffs1_din->di_size : ((pip))->dinode_u
.ffs2_din->di_size) >= ((lbn) + 1) << (fs)->fs_bshift
) ? (u_int64_t)(fs)->fs_bsize : ((((((((((pip))->i_ump->
um_fstype == 1) ? ((pip))->dinode_u.ffs1_din->di_size :
((pip))->dinode_u.ffs2_din->di_size)) & (fs)->fs_qbmask
)) + (fs)->fs_qfmask) & (fs)->fs_fmask)))
;
4614 error = bwrite(bp);
4615 } else
4616 brelse(bp);
4617 vput(pvp);
4618 if (error != 0)
4619 return (error);
4620 ACQUIRE_LOCK(&lk)(&lk)->lkt_spl = splraise(0x6);
4621 if (inodedep_lookup(fs, ip->i_number, 0, &inodedep) == 0)
4622 break;
4623 }
4624 FREE_LOCK(&lk)spllower((&lk)->lkt_spl);
4625 return (0);
4626}
4627
4628/*
4629 * Flush all the dirty bitmaps associated with the block device
4630 * before flushing the rest of the dirty blocks so as to reduce
4631 * the number of dependencies that will have to be rolled back.
4632 */
4633void
4634softdep_fsync_mountdev(struct vnode *vp, int waitfor)
4635{
4636 struct buf *bp, *nbp;
4637 struct worklist *wk;
4638
4639 if (!vn_isdisk(vp, NULL((void *)0)))
4640 panic("softdep_fsync_mountdev: vnode not a disk");
4641 ACQUIRE_LOCK(&lk)(&lk)->lkt_spl = splraise(0x6);
4642 LIST_FOREACH_SAFE(bp, &vp->v_dirtyblkhd, b_vnbufs, nbp)for ((bp) = ((&vp->v_dirtyblkhd)->lh_first); (bp) &&
((nbp) = ((bp)->b_vnbufs.le_next), 1); (bp) = (nbp))
{
4643 /*
4644 * If it is already scheduled, skip to the next buffer.
4645 */
4646 splassert(IPL_BIO)do { if (splassert_ctl > 0) { splassert_check(0x6, __func__
); } } while (0)
;
4647 if (bp->b_flags & B_BUSY0x00000010)
4648 continue;
4649
4650 if ((bp->b_flags & B_DELWRI0x00000080) == 0) {
4651 FREE_LOCK(&lk)spllower((&lk)->lkt_spl);
4652 panic("softdep_fsync_mountdev: not dirty");
4653 }
4654 /*
4655 * We are only interested in bitmaps with outstanding
4656 * dependencies.
4657 */
4658 if ((wk = LIST_FIRST(&bp->b_dep)((&bp->b_dep)->lh_first)) == NULL((void *)0) ||
4659 wk->wk_type != D_BMSAFEMAP3) {
4660 continue;
4661 }
4662 bremfreebufcache_take(bp);
4663 buf_acquire(bp);
4664 FREE_LOCK(&lk)spllower((&lk)->lkt_spl);
4665 (void) bawrite(bp);
4666 ACQUIRE_LOCK(&lk)(&lk)->lkt_spl = splraise(0x6);
4667 /*
4668 * Since we may have slept during the I/O, we need
4669 * to start from a known point.
4670 */
4671 nbp = LIST_FIRST(&vp->v_dirtyblkhd)((&vp->v_dirtyblkhd)->lh_first);
4672 }
4673 if (waitfor == MNT_WAIT1)
4674 drain_output(vp, 1);
4675 FREE_LOCK(&lk)spllower((&lk)->lkt_spl);
4676}
4677
4678/*
4679 * This routine is called when we are trying to synchronously flush a
4680 * file. This routine must eliminate any filesystem metadata dependencies
4681 * so that the syncing routine can succeed by pushing the dirty blocks
4682 * associated with the file. If any I/O errors occur, they are returned.
4683 */
4684int
4685softdep_sync_metadata(struct vop_fsync_args *ap)
4686{
4687 struct vnode *vp = ap->a_vp;
4688 struct pagedep *pagedep;
4689 struct allocdirect *adp;
4690 struct allocindir *aip;
4691 struct buf *bp, *nbp;
4692 struct worklist *wk;
4693 int i, gotit, error, waitfor;
4694
4695 /*
4696 * Check whether this vnode is involved in a filesystem
4697 * that is doing soft dependency processing.
4698 */
4699 if (!vn_isdisk(vp, NULL((void *)0))) {
4700 if (!DOINGSOFTDEP(vp)((vp)->v_mount->mnt_flag & 0x04000000))
4701 return (0);
4702 } else
4703 if (vp->v_specmountpointv_un.vu_specinfo->si_mountpoint == NULL((void *)0) ||
4704 (vp->v_specmountpointv_un.vu_specinfo->si_mountpoint->mnt_flag & MNT_SOFTDEP0x04000000) == 0)
4705 return (0);
4706 /*
4707 * Ensure that any direct block dependencies have been cleared.
4708 */
4709 ACQUIRE_LOCK(&lk)(&lk)->lkt_spl = splraise(0x6);
4710 if ((error = flush_inodedep_deps(VTOI(vp)((struct inode *)(vp)->v_data)->i_fsinode_u.fs, VTOI(vp)((struct inode *)(vp)->v_data)->i_number))) {
4711 FREE_LOCK(&lk)spllower((&lk)->lkt_spl);
4712 return (error);
4713 }
4714 /*
4715 * For most files, the only metadata dependencies are the
4716 * cylinder group maps that allocate their inode or blocks.
4717 * The block allocation dependencies can be found by traversing
4718 * the dependency lists for any buffers that remain on their
4719 * dirty buffer list. The inode allocation dependency will
4720 * be resolved when the inode is updated with MNT_WAIT.
4721 * This work is done in two passes. The first pass grabs most
4722 * of the buffers and begins asynchronously writing them. The
4723 * only way to wait for these asynchronous writes is to sleep
4724 * on the filesystem vnode which may stay busy for a long time
4725 * if the filesystem is active. So, instead, we make a second
4726 * pass over the dependencies blocking on each write. In the
4727 * usual case we will be blocking against a write that we
4728 * initiated, so when it is done the dependency will have been
4729 * resolved. Thus the second pass is expected to end quickly.
4730 */
4731 waitfor = MNT_NOWAIT2;
4732top:
4733 /*
4734 * We must wait for any I/O in progress to finish so that
4735 * all potential buffers on the dirty list will be visible.
4736 */
4737 drain_output(vp, 1);
4738 bp = LIST_FIRST(&vp->v_dirtyblkhd)((&vp->v_dirtyblkhd)->lh_first);
4739 gotit = getdirtybuf(bp, MNT_WAIT1);
4740 if (gotit == 0) {
4741 FREE_LOCK(&lk)spllower((&lk)->lkt_spl);
4742 return (0);
4743 } else if (gotit == -1)
4744 goto top;
4745loop:
4746 /*
4747 * As we hold the buffer locked, none of its dependencies
4748 * will disappear.
4749 */
4750 LIST_FOREACH(wk, &bp->b_dep, wk_list)for((wk) = ((&bp->b_dep)->lh_first); (wk)!= ((void *
)0); (wk) = ((wk)->wk_list.le_next))
{
4751 switch (wk->wk_type) {
4752
4753 case D_ALLOCDIRECT4:
4754 adp = WK_ALLOCDIRECT(wk)((struct allocdirect *)(wk));
4755 if (adp->ad_statead_list.wk_state & DEPCOMPLETE0x0008)
4756 break;
4757 nbp = adp->ad_buf;
4758 gotit = getdirtybuf(nbp, waitfor);
4759 if (gotit == 0)
4760 break;
4761 else if (gotit == -1)
4762 goto loop;
4763 FREE_LOCK(&lk)spllower((&lk)->lkt_spl);
4764 if (waitfor == MNT_NOWAIT2) {
4765 bawrite(nbp);
4766 } else if ((error = VOP_BWRITE(nbp)) != 0) {
4767 bawrite(bp);
4768 return (error);
4769 }
4770 ACQUIRE_LOCK(&lk)(&lk)->lkt_spl = splraise(0x6);
4771 break;
4772
4773 case D_ALLOCINDIR6:
4774 aip = WK_ALLOCINDIR(wk)((struct allocindir *)(wk));
4775 if (aip->ai_stateai_list.wk_state & DEPCOMPLETE0x0008)
4776 break;
4777 nbp = aip->ai_buf;
4778 gotit = getdirtybuf(nbp, waitfor);
4779 if (gotit == 0)
4780 break;
4781 else if (gotit == -1)
4782 goto loop;
4783 FREE_LOCK(&lk)spllower((&lk)->lkt_spl);
4784 if (waitfor == MNT_NOWAIT2) {
4785 bawrite(nbp);
4786 } else if ((error = VOP_BWRITE(nbp)) != 0) {
4787 bawrite(bp);
4788 return (error);
4789 }
4790 ACQUIRE_LOCK(&lk)(&lk)->lkt_spl = splraise(0x6);
4791 break;
4792
4793 case D_INDIRDEP5:
4794 restart:
4795
4796 LIST_FOREACH(aip, &WK_INDIRDEP(wk)->ir_deplisthd, ai_next)for((aip) = ((&((struct indirdep *)(wk))->ir_deplisthd
)->lh_first); (aip)!= ((void *)0); (aip) = ((aip)->ai_next
.le_next))
{
4797 if (aip->ai_stateai_list.wk_state & DEPCOMPLETE0x0008)
4798 continue;
4799 nbp = aip->ai_buf;
4800 if (getdirtybuf(nbp, MNT_WAIT1) <= 0)
4801 goto restart;
4802 FREE_LOCK(&lk)spllower((&lk)->lkt_spl);
4803 if ((error = VOP_BWRITE(nbp)) != 0) {
4804 bawrite(bp);
4805 return (error);
4806 }
4807 ACQUIRE_LOCK(&lk)(&lk)->lkt_spl = splraise(0x6);
4808 goto restart;
4809 }
4810 break;
4811
4812 case D_INODEDEP1:
4813 if ((error = flush_inodedep_deps(WK_INODEDEP(wk)((struct inodedep *)(wk))->id_fs,
4814 WK_INODEDEP(wk)((struct inodedep *)(wk))->id_ino)) != 0) {
4815 FREE_LOCK(&lk)spllower((&lk)->lkt_spl);
4816 bawrite(bp);
4817 return (error);
4818 }
4819 break;
4820
4821 case D_PAGEDEP0:
4822 /*
4823 * We are trying to sync a directory that may
4824 * have dependencies on both its own metadata
4825 * and/or dependencies on the inodes of any
4826 * recently allocated files. We walk its diradd
4827 * lists pushing out the associated inode.
4828 */
4829 pagedep = WK_PAGEDEP(wk)((struct pagedep *)(wk));
4830 for (i = 0; i < DAHASHSZ6; i++) {
4831 if (LIST_FIRST(&pagedep->pd_diraddhd[i])((&pagedep->pd_diraddhd[i])->lh_first) ==
4832 NULL((void *)0))
4833 continue;
4834 if ((error =
4835 flush_pagedep_deps(vp, pagedep->pd_mnt,
4836 &pagedep->pd_diraddhd[i]))) {
4837 FREE_LOCK(&lk)spllower((&lk)->lkt_spl);
4838 bawrite(bp);
4839 return (error);
4840 }
4841 }
4842 break;
4843
4844 case D_MKDIR11:
4845 /*
4846 * This case should never happen if the vnode has
4847 * been properly sync'ed. However, if this function
4848 * is used at a place where the vnode has not yet
4849 * been sync'ed, this dependency can show up. So,
4850 * rather than panic, just flush it.
4851 */
4852 nbp = WK_MKDIR(wk)((struct mkdir *)(wk))->md_buf;
4853 KASSERT(bp != nbp)((bp != nbp) ? (void)0 : __assert("diagnostic ", "/usr/src/sys/ufs/ffs/ffs_softdep.c"
, 4853, "bp != nbp"))
;
4854 gotit = getdirtybuf(nbp, waitfor);
4855 if (gotit == 0)
4856 break;
4857 else if (gotit == -1)
4858 goto loop;
4859 FREE_LOCK(&lk)spllower((&lk)->lkt_spl);
4860 if (waitfor == MNT_NOWAIT2) {
4861 bawrite(nbp);
4862 } else if ((error = VOP_BWRITE(nbp)) != 0) {
4863 bawrite(bp);
4864 return (error);
4865 }
4866 ACQUIRE_LOCK(&lk)(&lk)->lkt_spl = splraise(0x6);
4867 break;
4868
4869 case D_BMSAFEMAP3:
4870 /*
4871 * This case should never happen if the vnode has
4872 * been properly sync'ed. However, if this function
4873 * is used at a place where the vnode has not yet
4874 * been sync'ed, this dependency can show up. So,
4875 * rather than panic, just flush it.
4876 */
4877 nbp = WK_BMSAFEMAP(wk)((struct bmsafemap *)(wk))->sm_buf;
4878 if (bp == nbp)
4879 break;
4880 gotit = getdirtybuf(nbp, waitfor);
4881 if (gotit == 0)
4882 break;
4883 else if (gotit == -1)
4884 goto loop;
4885 FREE_LOCK(&lk)spllower((&lk)->lkt_spl);
4886 if (waitfor == MNT_NOWAIT2) {
4887 bawrite(nbp);
4888 } else if ((error = VOP_BWRITE(nbp)) != 0) {
4889 bawrite(bp);
4890 return (error);
4891 }
4892 ACQUIRE_LOCK(&lk)(&lk)->lkt_spl = splraise(0x6);
4893 break;
4894
4895 default:
4896 FREE_LOCK(&lk)spllower((&lk)->lkt_spl);
4897 panic("softdep_sync_metadata: Unknown type %s",
4898 TYPENAME(wk->wk_type)((unsigned)(wk->wk_type) <= 13 ? softdep_typenames[wk->
wk_type] : "???")
);
4899 /* NOTREACHED */
4900 }
4901 }
4902 do {
4903 nbp = LIST_NEXT(bp, b_vnbufs)((bp)->b_vnbufs.le_next);
4904 gotit = getdirtybuf(nbp, MNT_WAIT1);
4905 } while (gotit == -1);
4906 FREE_LOCK(&lk)spllower((&lk)->lkt_spl);
4907 bawrite(bp);
4908 ACQUIRE_LOCK(&lk)(&lk)->lkt_spl = splraise(0x6);
4909 if (nbp != NULL((void *)0)) {
4910 bp = nbp;
4911 goto loop;
4912 }
4913 /*
4914 * The brief unlock is to allow any pent up dependency
4915 * processing to be done. Then proceed with the second pass.
4916 */
4917 if (waitfor == MNT_NOWAIT2) {
4918 waitfor = MNT_WAIT1;
4919 FREE_LOCK(&lk)spllower((&lk)->lkt_spl);
4920 ACQUIRE_LOCK(&lk)(&lk)->lkt_spl = splraise(0x6);
4921 goto top;
4922 }
4923
4924 /*
4925 * If we have managed to get rid of all the dirty buffers,
4926 * then we are done. For certain directories and block
4927 * devices, we may need to do further work.
4928 *
4929 * We must wait for any I/O in progress to finish so that
4930 * all potential buffers on the dirty list will be visible.
4931 */
4932 drain_output(vp, 1);
4933 if (LIST_EMPTY(&vp->v_dirtyblkhd)(((&vp->v_dirtyblkhd)->lh_first) == ((void *)0))) {
4934 FREE_LOCK(&lk)spllower((&lk)->lkt_spl);
4935 return (0);
4936 }
4937
4938 FREE_LOCK(&lk)spllower((&lk)->lkt_spl);
4939 /*
4940 * If we are trying to sync a block device, some of its buffers may
4941 * contain metadata that cannot be written until the contents of some
4942 * partially written files have been written to disk. The only easy
4943 * way to accomplish this is to sync the entire filesystem (luckily
4944 * this happens rarely).
4945 */
4946 if (vn_isdisk(vp, NULL((void *)0)) &&
4947 vp->v_specmountpointv_un.vu_specinfo->si_mountpoint && !VOP_ISLOCKED(vp) &&
4948 (error = VFS_SYNC(vp->v_specmountpoint, MNT_WAIT, 0, ap->a_cred,(*(vp->v_un.vu_specinfo->si_mountpoint)->mnt_op->
vfs_sync)(vp->v_un.vu_specinfo->si_mountpoint, 1, 0, ap
->a_cred, ap->a_p)
4949 ap->a_p)(*(vp->v_un.vu_specinfo->si_mountpoint)->mnt_op->
vfs_sync)(vp->v_un.vu_specinfo->si_mountpoint, 1, 0, ap
->a_cred, ap->a_p)
) != 0)
4950 return (error);
4951 return (0);
4952}
4953
4954/*
4955 * Flush the dependencies associated with an inodedep.
4956 * Called with splbio blocked.
4957 */
4958STATIC int
4959flush_inodedep_deps(struct fs *fs, ufsino_t ino)
4960{
4961 struct inodedep *inodedep;
4962 struct allocdirect *adp;
4963 int gotit, error, waitfor;
4964 struct buf *bp;
4965
4966 splassert(IPL_BIO)do { if (splassert_ctl > 0) { splassert_check(0x6, __func__
); } } while (0)
;
4967
4968 /*
4969 * This work is done in two passes. The first pass grabs most
4970 * of the buffers and begins asynchronously writing them. The
4971 * only way to wait for these asynchronous writes is to sleep
4972 * on the filesystem vnode which may stay busy for a long time
4973 * if the filesystem is active. So, instead, we make a second
4974 * pass over the dependencies blocking on each write. In the
4975 * usual case we will be blocking against a write that we
4976 * initiated, so when it is done the dependency will have been
4977 * resolved. Thus the second pass is expected to end quickly.
4978 * We give a brief window at the top of the loop to allow
4979 * any pending I/O to complete.
4980 */
4981 for (waitfor = MNT_NOWAIT2; ; ) {
4982 retry_ino:
4983 FREE_LOCK(&lk)spllower((&lk)->lkt_spl);
4984 ACQUIRE_LOCK(&lk)(&lk)->lkt_spl = splraise(0x6);
4985 if (inodedep_lookup(fs, ino, 0, &inodedep) == 0)
4986 return (0);
4987 TAILQ_FOREACH(adp, &inodedep->id_inoupdt, ad_next)for((adp) = ((&inodedep->id_inoupdt)->tqh_first); (
adp) != ((void *)0); (adp) = ((adp)->ad_next.tqe_next))
{
4988 if (adp->ad_statead_list.wk_state & DEPCOMPLETE0x0008)
4989 continue;
4990 bp = adp->ad_buf;
4991 gotit = getdirtybuf(bp, waitfor);
4992 if (gotit == 0) {
4993 if (waitfor == MNT_NOWAIT2)
4994 continue;
4995 break;
4996 } else if (gotit == -1)
4997 goto retry_ino;
4998 FREE_LOCK(&lk)spllower((&lk)->lkt_spl);
4999 if (waitfor == MNT_NOWAIT2) {
5000 bawrite(bp);
5001 } else if ((error = VOP_BWRITE(bp)) != 0) {
5002 ACQUIRE_LOCK(&lk)(&lk)->lkt_spl = splraise(0x6);
5003 return (error);
5004 }
5005 ACQUIRE_LOCK(&lk)(&lk)->lkt_spl = splraise(0x6);
5006 break;
5007 }
5008 if (adp != NULL((void *)0))
5009 continue;
5010 retry_newino:
5011 TAILQ_FOREACH(adp, &inodedep->id_newinoupdt, ad_next)for((adp) = ((&inodedep->id_newinoupdt)->tqh_first)
; (adp) != ((void *)0); (adp) = ((adp)->ad_next.tqe_next))
{
5012 if (adp->ad_statead_list.wk_state & DEPCOMPLETE0x0008)
5013 continue;
5014 bp = adp->ad_buf;
5015 gotit = getdirtybuf(bp, waitfor);
5016 if (gotit == 0) {
5017 if (waitfor == MNT_NOWAIT2)
5018 continue;
5019 break;
5020 } else if (gotit == -1)
5021 goto retry_newino;
5022 FREE_LOCK(&lk)spllower((&lk)->lkt_spl);
5023 if (waitfor == MNT_NOWAIT2) {
5024 bawrite(bp);
5025 } else if ((error = VOP_BWRITE(bp)) != 0) {
5026 ACQUIRE_LOCK(&lk)(&lk)->lkt_spl = splraise(0x6);
5027 return (error);
5028 }
5029 ACQUIRE_LOCK(&lk)(&lk)->lkt_spl = splraise(0x6);
5030 break;
5031 }
5032 if (adp != NULL((void *)0))
5033 continue;
5034 /*
5035 * If pass2, we are done, otherwise do pass 2.
5036 */
5037 if (waitfor == MNT_WAIT1)
5038 break;
5039 waitfor = MNT_WAIT1;
5040 }
5041 /*
5042 * Try freeing inodedep in case all dependencies have been removed.
5043 */
5044 if (inodedep_lookup(fs, ino, 0, &inodedep) != 0)
5045 (void) free_inodedep(inodedep);
5046 return (0);
5047}
5048
5049/*
5050 * Eliminate a pagedep dependency by flushing out all its diradd dependencies.
5051 * Called with splbio blocked.
5052 */
5053STATIC int
5054flush_pagedep_deps(struct vnode *pvp, struct mount *mp,
5055 struct diraddhd *diraddhdp)
5056{
5057 struct proc *p = CURPROC({struct cpu_info *__ci; asm volatile("movq %%gs:%P1,%0" : "=r"
(__ci) :"n" (__builtin_offsetof(struct cpu_info, ci_self)));
__ci;})->ci_curproc
; /* XXX */
5058 struct worklist *wk;
5059 struct inodedep *inodedep;
5060 struct ufsmount *ump;
5061 struct diradd *dap;
5062 struct vnode *vp;
5063 int gotit, error = 0;
5064 struct buf *bp;
5065 ufsino_t inum;
5066
5067 splassert(IPL_BIO)do { if (splassert_ctl > 0) { splassert_check(0x6, __func__
); } } while (0)
;
5068
5069 ump = VFSTOUFS(mp)((struct ufsmount *)((mp)->mnt_data));
5070 while ((dap = LIST_FIRST(diraddhdp)((diraddhdp)->lh_first)) != NULL((void *)0)) {
5071 /*
5072 * Flush ourselves if this directory entry
5073 * has a MKDIR_PARENT dependency.
5074 */
5075 if (dap->da_stateda_list.wk_state & MKDIR_PARENT0x0010) {
5076 FREE_LOCK(&lk)spllower((&lk)->lkt_spl);
5077 if ((error = UFS_UPDATE(VTOI(pvp), 1)((((struct inode *)(pvp)->v_data))->i_vtbl->iv_update
)((((struct inode *)(pvp)->v_data)), (1))
))
5078 break;
5079 ACQUIRE_LOCK(&lk)(&lk)->lkt_spl = splraise(0x6);
5080 /*
5081 * If that cleared dependencies, go on to next.
5082 */
5083 if (dap != LIST_FIRST(diraddhdp)((diraddhdp)->lh_first))
5084 continue;
5085 if (dap->da_stateda_list.wk_state & MKDIR_PARENT0x0010) {
5086 FREE_LOCK(&lk)spllower((&lk)->lkt_spl);
5087 panic("flush_pagedep_deps: MKDIR_PARENT");
5088 }
5089 }
5090 /*
5091 * A newly allocated directory must have its "." and
5092 * ".." entries written out before its name can be
5093 * committed in its parent. We do not want or need
5094 * the full semantics of a synchronous VOP_FSYNC as
5095 * that may end up here again, once for each directory
5096 * level in the filesystem. Instead, we push the blocks
5097 * and wait for them to clear. We have to fsync twice
5098 * because the first call may choose to defer blocks
5099 * that still have dependencies, but deferral will
5100 * happen at most once.
5101 */
5102 inum = dap->da_newinum;
5103 if (dap->da_stateda_list.wk_state & MKDIR_BODY0x0020) {
5104 FREE_LOCK(&lk)spllower((&lk)->lkt_spl);
5105 if ((error = VFS_VGET(mp, inum, &vp)(*(mp)->mnt_op->vfs_vget)(mp, inum, &vp)) != 0)
5106 break;
5107 if ((error=VOP_FSYNC(vp, p->p_ucred, MNT_NOWAIT2, p)) ||
5108 (error=VOP_FSYNC(vp, p->p_ucred, MNT_NOWAIT2, p))) {
5109 vput(vp);
5110 break;
5111 }
5112 drain_output(vp, 0);
5113 /*
5114 * If first block is still dirty with a D_MKDIR
5115 * dependency then it needs to be written now.
5116 */
5117 for (;;) {
5118 error = 0;
5119 ACQUIRE_LOCK(&lk)(&lk)->lkt_spl = splraise(0x6);
5120 bp = incore(vp, 0);
5121 if (bp == NULL((void *)0)) {
5122 FREE_LOCK(&lk)spllower((&lk)->lkt_spl);
5123 break;
5124 }
5125 LIST_FOREACH(wk, &bp->b_dep, wk_list)for((wk) = ((&bp->b_dep)->lh_first); (wk)!= ((void *
)0); (wk) = ((wk)->wk_list.le_next))
5126 if (wk->wk_type == D_MKDIR11)
5127 break;
5128 if (wk) {
5129 gotit = getdirtybuf(bp, MNT_WAIT1);
5130 FREE_LOCK(&lk)spllower((&lk)->lkt_spl);
5131 if (gotit == -1)
5132 continue;
5133 if (gotit && (error = bwrite(bp)) != 0)
5134 break;
5135 } else
5136 FREE_LOCK(&lk)spllower((&lk)->lkt_spl);
5137 break;
5138 }
5139 vput(vp);
5140 /* Flushing of first block failed */
5141 if (error)
5142 break;
5143 ACQUIRE_LOCK(&lk)(&lk)->lkt_spl = splraise(0x6);
5144 /*
5145 * If that cleared dependencies, go on to next.
5146 */
5147 if (dap != LIST_FIRST(diraddhdp)((diraddhdp)->lh_first))
5148 continue;
5149 if (dap->da_stateda_list.wk_state & MKDIR_BODY0x0020) {
5150 FREE_LOCK(&lk)spllower((&lk)->lkt_spl);
5151 panic("flush_pagedep_deps: MKDIR_BODY");
5152 }
5153 }
5154 /*
5155 * Flush the inode on which the directory entry depends.
5156 * Having accounted for MKDIR_PARENT and MKDIR_BODY above,
5157 * the only remaining dependency is that the updated inode
5158 * count must get pushed to disk. The inode has already
5159 * been pushed into its inode buffer (via VOP_UPDATE) at
5160 * the time of the reference count change. So we need only
5161 * locate that buffer, ensure that there will be no rollback
5162 * caused by a bitmap dependency, then write the inode buffer.
5163 */
5164 if (inodedep_lookup(ump->um_fsufsmount_u.fs, inum, 0, &inodedep) == 0) {
5165 FREE_LOCK(&lk)spllower((&lk)->lkt_spl);
5166 panic("flush_pagedep_deps: lost inode");
5167 }
5168 /*
5169 * If the inode still has bitmap dependencies,
5170 * push them to disk.
5171 */
5172 retry:
5173 if ((inodedep->id_stateid_list.wk_state & DEPCOMPLETE0x0008) == 0) {
5174 bp = inodedep->id_buf;
5175 gotit = getdirtybuf(bp, MNT_WAIT1);
5176 if (gotit == -1)
5177 goto retry;
5178 FREE_LOCK(&lk)spllower((&lk)->lkt_spl);
5179 if (gotit && (error = bwrite(bp)) != 0)
5180 break;
5181 ACQUIRE_LOCK(&lk)(&lk)->lkt_spl = splraise(0x6);
5182 if (dap != LIST_FIRST(diraddhdp)((diraddhdp)->lh_first))
5183 continue;
5184 }
5185 /*
5186 * If the inode is still sitting in a buffer waiting
5187 * to be written, push it to disk.
5188 */
5189 FREE_LOCK(&lk)spllower((&lk)->lkt_spl);
5190 if ((error = bread(ump->um_devvp,
5191 fsbtodb(ump->um_fs, ino_to_fsba(ump->um_fs, inum))((((daddr_t)(((((daddr_t)(ump->ufsmount_u.fs)->fs_fpg *
(((inum) / (ump->ufsmount_u.fs)->fs_ipg))) + (ump->
ufsmount_u.fs)->fs_cgoffset * ((((inum) / (ump->ufsmount_u
.fs)->fs_ipg)) & ~((ump->ufsmount_u.fs)->fs_cgmask
))) + (ump->ufsmount_u.fs)->fs_iblkno) + ((((((inum) % (
ump->ufsmount_u.fs)->fs_ipg) / ((ump->ufsmount_u.fs)
->fs_inopb))) << ((ump->ufsmount_u.fs))->fs_fragshift
))))) << (ump->ufsmount_u.fs)->fs_fsbtodb)
,
5192 (int)ump->um_fsufsmount_u.fs->fs_bsize, &bp)) != 0) {
5193 brelse(bp);
5194 break;
5195 }
5196 if ((error = bwrite(bp)) != 0)
5197 break;
5198 ACQUIRE_LOCK(&lk)(&lk)->lkt_spl = splraise(0x6);
5199 /*
5200 * If we have failed to get rid of all the dependencies
5201 * then something is seriously wrong.
5202 */
5203 if (dap == LIST_FIRST(diraddhdp)((diraddhdp)->lh_first)) {
5204 FREE_LOCK(&lk)spllower((&lk)->lkt_spl);
5205 panic("flush_pagedep_deps: flush failed");
5206 }
5207 }
5208 if (error)
5209 ACQUIRE_LOCK(&lk)(&lk)->lkt_spl = splraise(0x6);
5210 return (error);
5211}
5212
5213/*
5214 * A large burst of file addition or deletion activity can drive the
5215 * memory load excessively high. First attempt to slow things down
5216 * using the techniques below. If that fails, this routine requests
5217 * the offending operations to fall back to running synchronously
5218 * until the memory load returns to a reasonable level.
5219 */
5220int
5221softdep_slowdown(struct vnode *vp)
5222{
5223 int max_softdeps_hard;
5224
5225 max_softdeps_hard = max_softdeps * 11 / 10;
5226 if (num_dirrem < max_softdeps_hard / 2 &&
5227 num_inodedep < max_softdeps_hard)
5228 return (0);
5229 stat_sync_limit_hit += 1;
5230 return (1);
5231}
5232
5233/*
5234 * If memory utilization has gotten too high, deliberately slow things
5235 * down and speed up the I/O processing.
5236 */
5237STATIC int
5238request_cleanup(int resource, int islocked)
5239{
5240 struct proc *p = CURPROC({struct cpu_info *__ci; asm volatile("movq %%gs:%P1,%0" : "=r"
(__ci) :"n" (__builtin_offsetof(struct cpu_info, ci_self)));
__ci;})->ci_curproc
;
5241 int s;
5242
5243 /*
5244 * We never hold up the filesystem syncer process.
5245 */
5246 if (p == filesys_syncer || (p->p_flag & P_SOFTDEP0x10000000))
5247 return (0);
5248 /*
5249 * First check to see if the work list has gotten backlogged.
5250 * If it has, co-opt this process to help clean up two entries.
5251 * Because this process may hold inodes locked, we cannot
5252 * handle any remove requests that might block on a locked
5253 * inode as that could lead to deadlock. We set P_SOFTDEP
5254 * to avoid recursively processing the worklist.
5255 */
5256 if (num_on_worklist > max_softdeps / 10) {
5257 atomic_setbits_intx86_atomic_setbits_u32(&p->p_flag, P_SOFTDEP0x10000000);
5258 if (islocked)
5259 FREE_LOCK(&lk)spllower((&lk)->lkt_spl);
5260 process_worklist_item(NULL((void *)0), NULL((void *)0), LK_NOWAIT0x0040UL);
5261 process_worklist_item(NULL((void *)0), NULL((void *)0), LK_NOWAIT0x0040UL);
5262 atomic_clearbits_intx86_atomic_clearbits_u32(&p->p_flag, P_SOFTDEP0x10000000);
5263 stat_worklist_push += 2;
5264 if (islocked)
5265 ACQUIRE_LOCK(&lk)(&lk)->lkt_spl = splraise(0x6);
5266 return(1);
5267 }
5268 /*
5269 * Next, we attempt to speed up the syncer process. If that
5270 * is successful, then we allow the process to continue.
5271 */
5272 if (speedup_syncer())
5273 return(0);
5274 /*
5275 * If we are resource constrained on inode dependencies, try
5276 * flushing some dirty inodes. Otherwise, we are constrained
5277 * by file deletions, so try accelerating flushes of directories
5278 * with removal dependencies. We would like to do the cleanup
5279 * here, but we probably hold an inode locked at this point and
5280 * that might deadlock against one that we try to clean. So,
5281 * the best that we can do is request the syncer daemon to do
5282 * the cleanup for us.
5283 */
5284 switch (resource) {
5285
5286 case FLUSH_INODES1:
5287 stat_ino_limit_push += 1;
5288 req_clear_inodedeps += 1;
5289 stat_countp = &stat_ino_limit_hit;
5290 break;
5291
5292 case FLUSH_REMOVE2:
5293 stat_blk_limit_push += 1;
5294 req_clear_remove += 1;
5295 stat_countp = &stat_blk_limit_hit;
5296 break;
5297
5298 default:
5299 if (islocked)
5300 FREE_LOCK(&lk)spllower((&lk)->lkt_spl);
5301 panic("request_cleanup: unknown type");
5302 }
5303 /*
5304 * Hopefully the syncer daemon will catch up and awaken us.
5305 * We wait at most tickdelay before proceeding in any case.
5306 */
5307 if (islocked == 0)
5308 ACQUIRE_LOCK(&lk)(&lk)->lkt_spl = splraise(0x6);
5309 proc_waiting += 1;
5310 if (!timeout_pending(&proc_waiting_timeout)((&proc_waiting_timeout)->to_flags & 0x02))
5311 timeout_add(&proc_waiting_timeout, tickdelay > 2 ? tickdelay : 2);
5312
5313 s = FREE_LOCK_INTERLOCKED(&lk)((&lk)->lkt_spl);
5314 tsleep_nsec(&proc_waiting, PPAUSE40, "softupdate", INFSLP0xffffffffffffffffULL);
5315 ACQUIRE_LOCK_INTERLOCKED(&lk, s)(&lk)->lkt_spl = (s);
5316 proc_waiting -= 1;
5317 if (islocked == 0)
5318 FREE_LOCK(&lk)spllower((&lk)->lkt_spl);
5319 return (1);
5320}
5321
5322/*
5323 * Awaken processes pausing in request_cleanup and clear proc_waiting
5324 * to indicate that there is no longer a timer running.
5325 */
5326void
5327pause_timer(void *arg)
5328{
5329
5330 *stat_countp += 1;
5331 wakeup_one(&proc_waiting)wakeup_n((&proc_waiting), 1);
5332 if (proc_waiting > 0)
5333 timeout_add(&proc_waiting_timeout, tickdelay > 2 ? tickdelay : 2);
5334}
5335
5336/*
5337 * Flush out a directory with at least one removal dependency in an effort to
5338 * reduce the number of dirrem, freefile, and freeblks dependency structures.
5339 */
5340STATIC void
5341clear_remove(struct proc *p)
5342{
5343 struct pagedep_hashhead *pagedephd;
5344 struct pagedep *pagedep;
5345 static int next = 0;
5346 struct mount *mp;
5347 struct vnode *vp;
5348 int error, cnt;
5349 ufsino_t ino;
5350
5351 ACQUIRE_LOCK(&lk)(&lk)->lkt_spl = splraise(0x6);
5352 for (cnt = 0; cnt <= pagedep_hash; cnt++) {
5353 pagedephd = &pagedep_hashtbl[next++];
5354 if (next > pagedep_hash)
5355 next = 0;
5356 LIST_FOREACH(pagedep, pagedephd, pd_hash)for((pagedep) = ((pagedephd)->lh_first); (pagedep)!= ((void
*)0); (pagedep) = ((pagedep)->pd_hash.le_next))
{
5357 if (LIST_FIRST(&pagedep->pd_dirremhd)((&pagedep->pd_dirremhd)->lh_first) == NULL((void *)0))
5358 continue;
5359 mp = pagedep->pd_mnt;
5360 ino = pagedep->pd_ino;
5361#if 0
5362 if (vn_start_write(NULL((void *)0), &mp, V_NOWAIT) != 0)
5363 continue;
5364#endif
5365 FREE_LOCK(&lk)spllower((&lk)->lkt_spl);
5366 if ((error = VFS_VGET(mp, ino, &vp)(*(mp)->mnt_op->vfs_vget)(mp, ino, &vp)) != 0) {
5367 softdep_error("clear_remove: vget", error);
5368#if 0
5369 vn_finished_write(mp);
5370#endif
5371 return;
5372 }
5373 if ((error = VOP_FSYNC(vp, p->p_ucred, MNT_NOWAIT2, p)))
5374 softdep_error("clear_remove: fsync", error);
5375 drain_output(vp, 0);
5376 vput(vp);
5377#if 0
5378 vn_finished_write(mp);
5379#endif
5380 return;
5381 }
5382 }
5383 FREE_LOCK(&lk)spllower((&lk)->lkt_spl);
5384}
5385
5386/*
5387 * Clear out a block of dirty inodes in an effort to reduce
5388 * the number of inodedep dependency structures.
5389 */
5390STATIC void
5391clear_inodedeps(struct proc *p)
5392{
5393 struct inodedep_hashhead *inodedephd;
5394 struct inodedep *inodedep = NULL((void *)0);
5395 static int next = 0;
5396 struct mount *mp;
5397 struct vnode *vp;
5398 struct fs *fs;
5399 int error, cnt;
5400 ufsino_t firstino, lastino, ino;
5401
5402 ACQUIRE_LOCK(&lk)(&lk)->lkt_spl = splraise(0x6);
5403 /*
5404 * Pick a random inode dependency to be cleared.
5405 * We will then gather up all the inodes in its block
5406 * that have dependencies and flush them out.
5407 */
5408 for (cnt = 0; cnt <= inodedep_hash; cnt++) {
5409 inodedephd = &inodedep_hashtbl[next++];
5410 if (next > inodedep_hash)
5411 next = 0;
5412 if ((inodedep = LIST_FIRST(inodedephd)((inodedephd)->lh_first)) != NULL((void *)0))
5413 break;
5414 }
5415 if (inodedep == NULL((void *)0)) {
5416 FREE_LOCK(&lk)spllower((&lk)->lkt_spl);
5417 return;
5418 }
5419 /*
5420 * Ugly code to find mount point given pointer to superblock.
5421 */
5422 fs = inodedep->id_fs;
5423 TAILQ_FOREACH(mp, &mountlist, mnt_list)for((mp) = ((&mountlist)->tqh_first); (mp) != ((void *
)0); (mp) = ((mp)->mnt_list.tqe_next))
5424 if ((mp->mnt_flag & MNT_SOFTDEP0x04000000) && fs == VFSTOUFS(mp)((struct ufsmount *)((mp)->mnt_data))->um_fsufsmount_u.fs)
5425 break;
5426 /*
5427 * Find the last inode in the block with dependencies.
5428 */
5429 firstino = inodedep->id_ino & ~(INOPB(fs)((fs)->fs_inopb) - 1);
5430 for (lastino = firstino + INOPB(fs)((fs)->fs_inopb) - 1; lastino > firstino; lastino--)
5431 if (inodedep_lookup(fs, lastino, 0, &inodedep) != 0)
5432 break;
5433 /*
5434 * Asynchronously push all but the last inode with dependencies.
5435 * Synchronously push the last inode with dependencies to ensure
5436 * that the inode block gets written to free up the inodedeps.
5437 */
5438 for (ino = firstino; ino <= lastino; ino++) {
5439 if (inodedep_lookup(fs, ino, 0, &inodedep) == 0)
5440 continue;
5441 FREE_LOCK(&lk)spllower((&lk)->lkt_spl);
5442#if 0
5443 if (vn_start_write(NULL((void *)0), &mp, V_NOWAIT) != 0)
5444 continue;
5445#endif
5446 if ((error = VFS_VGET(mp, ino, &vp)(*(mp)->mnt_op->vfs_vget)(mp, ino, &vp)) != 0) {
5447 softdep_error("clear_inodedeps: vget", error);
5448#if 0
5449 vn_finished_write(mp);
5450#endif
5451 return;
5452 }
5453 if (ino == lastino) {
5454 if ((error = VOP_FSYNC(vp, p->p_ucred, MNT_WAIT1, p)))
5455 softdep_error("clear_inodedeps: fsync1", error);
5456 } else {
5457 if ((error = VOP_FSYNC(vp, p->p_ucred, MNT_NOWAIT2, p)))
5458 softdep_error("clear_inodedeps: fsync2", error);
5459 drain_output(vp, 0);
5460 }
5461 vput(vp);
5462#if 0
5463 vn_finished_write(mp);
5464#endif
5465 ACQUIRE_LOCK(&lk)(&lk)->lkt_spl = splraise(0x6);
5466 }
5467 FREE_LOCK(&lk)spllower((&lk)->lkt_spl);
5468}
5469
5470/*
5471 * Function to determine if the buffer has outstanding dependencies
5472 * that will cause a roll-back if the buffer is written. If wantcount
5473 * is set, return number of dependencies, otherwise just yes or no.
5474 */
5475int
5476softdep_count_dependencies(struct buf *bp, int wantcount, int islocked)
5477{
5478 struct worklist *wk;
5479 struct inodedep *inodedep;
5480 struct indirdep *indirdep;
5481 struct allocindir *aip;
5482 struct pagedep *pagedep;
5483 struct diradd *dap;
5484 int i, retval;
5485
5486 retval = 0;
5487 if (!islocked)
5488 ACQUIRE_LOCK(&lk)(&lk)->lkt_spl = splraise(0x6);
5489 LIST_FOREACH(wk, &bp->b_dep, wk_list)for((wk) = ((&bp->b_dep)->lh_first); (wk)!= ((void *
)0); (wk) = ((wk)->wk_list.le_next))
{
5490 switch (wk->wk_type) {
5491
5492 case D_INODEDEP1:
5493 inodedep = WK_INODEDEP(wk)((struct inodedep *)(wk));
5494 if ((inodedep->id_stateid_list.wk_state & DEPCOMPLETE0x0008) == 0) {
5495 /* bitmap allocation dependency */
5496 retval += 1;
5497 if (!wantcount)
5498 goto out;
5499 }
5500 if (TAILQ_FIRST(&inodedep->id_inoupdt)((&inodedep->id_inoupdt)->tqh_first)) {
5501 /* direct block pointer dependency */
5502 retval += 1;
5503 if (!wantcount)
5504 goto out;
5505 }
5506 continue;
5507
5508 case D_INDIRDEP5:
5509 indirdep = WK_INDIRDEP(wk)((struct indirdep *)(wk));
5510
5511 LIST_FOREACH(aip, &indirdep->ir_deplisthd, ai_next)for((aip) = ((&indirdep->ir_deplisthd)->lh_first); (
aip)!= ((void *)0); (aip) = ((aip)->ai_next.le_next))
{
5512 /* indirect block pointer dependency */
5513 retval += 1;
5514 if (!wantcount)
5515 goto out;
5516 }
5517 continue;
5518
5519 case D_PAGEDEP0:
5520 pagedep = WK_PAGEDEP(wk)((struct pagedep *)(wk));
5521 for (i = 0; i < DAHASHSZ6; i++) {
5522
5523 LIST_FOREACH(dap, &pagedep->pd_diraddhd[i], da_pdlist)for((dap) = ((&pagedep->pd_diraddhd[i])->lh_first);
(dap)!= ((void *)0); (dap) = ((dap)->da_pdlist.le_next))
{
5524 /* directory entry dependency */
5525 retval += 1;
5526 if (!wantcount)
5527 goto out;
5528 }
5529 }
5530 continue;
5531
5532 case D_BMSAFEMAP3:
5533 case D_ALLOCDIRECT4:
5534 case D_ALLOCINDIR6:
5535 case D_MKDIR11:
5536 /* never a dependency on these blocks */
5537 continue;
5538
5539 default:
5540 if (!islocked)
5541 FREE_LOCK(&lk)spllower((&lk)->lkt_spl);
5542 panic("softdep_check_for_rollback: Unexpected type %s",
5543 TYPENAME(wk->wk_type)((unsigned)(wk->wk_type) <= 13 ? softdep_typenames[wk->
wk_type] : "???")
);
5544 /* NOTREACHED */
5545 }
5546 }
5547out:
5548 if (!islocked)
5549 FREE_LOCK(&lk)spllower((&lk)->lkt_spl);
5550 return retval;
5551}
5552
5553/*
5554 * Acquire exclusive access to a buffer.
5555 * Must be called with splbio blocked.
5556 * Returns:
5557 * 1 if the buffer was acquired and is dirty;
5558 * 0 if the buffer was clean, or we would have slept but had MN_NOWAIT;
5559 * -1 if we slept and may try again (but not with this bp).
5560 */
5561STATIC int
5562getdirtybuf(struct buf *bp, int waitfor)
5563{
5564 int s;
5565
5566 if (bp == NULL((void *)0))
5567 return (0);
5568
5569 splassert(IPL_BIO)do { if (splassert_ctl > 0) { splassert_check(0x6, __func__
); } } while (0)
;
5570
5571 if (bp->b_flags & B_BUSY0x00000010) {
5572 if (waitfor != MNT_WAIT1)
5573 return (0);
5574 bp->b_flags |= B_WANTED0x00010000;
5575 s = FREE_LOCK_INTERLOCKED(&lk)((&lk)->lkt_spl);
5576 tsleep_nsec(bp, PRIBIO16+1, "sdsdty", INFSLP0xffffffffffffffffULL);
5577 ACQUIRE_LOCK_INTERLOCKED(&lk, s)(&lk)->lkt_spl = (s);
5578 return (-1);
5579 }
5580 if ((bp->b_flags & B_DELWRI0x00000080) == 0)
5581 return (0);
5582 bremfreebufcache_take(bp);
5583 buf_acquire(bp);
5584 return (1);
5585}
5586
5587/*
5588 * Wait for pending output on a vnode to complete.
5589 * Must be called with vnode locked.
5590 */
5591STATIC void
5592drain_output(struct vnode *vp, int islocked)
5593{
5594 int s;
5595
5596 if (!islocked)
5597 ACQUIRE_LOCK(&lk)(&lk)->lkt_spl = splraise(0x6);
5598
5599 splassert(IPL_BIO)do { if (splassert_ctl > 0) { splassert_check(0x6, __func__
); } } while (0)
;
5600
5601 while (vp->v_numoutput) {
5602 vp->v_bioflag |= VBIOWAIT0x0001;
5603 s = FREE_LOCK_INTERLOCKED(&lk)((&lk)->lkt_spl);
5604 tsleep_nsec(&vp->v_numoutput, PRIBIO16+1, "drain_output", INFSLP0xffffffffffffffffULL);
5605 ACQUIRE_LOCK_INTERLOCKED(&lk, s)(&lk)->lkt_spl = (s);
5606 }
5607 if (!islocked)
5608 FREE_LOCK(&lk)spllower((&lk)->lkt_spl);
5609}
5610
5611/*
5612 * Called whenever a buffer that is being invalidated or reallocated
5613 * contains dependencies. This should only happen if an I/O error has
5614 * occurred. The routine is called with the buffer locked.
5615 */
5616void
5617softdep_deallocate_dependencies(struct buf *bp)
5618{
5619
5620 if ((bp->b_flags & B_ERROR0x00000400) == 0)
5621 panic("softdep_deallocate_dependencies: dangling deps");
5622 softdep_error(bp->b_vp->v_mount->mnt_stat.f_mntonname, bp->b_error);
5623 panic("softdep_deallocate_dependencies: unrecovered I/O error");
5624}
5625
5626/*
5627 * Function to handle asynchronous write errors in the filesystem.
5628 */
5629void
5630softdep_error(char *func, int error)
5631{
5632
5633 /* XXX should do something better! */
5634 printf("%s: got error %d while accessing filesystem\n", func, error);
5635}
5636
5637#ifdef DDB1
5638#include <machine/db_machdep.h>
5639#include <ddb/db_interface.h>
5640#include <ddb/db_output.h>
5641
5642void
5643softdep_print(struct buf *bp, int full,
5644 int (*pr)(const char *, ...) __attribute__((__format__(__kprintf__,1,2))))
5645{
5646 struct worklist *wk;
5647
5648 (*pr)(" deps:\n");
5649 LIST_FOREACH(wk, &bp->b_dep, wk_list)for((wk) = ((&bp->b_dep)->lh_first); (wk)!= ((void *
)0); (wk) = ((wk)->wk_list.le_next))
5650 worklist_print(wk, full, pr);
5651}
5652
5653void
5654worklist_print(struct worklist *wk, int full,
5655 int (*pr)(const char *, ...) __attribute__((__format__(__kprintf__,1,2))))
5656{
5657 struct pagedep *pagedep;
5658 struct inodedep *inodedep;
5659 struct newblk *newblk;
5660 struct bmsafemap *bmsafemap;
5661 struct allocdirect *adp;
5662 struct indirdep *indirdep;
5663 struct allocindir *aip;
5664 struct freefrag *freefrag;
5665 struct freeblks *freeblks;
5666 struct freefile *freefile;
5667 struct diradd *dap;
5668 struct mkdir *mkdir;
5669 struct dirrem *dirrem;
5670 struct newdirblk *newdirblk;
5671 char prefix[33];
5672 int i;
5673
5674 for (prefix[i = 2 * MIN(16, full)(((16)<(full))?(16):(full))] = '\0'; i--; prefix[i] = ' ')
5675 ;
5676
5677 (*pr)("%s%s(%p) state %b\n%s", prefix, TYPENAME(wk->wk_type)((unsigned)(wk->wk_type) <= 13 ? softdep_typenames[wk->
wk_type] : "???")
, wk,
5678 wk->wk_state, DEP_BITS"\020\01ATTACHED\02UNDONE\03COMPLETE\04DEPCOMPLETE" "\05MKDIR_PARENT\06MKDIR_BODY\07RMDIR\010DIRCHG\011GOINGAWAY"
"\012IOSTARTED\013SPACECOUNTED\014NEWBLOCK\016UFS1FMT\020ONWORKLIST"
, prefix);
5679 switch (wk->wk_type) {
5680 case D_PAGEDEP0:
5681 pagedep = WK_PAGEDEP(wk)((struct pagedep *)(wk));
5682 (*pr)("mount %p ino %u lbn %lld\n", pagedep->pd_mnt,
5683 pagedep->pd_ino, (long long)pagedep->pd_lbn);
5684 break;
5685 case D_INODEDEP1:
5686 inodedep = WK_INODEDEP(wk)((struct inodedep *)(wk));
5687 (*pr)("fs %p ino %u nlinkdelta %u dino %p\n"
5688 "%s bp %p savsz %lld\n", inodedep->id_fs,
5689 inodedep->id_ino, inodedep->id_nlinkdelta,
5690 inodedep->id_un.idu_savedino1,
5691 prefix, inodedep->id_buf, inodedep->id_savedsize);
5692 break;
5693 case D_NEWBLK2:
5694 newblk = WK_NEWBLK(wk)((struct newblk *)(wk));
5695 (*pr)("fs %p newblk %lld state %d bmsafemap %p\n",
5696 newblk->nb_fs, (long long)newblk->nb_newblkno,
5697 newblk->nb_state, newblk->nb_bmsafemap);
5698 break;
5699 case D_BMSAFEMAP3:
5700 bmsafemap = WK_BMSAFEMAP(wk)((struct bmsafemap *)(wk));
5701 (*pr)("buf %p\n", bmsafemap->sm_buf);
5702 break;
5703 case D_ALLOCDIRECT4:
5704 adp = WK_ALLOCDIRECT(wk)((struct allocdirect *)(wk));
5705 (*pr)("lbn %lld newlbk %lld oldblk %lld newsize %ld olsize "
5706 "%ld\n%s bp %p inodedep %p freefrag %p\n",
5707 (long long)adp->ad_lbn, (long long)adp->ad_newblkno,
5708 (long long)adp->ad_oldblkno, adp->ad_newsize,
5709 adp->ad_oldsize,
5710 prefix, adp->ad_buf, adp->ad_inodedep, adp->ad_freefrag);
5711 break;
5712 case D_INDIRDEP5:
5713 indirdep = WK_INDIRDEP(wk)((struct indirdep *)(wk));
5714 (*pr)("savedata %p savebp %p\n", indirdep->ir_saveddata,
5715 indirdep->ir_savebp);
5716 break;
5717 case D_ALLOCINDIR6:
5718 aip = WK_ALLOCINDIR(wk)((struct allocindir *)(wk));
5719 (*pr)("off %d newblk %lld oldblk %lld freefrag %p\n"
5720 "%s indirdep %p buf %p\n", aip->ai_offset,
5721 (long long)aip->ai_newblkno, (long long)aip->ai_oldblkno,
5722 aip->ai_freefrag, prefix, aip->ai_indirdep, aip->ai_buf);
5723 break;
5724 case D_FREEFRAG7:
5725 freefrag = WK_FREEFRAG(wk)((struct freefrag *)(wk));
5726 (*pr)("vnode %p mp %p blkno %lld fsize %ld ino %u\n",
5727 freefrag->ff_devvp, freefrag->ff_mnt,
5728 (long long)freefrag->ff_blkno, freefrag->ff_fragsize,
5729 freefrag->ff_inum);
5730 break;
5731 case D_FREEBLKS8:
5732 freeblks = WK_FREEBLKS(wk)((struct freeblks *)(wk));
5733 (*pr)("previno %u devvp %p mp %p oldsz %lld newsz %lld\n"
5734 "%s chkcnt %d uid %d\n", freeblks->fb_previousinum,
5735 freeblks->fb_devvp, freeblks->fb_mnt, freeblks->fb_oldsize,
5736 freeblks->fb_newsize,
5737 prefix, freeblks->fb_chkcnt, freeblks->fb_uid);
5738 break;
5739 case D_FREEFILE9:
5740 freefile = WK_FREEFILE(wk)((struct freefile *)(wk));
5741 (*pr)("mode %x oldino %u vnode %p mp %p\n", freefile->fx_mode,
5742 freefile->fx_oldinum, freefile->fx_devvp, freefile->fx_mnt);
5743 break;
5744 case D_DIRADD10:
5745 dap = WK_DIRADD(wk)((struct diradd *)(wk));
5746 (*pr)("off %d ino %u da_un %p\n", dap->da_offset,
5747 dap->da_newinum, dap->da_un.dau_previous);
5748 break;
5749 case D_MKDIR11:
5750 mkdir = WK_MKDIR(wk)((struct mkdir *)(wk));
5751 (*pr)("diradd %p bp %p\n", mkdir->md_diradd, mkdir->md_buf);
5752 break;
5753 case D_DIRREM12:
5754 dirrem = WK_DIRREM(wk)((struct dirrem *)(wk));
5755 (*pr)("mp %p ino %u dm_un %p\n", dirrem->dm_mnt,
5756 dirrem->dm_oldinum, dirrem->dm_un.dmu_pagedep);
5757 break;
5758 case D_NEWDIRBLK13:
5759 newdirblk = WK_NEWDIRBLK(wk)((struct newdirblk *)(wk));
5760 (*pr)("pagedep %p\n", newdirblk->db_pagedep);
5761 break;
5762 }
5763}
5764#endif