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.0 -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name ext2fs_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/ext2fs/ext2fs_vfsops.c
1/* $OpenBSD: ext2fs_vfsops.c,v 1.116 2021/10/04 08:11:02 claudio 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
6
Taking false branch
194 error = ext2fs_reload(mp, ndp->ni_cnd.cn_cred, p);
195 if (error)
196 return (error);
197 }
198 if (fs->e2fs_ronly
6.1
Field 'e2fs_ronly' is not equal to 0
&& (mp->mnt_flag & MNT_WANTRDWR0x02000000)) {
7
Assuming the condition is false
8
Taking false branch
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)) {
9
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
9.1
'args' is equal to NULL
== NULL((void *)0))
10
Taking true branch
214 goto success;
11
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);
12
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
717 if (vp->v_type == VNON)
718 return (0);
719
720 ip = VTOI(vp)((struct inode *)(vp)->v_data);
721
722 if (ip->i_e2fs_nlinkdinode_u.e2fs_din->e2di_nlink == 0)
723 nlink0 = 1;
724
725 if ((ip->i_flag & (IN_ACCESS0x0001 | IN_CHANGE0x0002 | IN_MODIFIED0x0008 | IN_UPDATE0x0004)) == 0 &&
726 LIST_EMPTY(&vp->v_dirtyblkhd)(((&vp->v_dirtyblkhd)->lh_first) == ((void *)0))) {
727 goto end;
728 }
729
730 if (vget(vp, LK_EXCLUSIVE0x0001UL | LK_NOWAIT0x0040UL)) {
731 esa->inflight = MIN(esa->inflight+1, 65536)(((esa->inflight+1)<(65536))?(esa->inflight+1):(65536
))
;
732 goto end;
733 }
734
735 if ((error = VOP_FSYNC(vp, esa->cred, esa->waitfor, esa->p)) != 0)
736 esa->allerror = error;
737 vput(vp);
738end:
739 esa->nlink0 = MIN(esa->nlink0 + nlink0, 65536)(((esa->nlink0 + nlink0)<(65536))?(esa->nlink0 + nlink0
):(65536))
;
740 return (0);
741}
742
743/*
744 * Go through the disk queues to initiate sandbagged IO;
745 * go through the inodes to write those that have been modified;
746 * initiate the writing of the super block if it has been modified.
747 *
748 * Should always be called with the mount point locked.
749 */
750int
751ext2fs_sync(struct mount *mp, int waitfor, int stall,
752 struct ucred *cred, struct proc *p)
753{
754 struct ufsmount *ump = VFSTOUFS(mp)((struct ufsmount *)((mp)->mnt_data));
755 struct m_ext2fs *fs;
756 int error, allerror = 0, state, fmod;
757 struct ext2fs_sync_args esa;
758
759 fs = ump->um_e2fsufsmount_u.e2fs;
760 if (fs->e2fs_ronly != 0) { /* XXX */
761 printf("fs = %s\n", fs->e2fs_fsmnt);
762 panic("update: rofs mod");
763 }
764
765 /*
766 * Write back each (modified) inode.
767 */
768 esa.p = p;
769 esa.cred = cred;
770 esa.allerror = 0;
771 esa.waitfor = waitfor;
772 esa.nlink0 = 0;
773 esa.inflight = 0;
774
775 vfs_mount_foreach_vnode(mp, ext2fs_sync_vnode, &esa);
776 if (esa.allerror != 0)
777 allerror = esa.allerror;
778
779 /*
780 * Force stale file system control information to be flushed.
781 */
782 if (waitfor != MNT_LAZY3) {
783 vn_lock(ump->um_devvp, LK_EXCLUSIVE0x0001UL | LK_RETRY0x2000UL);
784 if ((error = VOP_FSYNC(ump->um_devvp, cred, waitfor, p)) != 0)
785 allerror = error;
786 VOP_UNLOCK(ump->um_devvp);
787 }
788 /*
789 * Write back modified superblock.
790 */
791 state = fs->e2fs.e2fs_state;
792 fmod = fs->e2fs_fmod;
793 if (stall && fs->e2fs_ronly == 0) {
794 fs->e2fs_fmod = 1;
795 if (allerror == 0 && esa.nlink0 == 0 && esa.inflight == 0) {
796 if ((fs->e2fs.e2fs_state & E2FS_ERRORS0x02) == 0)
797 fs->e2fs.e2fs_state = E2FS_ISCLEAN0x01;
798#if 0
799 printf("%s force clean (dangling %d inflight %d)\n",
800 mp->mnt_stat.f_mntonname, esa.nlink0, esa.inflight);
801#endif
802 } else {
803 fs->e2fs.e2fs_state = 0;
804#if 0
805 printf("%s force dirty (dangling %d inflight %d)\n",
806 mp->mnt_stat.f_mntonname, esa.nlink0, esa.inflight);
807#endif
808 }
809 }
810 if (fs->e2fs_fmod != 0) {
811 fs->e2fs_fmod = 0;
812 fs->e2fs.e2fs_wtime = gettime();
813 if ((error = ext2fs_cgupdate(ump, waitfor)))
814 allerror = error;
815 }
816 fs->e2fs.e2fs_state = state;
817 fs->e2fs_fmod = fmod;
818 return (allerror);
819}
820
821/*
822 * Look up a EXT2FS dinode number to find its incore vnode, otherwise read it
823 * in from disk. If it is in core, wait for the lock bit to clear, then
824 * return the inode locked. Detection and handling of mount points must be
825 * done by the calling routine.
826 */
827int
828ext2fs_vget(struct mount *mp, ino_t ino, struct vnode **vpp)
829{
830 struct m_ext2fs *fs;
831 struct inode *ip;
832 struct ext2fs_dinode *dp;
833 struct ufsmount *ump;
834 struct buf *bp;
835 struct vnode *vp;
836 dev_t dev;
837 int error;
838
839 if (ino > (ufsino_t)-1)
840 panic("ext2fs_vget: alien ino_t %llu",
841 (unsigned long long)ino);
842
843 ump = VFSTOUFS(mp)((struct ufsmount *)((mp)->mnt_data));
844 dev = ump->um_dev;
845
846 retry:
847 if ((*vpp = ufs_ihashget(dev, ino)) != NULL((void *)0))
848 return (0);
849
850 /* Allocate a new vnode/inode. */
851 if ((error = getnewvnode(VT_EXT2FS, mp, &ext2fs_vops, &vp)) != 0) {
852 *vpp = NULL((void *)0);
853 return (error);
854 }
855
856 ip = pool_get(&ext2fs_inode_pool, PR_WAITOK0x0001|PR_ZERO0x0008);
857 rrw_init_flags(&ip->i_lock, "inode", RWL_DUPOK | RWL_IS_VNODE)_rrw_init_flags(&ip->i_lock, "inode", 0, ((void *)0));
858 vp->v_data = ip;
859 ip->i_vnode = vp;
860 ip->i_ump = ump;
861 ip->i_e2fsinode_u.e2fs = fs = ump->um_e2fsufsmount_u.e2fs;
862 ip->i_dev = dev;
863 ip->i_number = ino;
864 ip->i_e2fs_last_lblkinode_ext.e2fs.ext2fs_last_lblk = 0;
865 ip->i_e2fs_last_blkinode_ext.e2fs.ext2fs_last_blk = 0;
866
867 /*
868 * Put it onto its hash chain and lock it so that other requests for
869 * this inode will block if they arrive while we are sleeping waiting
870 * for old data structures to be purged or for the contents of the
871 * disk portion of this inode to be read.
872 */
873 error = ufs_ihashins(ip);
874
875 if (error) {
876 vrele(vp);
877
878 if (error == EEXIST17)
879 goto retry;
880
881 return (error);
882 }
883
884 /* Read in the disk contents for the inode, copy into the inode. */
885 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)
,
886 (int)fs->e2fs_bsize, &bp);
887 if (error) {
888 /*
889 * The inode does not contain anything useful, so it would
890 * be misleading to leave it on its hash chain. With mode
891 * still zero, it will be unlinked and returned to the free
892 * list by vput().
893 */
894 vput(vp);
895 brelse(bp);
896 *vpp = NULL((void *)0);
897 return (error);
898 }
899
900 dp = (struct ext2fs_dinode *) ((char *)bp->b_data
901 + 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));
902
903 ip->i_e2dindinode_u.e2fs_din = pool_get(&ext2fs_dinode_pool, PR_WAITOK0x0001);
904 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)))))
;
905 brelse(bp);
906
907 ip->i_effnlink = ip->i_e2fs_nlinkdinode_u.e2fs_din->e2di_nlink;
908
909 /*
910 * The fields for storing the UID and GID of an ext2fs inode are
911 * limited to 16 bits. To overcome this limitation, Linux decided to
912 * scatter the highest bits of these values into a previously reserved
913 * area on the disk inode. We deal with this situation by having two
914 * 32-bit fields *out* of the disk inode to hold the complete values.
915 * Now that we are reading in the inode, compute these fields.
916 */
917 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);
918 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);
919
920 /* If the inode was deleted, reset all fields */
921 if (ip->i_e2fs_dtimedinode_u.e2fs_din->e2di_dtime != 0) {
922 ip->i_e2fs_modedinode_u.e2fs_din->e2di_mode = ip->i_e2fs_nblockdinode_u.e2fs_din->e2di_nblock = 0;
923 (void)ext2fs_setsize(ip, 0);
924 }
925
926 /*
927 * Initialize the vnode from the inode, check for aliases.
928 * Note that the underlying vnode may have changed.
929 */
930 error = ext2fs_vinit(mp, &vp);
931 if (error) {
932 vput(vp);
933 *vpp = NULL((void *)0);
934 return (error);
935 }
936
937 /*
938 * Finish inode initialization now that aliasing has been resolved.
939 */
940 vref(ip->i_devvpi_ump->um_devvp);
941 /*
942 * Set up a generation number for this inode if it does not
943 * already have one. This should only happen on old filesystems.
944 */
945 if (ip->i_e2fs_gendinode_u.e2fs_din->e2di_gen == 0) {
946 if (++ext2gennumber < (u_long)gettime())
947 ext2gennumber = gettime();
948 ip->i_e2fs_gendinode_u.e2fs_din->e2di_gen = ext2gennumber;
949 if ((vp->v_mount->mnt_flag & MNT_RDONLY0x00000001) == 0)
950 ip->i_flag |= IN_MODIFIED0x0008;
951 }
952
953 *vpp = vp;
954 return (0);
955}
956
957/*
958 * File handle to vnode
959 *
960 * Have to be really careful about stale file handles:
961 * - check that the inode number is valid
962 * - call ext2fs_vget() to get the locked inode
963 * - check for an unallocated inode (i_mode == 0)
964 * - check that the given client host has export rights and return
965 * those rights via. exflagsp and credanonp
966 */
967int
968ext2fs_fhtovp(struct mount *mp, struct fid *fhp, struct vnode **vpp)
969{
970 struct inode *ip;
971 struct vnode *nvp;
972 int error;
973 struct ufid *ufhp;
974 struct m_ext2fs *fs;
975
976 ufhp = (struct ufid *)fhp;
977 fs = VFSTOUFS(mp)((struct ufsmount *)((mp)->mnt_data))->um_e2fsufsmount_u.e2fs;
978 if ((ufhp->ufid_ino < EXT2_FIRSTINO((ufsino_t)11) && ufhp->ufid_ino != EXT2_ROOTINO((ufsino_t)2)) ||
979 ufhp->ufid_ino > fs->e2fs_ncg * fs->e2fs.e2fs_ipg)
980 return (ESTALE70);
981
982 if ((error = VFS_VGET(mp, ufhp->ufid_ino, &nvp)(*(mp)->mnt_op->vfs_vget)(mp, ufhp->ufid_ino, &nvp
)
) != 0) {
983 *vpp = NULLVP((struct vnode *)((void *)0));
984 return (error);
985 }
986 ip = VTOI(nvp)((struct inode *)(nvp)->v_data);
987 if (ip->i_e2fs_modedinode_u.e2fs_din->e2di_mode == 0 || ip->i_e2fs_dtimedinode_u.e2fs_din->e2di_dtime != 0 ||
988 ip->i_e2fs_gendinode_u.e2fs_din->e2di_gen != ufhp->ufid_gen) {
989 vput(nvp);
990 *vpp = NULLVP((struct vnode *)((void *)0));
991 return (ESTALE70);
992 }
993 *vpp = nvp;
994 return (0);
995}
996
997/*
998 * Vnode pointer to File handle
999 */
1000/* ARGSUSED */
1001int
1002ext2fs_vptofh(struct vnode *vp, struct fid *fhp)
1003{
1004 struct inode *ip;
1005 struct ufid *ufhp;
1006
1007 ip = VTOI(vp)((struct inode *)(vp)->v_data);
1008 ufhp = (struct ufid *)fhp;
1009 ufhp->ufid_len = sizeof(struct ufid);
1010 ufhp->ufid_ino = ip->i_number;
1011 ufhp->ufid_gen = ip->i_e2fs_gendinode_u.e2fs_din->e2di_gen;
1012 return (0);
1013}
1014
1015/*
1016 * no sysctl for ext2fs
1017 */
1018
1019int
1020ext2fs_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp,
1021 void *newp, size_t newlen, struct proc *p)
1022{
1023 return (EOPNOTSUPP45);
1024}
1025
1026/*
1027 * Write a superblock and associated information back to disk.
1028 */
1029int
1030ext2fs_sbupdate(struct ufsmount *mp, int waitfor)
1031{
1032 struct m_ext2fs *fs = mp->um_e2fsufsmount_u.e2fs;
1033 struct buf *bp;
1034 int error = 0;
1035
1036 bp = getblk(mp->um_devvp, SBLOCK((daddr_t)(((daddr_t)(0)) + 1024 / (1 << 9))), SBSIZE1024, 0, INFSLP0xffffffffffffffffULL);
1037 e2fs_sbsave(&fs->e2fs, (struct ext2fs *) bp->b_data)__builtin_memcpy((((struct ext2fs *) bp->b_data)), ((&
fs->e2fs)), (1024));
;
1038 if (waitfor == MNT_WAIT1)
1039 error = bwrite(bp);
1040 else
1041 bawrite(bp);
1042 fs->e2fs_fmod = 0;
1043 return (error);
1044}
1045
1046int
1047ext2fs_cgupdate(struct ufsmount *mp, int waitfor)
1048{
1049 struct m_ext2fs *fs = mp->um_e2fsufsmount_u.e2fs;
1050 struct buf *bp;
1051 int i, error = 0, allerror = 0;
1052
1053 allerror = ext2fs_sbupdate(mp, waitfor);
1054 for (i = 0; i < fs->e2fs_ngdb; i++) {
1055 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
)
,
1056 fs->e2fs_bsize, 0, INFSLP0xffffffffffffffffULL);
1057 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)));
;
1058 if (waitfor == MNT_WAIT1)
1059 error = bwrite(bp);
1060 else
1061 bawrite(bp);
1062 }
1063
1064 if (!allerror && error)
1065 allerror = error;
1066 return (allerror);
1067}
1068
1069/* This is called before the superblock is copied. Watch out for endianity! */
1070static int
1071e2fs_sbcheck(struct ext2fs *fs, int ronly)
1072{
1073 u_int32_t mask, tmp;
1074 int i;
1075
1076 tmp = letoh16(fs->e2fs_magic)((__uint16_t)(fs->e2fs_magic));
1077 if (tmp != E2FS_MAGIC0xef53) {
1078 printf("ext2fs: wrong magic number 0x%x\n", tmp);
1079 return (EIO5); /* XXX needs translation */
1080 }
1081
1082 tmp = letoh32(fs->e2fs_log_bsize)((__uint32_t)(fs->e2fs_log_bsize));
1083 if (tmp > 2) {
1084 /* skewed log(block size): 1024 -> 0 | 2048 -> 1 | 4096 -> 2 */
1085 tmp += 10;
1086 printf("ext2fs: wrong log2(block size) %d\n", tmp);
1087 return (EIO5); /* XXX needs translation */
1088 }
1089
1090 if (fs->e2fs_bpg == 0) {
1091 printf("ext2fs: zero blocks per group\n");
1092 return (EIO5);
1093 }
1094
1095 tmp = letoh32(fs->e2fs_rev)((__uint32_t)(fs->e2fs_rev));
1096 if (tmp > E2FS_REV11) {
1097 printf("ext2fs: wrong revision number 0x%x\n", tmp);
1098 return (EIO5); /* XXX needs translation */
1099 }
1100 else if (tmp == E2FS_REV00)
1101 return (0);
1102
1103 tmp = letoh32(fs->e2fs_first_ino)((__uint32_t)(fs->e2fs_first_ino));
1104 if (tmp != EXT2_FIRSTINO((ufsino_t)11)) {
1105 printf("ext2fs: first inode at 0x%x\n", tmp);
1106 return (EINVAL22); /* XXX needs translation */
1107 }
1108
1109 tmp = letoh32(fs->e2fs_features_incompat)((__uint32_t)(fs->e2fs_features_incompat));
1110 mask = tmp & ~(EXT2F_INCOMPAT_SUPP(0x0002) | EXT4F_RO_INCOMPAT_SUPP(0x0040 | 0x0200 | 0x0010 | 0x0004));
1111 if (mask) {
1112 printf("ext2fs: unsupported incompat features: ");
1113 for (i = 0; i < nitems(incompat)(sizeof((incompat)) / sizeof((incompat)[0])); i++)
1114 if (mask & incompat[i].mask)
1115 printf("%s ", incompat[i].name);
1116 printf("\n");
1117 return (EINVAL22); /* XXX needs translation */
1118 }
1119
1120 if (!ronly && (tmp & EXT4F_RO_INCOMPAT_SUPP(0x0040 | 0x0200 | 0x0010 | 0x0004))) {
1121 printf("ext4fs: only read-only support right now\n");
1122 return (EROFS30); /* XXX needs translation */
1123 }
1124
1125 if (tmp & EXT2F_INCOMPAT_RECOVER0x0004) {
1126 printf("ext2fs: your file system says it needs recovery\n");
1127 if (!ronly)
1128 return (EROFS30); /* XXX needs translation */
1129 }
1130
1131 tmp = letoh32(fs->e2fs_features_rocompat)((__uint32_t)(fs->e2fs_features_rocompat)) & ~EXT2F_ROCOMPAT_SUPP(0x0001 | 0x0002);
1132 if (!ronly && tmp) {
1133 printf("ext2fs: unsupported R/O compat features: ");
1134 for (i = 0; i < nitems(ro_compat)(sizeof((ro_compat)) / sizeof((ro_compat)[0])); i++)
1135 if (tmp & ro_compat[i].mask)
1136 printf("%s ", ro_compat[i].name);
1137 printf("\n");
1138 return (EROFS30); /* XXX needs translation */
1139 }
1140
1141 return (0);
1142}