Bug Summary

File:ufs/ext2fs/ext2fs_vfsops.c
Warning:line 287, column 2
Undefined or garbage value returned to caller

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 ext2fs_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/ext2fs/ext2fs_vfsops.c
1/* $OpenBSD: ext2fs_vfsops.c,v 1.118 2023/03/08 04:43:09 guenther Exp $ */
2/* $NetBSD: ext2fs_vfsops.c,v 1.1 1997/06/11 09:34:07 bouyer Exp $ */
3
4/*
5 * Copyright (c) 1997 Manuel Bouyer.
6 * Copyright (c) 1989, 1991, 1993, 1994
7 * The Regents of the University of California. All rights reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 * 3. Neither the name of the University nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 *
33 * @(#)ffs_vfsops.c 8.14 (Berkeley) 11/28/94
34 * Modified for ext2fs by Manuel Bouyer.
35 */
36
37#include <sys/param.h>
38#include <sys/systm.h>
39#include <sys/namei.h>
40#include <sys/proc.h>
41#include <sys/kernel.h>
42#include <sys/vnode.h>
43#include <sys/socket.h>
44#include <sys/mount.h>
45#include <sys/buf.h>
46#include <sys/disk.h>
47#include <sys/mbuf.h>
48#include <sys/fcntl.h>
49#include <sys/disklabel.h>
50#include <sys/ioctl.h>
51#include <sys/errno.h>
52#include <sys/malloc.h>
53#include <sys/pool.h>
54#include <sys/lock.h>
55#include <sys/dkio.h>
56#include <sys/specdev.h>
57
58#include <ufs/ufs/quota.h>
59#include <ufs/ufs/ufsmount.h>
60#include <ufs/ufs/inode.h>
61#include <ufs/ufs/dir.h>
62#include <ufs/ufs/ufs_extern.h>
63
64#include <ufs/ext2fs/ext2fs.h>
65#include <ufs/ext2fs/ext2fs_extern.h>
66
67extern struct lock ufs_hashlock;
68
69int ext2fs_sbupdate(struct ufsmount *, int);
70static int e2fs_sbcheck(struct ext2fs *, int);
71
72const struct vfsops ext2fs_vfsops = {
73 .vfs_mount = ext2fs_mount,
74 .vfs_start = ufs_start,
75 .vfs_unmount = ext2fs_unmount,
76 .vfs_root = ufs_root,
77 .vfs_quotactl = ufs_quotactl,
78 .vfs_statfs = ext2fs_statfs,
79 .vfs_sync = ext2fs_sync,
80 .vfs_vget = ext2fs_vget,
81 .vfs_fhtovp = ext2fs_fhtovp,
82 .vfs_vptofh = ext2fs_vptofh,
83 .vfs_init = ext2fs_init,
84 .vfs_sysctl = ext2fs_sysctl,
85 .vfs_checkexp = ufs_check_export,
86};
87
88struct pool ext2fs_inode_pool;
89struct pool ext2fs_dinode_pool;
90
91extern u_long ext2gennumber;
92
93int
94ext2fs_init(struct vfsconf *vfsp)
95{
96 pool_init(&ext2fs_inode_pool, sizeof(struct inode), 0,
97 IPL_NONE0x0, PR_WAITOK0x0001, "ext2inopl", NULL((void *)0));
98 pool_init(&ext2fs_dinode_pool, sizeof(struct ext2fs_dinode), 0,
99 IPL_NONE0x0, PR_WAITOK0x0001, "ext2dinopl", NULL((void *)0));
100
101 return (ufs_init(vfsp));
102}
103
104/*
105 * Called by main() when ext2fs is going to be mounted as root.
106 *
107 * Name is updated by mount(8) after booting.
108 */
109#define ROOTNAME"root_device" "root_device"
110
111int
112ext2fs_mountroot(void)
113{
114 struct m_ext2fs *fs;
115 struct mount *mp;
116 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 */
117 struct ufsmount *ump;
118 int error;
119
120 /*
121 * Get vnodes for swapdev and rootdev.
122 */
123 if (bdevvp(swapdev, &swapdev_vp) || bdevvp(rootdev, &rootvp))
124 panic("ext2fs_mountroot: can't setup bdevvp's");
125
126 if ((error = vfs_rootmountalloc("ext2fs", "root_device", &mp)) != 0) {
127 vrele(rootvp);
128 return (error);
129 }
130
131 if ((error = ext2fs_mountfs(rootvp, mp, p)) != 0) {
132 vfs_unbusy(mp);
133 vfs_mount_free(mp);
134 vrele(rootvp);
135 return (error);
136 }
137
138 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)
;
139 ump = VFSTOUFS(mp)((struct ufsmount *)((mp)->mnt_data));
140 fs = ump->um_e2fsufsmount_u.e2fs;
141 memset(fs->e2fs_fsmnt, 0, sizeof(fs->e2fs_fsmnt))__builtin_memset((fs->e2fs_fsmnt), (0), (sizeof(fs->e2fs_fsmnt
)))
;
142 strlcpy(fs->e2fs_fsmnt, mp->mnt_stat.f_mntonname, sizeof(fs->e2fs_fsmnt));
143 if (fs->e2fs.e2fs_rev > E2FS_REV00) {
144 memset(fs->e2fs.e2fs_fsmnt, 0, sizeof(fs->e2fs.e2fs_fsmnt))__builtin_memset((fs->e2fs.e2fs_fsmnt), (0), (sizeof(fs->
e2fs.e2fs_fsmnt)))
;
145 strlcpy(fs->e2fs.e2fs_fsmnt, mp->mnt_stat.f_mntonname,
146 sizeof(fs->e2fs.e2fs_fsmnt));
147 }
148 (void)ext2fs_statfs(mp, &mp->mnt_stat, p);
149 vfs_unbusy(mp);
150 inittodr(fs->e2fs.e2fs_wtime);
151 return (0);
152}
153
154/*
155 * VFS Operations.
156 *
157 * mount system call
158 */
159int
160ext2fs_mount(struct mount *mp, const char *path, void *data,
161 struct nameidata *ndp, struct proc *p)
162{
163 struct vnode *devvp;
164 struct ufs_args *args = data;
165 struct ufsmount *ump = NULL((void *)0);
166 struct m_ext2fs *fs;
167 char fname[MNAMELEN90];
168 char fspec[MNAMELEN90];
169 int error, flags;
1
'error' declared without an initial value
170
171 /*
172 * If updating, check whether changing from read-only to
173 * read/write; if there is no device name, that's all we do.
174 */
175 if (mp->mnt_flag & MNT_UPDATE0x00010000) {
2
Assuming the condition is true
3
Taking true branch
176 ump = VFSTOUFS(mp)((struct ufsmount *)((mp)->mnt_data));
177 fs = ump->um_e2fsufsmount_u.e2fs;
178 if (fs->e2fs_ronly == 0 && (mp->mnt_flag & MNT_RDONLY0x00000001)) {
4
Assuming field 'e2fs_ronly' is not equal to 0
179 flags = WRITECLOSE0x0004;
180 if (mp->mnt_flag & MNT_FORCE0x00080000)
181 flags |= FORCECLOSE0x0002;
182 error = ext2fs_flushfiles(mp, flags, p);
183 if (error == 0 &&
184 ext2fs_cgupdate(ump, MNT_WAIT1) == 0 &&
185 (fs->e2fs.e2fs_state & E2FS_ERRORS0x02) == 0) {
186 fs->e2fs.e2fs_state = E2FS_ISCLEAN0x01;
187 (void)ext2fs_sbupdate(ump, MNT_WAIT1);
188 }
189 if (error)
190 return (error);
191 fs->e2fs_ronly = 1;
192 }
193 if (mp->mnt_flag & MNT_RELOAD0x00040000) {
5
Assuming the condition is false
194 error = ext2fs_reload(mp, ndp->ni_cnd.cn_cred, p);
195 if (error)
196 return (error);
197 }
198 if (fs->e2fs_ronly
5.1
Field 'e2fs_ronly' is not equal to 0
&& (mp->mnt_flag & MNT_WANTRDWR0x02000000)) {
6
Assuming the condition is false
199 fs->e2fs_ronly = 0;
200 if (fs->e2fs.e2fs_state == E2FS_ISCLEAN0x01)
201 fs->e2fs.e2fs_state = 0;
202 else
203 fs->e2fs.e2fs_state = E2FS_ERRORS0x02;
204 fs->e2fs_fmod = 1;
205 }
206 if (args && args->fspec == NULL((void *)0)) {
7
Assuming 'args' is null
207 /*
208 * Process export requests.
209 */
210 return (vfs_export(mp, &ump->um_export,
211 &args->export_info));
212 }
213 if (args
7.1
'args' is equal to NULL
== NULL((void *)0))
8
Taking true branch
214 goto success;
9
Control jumps to line 287
215 }
216 /*
217 * Not an update, or updating the name: look up the name
218 * and verify that it refers to a sensible block device.
219 */
220 error = copyinstr(args->fspec, fspec, sizeof(fspec), NULL((void *)0));
221 if (error)
222 goto error;
223
224 if (disk_map(fspec, fname, MNAMELEN90, DM_OPENBLCK0x2) == -1)
225 memcpy(fname, fspec, sizeof(fname))__builtin_memcpy((fname), (fspec), (sizeof(fname)));
226
227 NDINIT(ndp, LOOKUP, FOLLOW, UIO_SYSSPACE, fname, p)ndinitat(ndp, 0, 0x0040, UIO_SYSSPACE, -100, fname, p);
228 if ((error = namei(ndp)) != 0)
229 goto error;
230 devvp = ndp->ni_vp;
231
232 if (devvp->v_type != VBLK) {
233 error = ENOTBLK15;
234 goto error_devvp;
235 }
236 if (major(devvp->v_rdev)(((unsigned)(devvp->v_un.vu_specinfo->si_rdev) >>
8) & 0xff)
>= nblkdev) {
237 error = ENXIO6;
238 goto error_devvp;
239 }
240 if ((mp->mnt_flag & MNT_UPDATE0x00010000) == 0)
241 error = ext2fs_mountfs(devvp, mp, p);
242 else {
243 if (devvp != ump->um_devvp)
244 error = EINVAL22; /* XXX needs translation */
245 else
246 vrele(devvp);
247 }
248 if (error)
249 goto error_devvp;
250 ump = VFSTOUFS(mp)((struct ufsmount *)((mp)->mnt_data));
251 fs = ump->um_e2fsufsmount_u.e2fs;
252
253 memset(fs->e2fs_fsmnt, 0, sizeof(fs->e2fs_fsmnt))__builtin_memset((fs->e2fs_fsmnt), (0), (sizeof(fs->e2fs_fsmnt
)))
;
254 strlcpy(fs->e2fs_fsmnt, path, sizeof(fs->e2fs_fsmnt));
255 if (fs->e2fs.e2fs_rev > E2FS_REV00) {
256 memset(fs->e2fs.e2fs_fsmnt, 0, sizeof(fs->e2fs.e2fs_fsmnt))__builtin_memset((fs->e2fs.e2fs_fsmnt), (0), (sizeof(fs->
e2fs.e2fs_fsmnt)))
;
257 strlcpy(fs->e2fs.e2fs_fsmnt, mp->mnt_stat.f_mntonname,
258 sizeof(fs->e2fs.e2fs_fsmnt));
259 }
260 memcpy(mp->mnt_stat.f_mntonname, fs->e2fs_fsmnt, MNAMELEN)__builtin_memcpy((mp->mnt_stat.f_mntonname), (fs->e2fs_fsmnt
), (90))
;
261 memset(mp->mnt_stat.f_mntfromname, 0, MNAMELEN)__builtin_memset((mp->mnt_stat.f_mntfromname), (0), (90));
262 strlcpy(mp->mnt_stat.f_mntfromname, fname, MNAMELEN90);
263 memset(mp->mnt_stat.f_mntfromspec, 0, MNAMELEN)__builtin_memset((mp->mnt_stat.f_mntfromspec), (0), (90));
264 strlcpy(mp->mnt_stat.f_mntfromspec, fspec, MNAMELEN90);
265 memcpy(&mp->mnt_stat.mount_info.ufs_args, args, sizeof(*args))__builtin_memcpy((&mp->mnt_stat.mount_info.ufs_args), (
args), (sizeof(*args)))
;
266
267 if (fs->e2fs_fmod != 0) { /* XXX */
268 fs->e2fs_fmod = 0;
269 if (fs->e2fs.e2fs_state == 0)
270 fs->e2fs.e2fs_wtime = gettime();
271 else
272 printf("%s: file system not clean; please fsck(8)\n",
273 mp->mnt_stat.f_mntfromname);
274 ext2fs_cgupdate(ump, MNT_WAIT1);
275 }
276
277 goto success;
278
279error_devvp:
280 /* Error with devvp held. */
281 vrele(devvp);
282
283error:
284 /* Error with no state to backout. */
285
286success:
287 return (error);
10
Undefined or garbage value returned to caller
288}
289
290int ext2fs_reload_vnode(struct vnode *, void *args);
291
292struct ext2fs_reload_args {
293 struct m_ext2fs *fs;
294 struct proc *p;
295 struct ucred *cred;
296 struct vnode *devvp;
297};
298
299int
300ext2fs_reload_vnode(struct vnode *vp, void *args)
301{
302 struct ext2fs_reload_args *era = args;
303 struct buf *bp;
304 struct inode *ip;
305 int error;
306 caddr_t cp;
307
308 /*
309 * Step 4: invalidate all inactive vnodes.
310 */
311 if (vp->v_usecount == 0) {
312 vgonel(vp, era->p);
313 return (0);
314 }
315
316 /*
317 * Step 5: invalidate all cached file data.
318 */
319 if (vget(vp, LK_EXCLUSIVE0x0001UL))
320 return (0);
321
322 if (vinvalbuf(vp, 0, era->cred, era->p, 0, INFSLP0xffffffffffffffffULL))
323 panic("ext2fs_reload: dirty2");
324 /*
325 * Step 6: re-read inode data for all active vnodes.
326 */
327 ip = VTOI(vp)((struct inode *)(vp)->v_data);
328 error = bread(era->devvp,
329 fsbtodb(era->fs, ino_to_fsba(era->fs, ip->i_number))((((era->fs)->e2fs_gd[(((ip->i_number) - 1) / (era->
fs)->e2fs.e2fs_ipg)].ext2bgd_i_tables + (((ip->i_number
)-1) % (era->fs)->e2fs.e2fs_ipg)/(era->fs)->e2fs_ipb
)) << (era->fs)->e2fs_fsbtodb)
,
330 (int)era->fs->e2fs_bsize, &bp);
331 if (error) {
332 vput(vp);
333 return (error);
334 }
335 cp = (caddr_t)bp->b_data +
336 (ino_to_fsbo(era->fs, ip->i_number)(((ip->i_number)-1) % (era->fs)->e2fs_ipb) * EXT2_DINODE_SIZE(era->fs)((era->fs)->e2fs.e2fs_rev > 0 ? (era->fs)->e2fs
.e2fs_inode_size : 128)
);
337 e2fs_iload(era->fs, (struct ext2fs_dinode *)cp, ip->i_e2din)__builtin_memcpy(((ip->dinode_u.e2fs_din)), (((struct ext2fs_dinode
*)cp)), ((((((era->fs)->e2fs.e2fs_rev > 0 ? (era->
fs)->e2fs.e2fs_inode_size : 128))<(sizeof(*ip->dinode_u
.e2fs_din)))?(((era->fs)->e2fs.e2fs_rev > 0 ? (era->
fs)->e2fs.e2fs_inode_size : 128)):(sizeof(*ip->dinode_u
.e2fs_din)))))
;
338 brelse(bp);
339 vput(vp);
340 return (0);
341}
342
343static off_t
344ext2fs_maxfilesize(struct m_ext2fs *fs)
345{
346 bool_Bool huge = fs->e2fs.e2fs_features_rocompat & EXT2F_ROCOMPAT_HUGE_FILE0x0008;
347 off_t b = fs->e2fs_bsize / 4;
348 off_t physically, logically;
349
350 physically = dbtob(huge ? ((1ULL << 48) - 1) : UINT_MAX)((huge ? ((1ULL << 48) - 1) : 0xffffffffU) << 9);
351 logically = (12ULL + b + b*b + b*b*b) * fs->e2fs_bsize;
352
353 return MIN(logically, physically)(((logically)<(physically))?(logically):(physically));
354}
355
356static int
357e2fs_sbfill(struct vnode *devvp, struct m_ext2fs *fs)
358{
359 struct buf *bp = NULL((void *)0);
360 int i, error;
361
362 /* XXX assume hardware block size == 512 */
363 fs->e2fs_ncg = howmany(fs->e2fs.e2fs_bcount - fs->e2fs.e2fs_first_dblock,(((fs->e2fs.e2fs_bcount - fs->e2fs.e2fs_first_dblock) +
((fs->e2fs.e2fs_bpg) - 1)) / (fs->e2fs.e2fs_bpg))
364 fs->e2fs.e2fs_bpg)(((fs->e2fs.e2fs_bcount - fs->e2fs.e2fs_first_dblock) +
((fs->e2fs.e2fs_bpg) - 1)) / (fs->e2fs.e2fs_bpg))
;
365 fs->e2fs_fsbtodb = fs->e2fs.e2fs_log_bsize + 1;
366 fs->e2fs_bsize = 1024 << fs->e2fs.e2fs_log_bsize;
367 fs->e2fs_bshift = LOG_MINBSIZE10 + fs->e2fs.e2fs_log_bsize;
368 fs->e2fs_fsize = 1024 << fs->e2fs.e2fs_log_fsize;
369
370 fs->e2fs_qbmask = fs->e2fs_bsize - 1;
371 fs->e2fs_bmask = ~fs->e2fs_qbmask;
372
373 fs->e2fs_ipb = fs->e2fs_bsize / EXT2_DINODE_SIZE(fs)((fs)->e2fs.e2fs_rev > 0 ? (fs)->e2fs.e2fs_inode_size
: 128)
;
374 fs->e2fs_itpg = fs->e2fs.e2fs_ipg / fs->e2fs_ipb;
375
376 /* Re-read group descriptors from the disk. */
377 fs->e2fs_ngdb = howmany(fs->e2fs_ncg,(((fs->e2fs_ncg) + ((fs->e2fs_bsize / sizeof(struct ext2_gd
)) - 1)) / (fs->e2fs_bsize / sizeof(struct ext2_gd)))
378 fs->e2fs_bsize / sizeof(struct ext2_gd))(((fs->e2fs_ncg) + ((fs->e2fs_bsize / sizeof(struct ext2_gd
)) - 1)) / (fs->e2fs_bsize / sizeof(struct ext2_gd)))
;
379 fs->e2fs_gd = mallocarray(fs->e2fs_ngdb, fs->e2fs_bsize,
380 M_UFSMNT28, M_WAITOK0x0001);
381
382 for (i = 0; i < fs->e2fs_ngdb; ++i) {
383 daddr_t dblk = ((fs->e2fs_bsize > 1024) ? 0 : 1) + i + 1;
384 size_t gdesc = i * fs->e2fs_bsize / sizeof(struct ext2_gd);
385 struct ext2_gd *gd;
386
387 error = bread(devvp, fsbtodb(fs, dblk)((dblk) << (fs)->e2fs_fsbtodb), fs->e2fs_bsize, &bp);
388 if (error) {
389 size_t gdescs_space = fs->e2fs_ngdb * fs->e2fs_bsize;
390
391 free(fs->e2fs_gd, M_UFSMNT28, gdescs_space);
392 fs->e2fs_gd = NULL((void *)0);
393 brelse(bp);
394 return (error);
395 }
396
397 gd = (struct ext2_gd *) bp->b_data;
398 e2fs_cgload(gd, fs->e2fs_gd + gdesc, fs->e2fs_bsize)__builtin_memcpy(((fs->e2fs_gd + gdesc)), ((gd)), ((fs->
e2fs_bsize)));
;
399 brelse(bp);
400 bp = NULL((void *)0);
401 }
402
403 if (!(fs->e2fs.e2fs_features_rocompat & EXT2F_ROCOMPAT_LARGE_FILE0x0002) ||
404 (fs->e2fs.e2fs_rev == E2FS_REV00))
405 fs->e2fs_maxfilesize = INT_MAX0x7fffffff;
406 else
407 fs->e2fs_maxfilesize = ext2fs_maxfilesize(fs);
408
409 if (fs->e2fs.e2fs_features_incompat & EXT2F_INCOMPAT_EXTENTS0x0040)
410 fs->e2fs_maxfilesize *= 4;
411
412 return (0);
413}
414
415/*
416 * Reload all incore data for a filesystem (used after running fsck on
417 * the root filesystem and finding things to fix). The filesystem must
418 * be mounted read-only.
419 *
420 * Things to do to update the mount:
421 * 1) invalidate all cached meta-data.
422 * 2) re-read superblock from disk.
423 * 3) re-read summary information from disk.
424 * 4) invalidate all inactive vnodes.
425 * 5) invalidate all cached file data.
426 * 6) re-read inode data for all active vnodes.
427 */
428int
429ext2fs_reload(struct mount *mountp, struct ucred *cred, struct proc *p)
430{
431 struct vnode *devvp;
432 struct buf *bp;
433 struct m_ext2fs *fs;
434 struct ext2fs *newfs;
435 int error;
436 struct ext2fs_reload_args era;
437
438 if ((mountp->mnt_flag & MNT_RDONLY0x00000001) == 0)
439 return (EINVAL22);
440 /*
441 * Step 1: invalidate all cached meta-data.
442 */
443 devvp = VFSTOUFS(mountp)((struct ufsmount *)((mountp)->mnt_data))->um_devvp;
444 vn_lock(devvp, LK_EXCLUSIVE0x0001UL | LK_RETRY0x2000UL);
445 error = vinvalbuf(devvp, 0, cred, p, 0, INFSLP0xffffffffffffffffULL);
446 VOP_UNLOCK(devvp);
447 if (error != 0)
448 panic("ext2fs_reload: dirty1");
449
450 /*
451 * Step 2: re-read superblock from disk.
452 */
453 error = bread(devvp, (daddr_t)(SBOFF((off_t)(((off_t)(0)) + 1024)) / DEV_BSIZE(1 << 9)), SBSIZE1024, &bp);
454 if (error) {
455 brelse(bp);
456 return (error);
457 }
458 newfs = (struct ext2fs *)bp->b_data;
459 error = e2fs_sbcheck(newfs, (mountp->mnt_flag & MNT_RDONLY0x00000001));
460 if (error) {
461 brelse(bp);
462 return (error);
463 }
464
465 fs = VFSTOUFS(mountp)((struct ufsmount *)((mountp)->mnt_data))->um_e2fsufsmount_u.e2fs;
466 /*
467 * Copy in the new superblock, compute in-memory values
468 * and load group descriptors.
469 */
470 e2fs_sbload(newfs, &fs->e2fs)__builtin_memcpy(((&fs->e2fs)), ((newfs)), (1024));;
471 if ((error = e2fs_sbfill(devvp, fs)) != 0)
472 return (error);
473
474 era.p = p;
475 era.cred = cred;
476 era.fs = fs;
477 era.devvp = devvp;
478
479 error = vfs_mount_foreach_vnode(mountp, ext2fs_reload_vnode, &era);
480
481 return (error);
482}
483
484/*
485 * Common code for mount and mountroot
486 */
487int
488ext2fs_mountfs(struct vnode *devvp, struct mount *mp, struct proc *p)
489{
490 struct ufsmount *ump;
491 struct buf *bp;
492 struct ext2fs *fs;
493 dev_t dev;
494 int error, ronly;
495 struct ucred *cred;
496
497 dev = devvp->v_rdevv_un.vu_specinfo->si_rdev;
498 cred = p ? p->p_ucred : NOCRED((struct ucred *)-1);
499 /*
500 * Disallow multiple mounts of the same device.
501 * Disallow mounting of a device that is currently in use
502 * (except for root, which might share swap device for miniroot).
503 * Flush out any old buffers remaining from a previous use.
504 */
505 if ((error = vfs_mountedon(devvp)) != 0)
506 return (error);
507 if (vcount(devvp) > 1 && devvp != rootvp)
508 return (EBUSY16);
509 vn_lock(devvp, LK_EXCLUSIVE0x0001UL | LK_RETRY0x2000UL);
510 error = vinvalbuf(devvp, V_SAVE0x0001, cred, p, 0, INFSLP0xffffffffffffffffULL);
511 VOP_UNLOCK(devvp);
512 if (error != 0)
513 return (error);
514
515 ronly = (mp->mnt_flag & MNT_RDONLY0x00000001) != 0;
516 error = VOP_OPEN(devvp, ronly ? FREAD0x0001 : FREAD0x0001|FWRITE0x0002, FSCRED((struct ucred *)-2), p);
517 if (error)
518 return (error);
519
520 bp = NULL((void *)0);
521 ump = NULL((void *)0);
522
523 /*
524 * Read the superblock from disk.
525 */
526 error = bread(devvp, (daddr_t)(SBOFF((off_t)(((off_t)(0)) + 1024)) / DEV_BSIZE(1 << 9)), SBSIZE1024, &bp);
527 if (error)
528 goto out;
529 fs = (struct ext2fs *)bp->b_data;
530 error = e2fs_sbcheck(fs, ronly);
531 if (error)
532 goto out;
533
534 ump = malloc(sizeof *ump, M_UFSMNT28, M_WAITOK0x0001 | M_ZERO0x0008);
535 ump->um_e2fsufsmount_u.e2fs = malloc(sizeof(struct m_ext2fs), M_UFSMNT28,
536 M_WAITOK0x0001 | M_ZERO0x0008);
537
538 /*
539 * Copy in the superblock, compute in-memory values
540 * and load group descriptors.
541 */
542 e2fs_sbload(fs, &ump->um_e2fs->e2fs)__builtin_memcpy(((&ump->ufsmount_u.e2fs->e2fs)), (
(fs)), (1024));
;
543 if ((error = e2fs_sbfill(devvp, ump->um_e2fsufsmount_u.e2fs)) != 0)
544 goto out;
545 brelse(bp);
546 bp = NULL((void *)0);
547 fs = &ump->um_e2fsufsmount_u.e2fs->e2fs;
548 ump->um_e2fsufsmount_u.e2fs->e2fs_ronly = ronly;
549 ump->um_fstype = UM_EXT2FS3;
550
551 if (ronly == 0) {
552 if (fs->e2fs_state == E2FS_ISCLEAN0x01)
553 fs->e2fs_state = 0;
554 else
555 fs->e2fs_state = E2FS_ERRORS0x02;
556 ump->um_e2fsufsmount_u.e2fs->e2fs_fmod = 1;
557 }
558
559 mp->mnt_data = ump;
560 mp->mnt_stat.f_fsid.val[0] = (long)dev;
561 mp->mnt_stat.f_fsid.val[1] = mp->mnt_vfc->vfc_typenum;
562 mp->mnt_stat.f_namemax = MAXNAMLEN255;
563 mp->mnt_flag |= MNT_LOCAL0x00001000;
564 ump->um_mountp = mp;
565 ump->um_dev = dev;
566 ump->um_devvp = devvp;
567 ump->um_nindir = NINDIR(ump->um_e2fs)((ump->ufsmount_u.e2fs)->e2fs_bsize / sizeof(u_int32_t)
)
;
568 ump->um_bptrtodb = ump->um_e2fsufsmount_u.e2fs->e2fs_fsbtodb;
569 ump->um_seqinc = 1; /* no frags */
570 ump->um_maxsymlinklen = EXT2_MAXSYMLINKLEN((12 +3) * sizeof (u_int32_t));
571 devvp->v_specmountpointv_un.vu_specinfo->si_mountpoint = mp;
572 return (0);
573out:
574 if (devvp->v_specinfov_un.vu_specinfo)
575 devvp->v_specmountpointv_un.vu_specinfo->si_mountpoint = NULL((void *)0);
576 if (bp)
577 brelse(bp);
578 vn_lock(devvp, LK_EXCLUSIVE0x0001UL | LK_RETRY0x2000UL);
579 (void)VOP_CLOSE(devvp, ronly ? FREAD0x0001 : FREAD0x0001|FWRITE0x0002, cred, p);
580 VOP_UNLOCK(devvp);
581 if (ump) {
582 free(ump->um_e2fsufsmount_u.e2fs, M_UFSMNT28, sizeof *ump->um_e2fsufsmount_u.e2fs);
583 free(ump, M_UFSMNT28, sizeof *ump);
584 mp->mnt_data = NULL((void *)0);
585 }
586 return (error);
587}
588
589/*
590 * unmount system call
591 */
592int
593ext2fs_unmount(struct mount *mp, int mntflags, struct proc *p)
594{
595 struct ufsmount *ump;
596 struct m_ext2fs *fs;
597 int error, flags;
598 size_t gdescs_space;
599
600 flags = 0;
601 if (mntflags & MNT_FORCE0x00080000)
602 flags |= FORCECLOSE0x0002;
603 if ((error = ext2fs_flushfiles(mp, flags, p)) != 0)
604 return (error);
605 ump = VFSTOUFS(mp)((struct ufsmount *)((mp)->mnt_data));
606 fs = ump->um_e2fsufsmount_u.e2fs;
607 gdescs_space = fs->e2fs_ngdb * fs->e2fs_bsize;
608
609 if (!fs->e2fs_ronly && ext2fs_cgupdate(ump, MNT_WAIT1) == 0 &&
610 (fs->e2fs.e2fs_state & E2FS_ERRORS0x02) == 0) {
611 fs->e2fs.e2fs_state = E2FS_ISCLEAN0x01;
612 (void) ext2fs_sbupdate(ump, MNT_WAIT1);
613 }
614
615 if (ump->um_devvp->v_type != VBAD)
616 ump->um_devvp->v_specmountpointv_un.vu_specinfo->si_mountpoint = NULL((void *)0);
617 vn_lock(ump->um_devvp, LK_EXCLUSIVE0x0001UL | LK_RETRY0x2000UL);
618 (void)VOP_CLOSE(ump->um_devvp, fs->e2fs_ronly ? FREAD0x0001 : FREAD0x0001|FWRITE0x0002,
619 NOCRED((struct ucred *)-1), p);
620 vput(ump->um_devvp);
621 free(fs->e2fs_gd, M_UFSMNT28, gdescs_space);
622 free(fs, M_UFSMNT28, sizeof *fs);
623 free(ump, M_UFSMNT28, sizeof *ump);
624 mp->mnt_data = NULL((void *)0);
625 mp->mnt_flag &= ~MNT_LOCAL0x00001000;
626 return (0);
627}
628
629/*
630 * Flush out all the files in a filesystem.
631 */
632int
633ext2fs_flushfiles(struct mount *mp, int flags, struct proc *p)
634{
635 struct ufsmount *ump;
636 int error;
637
638 ump = VFSTOUFS(mp)((struct ufsmount *)((mp)->mnt_data));
639 /*
640 * Flush all the files.
641 */
642 if ((error = vflush(mp, NULL((void *)0), flags)) != 0)
643 return (error);
644 /*
645 * Flush filesystem metadata.
646 */
647 vn_lock(ump->um_devvp, LK_EXCLUSIVE0x0001UL | LK_RETRY0x2000UL);
648 error = VOP_FSYNC(ump->um_devvp, p->p_ucred, MNT_WAIT1, p);
649 VOP_UNLOCK(ump->um_devvp);
650 return (error);
651}
652
653/*
654 * Get file system statistics.
655 */
656int
657ext2fs_statfs(struct mount *mp, struct statfs *sbp, struct proc *p)
658{
659 struct ufsmount *ump;
660 struct m_ext2fs *fs;
661 u_int32_t overhead, overhead_per_group;
662 int i, ngroups;
663
664 ump = VFSTOUFS(mp)((struct ufsmount *)((mp)->mnt_data));
665 fs = ump->um_e2fsufsmount_u.e2fs;
666 if (fs->e2fs.e2fs_magic != E2FS_MAGIC0xef53)
667 panic("ext2fs_statfs");
668
669 /*
670 * Compute the overhead (FS structures)
671 */
672 overhead_per_group = 1 /* block bitmap */ + 1 /* inode bitmap */ +
673 fs->e2fs_itpg;
674 overhead = fs->e2fs.e2fs_first_dblock +
675 fs->e2fs_ncg * overhead_per_group;
676 if (fs->e2fs.e2fs_rev > E2FS_REV00 &&
677 fs->e2fs.e2fs_features_rocompat & EXT2F_ROCOMPAT_SPARSE_SUPER0x0001) {
678 for (i = 0, ngroups = 0; i < fs->e2fs_ncg; i++) {
679 if (cg_has_sb(i))
680 ngroups++;
681 }
682 } else {
683 ngroups = fs->e2fs_ncg;
684 }
685 overhead += ngroups * (1 + fs->e2fs_ngdb);
686
687 sbp->f_bsize = fs->e2fs_bsize;
688 sbp->f_iosize = fs->e2fs_bsize;
689 sbp->f_blocks = fs->e2fs.e2fs_bcount - overhead;
690 sbp->f_bfree = fs->e2fs.e2fs_fbcount;
691 sbp->f_bavail = sbp->f_bfree - fs->e2fs.e2fs_rbcount;
692 sbp->f_files = fs->e2fs.e2fs_icount;
693 sbp->f_favail = sbp->f_ffree = fs->e2fs.e2fs_ficount;
694 copy_statfs_info(sbp, mp);
695
696 return (0);
697}
698
699int ext2fs_sync_vnode(struct vnode *vp, void *);
700
701struct ext2fs_sync_args {
702 int allerror;
703 int waitfor;
704 int nlink0;
705 int inflight;
706 struct proc *p;
707 struct ucred *cred;
708};
709
710int
711ext2fs_sync_vnode(struct vnode *vp, void *args)
712{
713 struct ext2fs_sync_args *esa = args;
714 struct inode *ip;
715 int error, nlink0 = 0;
716 int s, skip = 0;
717
718 if (vp->v_type == VNON)
719 return (0);
720
721 ip = VTOI(vp)((struct inode *)(vp)->v_data);
722
723 if (ip->i_e2fs_nlinkdinode_u.e2fs_din->e2di_nlink == 0)
724 nlink0 = 1;
725
726 s = splbio()splraise(0x3);
727 if ((ip->i_flag & (IN_ACCESS0x0001 | IN_CHANGE0x0002 | IN_MODIFIED0x0008 | IN_UPDATE0x0004)) == 0 &&
728 LIST_EMPTY(&vp->v_dirtyblkhd)(((&vp->v_dirtyblkhd)->lh_first) == ((void *)0))) {
729 skip = 1;
730 }
731 splx(s)spllower(s);
732
733 if (skip)
734 goto end;
735
736 if (vget(vp, LK_EXCLUSIVE0x0001UL | LK_NOWAIT0x0040UL)) {
737 esa->inflight = MIN(esa->inflight+1, 65536)(((esa->inflight+1)<(65536))?(esa->inflight+1):(65536
))
;
738 goto end;
739 }
740
741 if ((error = VOP_FSYNC(vp, esa->cred, esa->waitfor, esa->p)) != 0)
742 esa->allerror = error;
743 vput(vp);
744end:
745 esa->nlink0 = MIN(esa->nlink0 + nlink0, 65536)(((esa->nlink0 + nlink0)<(65536))?(esa->nlink0 + nlink0
):(65536))
;
746 return (0);
747}
748
749/*
750 * Go through the disk queues to initiate sandbagged IO;
751 * go through the inodes to write those that have been modified;
752 * initiate the writing of the super block if it has been modified.
753 *
754 * Should always be called with the mount point locked.
755 */
756int
757ext2fs_sync(struct mount *mp, int waitfor, int stall,
758 struct ucred *cred, struct proc *p)
759{
760 struct ufsmount *ump = VFSTOUFS(mp)((struct ufsmount *)((mp)->mnt_data));
761 struct m_ext2fs *fs;
762 int error, allerror = 0, state, fmod;
763 struct ext2fs_sync_args esa;
764
765 fs = ump->um_e2fsufsmount_u.e2fs;
766 if (fs->e2fs_ronly != 0) { /* XXX */
767 printf("fs = %s\n", fs->e2fs_fsmnt);
768 panic("update: rofs mod");
769 }
770
771 /*
772 * Write back each (modified) inode.
773 */
774 esa.p = p;
775 esa.cred = cred;
776 esa.allerror = 0;
777 esa.waitfor = waitfor;
778 esa.nlink0 = 0;
779 esa.inflight = 0;
780
781 vfs_mount_foreach_vnode(mp, ext2fs_sync_vnode, &esa);
782 if (esa.allerror != 0)
783 allerror = esa.allerror;
784
785 /*
786 * Force stale file system control information to be flushed.
787 */
788 if (waitfor != MNT_LAZY3) {
789 vn_lock(ump->um_devvp, LK_EXCLUSIVE0x0001UL | LK_RETRY0x2000UL);
790 if ((error = VOP_FSYNC(ump->um_devvp, cred, waitfor, p)) != 0)
791 allerror = error;
792 VOP_UNLOCK(ump->um_devvp);
793 }
794 /*
795 * Write back modified superblock.
796 */
797 state = fs->e2fs.e2fs_state;
798 fmod = fs->e2fs_fmod;
799 if (stall && fs->e2fs_ronly == 0) {
800 fs->e2fs_fmod = 1;
801 if (allerror == 0 && esa.nlink0 == 0 && esa.inflight == 0) {
802 if ((fs->e2fs.e2fs_state & E2FS_ERRORS0x02) == 0)
803 fs->e2fs.e2fs_state = E2FS_ISCLEAN0x01;
804#if 0
805 printf("%s force clean (dangling %d inflight %d)\n",
806 mp->mnt_stat.f_mntonname, esa.nlink0, esa.inflight);
807#endif
808 } else {
809 fs->e2fs.e2fs_state = 0;
810#if 0
811 printf("%s force dirty (dangling %d inflight %d)\n",
812 mp->mnt_stat.f_mntonname, esa.nlink0, esa.inflight);
813#endif
814 }
815 }
816 if (fs->e2fs_fmod != 0) {
817 fs->e2fs_fmod = 0;
818 fs->e2fs.e2fs_wtime = gettime();
819 if ((error = ext2fs_cgupdate(ump, waitfor)))
820 allerror = error;
821 }
822 fs->e2fs.e2fs_state = state;
823 fs->e2fs_fmod = fmod;
824 return (allerror);
825}
826
827/*
828 * Look up a EXT2FS dinode number to find its incore vnode, otherwise read it
829 * in from disk. If it is in core, wait for the lock bit to clear, then
830 * return the inode locked. Detection and handling of mount points must be
831 * done by the calling routine.
832 */
833int
834ext2fs_vget(struct mount *mp, ino_t ino, struct vnode **vpp)
835{
836 struct m_ext2fs *fs;
837 struct inode *ip;
838 struct ext2fs_dinode *dp;
839 struct ufsmount *ump;
840 struct buf *bp;
841 struct vnode *vp;
842 dev_t dev;
843 int error;
844
845 if (ino > (ufsino_t)-1)
846 panic("ext2fs_vget: alien ino_t %llu",
847 (unsigned long long)ino);
848
849 ump = VFSTOUFS(mp)((struct ufsmount *)((mp)->mnt_data));
850 dev = ump->um_dev;
851
852 retry:
853 if ((*vpp = ufs_ihashget(dev, ino)) != NULL((void *)0))
854 return (0);
855
856 /* Allocate a new vnode/inode. */
857 if ((error = getnewvnode(VT_EXT2FS, mp, &ext2fs_vops, &vp)) != 0) {
858 *vpp = NULL((void *)0);
859 return (error);
860 }
861
862 ip = pool_get(&ext2fs_inode_pool, PR_WAITOK0x0001|PR_ZERO0x0008);
863 rrw_init_flags(&ip->i_lock, "inode", RWL_DUPOK | RWL_IS_VNODE)_rrw_init_flags(&ip->i_lock, "inode", 0, ((void *)0));
864 vp->v_data = ip;
865 ip->i_vnode = vp;
866 ip->i_ump = ump;
867 ip->i_e2fsinode_u.e2fs = fs = ump->um_e2fsufsmount_u.e2fs;
868 ip->i_dev = dev;
869 ip->i_number = ino;
870 ip->i_e2fs_last_lblkinode_ext.e2fs.ext2fs_last_lblk = 0;
871 ip->i_e2fs_last_blkinode_ext.e2fs.ext2fs_last_blk = 0;
872
873 /*
874 * Put it onto its hash chain and lock it so that other requests for
875 * this inode will block if they arrive while we are sleeping waiting
876 * for old data structures to be purged or for the contents of the
877 * disk portion of this inode to be read.
878 */
879 error = ufs_ihashins(ip);
880
881 if (error) {
882 vrele(vp);
883
884 if (error == EEXIST17)
885 goto retry;
886
887 return (error);
888 }
889
890 /* Read in the disk contents for the inode, copy into the inode. */
891 error = bread(ump->um_devvp, fsbtodb(fs, ino_to_fsba(fs, ino))((((fs)->e2fs_gd[(((ino) - 1) / (fs)->e2fs.e2fs_ipg)].ext2bgd_i_tables
+ (((ino)-1) % (fs)->e2fs.e2fs_ipg)/(fs)->e2fs_ipb)) <<
(fs)->e2fs_fsbtodb)
,
892 (int)fs->e2fs_bsize, &bp);
893 if (error) {
894 /*
895 * The inode does not contain anything useful, so it would
896 * be misleading to leave it on its hash chain. With mode
897 * still zero, it will be unlinked and returned to the free
898 * list by vput().
899 */
900 vput(vp);
901 brelse(bp);
902 *vpp = NULL((void *)0);
903 return (error);
904 }
905
906 dp = (struct ext2fs_dinode *) ((char *)bp->b_data
907 + EXT2_DINODE_SIZE(fs)((fs)->e2fs.e2fs_rev > 0 ? (fs)->e2fs.e2fs_inode_size
: 128)
* ino_to_fsbo(fs, ino)(((ino)-1) % (fs)->e2fs_ipb));
908
909 ip->i_e2dindinode_u.e2fs_din = pool_get(&ext2fs_dinode_pool, PR_WAITOK0x0001);
910 e2fs_iload(fs, dp, ip->i_e2din)__builtin_memcpy(((ip->dinode_u.e2fs_din)), ((dp)), ((((((
fs)->e2fs.e2fs_rev > 0 ? (fs)->e2fs.e2fs_inode_size :
128))<(sizeof(*ip->dinode_u.e2fs_din)))?(((fs)->e2fs
.e2fs_rev > 0 ? (fs)->e2fs.e2fs_inode_size : 128)):(sizeof
(*ip->dinode_u.e2fs_din)))))
;
911 brelse(bp);
912
913 ip->i_effnlink = ip->i_e2fs_nlinkdinode_u.e2fs_din->e2di_nlink;
914
915 /*
916 * The fields for storing the UID and GID of an ext2fs inode are
917 * limited to 16 bits. To overcome this limitation, Linux decided to
918 * scatter the highest bits of these values into a previously reserved
919 * area on the disk inode. We deal with this situation by having two
920 * 32-bit fields *out* of the disk inode to hold the complete values.
921 * Now that we are reading in the inode, compute these fields.
922 */
923 ip->i_e2fs_uidinode_ext.e2fs.ext2fs_effective_uid = ip->i_e2fs_uid_lowdinode_u.e2fs_din->e2di_uid_low | (ip->i_e2fs_uid_highdinode_u.e2fs_din->e2di_uid_high << 16);
924 ip->i_e2fs_gidinode_ext.e2fs.ext2fs_effective_gid = ip->i_e2fs_gid_lowdinode_u.e2fs_din->e2di_gid_low | (ip->i_e2fs_gid_highdinode_u.e2fs_din->e2di_gid_high << 16);
925
926 /* If the inode was deleted, reset all fields */
927 if (ip->i_e2fs_dtimedinode_u.e2fs_din->e2di_dtime != 0) {
928 ip->i_e2fs_modedinode_u.e2fs_din->e2di_mode = ip->i_e2fs_nblockdinode_u.e2fs_din->e2di_nblock = 0;
929 (void)ext2fs_setsize(ip, 0);
930 }
931
932 /*
933 * Initialize the vnode from the inode, check for aliases.
934 * Note that the underlying vnode may have changed.
935 */
936 error = ext2fs_vinit(mp, &vp);
937 if (error) {
938 vput(vp);
939 *vpp = NULL((void *)0);
940 return (error);
941 }
942
943 /*
944 * Finish inode initialization now that aliasing has been resolved.
945 */
946 vref(ip->i_devvpi_ump->um_devvp);
947 /*
948 * Set up a generation number for this inode if it does not
949 * already have one. This should only happen on old filesystems.
950 */
951 if (ip->i_e2fs_gendinode_u.e2fs_din->e2di_gen == 0) {
952 if (++ext2gennumber < (u_long)gettime())
953 ext2gennumber = gettime();
954 ip->i_e2fs_gendinode_u.e2fs_din->e2di_gen = ext2gennumber;
955 if ((vp->v_mount->mnt_flag & MNT_RDONLY0x00000001) == 0)
956 ip->i_flag |= IN_MODIFIED0x0008;
957 }
958
959 *vpp = vp;
960 return (0);
961}
962
963/*
964 * File handle to vnode
965 *
966 * Have to be really careful about stale file handles:
967 * - check that the inode number is valid
968 * - call ext2fs_vget() to get the locked inode
969 * - check for an unallocated inode (i_mode == 0)
970 * - check that the given client host has export rights and return
971 * those rights via. exflagsp and credanonp
972 */
973int
974ext2fs_fhtovp(struct mount *mp, struct fid *fhp, struct vnode **vpp)
975{
976 struct inode *ip;
977 struct vnode *nvp;
978 int error;
979 struct ufid *ufhp;
980 struct m_ext2fs *fs;
981
982 ufhp = (struct ufid *)fhp;
983 fs = VFSTOUFS(mp)((struct ufsmount *)((mp)->mnt_data))->um_e2fsufsmount_u.e2fs;
984 if ((ufhp->ufid_ino < EXT2_FIRSTINO((ufsino_t)11) && ufhp->ufid_ino != EXT2_ROOTINO((ufsino_t)2)) ||
985 ufhp->ufid_ino > fs->e2fs_ncg * fs->e2fs.e2fs_ipg)
986 return (ESTALE70);
987
988 if ((error = VFS_VGET(mp, ufhp->ufid_ino, &nvp)(*(mp)->mnt_op->vfs_vget)(mp, ufhp->ufid_ino, &nvp
)
) != 0) {
989 *vpp = NULLVP((struct vnode *)((void *)0));
990 return (error);
991 }
992 ip = VTOI(nvp)((struct inode *)(nvp)->v_data);
993 if (ip->i_e2fs_modedinode_u.e2fs_din->e2di_mode == 0 || ip->i_e2fs_dtimedinode_u.e2fs_din->e2di_dtime != 0 ||
994 ip->i_e2fs_gendinode_u.e2fs_din->e2di_gen != ufhp->ufid_gen) {
995 vput(nvp);
996 *vpp = NULLVP((struct vnode *)((void *)0));
997 return (ESTALE70);
998 }
999 *vpp = nvp;
1000 return (0);
1001}
1002
1003/*
1004 * Vnode pointer to File handle
1005 */
1006int
1007ext2fs_vptofh(struct vnode *vp, struct fid *fhp)
1008{
1009 struct inode *ip;
1010 struct ufid *ufhp;
1011
1012 ip = VTOI(vp)((struct inode *)(vp)->v_data);
1013 ufhp = (struct ufid *)fhp;
1014 ufhp->ufid_len = sizeof(struct ufid);
1015 ufhp->ufid_ino = ip->i_number;
1016 ufhp->ufid_gen = ip->i_e2fs_gendinode_u.e2fs_din->e2di_gen;
1017 return (0);
1018}
1019
1020/*
1021 * no sysctl for ext2fs
1022 */
1023
1024int
1025ext2fs_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp,
1026 void *newp, size_t newlen, struct proc *p)
1027{
1028 return (EOPNOTSUPP45);
1029}
1030
1031/*
1032 * Write a superblock and associated information back to disk.
1033 */
1034int
1035ext2fs_sbupdate(struct ufsmount *mp, int waitfor)
1036{
1037 struct m_ext2fs *fs = mp->um_e2fsufsmount_u.e2fs;
1038 struct buf *bp;
1039 int error = 0;
1040
1041 bp = getblk(mp->um_devvp, SBLOCK((daddr_t)(((daddr_t)(0)) + 1024 / (1 << 9))), SBSIZE1024, 0, INFSLP0xffffffffffffffffULL);
1042 e2fs_sbsave(&fs->e2fs, (struct ext2fs *) bp->b_data)__builtin_memcpy((((struct ext2fs *) bp->b_data)), ((&
fs->e2fs)), (1024));
;
1043 if (waitfor == MNT_WAIT1)
1044 error = bwrite(bp);
1045 else
1046 bawrite(bp);
1047 fs->e2fs_fmod = 0;
1048 return (error);
1049}
1050
1051int
1052ext2fs_cgupdate(struct ufsmount *mp, int waitfor)
1053{
1054 struct m_ext2fs *fs = mp->um_e2fsufsmount_u.e2fs;
1055 struct buf *bp;
1056 int i, error = 0, allerror = 0;
1057
1058 allerror = ext2fs_sbupdate(mp, waitfor);
1059 for (i = 0; i < fs->e2fs_ngdb; i++) {
1060 bp = getblk(mp->um_devvp, fsbtodb(fs, ((fs->e2fs_bsize>1024)?0:1)+i+1)((((fs->e2fs_bsize>1024)?0:1)+i+1) << (fs)->e2fs_fsbtodb
)
,
1061 fs->e2fs_bsize, 0, INFSLP0xffffffffffffffffULL);
1062 e2fs_cgsave(&fs->e2fs_gd[i* fs->e2fs_bsize / sizeof(struct ext2_gd)], (struct ext2_gd*)bp->b_data, fs->e2fs_bsize)__builtin_memcpy((((struct ext2_gd*)bp->b_data)), ((&fs
->e2fs_gd[i* fs->e2fs_bsize / sizeof(struct ext2_gd)]))
, ((fs->e2fs_bsize)));
;
1063 if (waitfor == MNT_WAIT1)
1064 error = bwrite(bp);
1065 else
1066 bawrite(bp);
1067 }
1068
1069 if (!allerror && error)
1070 allerror = error;
1071 return (allerror);
1072}
1073
1074/* This is called before the superblock is copied. Watch out for endianity! */
1075static int
1076e2fs_sbcheck(struct ext2fs *fs, int ronly)
1077{
1078 u_int32_t mask, tmp;
1079 int i;
1080
1081 tmp = letoh16(fs->e2fs_magic)((__uint16_t)(fs->e2fs_magic));
1082 if (tmp != E2FS_MAGIC0xef53) {
1083 printf("ext2fs: wrong magic number 0x%x\n", tmp);
1084 return (EIO5); /* XXX needs translation */
1085 }
1086
1087 tmp = letoh32(fs->e2fs_log_bsize)((__uint32_t)(fs->e2fs_log_bsize));
1088 if (tmp > 2) {
1089 /* skewed log(block size): 1024 -> 0 | 2048 -> 1 | 4096 -> 2 */
1090 tmp += 10;
1091 printf("ext2fs: wrong log2(block size) %d\n", tmp);
1092 return (EIO5); /* XXX needs translation */
1093 }
1094
1095 if (fs->e2fs_bpg == 0) {
1096 printf("ext2fs: zero blocks per group\n");
1097 return (EIO5);
1098 }
1099
1100 tmp = letoh32(fs->e2fs_rev)((__uint32_t)(fs->e2fs_rev));
1101 if (tmp > E2FS_REV11) {
1102 printf("ext2fs: wrong revision number 0x%x\n", tmp);
1103 return (EIO5); /* XXX needs translation */
1104 }
1105 else if (tmp == E2FS_REV00)
1106 return (0);
1107
1108 tmp = letoh32(fs->e2fs_first_ino)((__uint32_t)(fs->e2fs_first_ino));
1109 if (tmp != EXT2_FIRSTINO((ufsino_t)11)) {
1110 printf("ext2fs: first inode at 0x%x\n", tmp);
1111 return (EINVAL22); /* XXX needs translation */
1112 }
1113
1114 tmp = letoh32(fs->e2fs_features_incompat)((__uint32_t)(fs->e2fs_features_incompat));
1115 mask = tmp & ~(EXT2F_INCOMPAT_SUPP(0x0002) | EXT4F_RO_INCOMPAT_SUPP(0x0040 | 0x0200 | 0x0010 | 0x0004));
1116 if (mask) {
1117 printf("ext2fs: unsupported incompat features: ");
1118 for (i = 0; i < nitems(incompat)(sizeof((incompat)) / sizeof((incompat)[0])); i++)
1119 if (mask & incompat[i].mask)
1120 printf("%s ", incompat[i].name);
1121 printf("\n");
1122 return (EINVAL22); /* XXX needs translation */
1123 }
1124
1125 if (!ronly && (tmp & EXT4F_RO_INCOMPAT_SUPP(0x0040 | 0x0200 | 0x0010 | 0x0004))) {
1126 printf("ext4fs: only read-only support right now\n");
1127 return (EROFS30); /* XXX needs translation */
1128 }
1129
1130 if (tmp & EXT2F_INCOMPAT_RECOVER0x0004) {
1131 printf("ext2fs: your file system says it needs recovery\n");
1132 if (!ronly)
1133 return (EROFS30); /* XXX needs translation */
1134 }
1135
1136 tmp = letoh32(fs->e2fs_features_rocompat)((__uint32_t)(fs->e2fs_features_rocompat)) & ~EXT2F_ROCOMPAT_SUPP(0x0001 | 0x0002);
1137 if (!ronly && tmp) {
1138 printf("ext2fs: unsupported R/O compat features: ");
1139 for (i = 0; i < nitems(ro_compat)(sizeof((ro_compat)) / sizeof((ro_compat)[0])); i++)
1140 if (tmp & ro_compat[i].mask)
1141 printf("%s ", ro_compat[i].name);
1142 printf("\n");
1143 return (EROFS30); /* XXX needs translation */
1144 }
1145
1146 return (0);
1147}