]> git.saurik.com Git - apple/xnu.git/blob - bsd/ufs/ffs/ffs_vfsops.c
xnu-1228.5.18.tar.gz
[apple/xnu.git] / bsd / ufs / ffs / ffs_vfsops.c
1 /*
2 * Copyright (c) 2000-2006 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
14 *
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
17 *
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
25 *
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27 */
28 /* Copyright (c) 1995 NeXT Computer, Inc. All Rights Reserved */
29 /*
30 * Copyright (c) 1989, 1991, 1993, 1994
31 * The Regents of the University of California. All rights reserved.
32 *
33 * Redistribution and use in source and binary forms, with or without
34 * modification, are permitted provided that the following conditions
35 * are met:
36 * 1. Redistributions of source code must retain the above copyright
37 * notice, this list of conditions and the following disclaimer.
38 * 2. Redistributions in binary form must reproduce the above copyright
39 * notice, this list of conditions and the following disclaimer in the
40 * documentation and/or other materials provided with the distribution.
41 * 3. All advertising materials mentioning features or use of this software
42 * must display the following acknowledgement:
43 * This product includes software developed by the University of
44 * California, Berkeley and its contributors.
45 * 4. Neither the name of the University nor the names of its contributors
46 * may be used to endorse or promote products derived from this software
47 * without specific prior written permission.
48 *
49 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
50 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
51 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
52 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
53 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
54 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
55 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
56 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
57 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
58 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
59 * SUCH DAMAGE.
60 *
61 * @(#)ffs_vfsops.c 8.31 (Berkeley) 5/20/95
62 */
63
64 #include <rev_endian_fs.h>
65 #include <sys/param.h>
66 #include <sys/systm.h>
67 #include <sys/namei.h>
68 #include <sys/proc.h>
69 #include <sys/kauth.h>
70 #include <sys/kernel.h>
71 #include <sys/vnode_internal.h>
72 #include <sys/socket.h>
73 #include <sys/mount_internal.h>
74 #include <sys/mount.h>
75 #include <sys/buf.h>
76 #include <sys/mbuf.h>
77 #include <sys/file.h>
78 #include <sys/disk.h>
79 #include <sys/ioctl.h>
80 #include <sys/errno.h>
81 #include <sys/malloc.h>
82 #include <sys/ubc.h>
83 #include <sys/quota.h>
84
85 #include <miscfs/specfs/specdev.h>
86
87 #include <ufs/ufs/quota.h>
88 #include <ufs/ufs/ufsmount.h>
89 #include <ufs/ufs/inode.h>
90 #include <ufs/ufs/ufs_extern.h>
91
92 #include <ufs/ffs/fs.h>
93 #include <ufs/ffs/ffs_extern.h>
94 #if REV_ENDIAN_FS
95 #include <ufs/ufs/ufs_byte_order.h>
96 #include <libkern/OSByteOrder.h>
97 #endif /* REV_ENDIAN_FS */
98
99 int ffs_sbupdate(struct ufsmount *, int);
100
101 struct vfsops ufs_vfsops = {
102 ffs_mount,
103 ufs_start,
104 ffs_unmount,
105 ufs_root,
106 ufs_quotactl,
107 ffs_vfs_getattr,
108 ffs_sync,
109 ffs_vget,
110 ffs_fhtovp,
111 ffs_vptofh,
112 ffs_init,
113 ffs_sysctl,
114 ffs_vfs_setattr,
115 {0}
116 };
117
118 extern u_long nextgennumber;
119
120 union _qcvt {
121 int64_t qcvt;
122 int32_t val[2];
123 };
124 #define SETHIGH(q, h) { \
125 union _qcvt tmp; \
126 tmp.qcvt = (q); \
127 tmp.val[_QUAD_HIGHWORD] = (h); \
128 (q) = tmp.qcvt; \
129 }
130 #define SETLOW(q, l) { \
131 union _qcvt tmp; \
132 tmp.qcvt = (q); \
133 tmp.val[_QUAD_LOWWORD] = (l); \
134 (q) = tmp.qcvt; \
135 }
136
137 /*
138 * Called by main() when ufs is going to be mounted as root.
139 */
140 int
141 ffs_mountroot(mount_t mp, vnode_t rvp, vfs_context_t context)
142 {
143 struct proc *p = current_proc(); /* XXX */
144 int error;
145
146 /* Set asynchronous flag by default */
147 vfs_setflags(mp, MNT_ASYNC);
148
149 if (error = ffs_mountfs(rvp, mp, context))
150 return (error);
151
152 (void)ffs_statfs(mp, vfs_statfs(mp), NULL);
153
154 return (0);
155 }
156
157 /*
158 * VFS Operations.
159 *
160 * mount system call
161 */
162 int
163 ffs_mount(struct mount *mp, vnode_t devvp, __unused user_addr_t data, vfs_context_t context)
164 {
165 struct proc *p = vfs_context_proc(context);
166 struct ufsmount *ump;
167 register struct fs *fs;
168 u_int size;
169 int error = 0, flags;
170 mode_t accessmode;
171 int ronly;
172 int reload = 0;
173
174 /*
175 * If updating, check whether changing from read-write to
176 * read-only; if there is no device name, that's all we do.
177 */
178 if (mp->mnt_flag & MNT_UPDATE) {
179 ump = VFSTOUFS(mp);
180 fs = ump->um_fs;
181 if (fs->fs_ronly == 0 && (mp->mnt_flag & MNT_RDONLY)) {
182 /*
183 * Flush any dirty data.
184 */
185 VFS_SYNC(mp, MNT_WAIT, context);
186 /*
187 * Check for and optionally get rid of files open
188 * for writing.
189 */
190 flags = WRITECLOSE;
191 if (mp->mnt_flag & MNT_FORCE)
192 flags |= FORCECLOSE;
193 if (error = ffs_flushfiles(mp, flags, p))
194 return (error);
195 fs->fs_clean = 1;
196 fs->fs_ronly = 1;
197 if (error = ffs_sbupdate(ump, MNT_WAIT)) {
198 fs->fs_clean = 0;
199 fs->fs_ronly = 0;
200 return (error);
201 }
202 }
203 /* save fs_ronly to later use */
204 ronly = fs->fs_ronly;
205 if ((mp->mnt_flag & MNT_RELOAD) || ronly)
206 reload = 1;
207 if ((reload) &&
208 (error = ffs_reload(mp, vfs_context_ucred(context), p)))
209 return (error);
210 /* replace the ronly after load */
211 fs->fs_ronly = ronly;
212 /*
213 * Do not update the file system if the user was in singleuser
214 * and then tries to mount -uw without fscking
215 */
216 if (!fs->fs_clean && ronly) {
217 printf("WARNING: trying to mount a dirty file system\n");
218 if (issingleuser() && (mp->mnt_flag & MNT_ROOTFS)) {
219 printf("WARNING: R/W mount of %s denied. Filesystem is not clean - run fsck\n",fs->fs_fsmnt);
220 /*
221 * Reset the readonly bit as reload might have
222 * modified this bit
223 */
224 fs->fs_ronly = 1;
225 return(EPERM);
226 }
227 }
228
229 if (ronly && (mp->mnt_kern_flag & MNTK_WANTRDWR)) {
230 fs->fs_ronly = 0;
231 fs->fs_clean = 0;
232 (void) ffs_sbupdate(ump, MNT_WAIT);
233 }
234 if (devvp == 0) {
235 return(0);
236 }
237 }
238 if ((mp->mnt_flag & MNT_UPDATE) == 0) {
239 ufs_ihashinit();
240 error = ffs_mountfs(devvp, mp, context);
241 } else {
242 if (devvp != ump->um_devvp)
243 error = EINVAL; /* needs translation */
244 }
245 if (error) {
246 return (error);
247 }
248 ump = VFSTOUFS(mp);
249 fs = ump->um_fs;
250 bzero(fs->fs_fsmnt , sizeof(fs->fs_fsmnt));
251 strncpy(fs->fs_fsmnt, (caddr_t)mp->mnt_vfsstat.f_mntonname, sizeof(fs->fs_fsmnt) - 1);
252 (void)ffs_statfs(mp, &mp->mnt_vfsstat, p);
253 return (0);
254 }
255
256
257 struct ffs_reload_cargs {
258 struct vnode *devvp;
259 kauth_cred_t cred;
260 struct fs *fs;
261 struct proc *p;
262 int error;
263 #if REV_ENDIAN_FS
264 int rev_endian;
265 #endif /* REV_ENDIAN_FS */
266 };
267
268
269 static int
270 ffs_reload_callback(struct vnode *vp, void *cargs)
271 {
272 struct inode *ip;
273 struct buf *bp;
274 struct fs *fs;
275 struct ffs_reload_cargs *args;
276
277 args = (struct ffs_reload_cargs *)cargs;
278
279 /*
280 * flush all the buffers associated with this node
281 */
282 if (buf_invalidateblks(vp, 0, 0, 0))
283 panic("ffs_reload: dirty2");
284
285 /*
286 * Step 6: re-read inode data
287 */
288 ip = VTOI(vp);
289 fs = args->fs;
290
291 if (args->error = (int)buf_bread(args->devvp, (daddr64_t)((unsigned)fsbtodb(fs, ino_to_fsba(fs, ip->i_number))),
292 (int)fs->fs_bsize, NOCRED, &bp)) {
293 buf_brelse(bp);
294
295 return (VNODE_RETURNED_DONE);
296 }
297
298 #if REV_ENDIAN_FS
299 if (args->rev_endian) {
300 byte_swap_inode_in(((struct dinode *)buf_dataptr(bp) +
301 ino_to_fsbo(fs, ip->i_number)), ip);
302 } else {
303 #endif /* REV_ENDIAN_FS */
304 ip->i_din = *((struct dinode *)buf_dataptr(bp) +
305 ino_to_fsbo(fs, ip->i_number));
306 #if REV_ENDIAN_FS
307 }
308 #endif /* REV_ENDIAN_FS */
309
310 buf_brelse(bp);
311
312 return (VNODE_RETURNED);
313 }
314
315
316 /*
317 * Reload all incore data for a filesystem (used after running fsck on
318 * the root filesystem and finding things to fix). The filesystem must
319 * be mounted read-only.
320 *
321 * Things to do to update the mount:
322 * 1) invalidate all cached meta-data.
323 * 2) re-read superblock from disk.
324 * 3) re-read summary information from disk.
325 * 4) invalidate all inactive vnodes.
326 * 5) invalidate all cached file data.
327 * 6) re-read inode data for all active vnodes.
328 */
329 ffs_reload(struct mount *mountp, kauth_cred_t cred, struct proc *p)
330 {
331 register struct vnode *devvp;
332 void *space;
333 struct buf *bp;
334 struct fs *fs, *newfs;
335 int i, blks, size, error;
336 u_int64_t maxfilesize; /* XXX */
337 int32_t *lp;
338 struct ffs_reload_cargs args;
339 #if REV_ENDIAN_FS
340 int rev_endian = (mountp->mnt_flag & MNT_REVEND);
341 #endif /* REV_ENDIAN_FS */
342
343 if ((mountp->mnt_flag & MNT_RDONLY) == 0)
344 return (EINVAL);
345 /*
346 * Step 1: invalidate all cached meta-data.
347 */
348 devvp = VFSTOUFS(mountp)->um_devvp;
349 if (buf_invalidateblks(devvp, 0, 0, 0))
350 panic("ffs_reload: dirty1");
351 /*
352 * Step 2: re-read superblock from disk.
353 */
354 size = vfs_devblocksize(mountp);
355
356 if (error = (int)buf_bread(devvp, (daddr64_t)((unsigned)(SBOFF/size)), SBSIZE, NOCRED,&bp)) {
357 buf_brelse(bp);
358 return (error);
359 }
360 newfs = (struct fs *)buf_dataptr(bp);
361 #if REV_ENDIAN_FS
362 if (rev_endian) {
363 error = byte_swap_sbin(newfs);
364 if (error) {
365 buf_brelse(bp);
366 return (error);
367 }
368 }
369 #endif /* REV_ENDIAN_FS */
370 if (newfs->fs_magic != FS_MAGIC || newfs->fs_bsize > MAXBSIZE ||
371 newfs->fs_bsize < sizeof(struct fs)) {
372 #if REV_ENDIAN_FS
373 if (rev_endian)
374 byte_swap_sbout(newfs);
375 #endif /* REV_ENDIAN_FS */
376
377 buf_brelse(bp);
378 return (EIO); /* XXX needs translation */
379 }
380 fs = VFSTOUFS(mountp)->um_fs;
381 /*
382 * Copy pointer fields back into superblock before copying in XXX
383 * new superblock. These should really be in the ufsmount. XXX
384 * Note that important parameters (eg fs_ncg) are unchanged.
385 */
386 newfs->fs_csp = fs->fs_csp;
387 newfs->fs_maxcluster = fs->fs_maxcluster;
388 newfs->fs_contigdirs = fs->fs_contigdirs;
389 bcopy(newfs, fs, (u_int)fs->fs_sbsize);
390 if (fs->fs_sbsize < SBSIZE)
391 buf_markinvalid(bp);
392 #if REV_ENDIAN_FS
393 if (rev_endian)
394 byte_swap_sbout(newfs);
395 #endif /* REV_ENDIAN_FS */
396 buf_brelse(bp);
397 mountp->mnt_maxsymlinklen = fs->fs_maxsymlinklen;
398 ffs_oldfscompat(fs);
399 maxfilesize = 0x100000000ULL; /* 4GB */
400 if (fs->fs_maxfilesize > maxfilesize) /* XXX */
401 fs->fs_maxfilesize = maxfilesize; /* XXX */
402 /*
403 * Step 3: re-read summary information from disk.
404 */
405 blks = howmany(fs->fs_cssize, fs->fs_fsize);
406 space = fs->fs_csp;
407 for (i = 0; i < blks; i += fs->fs_frag) {
408 size = fs->fs_bsize;
409 if (i + fs->fs_frag > blks)
410 size = (blks - i) * fs->fs_fsize;
411 if (error = (int)buf_bread(devvp, (daddr64_t)((unsigned)fsbtodb(fs, fs->fs_csaddr + i)), size,
412 NOCRED, &bp)) {
413 buf_brelse(bp);
414 return (error);
415 }
416 #if REV_ENDIAN_FS
417 if (rev_endian) {
418 /* csum swaps */
419 byte_swap_ints((int *)buf_dataptr(bp), size / sizeof(int));
420 }
421 #endif /* REV_ENDIAN_FS */
422 bcopy((char *)buf_dataptr(bp), space, (u_int)size);
423 #if REV_ENDIAN_FS
424 if (rev_endian) {
425 /* csum swaps */
426 byte_swap_ints((int *)buf_dataptr(bp), size / sizeof(int));
427 }
428 #endif /* REV_ENDIAN_FS */
429 space = (char *) space + size;
430 buf_brelse(bp);
431 }
432 /*
433 * We no longer know anything about clusters per cylinder group.
434 */
435 if (fs->fs_contigsumsize > 0) {
436 lp = fs->fs_maxcluster;
437 for (i = 0; i < fs->fs_ncg; i++)
438 *lp++ = fs->fs_contigsumsize;
439 }
440 #if REV_ENDIAN_FS
441 args.rev_endian = rev_endian;
442 #endif /* REV_ENDIAN_FS */
443 args.devvp = devvp;
444 args.cred = cred;
445 args.fs = fs;
446 args.p = p;
447 args.error = 0;
448 /*
449 * ffs_reload_callback will be called for each vnode
450 * hung off of this mount point that can't be recycled...
451 * vnode_iterate will recycle those that it can (the VNODE_RELOAD option)
452 * the vnode will be in an 'unbusy' state (VNODE_WAIT) and
453 * properly referenced and unreferenced around the callback
454 */
455 vnode_iterate(mountp, VNODE_RELOAD | VNODE_WAIT, ffs_reload_callback, (void *)&args);
456
457 return (args.error);
458 }
459
460 /*
461 * Common code for mount and mountroot
462 */
463 int
464 ffs_mountfs(devvp, mp, context)
465 struct vnode *devvp;
466 struct mount *mp;
467 vfs_context_t context;
468 {
469 struct ufsmount *ump;
470 struct buf *bp;
471 struct fs *fs;
472 dev_t dev;
473 struct buf *cgbp;
474 struct cg *cgp;
475 int32_t clustersumoff;
476 void *space;
477 int error, i, blks, ronly;
478 u_int32_t size;
479 int32_t *lp;
480 kauth_cred_t cred;
481 u_int64_t maxfilesize; /* XXX */
482 u_int dbsize = DEV_BSIZE;
483 #if REV_ENDIAN_FS
484 int rev_endian=0;
485 #endif /* REV_ENDIAN_FS */
486 dev = devvp->v_rdev;
487 cred = vfs_context_ucred(context);
488
489 ronly = vfs_isrdonly(mp);
490 bp = NULL;
491 ump = NULL;
492
493 /* Advisory locking should be handled at the VFS layer */
494 vfs_setlocklocal(mp);
495
496 /* Obtain the actual device block size */
497 if (VNOP_IOCTL(devvp, DKIOCGETBLOCKSIZE, (caddr_t)&size, 0, context)) {
498 error = ENXIO;
499 goto out;
500 }
501
502 if (error = (int)buf_bread(devvp, (daddr64_t)((unsigned)(SBOFF/size)),
503 SBSIZE, cred, &bp))
504 goto out;
505 fs = (struct fs *)buf_dataptr(bp);
506 #if REV_ENDIAN_FS
507 if (fs->fs_magic != FS_MAGIC || fs->fs_bsize > MAXBSIZE ||
508 fs->fs_bsize < sizeof(struct fs)) {
509 int magic = fs->fs_magic;
510
511 byte_swap_ints(&magic, 1);
512 if (magic != FS_MAGIC) {
513 error = EINVAL;
514 goto out;
515 }
516 if (error = byte_swap_sbin(fs))
517 goto out;
518
519 if (fs->fs_magic != FS_MAGIC || fs->fs_bsize > MAXBSIZE ||
520 fs->fs_bsize < sizeof(struct fs)) {
521 byte_swap_sbout(fs);
522 error = EINVAL; /* XXX needs translation */
523 goto out;
524 }
525 rev_endian=1;
526 }
527 #endif /* REV_ENDIAN_FS */
528 if (fs->fs_magic != FS_MAGIC || fs->fs_bsize > MAXBSIZE ||
529 fs->fs_bsize < sizeof(struct fs)) {
530 #if REV_ENDIAN_FS
531 if (rev_endian)
532 byte_swap_sbout(fs);
533 #endif /* REV_ENDIAN_FS */
534 error = EINVAL; /* XXX needs translation */
535 goto out;
536 }
537
538 if (fs->fs_sbsize < 0 || fs->fs_sbsize > SBSIZE) {
539 error = EINVAL;
540 goto out;
541 }
542
543 /*
544 * Buffer cache does not handle multiple pages in a buf when
545 * invalidating incore buffer in pageout. There are no locks
546 * in the pageout path. So there is a danger of loosing data when
547 * block allocation happens at the same time a pageout of buddy
548 * page occurs. incore() returns buf with both
549 * pages, this leads vnode-pageout to incorrectly flush of entire.
550 * buf. Till the low level ffs code is modified to deal with these
551 * do not mount any FS more than 4K size.
552 */
553 /*
554 * Can't mount filesystems with a fragment size less than DIRBLKSIZ
555 */
556 /*
557 * Don't mount dirty filesystems, except for the root filesystem
558 */
559 if ((fs->fs_bsize > PAGE_SIZE) || (fs->fs_fsize < DIRBLKSIZ) ||
560 ((!(mp->mnt_flag & MNT_ROOTFS)) && (!fs->fs_clean))) {
561 #if REV_ENDIAN_FS
562 if (rev_endian)
563 byte_swap_sbout(fs);
564 #endif /* REV_ENDIAN_FS */
565 error = ENOTSUP;
566 goto out;
567 }
568
569 /* Let's figure out the devblock size the file system is with */
570 /* the device block size = fragment size / number of sectors per frag */
571
572 dbsize = fs->fs_fsize / NSPF(fs);
573 if(dbsize <= 0 ) {
574 kprintf("device blocksize computaion failed\n");
575 } else {
576 if (VNOP_IOCTL(devvp, DKIOCSETBLOCKSIZE, (caddr_t)&dbsize,
577 FWRITE, context) != 0) {
578 kprintf("failed to set device blocksize\n");
579 }
580 /* force the specfs to reread blocksize from size() */
581 set_fsblocksize(devvp);
582 }
583
584 /* XXX updating 4.2 FFS superblocks trashes rotational layout tables */
585 if (fs->fs_postblformat == FS_42POSTBLFMT && !ronly) {
586 #if REV_ENDIAN_FS
587 if (rev_endian)
588 byte_swap_sbout(fs);
589 #endif /* REV_ENDIAN_FS */
590 error = EROFS; /* needs translation */
591 goto out;
592 }
593
594 /* If we are not mounting read only, then check for overlap
595 * condition in cylinder group's free block map.
596 * If overlap exists, then force this into a read only mount
597 * to avoid further corruption. PR#2216969
598 */
599 if (ronly == 0){
600 if (error = (int)buf_bread (devvp, (daddr64_t)((unsigned)fsbtodb(fs, cgtod(fs, 0))),
601 (int)fs->fs_cgsize, NOCRED, &cgbp)) {
602 buf_brelse(cgbp);
603 goto out;
604 }
605 cgp = (struct cg *)buf_dataptr(cgbp);
606 #if REV_ENDIAN_FS
607 if (rev_endian)
608 byte_swap_cgin(cgp,fs);
609 #endif /* REV_ENDIAN_FS */
610 if (!cg_chkmagic(cgp)){
611 #if REV_ENDIAN_FS
612 if (rev_endian)
613 byte_swap_cgout(cgp,fs);
614 #endif /* REV_ENDIAN_FS */
615 buf_brelse(cgbp);
616 goto out;
617 }
618 if (cgp->cg_clustersumoff != 0) {
619 /* Check for overlap */
620 clustersumoff = cgp->cg_freeoff +
621 howmany(fs->fs_cpg * fs->fs_spc / NSPF(fs), NBBY);
622 clustersumoff = roundup(clustersumoff, sizeof(long));
623 if (cgp->cg_clustersumoff < clustersumoff) {
624 /* Overlap exists */
625 mp->mnt_flag |= MNT_RDONLY;
626 ronly = 1;
627 }
628 }
629 #if REV_ENDIAN_FS
630 if (rev_endian)
631 byte_swap_cgout(cgp,fs);
632 #endif /* REV_ENDIAN_FS */
633 buf_brelse(cgbp);
634 }
635
636 ump = _MALLOC(sizeof *ump, M_UFSMNT, M_WAITOK);
637 bzero((caddr_t)ump, sizeof *ump);
638 ump->um_fs = _MALLOC((u_long)fs->fs_sbsize, M_UFSMNT,
639 M_WAITOK);
640 bcopy((char *)buf_dataptr(bp), ump->um_fs, (u_int)fs->fs_sbsize);
641 if (fs->fs_sbsize < SBSIZE)
642 buf_markinvalid(bp);
643 #if REV_ENDIAN_FS
644 if (rev_endian)
645 byte_swap_sbout(fs);
646 #endif /* REV_ENDIAN_FS */
647 buf_brelse(bp);
648 bp = NULL;
649 fs = ump->um_fs;
650 fs->fs_ronly = ronly;
651 if (fs->fs_cssize < 1 || fs->fs_fsize < 1 || fs->fs_ncg < 1) {
652 error = EINVAL;
653 goto out;
654 }
655 if (fs->fs_frag < 1 || fs->fs_frag > MAXFRAG) {
656 error = EINVAL;
657 goto out;
658 }
659
660 size = fs->fs_cssize;
661 blks = howmany(size, fs->fs_fsize);
662 if (fs->fs_contigsumsize > 0) {
663 if (fs->fs_ncg > INT_MAX / sizeof(int32_t) || size > INT_MAX - fs->fs_ncg * sizeof(int32_t)) {
664 error = EINVAL;
665 goto out;
666 }
667 size += fs->fs_ncg * sizeof(int32_t);
668 }
669 if (fs->fs_ncg > INT_MAX / sizeof(u_int8_t) || size > INT_MAX - fs->fs_ncg * sizeof(u_int8_t)) {
670 error = EINVAL;
671 goto out;
672 }
673 size += fs->fs_ncg * sizeof(u_int8_t);
674 space = _MALLOC((u_long)size, M_UFSMNT, M_WAITOK);
675 fs->fs_csp = space;
676 for (i = 0; i < blks; i += fs->fs_frag) {
677 size = fs->fs_bsize;
678 if (i + fs->fs_frag > blks)
679 size = (blks - i) * fs->fs_fsize;
680 if (error = (int)buf_bread(devvp, (daddr64_t)((unsigned)fsbtodb(fs, fs->fs_csaddr + i)),
681 size, cred, &bp)) {
682 _FREE(fs->fs_csp, M_UFSMNT);
683 goto out;
684 }
685 bcopy((char *)buf_dataptr(bp), space, (u_int)size);
686 #if REV_ENDIAN_FS
687 if (rev_endian)
688 byte_swap_ints((int *) space, size / sizeof(int));
689 #endif /* REV_ENDIAN_FS */
690 space = (char *)space + size;
691 buf_brelse(bp);
692 bp = NULL;
693 }
694 if (fs->fs_contigsumsize > 0) {
695 fs->fs_maxcluster = lp = space;
696 for (i = 0; i < fs->fs_ncg; i++)
697 *lp++ = fs->fs_contigsumsize;
698 space = lp;
699 }
700 size = fs->fs_ncg * sizeof(u_int8_t);
701 fs->fs_contigdirs = (u_int8_t *)space;
702 space = (u_int8_t *)space + size;
703 bzero(fs->fs_contigdirs, size);
704 /* XXX Compatibility for old filesystems */
705 if (fs->fs_avgfilesize <= 0)
706 fs->fs_avgfilesize = AVFILESIZ;
707 if (fs->fs_avgfpdir <= 0)
708 fs->fs_avgfpdir = AFPDIR;
709 /* XXX End of compatibility */
710 mp->mnt_data = (qaddr_t)ump;
711 mp->mnt_vfsstat.f_fsid.val[0] = (long)dev;
712 mp->mnt_vfsstat.f_fsid.val[1] = vfs_typenum(mp);
713 /* XXX warning hardcoded max symlen and not "mp->mnt_maxsymlinklen = fs->fs_maxsymlinklen;" */
714 mp->mnt_maxsymlinklen = 60;
715 #if REV_ENDIAN_FS
716 if (rev_endian)
717 mp->mnt_flag |= MNT_REVEND;
718 #endif /* REV_ENDIAN_FS */
719 ump->um_mountp = mp;
720 ump->um_dev = dev;
721 ump->um_devvp = devvp;
722 ump->um_nindir = fs->fs_nindir;
723 ump->um_bptrtodb = fs->fs_fsbtodb;
724 ump->um_seqinc = fs->fs_frag;
725 for (i = 0; i < MAXQUOTAS; i++)
726 dqfileinit(&ump->um_qfiles[i]);
727 ffs_oldfscompat(fs);
728 ump->um_savedmaxfilesize = fs->fs_maxfilesize; /* XXX */
729 maxfilesize = 0x100000000ULL; /* 4GB */
730 #if 0
731 maxfilesize = (u_int64_t)0x40000000 * fs->fs_bsize - 1; /* XXX */
732 #endif /* 0 */
733 if (fs->fs_maxfilesize > maxfilesize) /* XXX */
734 fs->fs_maxfilesize = maxfilesize; /* XXX */
735 if (ronly == 0) {
736 fs->fs_clean = 0;
737 (void) ffs_sbupdate(ump, MNT_WAIT);
738 }
739 return (0);
740 out:
741 if (bp)
742 buf_brelse(bp);
743 if (ump) {
744 _FREE(ump->um_fs, M_UFSMNT);
745 _FREE(ump, M_UFSMNT);
746 }
747 return (error);
748 }
749
750 /*
751 * Sanity checks for old file systems.
752 *
753 * XXX - goes away some day.
754 */
755 ffs_oldfscompat(fs)
756 struct fs *fs;
757 {
758 int i;
759
760 fs->fs_npsect = max(fs->fs_npsect, fs->fs_nsect); /* XXX */
761 fs->fs_interleave = max(fs->fs_interleave, 1); /* XXX */
762 if (fs->fs_postblformat == FS_42POSTBLFMT) /* XXX */
763 fs->fs_nrpos = 8; /* XXX */
764 if (fs->fs_inodefmt < FS_44INODEFMT) { /* XXX */
765 u_int64_t sizepb = fs->fs_bsize; /* XXX */
766 /* XXX */
767 fs->fs_maxfilesize = fs->fs_bsize * NDADDR - 1; /* XXX */
768 for (i = 0; i < NIADDR; i++) { /* XXX */
769 sizepb *= NINDIR(fs); /* XXX */
770 fs->fs_maxfilesize += sizepb; /* XXX */
771 } /* XXX */
772 fs->fs_qbmask = ~fs->fs_bmask; /* XXX */
773 fs->fs_qfmask = ~fs->fs_fmask; /* XXX */
774 } /* XXX */
775 return (0);
776 }
777
778 /*
779 * unmount system call
780 */
781 int
782 ffs_unmount(mp, mntflags, context)
783 struct mount *mp;
784 int mntflags;
785 vfs_context_t context;
786 {
787 struct proc *p = vfs_context_proc(context);
788 register struct ufsmount *ump;
789 register struct fs *fs;
790 int error, flags;
791 int force;
792
793 flags = 0;
794 force = 0;
795 if (mntflags & MNT_FORCE) {
796 flags |= FORCECLOSE;
797 force = 1;
798 }
799 if ( (error = ffs_flushfiles(mp, flags, p)) && !force )
800 return (error);
801 ump = VFSTOUFS(mp);
802 fs = ump->um_fs;
803
804 if (fs->fs_ronly == 0) {
805 fs->fs_clean = 1;
806 if (error = ffs_sbupdate(ump, MNT_WAIT)) {
807 fs->fs_clean = 0;
808 #ifdef notyet
809 /* we can atleast cleanup ; as the media could be WP */
810 /* & during mount, we do not check for write failures */
811 /* FIXME LATER : the Correct fix would be to have */
812 /* mount detect the WP media and downgrade to readonly mount */
813 /* For now, here it is */
814 return (error);
815 #endif /* notyet */
816 }
817 }
818 _FREE(fs->fs_csp, M_UFSMNT);
819 _FREE(fs, M_UFSMNT);
820 _FREE(ump, M_UFSMNT);
821
822 return (0);
823 }
824
825 /*
826 * Flush out all the files in a filesystem.
827 */
828 ffs_flushfiles(mp, flags, p)
829 register struct mount *mp;
830 int flags;
831 struct proc *p;
832 {
833 register struct ufsmount *ump;
834 int i, error;
835
836 ump = VFSTOUFS(mp);
837
838 #if QUOTA
839 /*
840 * NOTE: The open quota files have an indirect reference
841 * on the root directory vnode. We must account for this
842 * extra reference when doing the intial vflush.
843 */
844 if (mp->mnt_flag & MNT_QUOTA) {
845 struct vnode *rootvp = NULLVP;
846 int quotafilecnt = 0;
847
848 /* Find out how many quota files we have open. */
849 for (i = 0; i < MAXQUOTAS; i++) {
850 if (ump->um_qfiles[i].qf_vp != NULLVP)
851 ++quotafilecnt;
852 }
853
854 /*
855 * Check if the root vnode is in our inode hash
856 * (so we can skip over it).
857 */
858 rootvp = ufs_ihashget(ump->um_dev, ROOTINO);
859
860 error = vflush(mp, rootvp, SKIPSYSTEM|flags);
861
862 if (rootvp) {
863 /*
864 * See if there are additional references on the
865 * root vp besides the ones obtained from the open
866 * quota files and the hfs_chashget call above.
867 */
868 if ((error == 0) &&
869 (rootvp->v_usecount > (1 + quotafilecnt))) {
870 error = EBUSY; /* root dir is still open */
871 }
872 vnode_put(rootvp);
873 }
874 if (error && (flags & FORCECLOSE) == 0)
875 return (error);
876
877 for (i = 0; i < MAXQUOTAS; i++) {
878 if (ump->um_qfiles[i].qf_vp == NULLVP)
879 continue;
880 quotaoff(mp, i);
881 }
882 /*
883 * Here we fall through to vflush again to ensure
884 * that we have gotten rid of all the system vnodes.
885 */
886 }
887 #endif
888 error = vflush(mp, NULLVP, SKIPSWAP|flags);
889 error = vflush(mp, NULLVP, flags);
890 return (error);
891 }
892
893 /*
894 * Get file system statistics.
895 */
896 int
897 ffs_statfs(mp, sbp, context)
898 struct mount *mp;
899 register struct vfsstatfs *sbp;
900 vfs_context_t context;
901 {
902 register struct ufsmount *ump;
903 register struct fs *fs;
904
905 ump = VFSTOUFS(mp);
906 fs = ump->um_fs;
907 if (fs->fs_magic != FS_MAGIC)
908 panic("ffs_statfs");
909 sbp->f_bsize = fs->fs_fsize;
910 sbp->f_iosize = fs->fs_bsize;
911 sbp->f_blocks = (uint64_t)((unsigned long)fs->fs_dsize);
912 sbp->f_bfree = (uint64_t) ((unsigned long)(fs->fs_cstotal.cs_nbfree * fs->fs_frag +
913 fs->fs_cstotal.cs_nffree));
914 sbp->f_bavail = (uint64_t) ((unsigned long)freespace(fs, fs->fs_minfree));
915 sbp->f_files = (uint64_t) ((unsigned long)(fs->fs_ncg * fs->fs_ipg - ROOTINO));
916 sbp->f_ffree = (uint64_t) ((unsigned long)fs->fs_cstotal.cs_nifree);
917 return (0);
918 }
919
920 int
921 ffs_vfs_getattr(mp, fsap, context)
922 struct mount *mp;
923 struct vfs_attr *fsap;
924 vfs_context_t context;
925 {
926 struct ufsmount *ump;
927 struct fs *fs;
928 kauth_cred_t cred;
929 struct vnode *devvp;
930 struct buf *bp;
931 struct ufslabel *ulp;
932 char *offset;
933 int bs, error, length;
934
935 ump = VFSTOUFS(mp);
936 fs = ump->um_fs;
937 cred = vfs_context_ucred(context);
938
939 VFSATTR_RETURN(fsap, f_bsize, fs->fs_fsize);
940 VFSATTR_RETURN(fsap, f_iosize, fs->fs_bsize);
941 VFSATTR_RETURN(fsap, f_blocks, (uint64_t)((unsigned long)fs->fs_dsize));
942 VFSATTR_RETURN(fsap, f_bfree, (uint64_t)((unsigned long)
943 (fs->fs_cstotal.cs_nbfree * fs->fs_frag +
944 fs->fs_cstotal.cs_nffree)));
945 VFSATTR_RETURN(fsap, f_bavail, (uint64_t)((unsigned long)freespace(fs,
946 fs->fs_minfree)));
947 VFSATTR_RETURN(fsap, f_files, (uint64_t)((unsigned long)
948 (fs->fs_ncg * fs->fs_ipg - ROOTINO)));
949 VFSATTR_RETURN(fsap, f_ffree, (uint64_t)((unsigned long)
950 fs->fs_cstotal.cs_nifree));
951
952 if (VFSATTR_IS_ACTIVE(fsap, f_fsid)) {
953 fsap->f_fsid.val[0] = mp->mnt_vfsstat.f_fsid.val[0];
954 fsap->f_fsid.val[1] = mp->mnt_vfsstat.f_fsid.val[1];
955 VFSATTR_SET_SUPPORTED(fsap, f_fsid);
956 }
957
958 if (VFSATTR_IS_ACTIVE(fsap, f_vol_name)) {
959 devvp = ump->um_devvp;
960 bs = vfs_devblocksize(mp);
961
962 if (error = (int)buf_meta_bread(devvp,
963 (daddr64_t)(UFS_LABEL_OFFSET / bs),
964 MAX(bs, UFS_LABEL_SIZE), cred, &bp)) {
965 if (bp)
966 buf_brelse(bp);
967 return (error);
968 }
969
970 /*
971 * Since the disklabel is read directly by older user space
972 * code, make sure this buffer won't remain in the cache when
973 * we release it.
974 */
975 buf_setflags(bp, B_NOCACHE);
976
977 offset = buf_dataptr(bp) + (UFS_LABEL_OFFSET % bs);
978 ulp = (struct ufslabel *)offset;
979
980 if (ufs_label_check(ulp)) {
981 length = ulp->ul_namelen;
982 #if REV_ENDIAN_FS
983 if (mp->mnt_flag & MNT_REVEND)
984 length = OSSwapInt16(length);
985 #endif
986 if (length > 0 && length <= UFS_MAX_LABEL_NAME) {
987 bcopy(ulp->ul_name, fsap->f_vol_name, length);
988 fsap->f_vol_name[UFS_MAX_LABEL_NAME - 1] = '\0';
989 fsap->f_vol_name[length] = '\0';
990 }
991 }
992
993 buf_brelse(bp);
994 VFSATTR_SET_SUPPORTED(fsap, f_vol_name);
995 }
996
997 if (VFSATTR_IS_ACTIVE(fsap, f_capabilities)) {
998 fsap->f_capabilities.capabilities[VOL_CAPABILITIES_FORMAT] =
999 VOL_CAP_FMT_SYMBOLICLINKS |
1000 VOL_CAP_FMT_HARDLINKS |
1001 VOL_CAP_FMT_SPARSE_FILES |
1002 VOL_CAP_FMT_CASE_SENSITIVE |
1003 VOL_CAP_FMT_CASE_PRESERVING |
1004 VOL_CAP_FMT_FAST_STATFS |
1005 VOL_CAP_FMT_HIDDEN_FILES ;
1006 fsap->f_capabilities.capabilities[VOL_CAPABILITIES_INTERFACES]
1007 = VOL_CAP_INT_NFSEXPORT |
1008 VOL_CAP_INT_VOL_RENAME |
1009 VOL_CAP_INT_ADVLOCK |
1010 VOL_CAP_INT_FLOCK;
1011 fsap->f_capabilities.capabilities[VOL_CAPABILITIES_RESERVED1]
1012 = 0;
1013 fsap->f_capabilities.capabilities[VOL_CAPABILITIES_RESERVED2]
1014 = 0;
1015
1016 /* Capabilities we know about: */
1017 fsap->f_capabilities.valid[VOL_CAPABILITIES_FORMAT] =
1018 VOL_CAP_FMT_PERSISTENTOBJECTIDS |
1019 VOL_CAP_FMT_SYMBOLICLINKS |
1020 VOL_CAP_FMT_HARDLINKS |
1021 VOL_CAP_FMT_JOURNAL |
1022 VOL_CAP_FMT_JOURNAL_ACTIVE |
1023 VOL_CAP_FMT_NO_ROOT_TIMES |
1024 VOL_CAP_FMT_SPARSE_FILES |
1025 VOL_CAP_FMT_ZERO_RUNS |
1026 VOL_CAP_FMT_CASE_SENSITIVE |
1027 VOL_CAP_FMT_CASE_PRESERVING |
1028 VOL_CAP_FMT_FAST_STATFS |
1029 VOL_CAP_FMT_2TB_FILESIZE |
1030 VOL_CAP_FMT_OPENDENYMODES |
1031 VOL_CAP_FMT_HIDDEN_FILES ;
1032 fsap->f_capabilities.valid[VOL_CAPABILITIES_INTERFACES] =
1033 VOL_CAP_INT_SEARCHFS |
1034 VOL_CAP_INT_ATTRLIST |
1035 VOL_CAP_INT_NFSEXPORT |
1036 VOL_CAP_INT_READDIRATTR |
1037 VOL_CAP_INT_EXCHANGEDATA |
1038 VOL_CAP_INT_COPYFILE |
1039 VOL_CAP_INT_ALLOCATE |
1040 VOL_CAP_INT_VOL_RENAME |
1041 VOL_CAP_INT_ADVLOCK |
1042 VOL_CAP_INT_FLOCK |
1043 VOL_CAP_INT_MANLOCK;
1044 fsap->f_capabilities.valid[VOL_CAPABILITIES_RESERVED1] = 0;
1045 fsap->f_capabilities.valid[VOL_CAPABILITIES_RESERVED2] = 0;
1046
1047 VFSATTR_SET_SUPPORTED(fsap, f_capabilities);
1048 }
1049
1050 if (VFSATTR_IS_ACTIVE(fsap, f_attributes)) {
1051 fsap->f_attributes.validattr.commonattr = 0;
1052 fsap->f_attributes.validattr.volattr =
1053 ATTR_VOL_NAME | ATTR_VOL_CAPABILITIES | ATTR_VOL_ATTRIBUTES;
1054 fsap->f_attributes.validattr.dirattr = 0;
1055 fsap->f_attributes.validattr.fileattr = 0;
1056 fsap->f_attributes.validattr.forkattr = 0;
1057
1058 fsap->f_attributes.nativeattr.commonattr = 0;
1059 fsap->f_attributes.nativeattr.volattr =
1060 ATTR_VOL_NAME | ATTR_VOL_CAPABILITIES | ATTR_VOL_ATTRIBUTES;
1061 fsap->f_attributes.nativeattr.dirattr = 0;
1062 fsap->f_attributes.nativeattr.fileattr = 0;
1063 fsap->f_attributes.nativeattr.forkattr = 0;
1064
1065 VFSATTR_SET_SUPPORTED(fsap, f_attributes);
1066 }
1067
1068 return (0);
1069 }
1070
1071
1072 int
1073 ffs_vfs_setattr(mp, fsap, context)
1074 struct mount *mp;
1075 struct vfs_attr *fsap;
1076 vfs_context_t context;
1077 {
1078 struct ufsmount *ump;
1079 struct vnode *devvp;
1080 struct buf *bp;
1081 struct ufslabel *ulp;
1082 kauth_cred_t cred;
1083 char *offset;
1084 int bs, error;
1085
1086
1087 ump = VFSTOUFS(mp);
1088 cred = vfs_context_ucred(context);
1089
1090 if (VFSATTR_IS_ACTIVE(fsap, f_vol_name)) {
1091 devvp = ump->um_devvp;
1092 bs = vfs_devblocksize(mp);
1093 if (error = buf_meta_bread(devvp,
1094 (daddr64_t)(UFS_LABEL_OFFSET / bs),
1095 MAX(bs, UFS_LABEL_SIZE), cred, &bp)) {
1096 if (bp)
1097 buf_brelse(bp);
1098 return (error);
1099 }
1100
1101 /*
1102 * Since the disklabel is read directly by older user space
1103 * code, make sure this buffer won't remain in the cache when
1104 * we release it.
1105 */
1106 buf_setflags(bp, B_NOCACHE);
1107
1108 /* Validate the label structure; init if not valid */
1109 offset = buf_dataptr(bp) + (UFS_LABEL_OFFSET % bs);
1110 ulp = (struct ufslabel *)offset;
1111 if (!ufs_label_check(ulp))
1112 ufs_label_init(ulp);
1113
1114 /* Copy new name over existing name */
1115 ulp->ul_namelen = strlen(fsap->f_vol_name);
1116 bcopy(fsap->f_vol_name, ulp->ul_name, ulp->ul_namelen);
1117 ulp->ul_name[UFS_MAX_LABEL_NAME - 1] = '\0';
1118 ulp->ul_name[ulp->ul_namelen] = '\0';
1119
1120 #if REV_ENDIAN_FS
1121 if (mp->mnt_flag & MNT_REVEND)
1122 ulp->ul_namelen = OSSwapInt16(ulp->ul_namelen);
1123 #endif
1124
1125 /* Update the checksum */
1126 ulp->ul_checksum = 0;
1127 ulp->ul_checksum = ul_cksum(ulp, sizeof(*ulp));
1128
1129 /* Write the label back to disk */
1130 buf_bwrite(bp);
1131 bp = NULL;
1132
1133 VFSATTR_SET_SUPPORTED(fsap, f_vol_name);
1134 }
1135
1136 return (0);
1137 }
1138 struct ffs_sync_cargs {
1139 vfs_context_t context;
1140 int waitfor;
1141 int error;
1142 };
1143
1144
1145 static int
1146 ffs_sync_callback(struct vnode *vp, void *cargs)
1147 {
1148 struct inode *ip;
1149 struct ffs_sync_cargs *args;
1150 int error;
1151
1152 args = (struct ffs_sync_cargs *)cargs;
1153
1154 ip = VTOI(vp);
1155
1156 if ((ip->i_flag & (IN_ACCESS | IN_CHANGE | IN_MODIFIED | IN_UPDATE)) || vnode_hasdirtyblks(vp)) {
1157 error = VNOP_FSYNC(vp, args->waitfor, args->context);
1158
1159 if (error)
1160 args->error = error;
1161
1162 }
1163 return (VNODE_RETURNED);
1164 }
1165
1166 /*
1167 * Go through the disk queues to initiate sandbagged IO;
1168 * go through the inodes to write those that have been modified;
1169 * initiate the writing of the super block if it has been modified.
1170 *
1171 * Note: we are always called with the filesystem marked `MPBUSY'.
1172 */
1173 int
1174 ffs_sync(mp, waitfor, context)
1175 struct mount *mp;
1176 int waitfor;
1177 vfs_context_t context;
1178 {
1179 struct vnode *nvp, *vp;
1180 struct ufsmount *ump = VFSTOUFS(mp);
1181 struct fs *fs;
1182 struct timeval tv;
1183 int error, allerror = 0;
1184 struct ffs_sync_cargs args;
1185
1186 fs = ump->um_fs;
1187 if (fs->fs_fmod != 0 && fs->fs_ronly != 0) { /* XXX */
1188 printf("fs = %s\n", fs->fs_fsmnt);
1189 panic("update: rofs mod");
1190 }
1191 /*
1192 * Write back each (modified) inode.
1193 */
1194 args.context = context;
1195 args.waitfor = waitfor;
1196 args.error = 0;
1197 /*
1198 * ffs_sync_callback will be called for each vnode
1199 * hung off of this mount point... the vnode will be
1200 * properly referenced and unreferenced around the callback
1201 */
1202 vnode_iterate(mp, 0, ffs_sync_callback, (void *)&args);
1203
1204 if (args.error)
1205 allerror = args.error;
1206
1207 /*
1208 * Force stale file system control information to be flushed.
1209 */
1210 if (error = VNOP_FSYNC(ump->um_devvp, waitfor, context))
1211 allerror = error;
1212 #if QUOTA
1213 qsync(mp);
1214 #endif
1215 /*
1216 * Write back modified superblock.
1217 */
1218 if (fs->fs_fmod != 0) {
1219 fs->fs_fmod = 0;
1220 microtime(&tv);
1221 fs->fs_time = tv.tv_sec;
1222 if (error = ffs_sbupdate(ump, waitfor))
1223 allerror = error;
1224 }
1225 return (allerror);
1226 }
1227
1228 /*
1229 * Look up a FFS dinode number to find its incore vnode, otherwise read it
1230 * in from disk. If it is in core, wait for the lock bit to clear, then
1231 * return the inode locked. Detection and handling of mount points must be
1232 * done by the calling routine.
1233 */
1234 int
1235 ffs_vget(mp, ino, vpp, context)
1236 mount_t mp;
1237 ino64_t ino;
1238 vnode_t *vpp;
1239 vfs_context_t context;
1240 {
1241 return(ffs_vget_internal(mp, (ino_t)ino, vpp, NULL, NULL, 0, 0));
1242 }
1243
1244
1245 int
1246 ffs_vget_internal(mp, ino, vpp, dvp, cnp, mode, fhwanted)
1247 mount_t mp;
1248 ino_t ino;
1249 vnode_t *vpp;
1250 vnode_t dvp;
1251 struct componentname *cnp;
1252 int mode;
1253 int fhwanted;
1254 {
1255 struct proc *p = current_proc(); /* XXX */
1256 struct fs *fs;
1257 struct inode *ip;
1258 struct ufsmount *ump;
1259 struct buf *bp;
1260 struct vnode *vp;
1261 struct vnode_fsparam vfsp;
1262 struct timeval tv;
1263 enum vtype vtype;
1264 dev_t dev;
1265 int i, type, error = 0;
1266
1267 *vpp = NULL;
1268 ump = VFSTOUFS(mp);
1269 dev = ump->um_dev;
1270 #if 0
1271 /* Check for unmount in progress */
1272 if (mp->mnt_kern_flag & MNTK_UNMOUNT) {
1273 return (EPERM);
1274 }
1275 #endif
1276 /*
1277 * Allocate a new inode... do it before we check the
1278 * cache, because the MALLOC_ZONE may block
1279 */
1280 type = M_FFSNODE;
1281 MALLOC_ZONE(ip, struct inode *, sizeof(struct inode), type, M_WAITOK);
1282
1283 /*
1284 * check in the inode hash
1285 */
1286 if ((*vpp = ufs_ihashget(dev, ino)) != NULL) {
1287 /*
1288 * found it... get rid of the allocation
1289 * that we didn't need and return
1290 * the 'found' vnode
1291 */
1292 FREE_ZONE(ip, sizeof(struct inode), type);
1293 vp = *vpp;
1294 return (0);
1295 }
1296 bzero((caddr_t)ip, sizeof(struct inode));
1297 /*
1298 * lock the inode
1299 */
1300 // lockinit(&ip->i_lock, PINOD, "inode", 0, 0);
1301 // lockmgr(&ip->i_lock, LK_EXCLUSIVE, (struct slock *)0, p);
1302
1303 ip->i_fs = fs = ump->um_fs;
1304 ip->i_dev = dev;
1305 ip->i_number = ino;
1306 #if QUOTA
1307 for (i = 0; i < MAXQUOTAS; i++)
1308 ip->i_dquot[i] = NODQUOT;
1309 #endif
1310 SET(ip->i_flag, IN_ALLOC);
1311 /*
1312 * Put it onto its hash chain locked so that other requests for
1313 * this inode will block if they arrive while we are sleeping waiting
1314 * for old data structures to be purged or for the contents of the
1315 * disk portion of this inode to be read.
1316 */
1317 ufs_ihashins(ip);
1318
1319 /* Read in the disk contents for the inode, copy into the inode. */
1320 if (error = (int)buf_bread(ump->um_devvp, (daddr64_t)((unsigned)fsbtodb(fs, ino_to_fsba(fs, ino))),
1321 (int)fs->fs_bsize, NOCRED, &bp)) {
1322 buf_brelse(bp);
1323 goto errout;
1324 }
1325 #if REV_ENDIAN_FS
1326 if (mp->mnt_flag & MNT_REVEND) {
1327 byte_swap_inode_in(((struct dinode *)buf_dataptr(bp) + ino_to_fsbo(fs, ino)),ip);
1328 } else {
1329 ip->i_din = *((struct dinode *)buf_dataptr(bp) + ino_to_fsbo(fs, ino));
1330 }
1331 #else
1332 ip->i_din = *((struct dinode *)buf_dataptr(bp) + ino_to_fsbo(fs, ino));
1333 #endif /* REV_ENDIAN_FS */
1334 buf_brelse(bp);
1335
1336 if (mode == 0)
1337 vtype = IFTOVT(ip->i_mode);
1338 else
1339 vtype = IFTOVT(mode);
1340
1341 if (vtype == VNON) {
1342 if (fhwanted) {
1343 /* NFS is in play */
1344 error = ESTALE;
1345 goto errout;
1346 } else {
1347 error = ENOENT;
1348 goto errout;
1349 }
1350 }
1351
1352 vfsp.vnfs_mp = mp;
1353 vfsp.vnfs_vtype = vtype;
1354 vfsp.vnfs_str = "ufs";
1355 vfsp.vnfs_dvp = dvp;
1356 vfsp.vnfs_fsnode = ip;
1357 vfsp.vnfs_cnp = cnp;
1358
1359 if (mode == 0)
1360 vfsp.vnfs_filesize = ip->i_din.di_size;
1361 else
1362 vfsp.vnfs_filesize = 0;
1363
1364 if (vtype == VFIFO )
1365 vfsp.vnfs_vops = FFS_FIFOOPS;
1366 else if (vtype == VBLK || vtype == VCHR)
1367 vfsp.vnfs_vops = ffs_specop_p;
1368 else
1369 vfsp.vnfs_vops = ffs_vnodeop_p;
1370
1371 if (vtype == VBLK || vtype == VCHR)
1372 vfsp.vnfs_rdev = ip->i_rdev;
1373 else
1374 vfsp.vnfs_rdev = 0;
1375
1376 if (dvp && cnp && (cnp->cn_flags & MAKEENTRY))
1377 vfsp.vnfs_flags = 0;
1378 else
1379 vfsp.vnfs_flags = VNFS_NOCACHE;
1380
1381 /*
1382 * Tag root directory
1383 */
1384 vfsp.vnfs_markroot = (ip->i_number == ROOTINO);
1385 vfsp.vnfs_marksystem = 0;
1386
1387 if ((error = vnode_create(VNCREATE_FLAVOR, VCREATESIZE, &vfsp, &vp)))
1388 goto errout;
1389
1390 /*
1391 * Finish inode initialization now that aliasing has been resolved.
1392 */
1393 ip->i_devvp = ump->um_devvp;
1394 ip->i_vnode = vp;
1395
1396 vnode_ref(ip->i_devvp);
1397 vnode_addfsref(vp);
1398 vnode_settag(vp, VT_UFS);
1399
1400 /*
1401 * Initialize modrev times
1402 */
1403 microtime(&tv);
1404 SETHIGH(ip->i_modrev, tv.tv_sec);
1405 SETLOW(ip->i_modrev, tv.tv_usec * 4294);
1406
1407 /*
1408 * Set up a generation number for this inode if it does not
1409 * already have one. This should only happen on old filesystems.
1410 */
1411 if (ip->i_gen == 0) {
1412 if (++nextgennumber < (u_long)tv.tv_sec)
1413 nextgennumber = tv.tv_sec;
1414 ip->i_gen = nextgennumber;
1415 if ((vp->v_mount->mnt_flag & MNT_RDONLY) == 0)
1416 ip->i_flag |= IN_MODIFIED;
1417 }
1418 /*
1419 * Ensure that uid and gid are correct. This is a temporary
1420 * fix until fsck has been changed to do the update.
1421 */
1422 if (fs->fs_inodefmt < FS_44INODEFMT) { /* XXX */
1423 ip->i_uid = ip->i_din.di_ouid; /* XXX */
1424 ip->i_gid = ip->i_din.di_ogid; /* XXX */
1425 } /* XXX */
1426 *vpp = vp;
1427
1428 CLR(ip->i_flag, IN_ALLOC);
1429
1430 if (ISSET(ip->i_flag, IN_WALLOC))
1431 wakeup(ip);
1432
1433 return (0);
1434
1435 errout:
1436 ufs_ihashrem(ip);
1437
1438 if (ISSET(ip->i_flag, IN_WALLOC))
1439 wakeup(ip);
1440 FREE_ZONE(ip, sizeof(struct inode), type);
1441
1442 return (error);
1443 }
1444
1445 /*
1446 * File handle to vnode
1447 *
1448 * Have to be really careful about stale file handles:
1449 * - check that the inode number is valid
1450 * - call vget to get the locked inode
1451 * - check for an unallocated inode (i_mode == 0)
1452 */
1453 int
1454 ffs_fhtovp(mp, fhlen, fhp, vpp, context)
1455 register struct mount *mp;
1456 int fhlen;
1457 unsigned char *fhp;
1458 struct vnode **vpp;
1459 vfs_context_t context;
1460 {
1461 register struct ufid *ufhp;
1462 register struct inode *ip;
1463 struct vnode *nvp;
1464 struct fs *fs;
1465 int error;
1466 ino_t ino;
1467
1468 if (fhlen < (int)sizeof(struct ufid))
1469 return (EINVAL);
1470 ufhp = (struct ufid *)fhp;
1471 fs = VFSTOUFS(mp)->um_fs;
1472 ino = ntohl(ufhp->ufid_ino);
1473 if (ino < ROOTINO || ino >= fs->fs_ncg * fs->fs_ipg)
1474 return (ESTALE);
1475 error = ffs_vget_internal(mp, ino, &nvp, NULL, NULL, 0, 1);
1476 if (error) {
1477 *vpp = NULLVP;
1478 return (error);
1479 }
1480 ip = VTOI(nvp);
1481 if (ip->i_mode == 0 || ip->i_gen != ntohl(ufhp->ufid_gen)) {
1482 vnode_put(nvp);
1483 *vpp = NULLVP;
1484 return (ESTALE);
1485 }
1486 *vpp = nvp;
1487 return (0);
1488 }
1489
1490 /*
1491 * Vnode pointer to File handle
1492 */
1493 /* ARGSUSED */
1494 int
1495 ffs_vptofh(vp, fhlenp, fhp, context)
1496 struct vnode *vp;
1497 int *fhlenp;
1498 unsigned char *fhp;
1499 vfs_context_t context;
1500 {
1501 register struct inode *ip;
1502 register struct ufid *ufhp;
1503
1504 if (*fhlenp < (int)sizeof(struct ufid))
1505 return (EOVERFLOW);
1506 ip = VTOI(vp);
1507 ufhp = (struct ufid *)fhp;
1508 ufhp->ufid_ino = htonl(ip->i_number);
1509 ufhp->ufid_gen = htonl(ip->i_gen);
1510 *fhlenp = sizeof(struct ufid);
1511 return (0);
1512 }
1513
1514 /*
1515 * Initialize the filesystem; just use ufs_init.
1516 */
1517 int
1518 ffs_init(vfsp)
1519 struct vfsconf *vfsp;
1520 {
1521
1522 return (ufs_init(vfsp));
1523 }
1524
1525 /*
1526 * fast filesystem related variables.
1527 */
1528 ffs_sysctl(int *name, u_int namelen, user_addr_t oldp, size_t *oldlenp,
1529 user_addr_t newp, size_t newlen, vfs_context_t context)
1530 {
1531 extern int doclusterread, doclusterwrite, doreallocblks, doasyncfree;
1532
1533 /* all sysctl names at this level are terminal */
1534 if (namelen != 1)
1535 return (ENOTDIR); /* overloaded */
1536
1537 switch (name[0]) {
1538 case FFS_CLUSTERREAD:
1539 return (sysctl_int(oldp, oldlenp, newp, newlen,
1540 &doclusterread));
1541 case FFS_CLUSTERWRITE:
1542 return (sysctl_int(oldp, oldlenp, newp, newlen,
1543 &doclusterwrite));
1544 case FFS_REALLOCBLKS:
1545 return (sysctl_int(oldp, oldlenp, newp, newlen,
1546 &doreallocblks));
1547 case FFS_ASYNCFREE:
1548 return (sysctl_int(oldp, oldlenp, newp, newlen, &doasyncfree));
1549 default:
1550 return (ENOTSUP);
1551 }
1552 /* NOTREACHED */
1553 }
1554
1555 /*
1556 * Write a superblock and associated information back to disk.
1557 */
1558 int
1559 ffs_sbupdate(mp, waitfor)
1560 struct ufsmount *mp;
1561 int waitfor;
1562 {
1563 register struct fs *dfs, *fs = mp->um_fs;
1564 register struct buf *bp;
1565 int blks;
1566 void *space;
1567 int i, size, error, allerror = 0;
1568 int devBlockSize=0;
1569 #if REV_ENDIAN_FS
1570 int rev_endian=(mp->um_mountp->mnt_flag & MNT_REVEND);
1571 #endif /* REV_ENDIAN_FS */
1572
1573 /*
1574 * First write back the summary information.
1575 */
1576 blks = howmany(fs->fs_cssize, fs->fs_fsize);
1577 space = fs->fs_csp;
1578 for (i = 0; i < blks; i += fs->fs_frag) {
1579 size = fs->fs_bsize;
1580 if (i + fs->fs_frag > blks)
1581 size = (blks - i) * fs->fs_fsize;
1582 bp = buf_getblk(mp->um_devvp, (daddr64_t)((unsigned)fsbtodb(fs, fs->fs_csaddr + i)),
1583 size, 0, 0, BLK_META);
1584 bcopy(space, (char *)buf_dataptr(bp), (u_int)size);
1585 #if REV_ENDIAN_FS
1586 if (rev_endian) {
1587 byte_swap_ints((int *)buf_dataptr(bp), size / sizeof(int));
1588 }
1589 #endif /* REV_ENDIAN_FS */
1590 space = (char *)space + size;
1591 if (waitfor != MNT_WAIT)
1592 buf_bawrite(bp);
1593 else if (error = (int)buf_bwrite(bp))
1594 allerror = error;
1595 }
1596 /*
1597 * Now write back the superblock itself. If any errors occurred
1598 * up to this point, then fail so that the superblock avoids
1599 * being written out as clean.
1600 */
1601 if (allerror)
1602 return (allerror);
1603 devBlockSize = vfs_devblocksize(mp->um_mountp);
1604
1605 bp = buf_getblk(mp->um_devvp, (daddr64_t)((unsigned)(SBOFF/devBlockSize)), (int)fs->fs_sbsize, 0, 0, BLK_META);
1606 bcopy((caddr_t)fs, (char *)buf_dataptr(bp), (u_int)fs->fs_sbsize);
1607 /* Restore compatibility to old file systems. XXX */
1608 dfs = (struct fs *)buf_dataptr(bp); /* XXX */
1609 if (fs->fs_postblformat == FS_42POSTBLFMT) /* XXX */
1610 dfs->fs_nrpos = -1; /* XXX */
1611 #if REV_ENDIAN_FS
1612 /*
1613 * Swapping bytes here ; so that in case
1614 * of inode format < FS_44INODEFMT appropriate
1615 * fields get moved
1616 */
1617 if (rev_endian) {
1618 byte_swap_sbout((struct fs *)buf_dataptr(bp));
1619 }
1620 #endif /* REV_ENDIAN_FS */
1621 if (fs->fs_inodefmt < FS_44INODEFMT) { /* XXX */
1622 int32_t *lp, tmp; /* XXX */
1623 /* XXX */
1624 lp = (int32_t *)&dfs->fs_qbmask; /* XXX */
1625 tmp = lp[4]; /* XXX */
1626 for (i = 4; i > 0; i--) /* XXX */
1627 lp[i] = lp[i-1]; /* XXX */
1628 lp[0] = tmp; /* XXX */
1629 } /* XXX */
1630 #if REV_ENDIAN_FS
1631 /* Note that dfs is already swapped so swap the filesize
1632 * before writing
1633 */
1634 if (rev_endian) {
1635 dfs->fs_maxfilesize = OSSwapInt64(mp->um_savedmaxfilesize); /* XXX */
1636 } else {
1637 #endif /* REV_ENDIAN_FS */
1638 dfs->fs_maxfilesize = mp->um_savedmaxfilesize; /* XXX */
1639 #if REV_ENDIAN_FS
1640 }
1641 #endif /* REV_ENDIAN_FS */
1642 if (waitfor != MNT_WAIT)
1643 buf_bawrite(bp);
1644 else if (error = (int)buf_bwrite(bp))
1645 allerror = error;
1646
1647 return (allerror);
1648 }