Bug Summary

File:ufs/ffs/ffs_vfsops.c
Warning:line 449, column 8
Dereference of null pointer

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple amd64-unknown-openbsd7.4 -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name ffs_vfsops.c -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 -ffp-contract=on -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 -target-feature +retpoline-external-thunk -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/llvm16/lib/clang/16 -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/legacy-dpm -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu/inc -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/swsmu/smu13 -I /usr/src/sys/dev/pci/drm/amd/pm/powerplay/inc -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/pm/swsmu/inc -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu/inc/pmfw_if -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 SUSPEND -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 -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 -fcf-protection=branch -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 /home/ben/Projects/scan/2024-01-11-110808-61670-1 -x c /usr/src/sys/ufs/ffs/ffs_vfsops.c
1/* $OpenBSD: ffs_vfsops.c,v 1.196 2024/01/09 03:16:00 guenther Exp $ */
2/* $NetBSD: ffs_vfsops.c,v 1.19 1996/02/09 22:22:26 christos Exp $ */
3
4/*
5 * Copyright (c) 1989, 1991, 1993, 1994
6 * The Regents of the University of California. All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. Neither the name of the University nor the names of its contributors
17 * may be used to endorse or promote products derived from this software
18 * without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
31 *
32 * @(#)ffs_vfsops.c 8.14 (Berkeley) 11/28/94
33 */
34
35#include <sys/param.h>
36#include <sys/systm.h>
37#include <sys/namei.h>
38#include <sys/proc.h>
39#include <sys/kernel.h>
40#include <sys/vnode.h>
41#include <sys/socket.h>
42#include <sys/mount.h>
43#include <sys/buf.h>
44#include <sys/mbuf.h>
45#include <sys/fcntl.h>
46#include <sys/ioctl.h>
47#include <sys/errno.h>
48#include <sys/malloc.h>
49#include <sys/sysctl.h>
50#include <sys/pool.h>
51#include <sys/dkio.h>
52#include <sys/disk.h>
53#include <sys/specdev.h>
54
55#include <ufs/ufs/quota.h>
56#include <ufs/ufs/ufsmount.h>
57#include <ufs/ufs/inode.h>
58#include <ufs/ufs/dir.h>
59#include <ufs/ufs/ufs_extern.h>
60#include <ufs/ufs/dirhash.h>
61
62#include <ufs/ffs/fs.h>
63#include <ufs/ffs/ffs_extern.h>
64
65#include <uvm/uvm_extern.h>
66
67int ffs_sbupdate(struct ufsmount *, int);
68int ffs_reload_vnode(struct vnode *, void *);
69int ffs_sync_vnode(struct vnode *, void *);
70int ffs_validate(struct fs *);
71
72void ffs1_compat_read(struct fs *, struct ufsmount *, daddr_t);
73void ffs1_compat_write(struct fs *, struct ufsmount *);
74
75const struct vfsops ffs_vfsops = {
76 .vfs_mount = ffs_mount,
77 .vfs_start = ufs_start,
78 .vfs_unmount = ffs_unmount,
79 .vfs_root = ufs_root,
80 .vfs_quotactl = ufs_quotactl,
81 .vfs_statfs = ffs_statfs,
82 .vfs_sync = ffs_sync,
83 .vfs_vget = ffs_vget,
84 .vfs_fhtovp = ffs_fhtovp,
85 .vfs_vptofh = ffs_vptofh,
86 .vfs_init = ffs_init,
87 .vfs_sysctl = ffs_sysctl,
88 .vfs_checkexp = ufs_check_export,
89};
90
91struct inode_vtbl ffs_vtbl = {
92 .iv_truncate = ffs_truncate,
93 .iv_update = ffs_update,
94 .iv_inode_alloc = ffs_inode_alloc,
95 .iv_inode_free = ffs_inode_free,
96 .iv_buf_alloc = ffs_balloc,
97 .iv_bufatoff = ffs_bufatoff
98};
99
100int
101ffs_checkrange(struct mount *mp, uint32_t ino)
102{
103 struct buf *bp;
104 struct cg *cgp;
105 struct fs *fs;
106 struct ufsmount *ump;
107 int cg, error;
108
109 fs = VFSTOUFS(mp)((struct ufsmount *)((mp)->mnt_data))->um_fsufsmount_u.fs;
110 if (ino < ROOTINO((ufsino_t)2) || ino >= fs->fs_ncg * fs->fs_ipg)
111 return ESTALE70;
112
113 /*
114 * Need to check if inode is initialized because ffsv2 does
115 * lazy initialization and we can get here from nfs_fhtovp
116 */
117 if (fs->fs_magic != FS_UFS2_MAGIC0x19540119)
118 return 0;
119
120 cg = ino_to_cg(fs, ino)((ino) / (fs)->fs_ipg);
121 ump = VFSTOUFS(mp)((struct ufsmount *)((mp)->mnt_data));
122
123 error = bread(ump->um_devvp, fsbtodb(fs, cgtod(fs, cg))((((((daddr_t)(fs)->fs_fpg * (cg)) + (fs)->fs_cgoffset *
((cg) & ~((fs)->fs_cgmask))) + (fs)->fs_cblkno)) <<
(fs)->fs_fsbtodb)
,
124 (int)fs->fs_cgsize, &bp);
125 if (error)
126 return error;
127
128 cgp = (struct cg *)bp->b_data;
129 if (!cg_chkmagic(cgp)((cgp)->cg_magic == 0x090255 || ((struct ocg *)(cgp))->
cg_magic == 0x090255)
) {
130 brelse(bp);
131 return ESTALE70;
132 }
133
134 brelse(bp);
135
136 if (cg * fs->fs_ipg + cgp->cg_initediblk < ino)
137 return ESTALE70;
138
139 return 0;
140}
141
142/*
143 * Called by main() when ufs is going to be mounted as root.
144 */
145
146struct pool ffs_ino_pool;
147struct pool ffs_dinode1_pool;
148#ifdef FFS21
149struct pool ffs_dinode2_pool;
150#endif
151
152int
153ffs_mountroot(void)
154{
155 struct fs *fs;
156 struct mount *mp;
157 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 */
158 struct ufsmount *ump;
159 int error;
160
161 /*
162 * Get vnodes for swapdev and rootdev.
163 */
164 swapdev_vp = NULL((void *)0);
165 if ((error = bdevvp(swapdev, &swapdev_vp)) ||
166 (error = bdevvp(rootdev, &rootvp))) {
167 printf("ffs_mountroot: can't setup bdevvp's\n");
168 if (swapdev_vp)
169 vrele(swapdev_vp);
170 return (error);
171 }
172
173 if ((error = vfs_rootmountalloc("ffs", "root_device", &mp)) != 0) {
174 vrele(swapdev_vp);
175 vrele(rootvp);
176 return (error);
177 }
178
179 if ((error = ffs_mountfs(rootvp, mp, p)) != 0) {
180 vfs_unbusy(mp);
181 vfs_mount_free(mp);
182 vrele(swapdev_vp);
183 vrele(rootvp);
184 return (error);
185 }
186
187 TAILQ_INSERT_TAIL(&mountlist, mp, mnt_list)do { (mp)->mnt_list.tqe_next = ((void *)0); (mp)->mnt_list
.tqe_prev = (&mountlist)->tqh_last; *(&mountlist)->
tqh_last = (mp); (&mountlist)->tqh_last = &(mp)->
mnt_list.tqe_next; } while (0)
;
188 ump = VFSTOUFS(mp)((struct ufsmount *)((mp)->mnt_data));
189 fs = ump->um_fsufsmount_u.fs;
190 strlcpy(fs->fs_fsmnt, mp->mnt_stat.f_mntonname, sizeof(fs->fs_fsmnt));
191 (void)ffs_statfs(mp, &mp->mnt_stat, p);
192 vfs_unbusy(mp);
193 inittodr(fs->fs_time);
194
195 return (0);
196}
197
198/*
199 * VFS Operations.
200 *
201 * mount system call
202 */
203int
204ffs_mount(struct mount *mp, const char *path, void *data,
205 struct nameidata *ndp, struct proc *p)
206{
207 struct vnode *devvp;
208 struct ufs_args *args = data;
209 struct ufsmount *ump = NULL((void *)0);
1
'ump' initialized to a null pointer value
210 struct fs *fs;
211 char fname[MNAMELEN90];
212 char fspec[MNAMELEN90];
213 int error = 0, flags;
214 int ronly;
215
216 /* Ask not for whom the bell tolls */
217 if (mp->mnt_flag & MNT_SOFTDEP0x04000000) {
2
Assuming the condition is false
3
Taking false branch
218 mp->mnt_flag &= ~MNT_SOFTDEP0x04000000;
219 }
220
221 /*
222 * Soft updates is incompatible with "async",
223 * so if we are doing softupdates stop the user
224 * from setting the async flag.
225 */
226 if ((mp->mnt_flag & (MNT_SOFTDEP0x04000000 | MNT_ASYNC0x00000040)) ==
4
Assuming the condition is false
5
Taking false branch
227 (MNT_SOFTDEP0x04000000 | MNT_ASYNC0x00000040)) {
228 return (EINVAL22);
229 }
230 /*
231 * If updating, check whether changing from read-only to
232 * read/write; if there is no device name, that's all we do.
233 */
234 if (mp->mnt_flag & MNT_UPDATE0x00010000) {
6
Assuming the condition is false
7
Taking false branch
235 ump = VFSTOUFS(mp)((struct ufsmount *)((mp)->mnt_data));
236 fs = ump->um_fsufsmount_u.fs;
237 devvp = ump->um_devvp;
238 error = 0;
239 ronly = fs->fs_ronly;
240
241 /*
242 * Soft updates won't be set if read/write,
243 * so "async" will be illegal.
244 */
245 if (ronly == 0 && (mp->mnt_flag & MNT_ASYNC0x00000040) &&
246 (fs->fs_flags & FS_DOSOFTDEP0x02)) {
247 error = EINVAL22;
248 goto error_1;
249 }
250
251 if (ronly == 0 && (mp->mnt_flag & MNT_RDONLY0x00000001)) {
252 /* Flush any dirty data */
253 VFS_SYNC(mp, MNT_WAIT, 0, p->p_ucred, p)(*(mp)->mnt_op->vfs_sync)(mp, 1, 0, p->p_ucred, p);
254
255 /*
256 * Get rid of files open for writing.
257 */
258 flags = WRITECLOSE0x0004;
259 if (args == NULL((void *)0))
260 flags |= IGNORECLEAN0x0010;
261 if (mp->mnt_flag & MNT_FORCE0x00080000)
262 flags |= FORCECLOSE0x0002;
263 if (fs->fs_flags & FS_DOSOFTDEP0x02) {
264 error = softdep_flushfiles(mp, flags, p);
265 mp->mnt_flag &= ~MNT_SOFTDEP0x04000000;
266 } else
267 error = ffs_flushfiles(mp, flags, p);
268 mp->mnt_flag |= MNT_RDONLY0x00000001;
269 ronly = 1;
270 }
271
272 /*
273 * Flush soft dependencies if disabling it via an update
274 * mount. This may leave some items to be processed,
275 * so don't do this yet XXX.
276 */
277 if ((fs->fs_flags & FS_DOSOFTDEP0x02) &&
278 !(mp->mnt_flag & MNT_SOFTDEP0x04000000) &&
279 !(mp->mnt_flag & MNT_RDONLY0x00000001) && fs->fs_ronly == 0) {
280#if 0
281 flags = WRITECLOSE0x0004;
282 if (mp->mnt_flag & MNT_FORCE0x00080000)
283 flags |= FORCECLOSE0x0002;
284 error = softdep_flushfiles(mp, flags, p);
285#endif
286 }
287 /*
288 * When upgrading to a softdep mount, we must first flush
289 * all vnodes. (not done yet -- see above)
290 */
291 if (!(fs->fs_flags & FS_DOSOFTDEP0x02) &&
292 (mp->mnt_flag & MNT_SOFTDEP0x04000000) && fs->fs_ronly == 0) {
293#if 0
294 flags = WRITECLOSE0x0004;
295 if (mp->mnt_flag & MNT_FORCE0x00080000)
296 flags |= FORCECLOSE0x0002;
297 error = ffs_flushfiles(mp, flags, p);
298#else
299 mp->mnt_flag &= ~MNT_SOFTDEP0x04000000;
300#endif
301 }
302
303 if (!error && (mp->mnt_flag & MNT_RELOAD0x00040000))
304 error = ffs_reload(mp, ndp->ni_cnd.cn_cred, p);
305 if (error)
306 goto error_1;
307
308 if (ronly && (mp->mnt_flag & MNT_WANTRDWR0x02000000)) {
309 if (fs->fs_clean == 0) {
310#if 0
311 /*
312 * It is safe to mount an unclean file system
313 * if it was previously mounted with softdep
314 * but we may lose space and must
315 * sometimes run fsck manually.
316 */
317 if (fs->fs_flags & FS_DOSOFTDEP0x02)
318 printf(
319"WARNING: %s was not properly unmounted\n",
320 fs->fs_fsmnt);
321 else
322#endif
323 if (mp->mnt_flag & MNT_FORCE0x00080000) {
324 printf(
325"WARNING: %s was not properly unmounted\n",
326 fs->fs_fsmnt);
327 } else {
328 printf(
329"WARNING: R/W mount of %s denied. Filesystem is not clean - run fsck\n",
330 fs->fs_fsmnt);
331 error = EROFS30;
332 goto error_1;
333 }
334 }
335
336 if ((fs->fs_flags & FS_DOSOFTDEP0x02)) {
337 error = softdep_mount(devvp, mp, fs,
338 p->p_ucred);
339 if (error)
340 goto error_1;
341 }
342 fs->fs_contigdirs = malloc((u_long)fs->fs_ncg,
343 M_UFSMNT28, M_WAITOK0x0001|M_ZERO0x0008);
344
345 ronly = 0;
346 }
347 if (args == NULL((void *)0))
348 goto success;
349 if (args->fspec == NULL((void *)0)) {
350 /*
351 * Process export requests.
352 */
353 error = vfs_export(mp, &ump->um_export,
354 &args->export_info);
355 if (error)
356 goto error_1;
357 else
358 goto success;
359 }
360 }
361
362 /*
363 * Not an update, or updating the name: look up the name
364 * and verify that it refers to a sensible block device.
365 */
366 error = copyinstr(args->fspec, fspec, sizeof(fspec), NULL((void *)0));
367 if (error)
8
Assuming 'error' is 0
9
Taking false branch
368 goto error_1;
369
370 if (disk_map(fspec, fname, MNAMELEN90, DM_OPENBLCK0x2) == -1)
10
Assuming the condition is false
11
Taking false branch
371 memcpy(fname, fspec, sizeof(fname))__builtin_memcpy((fname), (fspec), (sizeof(fname)));
372
373 NDINIT(ndp, LOOKUP, FOLLOW, UIO_SYSSPACE, fname, p)ndinitat(ndp, 0, 0x0040, UIO_SYSSPACE, -100, fname, p);
374 if ((error = namei(ndp)) != 0)
12
Assuming the condition is false
13
Taking false branch
375 goto error_1;
376
377 devvp = ndp->ni_vp;
378
379 if (devvp->v_type != VBLK) {
14
Assuming field 'v_type' is equal to VBLK
15
Taking false branch
380 error = ENOTBLK15;
381 goto error_2;
382 }
383
384 if (major(devvp->v_rdev)(((unsigned)(devvp->v_un.vu_specinfo->si_rdev) >>
8) & 0xff)
>= nblkdev
) {
16
Assuming the condition is false
17
Taking false branch
385 error = ENXIO6;
386 goto error_2;
387 }
388
389 if (mp->mnt_flag & MNT_UPDATE0x00010000) {
18
Taking false branch
390 /*
391 * UPDATE
392 * If it's not the same vnode, or at least the same device
393 * then it's not correct.
394 */
395
396 if (devvp != ump->um_devvp) {
397 if (devvp->v_rdevv_un.vu_specinfo->si_rdev == ump->um_devvp->v_rdevv_un.vu_specinfo->si_rdev) {
398 vrele(devvp);
399 } else {
400 error = EINVAL22; /* needs translation */
401 }
402 } else
403 vrele(devvp);
404 /*
405 * Update device name only on success
406 */
407 if (!error) {
408 /*
409 * Save "mounted from" info for mount point (NULL pad)
410 */
411 memset(mp->mnt_stat.f_mntfromname, 0, MNAMELEN)__builtin_memset((mp->mnt_stat.f_mntfromname), (0), (90));
412 strlcpy(mp->mnt_stat.f_mntfromname, fname, MNAMELEN90);
413 memset(mp->mnt_stat.f_mntfromspec, 0, MNAMELEN)__builtin_memset((mp->mnt_stat.f_mntfromspec), (0), (90));
414 strlcpy(mp->mnt_stat.f_mntfromspec, fspec, MNAMELEN90);
415 }
416 } else {
417 /*
418 * Since this is a new mount, we want the names for
419 * the device and the mount point copied in. If an
420 * error occurs, the mountpoint is discarded by the
421 * upper level code.
422 */
423 memset(mp->mnt_stat.f_mntonname, 0, MNAMELEN)__builtin_memset((mp->mnt_stat.f_mntonname), (0), (90));
424 strlcpy(mp->mnt_stat.f_mntonname, path, MNAMELEN90);
425 memset(mp->mnt_stat.f_mntfromname, 0, MNAMELEN)__builtin_memset((mp->mnt_stat.f_mntfromname), (0), (90));
426 strlcpy(mp->mnt_stat.f_mntfromname, fname, MNAMELEN90);
427 memset(mp->mnt_stat.f_mntfromspec, 0, MNAMELEN)__builtin_memset((mp->mnt_stat.f_mntfromspec), (0), (90));
428 strlcpy(mp->mnt_stat.f_mntfromspec, fspec, MNAMELEN90);
429
430 error = ffs_mountfs(devvp, mp, p);
431 }
432
433 if (error)
19
Assuming 'error' is 0
20
Taking false branch
434 goto error_2;
435
436 /*
437 * Initialize FS stat information in mount struct; uses both
438 * mp->mnt_stat.f_mntonname and mp->mnt_stat.f_mntfromname
439 *
440 * This code is common to root and non-root mounts
441 */
442 if (args
20.1
'args' is non-null
)
21
Taking true branch
443 memcpy(&mp->mnt_stat.mount_info.ufs_args, args, sizeof(*args))__builtin_memcpy((&mp->mnt_stat.mount_info.ufs_args), (
args), (sizeof(*args)))
;
444 VFS_STATFS(mp, &mp->mnt_stat, p)(*(mp)->mnt_op->vfs_statfs)(mp, &mp->mnt_stat, p
)
;
445
446success:
447 if (path
21.1
'path' is non-null
&& (mp->mnt_flag & MNT_UPDATE0x00010000)) {
22
Assuming the condition is true
23
Taking true branch
448 /* Update clean flag after changing read-onlyness. */
449 fs = ump->um_fsufsmount_u.fs;
24
Dereference of null pointer
450 if (ronly != fs->fs_ronly) {
451 fs->fs_ronly = ronly;
452 fs->fs_clean = ronly &&
453 (fs->fs_flags & FS_UNCLEAN0x01) == 0 ? 1 : 0;
454 if (ronly)
455 free(fs->fs_contigdirs, M_UFSMNT28, fs->fs_ncg);
456 }
457 if (!ronly) {
458 fs->fs_flags &= ~FS_DOSOFTDEP0x02;
459 }
460 ffs_sbupdate(ump, MNT_WAIT1);
461#if 0
462 if (ronly) {
463 int force = 0;
464
465 /*
466 * Updating mount to readonly. Try a cache flush.
467 * Ignore error because the ioctl may not be supported.
468 */
469 VOP_IOCTL(ump->um_devvp, DIOCCACHESYNC((unsigned long)0x80000000 | ((sizeof(int) & 0x1fff) <<
16) | ((('d')) << 8) | ((120)))
, &force,
470 FWRITE0x0002, FSCRED((struct ucred *)-2), p);
471 }
472#endif
473 }
474 return (0);
475
476error_2: /* error with devvp held */
477 vrele (devvp);
478
479error_1: /* no state to back out */
480 return (error);
481}
482
483struct ffs_reload_args {
484 struct fs *fs;
485 struct proc *p;
486 struct ucred *cred;
487 struct vnode *devvp;
488};
489
490int
491ffs_reload_vnode(struct vnode *vp, void *args)
492{
493 struct ffs_reload_args *fra = args;
494 struct inode *ip;
495 struct buf *bp;
496 int error;
497
498 /*
499 * Step 4: invalidate all inactive vnodes.
500 */
501 if (vp->v_usecount == 0) {
502 vgonel(vp, fra->p);
503 return (0);
504 }
505
506 /*
507 * Step 5: invalidate all cached file data.
508 */
509 if (vget(vp, LK_EXCLUSIVE0x0001UL))
510 return (0);
511
512 if (vinvalbuf(vp, 0, fra->cred, fra->p, 0, INFSLP0xffffffffffffffffULL))
513 panic("ffs_reload: dirty2");
514
515 /*
516 * Step 6: re-read inode data for all active vnodes.
517 */
518 ip = VTOI(vp)((struct inode *)(vp)->v_data);
519
520 error = bread(fra->devvp,
521 fsbtodb(fra->fs, ino_to_fsba(fra->fs, ip->i_number))((((daddr_t)(((((daddr_t)(fra->fs)->fs_fpg * (((ip->
i_number) / (fra->fs)->fs_ipg))) + (fra->fs)->fs_cgoffset
* ((((ip->i_number) / (fra->fs)->fs_ipg)) & ~((
fra->fs)->fs_cgmask))) + (fra->fs)->fs_iblkno) + (
(((((ip->i_number) % (fra->fs)->fs_ipg) / ((fra->
fs)->fs_inopb))) << ((fra->fs))->fs_fragshift)
)))) << (fra->fs)->fs_fsbtodb)
,
522 (int)fra->fs->fs_bsize, &bp);
523 if (error) {
524 brelse(bp);
525 vput(vp);
526 return (error);
527 }
528
529 if (fra->fs->fs_magic == FS_UFS1_MAGIC0x011954)
530 *ip->i_din1dinode_u.ffs1_din = *((struct ufs1_dinode *)bp->b_data +
531 ino_to_fsbo(fra->fs, ip->i_number)((ip->i_number) % ((fra->fs)->fs_inopb)));
532#ifdef FFS21
533 else
534 *ip->i_din2dinode_u.ffs2_din = *((struct ufs2_dinode *)bp->b_data +
535 ino_to_fsbo(fra->fs, ip->i_number)((ip->i_number) % ((fra->fs)->fs_inopb)));
536#endif /* FFS2 */
537 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)
;
538 brelse(bp);
539 vput(vp);
540 return (0);
541}
542
543/*
544 * Reload all incore data for a filesystem (used after running fsck on
545 * the root filesystem and finding things to fix). The filesystem must
546 * be mounted read-only.
547 *
548 * Things to do to update the mount:
549 * 1) invalidate all cached meta-data.
550 * 2) re-read superblock from disk.
551 * 3) re-read summary information from disk.
552 * 4) invalidate all inactive vnodes.
553 * 5) invalidate all cached file data.
554 * 6) re-read inode data for all active vnodes.
555 */
556int
557ffs_reload(struct mount *mountp, struct ucred *cred, struct proc *p)
558{
559 struct vnode *devvp;
560 caddr_t space;
561 struct fs *fs, *newfs;
562 int i, blks, size, error;
563 int32_t *lp;
564 struct buf *bp = NULL((void *)0);
565 struct ffs_reload_args fra;
566
567 if ((mountp->mnt_flag & MNT_RDONLY0x00000001) == 0)
568 return (EINVAL22);
569 /*
570 * Step 1: invalidate all cached meta-data.
571 */
572 devvp = VFSTOUFS(mountp)((struct ufsmount *)((mountp)->mnt_data))->um_devvp;
573 vn_lock(devvp, LK_EXCLUSIVE0x0001UL | LK_RETRY0x2000UL);
574 error = vinvalbuf(devvp, 0, cred, p, 0, INFSLP0xffffffffffffffffULL);
575 VOP_UNLOCK(devvp);
576 if (error)
577 panic("ffs_reload: dirty1");
578
579 /*
580 * Step 2: re-read superblock from disk.
581 */
582 fs = VFSTOUFS(mountp)((struct ufsmount *)((mountp)->mnt_data))->um_fsufsmount_u.fs;
583
584 error = bread(devvp, fs->fs_sblockloc / DEV_BSIZE(1 << 9), SBSIZE8192, &bp);
585 if (error) {
586 brelse(bp);
587 return (error);
588 }
589
590 newfs = (struct fs *)bp->b_data;
591 if (ffs_validate(newfs) == 0) {
592 brelse(bp);
593 return (EINVAL22);
594 }
595
596 /*
597 * Copy pointer fields back into superblock before copying in XXX
598 * new superblock. These should really be in the ufsmount. XXX
599 * Note that important parameters (eg fs_ncg) are unchanged.
600 */
601 newfs->fs_csp = fs->fs_csp;
602 newfs->fs_maxcluster = fs->fs_maxcluster;
603 newfs->fs_ronly = fs->fs_ronly;
604 memcpy(fs, newfs, fs->fs_sbsize)__builtin_memcpy((fs), (newfs), (fs->fs_sbsize));
605 if (fs->fs_sbsize < SBSIZE8192)
606 bp->b_flags |= B_INVAL0x00000800;
607 brelse(bp);
608 VFSTOUFS(mountp)((struct ufsmount *)((mountp)->mnt_data))->um_maxsymlinklen = fs->fs_maxsymlinklen;
609 ffs1_compat_read(fs, VFSTOUFS(mountp)((struct ufsmount *)((mountp)->mnt_data)), fs->fs_sblockloc);
610 ffs_oldfscompat(fs);
611 (void)ffs_statfs(mountp, &mountp->mnt_stat, p);
612 /*
613 * Step 3: re-read summary information from disk.
614 */
615 blks = howmany(fs->fs_cssize, fs->fs_fsize)(((fs->fs_cssize) + ((fs->fs_fsize) - 1)) / (fs->fs_fsize
))
;
616 space = (caddr_t)fs->fs_csp;
617 for (i = 0; i < blks; i += fs->fs_frag) {
618 size = fs->fs_bsize;
619 if (i + fs->fs_frag > blks)
620 size = (blks - i) * fs->fs_fsize;
621 error = bread(devvp, fsbtodb(fs, fs->fs_csaddr + i)((fs->fs_csaddr + i) << (fs)->fs_fsbtodb), size, &bp);
622 if (error) {
623 brelse(bp);
624 return (error);
625 }
626 memcpy(space, bp->b_data, size)__builtin_memcpy((space), (bp->b_data), (size));
627 space += size;
628 brelse(bp);
629 }
630 if ((fs->fs_flags & FS_DOSOFTDEP0x02))
631 (void) softdep_mount(devvp, mountp, fs, cred);
632 /*
633 * We no longer know anything about clusters per cylinder group.
634 */
635 if (fs->fs_contigsumsize > 0) {
636 lp = fs->fs_maxcluster;
637 for (i = 0; i < fs->fs_ncg; i++)
638 *lp++ = fs->fs_contigsumsize;
639 }
640
641 fra.p = p;
642 fra.cred = cred;
643 fra.fs = fs;
644 fra.devvp = devvp;
645
646 error = vfs_mount_foreach_vnode(mountp, ffs_reload_vnode, &fra);
647
648 return (error);
649}
650
651/*
652 * Checks if a super block is sane enough to be mounted.
653 */
654int
655ffs_validate(struct fs *fsp)
656{
657#ifdef FFS21
658 if (fsp->fs_magic != FS_UFS2_MAGIC0x19540119 && fsp->fs_magic != FS_UFS1_MAGIC0x011954)
659 return (0); /* Invalid magic */
660#else
661 if (fsp->fs_magic != FS_UFS1_MAGIC0x011954)
662 return (0); /* Invalid magic */
663#endif /* FFS2 */
664
665 if ((u_int)fsp->fs_bsize > MAXBSIZE(64 * 1024))
666 return (0); /* Invalid block size */
667
668 if ((u_int)fsp->fs_bsize < sizeof(struct fs))
669 return (0); /* Invalid block size */
670
671 if ((u_int)fsp->fs_sbsize > SBSIZE8192)
672 return (0); /* Invalid super block size */
673
674 if ((u_int)fsp->fs_frag > MAXFRAG8 || fragtbl[fsp->fs_frag] == NULL((void *)0))
675 return (0); /* Invalid number of fragments */
676
677 if (fsp->fs_inodefmt == FS_42INODEFMT-1)
678 return (0); /* Obsolete format, support broken in 2014 */
679 if (fsp->fs_maxsymlinklen <= 0)
680 return (0); /* Invalid max size of short symlink */
681
682 return (1); /* Super block is okay */
683}
684
685/*
686 * Possible locations for the super-block.
687 */
688const int sbtry[] = SBLOCKSEARCH{ 65536, 8192, 262144, -1 };
689
690/*
691 * Common code for mount and mountroot
692 */
693int
694ffs_mountfs(struct vnode *devvp, struct mount *mp, struct proc *p)
695{
696 struct ufsmount *ump;
697 struct buf *bp;
698 struct fs *fs;
699 dev_t dev;
700 caddr_t space;
701 daddr_t sbloc;
702 int error, i, blks, size, ronly;
703 int32_t *lp;
704 struct ucred *cred;
705 u_int64_t maxfilesize; /* XXX */
706
707 dev = devvp->v_rdevv_un.vu_specinfo->si_rdev;
708 cred = p ? p->p_ucred : NOCRED((struct ucred *)-1);
709 /*
710 * Disallow multiple mounts of the same device.
711 * Disallow mounting of a device that is currently in use
712 * (except for root, which might share swap device for miniroot).
713 * Flush out any old buffers remaining from a previous use.
714 */
715 if ((error = vfs_mountedon(devvp)) != 0)
716 return (error);
717 if (vcount(devvp) > 1 && devvp != rootvp)
718 return (EBUSY16);
719 vn_lock(devvp, LK_EXCLUSIVE0x0001UL | LK_RETRY0x2000UL);
720 error = vinvalbuf(devvp, V_SAVE0x0001, cred, p, 0, INFSLP0xffffffffffffffffULL);
721 VOP_UNLOCK(devvp);
722 if (error)
723 return (error);
724
725 ronly = (mp->mnt_flag & MNT_RDONLY0x00000001) != 0;
726 error = VOP_OPEN(devvp, ronly ? FREAD0x0001 : FREAD0x0001|FWRITE0x0002, FSCRED((struct ucred *)-2), p);
727 if (error)
728 return (error);
729
730 bp = NULL((void *)0);
731 ump = NULL((void *)0);
732
733 /*
734 * Try reading the super-block in each of its possible locations.
735 */
736 for (i = 0; sbtry[i] != -1; i++) {
737 if (bp != NULL((void *)0)) {
738 bp->b_flags |= B_NOCACHE0x00001000;
739 brelse(bp);
740 bp = NULL((void *)0);
741 }
742
743 error = bread(devvp, sbtry[i] / DEV_BSIZE(1 << 9), SBSIZE8192, &bp);
744 if (error)
745 goto out;
746
747 fs = (struct fs *) bp->b_data;
748 sbloc = sbtry[i];
749
750 /*
751 * Do not look for an FFS1 file system at SBLOCK_UFS2. Doing so
752 * will find the wrong super-block for file systems with 64k
753 * block size.
754 */
755 if (fs->fs_magic == FS_UFS1_MAGIC0x011954 && sbloc == SBLOCK_UFS265536)
756 continue;
757
758 if (ffs_validate(fs))
759 break; /* Super block validated */
760 }
761
762 if (sbtry[i] == -1) {
763 error = EINVAL22;
764 goto out;
765 }
766
767 fs->fs_fmod = 0;
768 fs->fs_flags &= ~FS_UNCLEAN0x01;
769 if (fs->fs_clean == 0) {
770#if 0
771 /*
772 * It is safe to mount an unclean file system
773 * if it was previously mounted with softdep
774 * but we may lose space and must
775 * sometimes run fsck manually.
776 */
777 if (fs->fs_flags & FS_DOSOFTDEP0x02)
778 printf(
779"WARNING: %s was not properly unmounted\n",
780 fs->fs_fsmnt);
781 else
782#endif
783 if (ronly || (mp->mnt_flag & MNT_FORCE0x00080000)) {
784 printf(
785"WARNING: %s was not properly unmounted\n",
786 fs->fs_fsmnt);
787 } else {
788 printf(
789"WARNING: R/W mount of %s denied. Filesystem is not clean - run fsck\n",
790 fs->fs_fsmnt);
791 error = EROFS30;
792 goto out;
793 }
794 }
795
796 if (fs->fs_postblformat == FS_42POSTBLFMT-1 && !ronly) {
797#ifndef SMALL_KERNEL
798 printf("ffs_mountfs(): obsolete rotational table format, "
799 "please use fsck_ffs(8) -c 1\n");
800#endif
801 error = EROFS30;
802 goto out;
803 }
804
805 ump = malloc(sizeof *ump, M_UFSMNT28, M_WAITOK0x0001|M_ZERO0x0008);
806 ump->um_fsufsmount_u.fs = malloc((u_long)fs->fs_sbsize, M_UFSMNT28,
807 M_WAITOK0x0001);
808
809 if (fs->fs_magic == FS_UFS1_MAGIC0x011954)
810 ump->um_fstype = UM_UFS11;
811#ifdef FFS21
812 else
813 ump->um_fstype = UM_UFS22;
814#endif
815
816 memcpy(ump->um_fs, bp->b_data, fs->fs_sbsize)__builtin_memcpy((ump->ufsmount_u.fs), (bp->b_data), (fs
->fs_sbsize))
;
817 if (fs->fs_sbsize < SBSIZE8192)
818 bp->b_flags |= B_INVAL0x00000800;
819 brelse(bp);
820 bp = NULL((void *)0);
821 fs = ump->um_fsufsmount_u.fs;
822
823 ffs1_compat_read(fs, ump, sbloc);
824
825 if (fs->fs_clean == 0)
826 fs->fs_flags |= FS_UNCLEAN0x01;
827 fs->fs_ronly = ronly;
828 size = fs->fs_cssize;
829 blks = howmany(size, fs->fs_fsize)(((size) + ((fs->fs_fsize) - 1)) / (fs->fs_fsize));
830 if (fs->fs_contigsumsize > 0)
831 size += fs->fs_ncg * sizeof(int32_t);
832 space = malloc((u_long)size, M_UFSMNT28, M_WAITOK0x0001);
833 fs->fs_csp = (struct csum *)space;
834 for (i = 0; i < blks; i += fs->fs_frag) {
835 size = fs->fs_bsize;
836 if (i + fs->fs_frag > blks)
837 size = (blks - i) * fs->fs_fsize;
838 error = bread(devvp, fsbtodb(fs, fs->fs_csaddr + i)((fs->fs_csaddr + i) << (fs)->fs_fsbtodb), size, &bp);
839 if (error) {
840 free(fs->fs_csp, M_UFSMNT28, 0);
841 goto out;
842 }
843 memcpy(space, bp->b_data, size)__builtin_memcpy((space), (bp->b_data), (size));
844 space += size;
845 brelse(bp);
846 bp = NULL((void *)0);
847 }
848 if (fs->fs_contigsumsize > 0) {
849 fs->fs_maxcluster = lp = (int32_t *)space;
850 for (i = 0; i < fs->fs_ncg; i++)
851 *lp++ = fs->fs_contigsumsize;
852 }
853 mp->mnt_data = ump;
854 mp->mnt_stat.f_fsid.val[0] = (long)dev;
855 /* Use on-disk fsid if it exists, else fake it */
856 if (fs->fs_id[0] != 0 && fs->fs_id[1] != 0)
857 mp->mnt_stat.f_fsid.val[1] = fs->fs_id[1];
858 else
859 mp->mnt_stat.f_fsid.val[1] = mp->mnt_vfc->vfc_typenum;
860 mp->mnt_stat.f_namemax = MAXNAMLEN255;
861 mp->mnt_flag |= MNT_LOCAL0x00001000;
862 ump->um_mountp = mp;
863 ump->um_dev = dev;
864 ump->um_devvp = devvp;
865 ump->um_nindir = fs->fs_nindir;
866 ump->um_bptrtodb = fs->fs_fsbtodb;
867 ump->um_seqinc = fs->fs_frag;
868 ump->um_maxsymlinklen = fs->fs_maxsymlinklen;
869 for (i = 0; i < MAXQUOTAS2; i++)
870 ump->um_quotas[i] = NULLVP((struct vnode *)((void *)0));
871
872 devvp->v_specmountpointv_un.vu_specinfo->si_mountpoint = mp;
873 ffs_oldfscompat(fs);
874
875 if (ronly)
876 fs->fs_contigdirs = NULL((void *)0);
877 else {
878 fs->fs_contigdirs = malloc((u_long)fs->fs_ncg,
879 M_UFSMNT28, M_WAITOK0x0001|M_ZERO0x0008);
880 }
881
882 /*
883 * Set FS local "last mounted on" information (NULL pad)
884 */
885 memset(fs->fs_fsmnt, 0, sizeof(fs->fs_fsmnt))__builtin_memset((fs->fs_fsmnt), (0), (sizeof(fs->fs_fsmnt
)))
;
886 strlcpy(fs->fs_fsmnt, mp->mnt_stat.f_mntonname, sizeof(fs->fs_fsmnt));
887
888#if 0
889 if( mp->mnt_flag & MNT_ROOTFS0x00004000) {
890 /*
891 * Root mount; update timestamp in mount structure.
892 * this will be used by the common root mount code
893 * to update the system clock.
894 */
895 mp->mnt_time = fs->fs_time;
896 }
897#endif
898
899 /*
900 * XXX
901 * Limit max file size. Even though ffs can handle files up to 16TB,
902 * we do limit the max file to 2^31 pages to prevent overflow of
903 * a 32-bit unsigned int. The buffer cache has its own checks but
904 * a little added paranoia never hurts.
905 */
906 ump->um_savedmaxfilesize = fs->fs_maxfilesize; /* XXX */
907 maxfilesize = FS_KERNMAXFILESIZE(PAGE_SIZE, fs)((u_int64_t)0x80000000 * (((((1 << 12)))<((fs)->fs_bsize
))?(((1 << 12))):((fs)->fs_bsize)) - 1)
;
908 if (fs->fs_maxfilesize > maxfilesize) /* XXX */
909 fs->fs_maxfilesize = maxfilesize; /* XXX */
910 if (ronly == 0) {
911 if ((fs->fs_flags & FS_DOSOFTDEP0x02) &&
912 (error = softdep_mount(devvp, mp, fs, cred)) != 0) {
913 free(fs->fs_csp, M_UFSMNT28, 0);
914 free(fs->fs_contigdirs, M_UFSMNT28, fs->fs_ncg);
915 goto out;
916 }
917 fs->fs_fmod = 1;
918 fs->fs_clean = 0;
919 fs->fs_flags &= ~FS_DOSOFTDEP0x02;
920 error = ffs_sbupdate(ump, MNT_WAIT1);
921 if (error == EROFS30)
922 goto out;
923 }
924 return (0);
925out:
926 if (devvp->v_specinfov_un.vu_specinfo)
927 devvp->v_specmountpointv_un.vu_specinfo->si_mountpoint = NULL((void *)0);
928 if (bp)
929 brelse(bp);
930
931 vn_lock(devvp, LK_EXCLUSIVE0x0001UL|LK_RETRY0x2000UL);
932 (void)VOP_CLOSE(devvp, ronly ? FREAD0x0001 : FREAD0x0001|FWRITE0x0002, cred, p);
933 VOP_UNLOCK(devvp);
934
935 if (ump) {
936 free(ump->um_fsufsmount_u.fs, M_UFSMNT28, ump->um_fsufsmount_u.fs->fs_sbsize);
937 free(ump, M_UFSMNT28, sizeof(*ump));
938 mp->mnt_data = NULL((void *)0);
939 }
940 return (error);
941}
942
943/*
944 * Sanity checks for old file systems.
945 */
946int
947ffs_oldfscompat(struct fs *fs)
948{
949 int i;
950
951 fs->fs_npsect = max(fs->fs_npsect, fs->fs_nsect); /* XXX */
952 fs->fs_interleave = max(fs->fs_interleave, 1); /* XXX */
953 if (fs->fs_postblformat == FS_42POSTBLFMT-1) /* XXX */
954 fs->fs_nrpos = 8; /* XXX */
955 if (fs->fs_inodefmt < FS_44INODEFMT2) { /* XXX */
956 u_int64_t sizepb = fs->fs_bsize; /* XXX */
957 /* XXX */
958 fs->fs_maxfilesize = fs->fs_bsize * NDADDR12 - 1; /* XXX */
959 for (i = 0; i < NIADDR3; i++) { /* XXX */
960 sizepb *= NINDIR(fs)((fs)->fs_nindir); /* XXX */
961 fs->fs_maxfilesize += sizepb; /* XXX */
962 } /* XXX */
963 fs->fs_qbmask = ~fs->fs_bmask; /* XXX */
964 fs->fs_qfmask = ~fs->fs_fmask; /* XXX */
965 } /* XXX */
966 if (fs->fs_avgfilesize <= 0) /* XXX */
967 fs->fs_avgfilesize = AVFILESIZ16384; /* XXX */
968 if (fs->fs_avgfpdir <= 0) /* XXX */
969 fs->fs_avgfpdir = AFPDIR64; /* XXX */
970 return (0);
971}
972
973/*
974 * Auxiliary function for reading FFS1 super blocks.
975 */
976void
977ffs1_compat_read(struct fs *fs, struct ufsmount *ump, daddr_t sbloc)
978{
979 if (fs->fs_magic == FS_UFS2_MAGIC0x19540119)
980 return; /* UFS2 */
981#if 0
982 if (fs->fs_ffs1_flags & FS_FLAGS_UPDATED0x80)
983 return; /* Already updated */
984#endif
985 fs->fs_flags = fs->fs_ffs1_flags;
986 fs->fs_sblockloc = sbloc;
987 fs->fs_maxbsize = fs->fs_bsize;
988 fs->fs_time = fs->fs_ffs1_time;
989 fs->fs_size = fs->fs_ffs1_size;
990 fs->fs_dsize = fs->fs_ffs1_dsize;
991 fs->fs_csaddr = fs->fs_ffs1_csaddr;
992 fs->fs_cstotal.cs_ndir = fs->fs_ffs1_cstotal.cs_ndir;
993 fs->fs_cstotal.cs_nbfree = fs->fs_ffs1_cstotal.cs_nbfree;
994 fs->fs_cstotal.cs_nifree = fs->fs_ffs1_cstotal.cs_nifree;
995 fs->fs_cstotal.cs_nffree = fs->fs_ffs1_cstotal.cs_nffree;
996 fs->fs_ffs1_flags |= FS_FLAGS_UPDATED0x80;
997}
998
999/*
1000 * Auxiliary function for writing FFS1 super blocks.
1001 */
1002void
1003ffs1_compat_write(struct fs *fs, struct ufsmount *ump)
1004{
1005 if (fs->fs_magic != FS_UFS1_MAGIC0x011954)
1006 return; /* UFS2 */
1007
1008 fs->fs_ffs1_time = fs->fs_time;
1009 fs->fs_ffs1_cstotal.cs_ndir = fs->fs_cstotal.cs_ndir;
1010 fs->fs_ffs1_cstotal.cs_nbfree = fs->fs_cstotal.cs_nbfree;
1011 fs->fs_ffs1_cstotal.cs_nifree = fs->fs_cstotal.cs_nifree;
1012 fs->fs_ffs1_cstotal.cs_nffree = fs->fs_cstotal.cs_nffree;
1013}
1014
1015/*
1016 * unmount system call
1017 */
1018int
1019ffs_unmount(struct mount *mp, int mntflags, struct proc *p)
1020{
1021 struct ufsmount *ump;
1022 struct fs *fs;
1023 int error, flags;
1024
1025 flags = 0;
1026 if (mntflags & MNT_FORCE0x00080000)
1027 flags |= FORCECLOSE0x0002;
1028
1029 ump = VFSTOUFS(mp)((struct ufsmount *)((mp)->mnt_data));
1030 fs = ump->um_fsufsmount_u.fs;
1031 if (mp->mnt_flag & MNT_SOFTDEP0x04000000)
1032 error = softdep_flushfiles(mp, flags, p);
1033 else
1034 error = ffs_flushfiles(mp, flags, p);
1035 if (error != 0)
1036 return (error);
1037
1038 if (fs->fs_ronly == 0) {
1039 fs->fs_clean = (fs->fs_flags & FS_UNCLEAN0x01) ? 0 : 1;
1040 error = ffs_sbupdate(ump, MNT_WAIT1);
1041 /* ignore write errors if mounted RW on read-only device */
1042 if (error && error != EROFS30) {
1043 fs->fs_clean = 0;
1044 return (error);
1045 }
1046 free(fs->fs_contigdirs, M_UFSMNT28, fs->fs_ncg);
1047 }
1048 ump->um_devvp->v_specmountpointv_un.vu_specinfo->si_mountpoint = NULL((void *)0);
1049
1050 vn_lock(ump->um_devvp, LK_EXCLUSIVE0x0001UL | LK_RETRY0x2000UL);
1051 vinvalbuf(ump->um_devvp, V_SAVE0x0001, NOCRED((struct ucred *)-1), p, 0, INFSLP0xffffffffffffffffULL);
1052 (void)VOP_CLOSE(ump->um_devvp, fs->fs_ronly ? FREAD0x0001 : FREAD0x0001|FWRITE0x0002,
1053 NOCRED((struct ucred *)-1), p);
1054 vput(ump->um_devvp);
1055 free(fs->fs_csp, M_UFSMNT28, 0);
1056 free(fs, M_UFSMNT28, fs->fs_sbsize);
1057 free(ump, M_UFSMNT28, sizeof(*ump));
1058 mp->mnt_data = NULL((void *)0);
1059 mp->mnt_flag &= ~MNT_LOCAL0x00001000;
1060 return (0);
1061}
1062
1063/*
1064 * Flush out all the files in a filesystem.
1065 */
1066int
1067ffs_flushfiles(struct mount *mp, int flags, struct proc *p)
1068{
1069 struct ufsmount *ump;
1070 int error;
1071
1072 ump = VFSTOUFS(mp)((struct ufsmount *)((mp)->mnt_data));
1073 if (mp->mnt_flag & MNT_QUOTA0x00002000) {
1074 int i;
1075 if ((error = vflush(mp, NULLVP((struct vnode *)((void *)0)), SKIPSYSTEM0x0001|flags)) != 0)
1076 return (error);
1077 for (i = 0; i < MAXQUOTAS2; i++) {
1078 if (ump->um_quotas[i] == NULLVP((struct vnode *)((void *)0)))
1079 continue;
1080 quotaoff(p, mp, i);
1081 }
1082 /*
1083 * Here we fall through to vflush again to ensure
1084 * that we have gotten rid of all the system vnodes.
1085 */
1086 }
1087
1088 /*
1089 * Flush all the files.
1090 */
1091 if ((error = vflush(mp, NULL((void *)0), flags)) != 0)
1092 return (error);
1093 /*
1094 * Flush filesystem metadata.
1095 */
1096 vn_lock(ump->um_devvp, LK_EXCLUSIVE0x0001UL | LK_RETRY0x2000UL);
1097 error = VOP_FSYNC(ump->um_devvp, p->p_ucred, MNT_WAIT1, p);
1098 VOP_UNLOCK(ump->um_devvp);
1099 return (error);
1100}
1101
1102/*
1103 * Get file system statistics.
1104 */
1105int
1106ffs_statfs(struct mount *mp, struct statfs *sbp, struct proc *p)
1107{
1108 struct ufsmount *ump;
1109 struct fs *fs;
1110
1111 ump = VFSTOUFS(mp)((struct ufsmount *)((mp)->mnt_data));
1112 fs = ump->um_fsufsmount_u.fs;
1113
1114#ifdef FFS21
1115 if (fs->fs_magic != FS_MAGIC0x011954 && fs->fs_magic != FS_UFS2_MAGIC0x19540119)
1116 panic("ffs_statfs");
1117#else
1118 if (fs->fs_magic != FS_MAGIC0x011954)
1119 panic("ffs_statfs");
1120#endif /* FFS2 */
1121
1122 sbp->f_bsize = fs->fs_fsize;
1123 sbp->f_iosize = fs->fs_bsize;
1124 sbp->f_blocks = fs->fs_dsize;
1125 sbp->f_bfree = fs->fs_cstotal.cs_nbfree * fs->fs_frag +
1126 fs->fs_cstotal.cs_nffree;
1127 sbp->f_bavail = sbp->f_bfree -
1128 ((int64_t)fs->fs_dsize * fs->fs_minfree / 100);
1129 sbp->f_files = fs->fs_ncg * fs->fs_ipg - ROOTINO((ufsino_t)2);
1130 sbp->f_ffree = fs->fs_cstotal.cs_nifree;
1131 sbp->f_favail = sbp->f_ffree;
1132 copy_statfs_info(sbp, mp);
1133
1134 return (0);
1135}
1136
1137struct ffs_sync_args {
1138 int allerror;
1139 struct proc *p;
1140 int waitfor;
1141 int nlink0;
1142 int inflight;
1143 struct ucred *cred;
1144};
1145
1146int
1147ffs_sync_vnode(struct vnode *vp, void *arg)
1148{
1149 struct ffs_sync_args *fsa = arg;
1150 struct inode *ip;
1151 int error, nlink0 = 0;
1152 int s, skip = 0;
1153
1154 if (vp->v_type == VNON)
1155 return (0);
1156
1157 ip = VTOI(vp)((struct inode *)(vp)->v_data);
1158
1159 /*
1160 * If unmounting or converting rw to ro, then stop deferring
1161 * timestamp writes.
1162 */
1163 if (fsa->waitfor == MNT_WAIT1 && (ip->i_flag & IN_LAZYMOD0x0080)) {
1164 ip->i_flag |= IN_MODIFIED0x0008;
1165 UFS_UPDATE(ip, 1)((ip)->i_vtbl->iv_update)((ip), (1));
1166 }
1167
1168 if (ip->i_effnlink == 0)
1169 nlink0 = 1;
1170
1171 s = splbio()splraise(0x3);
1172 if ((ip->i_flag &
1173 (IN_ACCESS0x0001 | IN_CHANGE0x0002 | IN_MODIFIED0x0008 | IN_UPDATE0x0004)) == 0 &&
1174 LIST_EMPTY(&vp->v_dirtyblkhd)(((&vp->v_dirtyblkhd)->lh_first) == ((void *)0))) {
1175 skip = 1;
1176 }
1177 splx(s)spllower(s);
1178
1179 if (skip)
1180 goto end;
1181
1182 if (vget(vp, LK_EXCLUSIVE0x0001UL | LK_NOWAIT0x0040UL)) {
1183 fsa->inflight = MIN(fsa->inflight+1, 65536)(((fsa->inflight+1)<(65536))?(fsa->inflight+1):(65536
))
;
1184 goto end;
1185 }
1186
1187 if ((error = VOP_FSYNC(vp, fsa->cred, fsa->waitfor, fsa->p)))
1188 fsa->allerror = error;
1189 VOP_UNLOCK(vp);
1190 vrele(vp);
1191
1192end:
1193 fsa->nlink0 = MIN(fsa->nlink0 + nlink0, 65536)(((fsa->nlink0 + nlink0)<(65536))?(fsa->nlink0 + nlink0
):(65536))
;
1194 return (0);
1195}
1196
1197/*
1198 * Go through the disk queues to initiate sandbagged IO;
1199 * go through the inodes to write those that have been modified;
1200 * initiate the writing of the super block if it has been modified.
1201 *
1202 * Should always be called with the mount point locked.
1203 */
1204int
1205ffs_sync(struct mount *mp, int waitfor, int stall, struct ucred *cred, struct proc *p)
1206{
1207 struct ufsmount *ump = VFSTOUFS(mp)((struct ufsmount *)((mp)->mnt_data));
1208 struct fs *fs;
1209 int error, allerror = 0, count, clean, fmod;
1210 struct ffs_sync_args fsa;
1211
1212 fs = ump->um_fsufsmount_u.fs;
1213 /*
1214 * Write back modified superblock.
1215 * Consistency check that the superblock
1216 * is still in the buffer cache.
1217 */
1218 if (fs->fs_fmod != 0 && fs->fs_ronly != 0) {
1219 printf("fs = %s\n", fs->fs_fsmnt);
1220 panic("update: rofs mod");
1221 }
1222 loop:
1223 /*
1224 * Write back each (modified) inode.
1225 */
1226 fsa.allerror = 0;
1227 fsa.p = p;
1228 fsa.cred = cred;
1229 fsa.waitfor = waitfor;
1230 fsa.nlink0 = 0;
1231 fsa.inflight = 0;
1232
1233 /*
1234 * Don't traverse the vnode list if we want to skip all of them.
1235 */
1236 if (waitfor != MNT_LAZY3) {
1237 vfs_mount_foreach_vnode(mp, ffs_sync_vnode, &fsa);
1238 allerror = fsa.allerror;
1239 }
1240
1241 /*
1242 * Force stale file system control information to be flushed.
1243 */
1244 if ((ump->um_mountp->mnt_flag & MNT_SOFTDEP0x04000000) && waitfor == MNT_WAIT1) {
1245 if ((error = softdep_flushworklist(ump->um_mountp, &count, p)))
1246 allerror = error;
1247 /* Flushed work items may create new vnodes to clean */
1248 if (count)
1249 goto loop;
1250 }
1251 if (waitfor != MNT_LAZY3) {
1252 vn_lock(ump->um_devvp, LK_EXCLUSIVE0x0001UL | LK_RETRY0x2000UL);
1253 if ((error = VOP_FSYNC(ump->um_devvp, cred, waitfor, p)) != 0)
1254 allerror = error;
1255 VOP_UNLOCK(ump->um_devvp);
1256 }
1257 qsync(mp);
1258 /*
1259 * Write back modified superblock.
1260 */
1261 clean = fs->fs_clean;
1262 fmod = fs->fs_fmod;
1263 if (stall && fs->fs_ronly == 0) {
1264 fs->fs_fmod = 1;
1265 if (allerror == 0 && fsa.nlink0 == 0 && fsa.inflight == 0) {
1266 fs->fs_clean = (fs->fs_flags & FS_UNCLEAN0x01) ? 0 : 1;
1267#if 0
1268 printf("%s force clean (dangling %d inflight %d)\n",
1269 mp->mnt_stat.f_mntonname, fsa.nlink0, fsa.inflight);
1270#endif
1271 } else {
1272 fs->fs_clean = 0;
1273#if 0
1274 printf("%s force dirty (dangling %d inflight %d)\n",
1275 mp->mnt_stat.f_mntonname, fsa.nlink0, fsa.inflight);
1276#endif
1277 }
1278 }
1279 if (fs->fs_fmod != 0 && (error = ffs_sbupdate(ump, waitfor)) != 0)
1280 allerror = error;
1281 fs->fs_clean = clean;
1282 fs->fs_fmod = fmod;
1283
1284 return (allerror);
1285}
1286
1287/*
1288 * Look up a FFS dinode number to find its incore vnode, otherwise read it
1289 * in from disk. If it is in core, wait for the lock bit to clear, then
1290 * return the inode locked. Detection and handling of mount points must be
1291 * done by the calling routine.
1292 */
1293int
1294ffs_vget(struct mount *mp, ino_t ino, struct vnode **vpp)
1295{
1296 struct fs *fs;
1297 struct inode *ip;
1298 struct ufs1_dinode *dp1;
1299#ifdef FFS21
1300 struct ufs2_dinode *dp2;
1301#endif
1302 struct ufsmount *ump;
1303 struct buf *bp;
1304 struct vnode *vp;
1305 dev_t dev;
1306 int error;
1307
1308 if (ino > (ufsino_t)-1)
1309 panic("ffs_vget: alien ino_t %llu", (unsigned long long)ino);
1310
1311 ump = VFSTOUFS(mp)((struct ufsmount *)((mp)->mnt_data));
1312 dev = ump->um_dev;
1313retry:
1314 if ((*vpp = ufs_ihashget(dev, ino)) != NULL((void *)0))
1315 return (0);
1316
1317 /* Allocate a new vnode/inode. */
1318 if ((error = getnewvnode(VT_UFS, mp, &ffs_vops, &vp)) != 0) {
1319 *vpp = NULL((void *)0);
1320 return (error);
1321 }
1322
1323#ifdef VFSLCKDEBUG
1324 vp->v_flag |= VLOCKSWORK0x4000;
1325#endif
1326 ip = pool_get(&ffs_ino_pool, PR_WAITOK0x0001|PR_ZERO0x0008);
1327 rrw_init_flags(&ip->i_lock, "inode", RWL_DUPOK | RWL_IS_VNODE)_rrw_init_flags(&ip->i_lock, "inode", 0, ((void *)0));
1328 ip->i_ump = ump;
1329 vref(ip->i_devvpi_ump->um_devvp);
1330 vp->v_data = ip;
1331 ip->i_vnode = vp;
1332 ip->i_fsinode_u.fs = fs = ump->um_fsufsmount_u.fs;
1333 ip->i_dev = dev;
1334 ip->i_number = ino;
1335 ip->i_vtbl = &ffs_vtbl;
1336
1337 /*
1338 * Put it onto its hash chain and lock it so that other requests for
1339 * this inode will block if they arrive while we are sleeping waiting
1340 * for old data structures to be purged or for the contents of the
1341 * disk portion of this inode to be read.
1342 */
1343 error = ufs_ihashins(ip);
1344
1345 if (error) {
1346 /*
1347 * VOP_INACTIVE will treat this as a stale file
1348 * and recycle it quickly
1349 */
1350 vrele(vp);
1351
1352 if (error == EEXIST17)
1353 goto retry;
1354
1355 return (error);
1356 }
1357
1358
1359 /* Read in the disk contents for the inode, copy into the inode. */
1360 error = bread(ump->um_devvp, fsbtodb(fs, ino_to_fsba(fs, ino))((((daddr_t)(((((daddr_t)(fs)->fs_fpg * (((ino) / (fs)->
fs_ipg))) + (fs)->fs_cgoffset * ((((ino) / (fs)->fs_ipg
)) & ~((fs)->fs_cgmask))) + (fs)->fs_iblkno) + ((((
((ino) % (fs)->fs_ipg) / ((fs)->fs_inopb))) << ((
fs))->fs_fragshift))))) << (fs)->fs_fsbtodb)
,
1361 (int)fs->fs_bsize, &bp);
1362 if (error) {
1363 /*
1364 * The inode does not contain anything useful, so it would
1365 * be misleading to leave it on its hash chain. With mode
1366 * still zero, it will be unlinked and returned to the free
1367 * list by vput().
1368 */
1369 vput(vp);
1370 brelse(bp);
1371 *vpp = NULL((void *)0);
1372 return (error);
1373 }
1374
1375#ifdef FFS21
1376 if (ip->i_ump->um_fstype == UM_UFS22) {
1377 ip->i_din2dinode_u.ffs2_din = pool_get(&ffs_dinode2_pool, PR_WAITOK0x0001);
1378 dp2 = (struct ufs2_dinode *) bp->b_data + ino_to_fsbo(fs, ino)((ino) % ((fs)->fs_inopb));
1379 *ip->i_din2dinode_u.ffs2_din = *dp2;
1380 } else
1381#endif
1382 {
1383 ip->i_din1dinode_u.ffs1_din = pool_get(&ffs_dinode1_pool, PR_WAITOK0x0001);
1384 dp1 = (struct ufs1_dinode *) bp->b_data + ino_to_fsbo(fs, ino)((ino) % ((fs)->fs_inopb));
1385 *ip->i_din1dinode_u.ffs1_din = *dp1;
1386 }
1387
1388 brelse(bp);
1389
1390 if (DOINGSOFTDEP(vp)((vp)->v_mount->mnt_flag & 0x04000000))
1391 softdep_load_inodeblock(ip);
1392 else
1393 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)
;
1394
1395 /*
1396 * Initialize the vnode from the inode, check for aliases.
1397 * Note that the underlying vnode may have changed.
1398 */
1399 if ((error = ffs_vinit(mp, &vp)) != 0) {
1400 vput(vp);
1401 *vpp = NULL((void *)0);
1402 return (error);
1403 }
1404
1405 /*
1406 * Set up a generation number for this inode if it does not
1407 * already have one. This should only happen on old filesystems.
1408 */
1409 if (DIP(ip, gen)(((ip)->i_ump->um_fstype == 1) ? (ip)->dinode_u.ffs1_din
->di_gen : (ip)->dinode_u.ffs2_din->di_gen)
== 0) {
1410 while (DIP(ip, gen)(((ip)->i_ump->um_fstype == 1) ? (ip)->dinode_u.ffs1_din
->di_gen : (ip)->dinode_u.ffs2_din->di_gen)
== 0)
1411 DIP_ASSIGN(ip, gen, arc4random())do { if ((ip)->i_ump->um_fstype == 1) (ip)->dinode_u
.ffs1_din->di_gen = (arc4random()); else (ip)->dinode_u
.ffs2_din->di_gen = (arc4random()); } while (0)
;
1412 if ((vp->v_mount->mnt_flag & MNT_RDONLY0x00000001) == 0)
1413 ip->i_flag |= IN_MODIFIED0x0008;
1414 }
1415
1416 /*
1417 * Ensure that uid and gid are correct. This is a temporary
1418 * fix until fsck has been changed to do the update.
1419 */
1420 if (fs->fs_magic == FS_UFS1_MAGIC0x011954 && fs->fs_inodefmt < FS_44INODEFMT2) {
1421 ip->i_ffs1_uiddinode_u.ffs1_din->di_uid = ip->i_din1dinode_u.ffs1_din->di_ouiddi_u.oldids[0];
1422 ip->i_ffs1_giddinode_u.ffs1_din->di_gid = ip->i_din1dinode_u.ffs1_din->di_ogiddi_u.oldids[1];
1423 }
1424
1425 *vpp = vp;
1426
1427 return (0);
1428}
1429
1430/*
1431 * File handle to vnode
1432 *
1433 * Have to be really careful about stale file handles.
1434 */
1435int
1436ffs_fhtovp(struct mount *mp, struct fid *fhp, struct vnode **vpp)
1437{
1438 struct ufid *ufhp;
1439 int error;
1440
1441 ufhp = (struct ufid *)fhp;
1442 if (ufhp->ufid_len != sizeof(*ufhp))
1443 return EINVAL22;
1444
1445 if ((error = ffs_checkrange(mp, ufhp->ufid_ino)) != 0)
1446 return error;
1447
1448 return (ufs_fhtovp(mp, ufhp, vpp));
1449}
1450
1451/*
1452 * Vnode pointer to File handle
1453 */
1454int
1455ffs_vptofh(struct vnode *vp, struct fid *fhp)
1456{
1457 struct inode *ip;
1458 struct ufid *ufhp;
1459
1460 ip = VTOI(vp)((struct inode *)(vp)->v_data);
1461 ufhp = (struct ufid *)fhp;
1462 ufhp->ufid_len = sizeof(struct ufid);
1463 ufhp->ufid_ino = ip->i_number;
1464 ufhp->ufid_gen = DIP(ip, gen)(((ip)->i_ump->um_fstype == 1) ? (ip)->dinode_u.ffs1_din
->di_gen : (ip)->dinode_u.ffs2_din->di_gen)
;
1465
1466 return (0);
1467}
1468
1469/*
1470 * Write a superblock and associated information back to disk.
1471 */
1472int
1473ffs_sbupdate(struct ufsmount *mp, int waitfor)
1474{
1475 struct fs *dfs, *fs = mp->um_fsufsmount_u.fs;
1476 struct buf *bp;
1477 int blks;
1478 caddr_t space;
1479 int i, size, error, allerror = 0;
1480
1481 /*
1482 * First write back the summary information.
1483 */
1484 blks = howmany(fs->fs_cssize, fs->fs_fsize)(((fs->fs_cssize) + ((fs->fs_fsize) - 1)) / (fs->fs_fsize
))
;
1485 space = (caddr_t)fs->fs_csp;
1486 for (i = 0; i < blks; i += fs->fs_frag) {
1487 size = fs->fs_bsize;
1488 if (i + fs->fs_frag > blks)
1489 size = (blks - i) * fs->fs_fsize;
1490 bp = getblk(mp->um_devvp, fsbtodb(fs, fs->fs_csaddr + i)((fs->fs_csaddr + i) << (fs)->fs_fsbtodb),
1491 size, 0, INFSLP0xffffffffffffffffULL);
1492 memcpy(bp->b_data, space, size)__builtin_memcpy((bp->b_data), (space), (size));
1493 space += size;
1494 if (waitfor != MNT_WAIT1)
1495 bawrite(bp);
1496 else if ((error = bwrite(bp)))
1497 allerror = error;
1498 }
1499
1500 /*
1501 * Now write back the superblock itself. If any errors occurred
1502 * up to this point, then fail so that the superblock avoids
1503 * being written out as clean.
1504 */
1505 if (allerror) {
1506 return (allerror);
1507 }
1508
1509 bp = getblk(mp->um_devvp,
1510 fs->fs_sblockloc >> (fs->fs_fshift - fs->fs_fsbtodb),
1511 (int)fs->fs_sbsize, 0, INFSLP0xffffffffffffffffULL);
1512 fs->fs_fmod = 0;
1513 fs->fs_time = gettime();
1514 memcpy(bp->b_data, fs, fs->fs_sbsize)__builtin_memcpy((bp->b_data), (fs), (fs->fs_sbsize));
1515 /* Restore compatibility to old file systems. XXX */
1516 dfs = (struct fs *)bp->b_data; /* XXX */
1517 if (fs->fs_postblformat == FS_42POSTBLFMT-1) /* XXX */
1518 dfs->fs_nrpos = -1; /* XXX */
1519 if (fs->fs_inodefmt < FS_44INODEFMT2) { /* XXX */
1520 int32_t *lp, tmp; /* XXX */
1521 /* XXX */
1522 lp = (int32_t *)&dfs->fs_qbmask; /* XXX */
1523 tmp = lp[4]; /* XXX */
1524 for (i = 4; i > 0; i--) /* XXX */
1525 lp[i] = lp[i-1]; /* XXX */
1526 lp[0] = tmp; /* XXX */
1527 } /* XXX */
1528 dfs->fs_maxfilesize = mp->um_savedmaxfilesize; /* XXX */
1529
1530 ffs1_compat_write(dfs, mp);
1531
1532 if (waitfor != MNT_WAIT1)
1533 bawrite(bp);
1534 else if ((error = bwrite(bp)))
1535 allerror = error;
1536
1537 return (allerror);
1538}
1539
1540int
1541ffs_init(struct vfsconf *vfsp)
1542{
1543 static int done;
1544
1545 if (done)
1546 return (0);
1547
1548 done = 1;
1549
1550 pool_init(&ffs_ino_pool, sizeof(struct inode), 0, IPL_NONE0x0,
1551 PR_WAITOK0x0001, "ffsino", NULL((void *)0));
1552 pool_init(&ffs_dinode1_pool, sizeof(struct ufs1_dinode), 0, IPL_NONE0x0,
1553 PR_WAITOK0x0001, "dino1pl", NULL((void *)0));
1554#ifdef FFS21
1555 pool_init(&ffs_dinode2_pool, sizeof(struct ufs2_dinode), 0, IPL_NONE0x0,
1556 PR_WAITOK0x0001, "dino2pl", NULL((void *)0));
1557#endif
1558
1559 softdep_initialize();
1560
1561 return (ufs_init(vfsp));
1562}
1563
1564#ifdef FFS_SOFTUPDATES1
1565extern int max_softdeps, tickdelay, stat_worklist_push;
1566extern int stat_blk_limit_push, stat_ino_limit_push, stat_blk_limit_hit;
1567extern int stat_ino_limit_hit, stat_sync_limit_hit, stat_indir_blk_ptrs;
1568extern int stat_inode_bitmap, stat_direct_blk_ptrs, stat_dir_entry;
1569#endif
1570const struct sysctl_bounded_args ffs_vars[] = {
1571#ifdef FFS_SOFTUPDATES1
1572 { FFS_MAX_SOFTDEPS5, &max_softdeps, 0, INT_MAX0x7fffffff },
1573 { FFS_SD_TICKDELAY6, &tickdelay, 2, INT_MAX0x7fffffff },
1574 { FFS_SD_WORKLIST_PUSH7, &stat_worklist_push, SYSCTL_INT_READONLY1,0 },
1575 { FFS_SD_BLK_LIMIT_PUSH8, &stat_blk_limit_push, SYSCTL_INT_READONLY1,0 },
1576 { FFS_SD_INO_LIMIT_PUSH9, &stat_ino_limit_push, SYSCTL_INT_READONLY1,0 },
1577 { FFS_SD_BLK_LIMIT_HIT10, &stat_blk_limit_hit, SYSCTL_INT_READONLY1,0 },
1578 { FFS_SD_INO_LIMIT_HIT11, &stat_ino_limit_hit, SYSCTL_INT_READONLY1,0 },
1579 { FFS_SD_SYNC_LIMIT_HIT12, &stat_sync_limit_hit, SYSCTL_INT_READONLY1,0 },
1580 { FFS_SD_INDIR_BLK_PTRS13, &stat_indir_blk_ptrs, SYSCTL_INT_READONLY1,0 },
1581 { FFS_SD_INODE_BITMAP14, &stat_inode_bitmap, SYSCTL_INT_READONLY1,0 },
1582 { FFS_SD_DIRECT_BLK_PTRS15, &stat_direct_blk_ptrs, SYSCTL_INT_READONLY1,0 },
1583 { FFS_SD_DIR_ENTRY16, &stat_dir_entry, SYSCTL_INT_READONLY1,0 },
1584#endif
1585#ifdef UFS_DIRHASH1
1586 { FFS_DIRHASH_DIRSIZE17, &ufs_mindirhashsize, 0, INT_MAX0x7fffffff },
1587 { FFS_DIRHASH_MAXMEM18, &ufs_dirhashmaxmem, 0, INT_MAX0x7fffffff },
1588 { FFS_DIRHASH_MEM19, &ufs_dirhashmem, SYSCTL_INT_READONLY1,0 },
1589#endif
1590};
1591
1592/*
1593 * fast filesystem related variables.
1594 */
1595int
1596ffs_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp,
1597 size_t newlen, struct proc *p)
1598{
1599 return sysctl_bounded_arr(ffs_vars, nitems(ffs_vars)(sizeof((ffs_vars)) / sizeof((ffs_vars)[0])), name,
1600 namelen, oldp, oldlenp, newp, newlen);
1601}