Bug Summary

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

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