cleanup of cred usage
[unix-history] / usr / src / sys / ufs / ffs / ffs_vfsops.c
CommitLineData
da7c5cc6 1/*
52ff95c2 2 * Copyright (c) 1989, 1991, 1993, 1994
80409bdc 3 * The Regents of the University of California. All rights reserved.
da7c5cc6 4 *
b702c21d 5 * %sccs.include.redist.c%
7188ac27 6 *
075135be 7 * @(#)ffs_vfsops.c 8.14 (Berkeley) %G%
da7c5cc6 8 */
71e4e98b 9
ab9f4fb0
KB
10#include <sys/param.h>
11#include <sys/systm.h>
12#include <sys/namei.h>
13#include <sys/proc.h>
14#include <sys/kernel.h>
15#include <sys/vnode.h>
9e4a3a4a 16#include <sys/socket.h>
ab9f4fb0
KB
17#include <sys/mount.h>
18#include <sys/buf.h>
03f3a6e4 19#include <sys/mbuf.h>
ab9f4fb0
KB
20#include <sys/file.h>
21#include <sys/disklabel.h>
22#include <sys/ioctl.h>
23#include <sys/errno.h>
24#include <sys/malloc.h>
41fc9770
KM
25
26#include <miscfs/specfs/specdev.h>
609e7cfa
MK
27#include "ioctl.h"
28#include "disklabel.h"
29#include "stat.h"
71e4e98b 30
ab9f4fb0
KB
31#include <ufs/ufs/quota.h>
32#include <ufs/ufs/ufsmount.h>
33#include <ufs/ufs/inode.h>
34#include <ufs/ufs/ufs_extern.h>
35
36#include <ufs/ffs/fs.h>
37#include <ufs/ffs/ffs_extern.h>
38
06445aba 39int ffs_sbupdate __P((struct ufsmount *, int));
c6f5111d 40
7188ac27 41struct vfsops ufs_vfsops = {
ab9f4fb0 42 ffs_mount,
5bf9d21f 43 ufs_start,
ab9f4fb0 44 ffs_unmount,
52ff95c2 45 ufs_root,
8dc876c1 46 ufs_quotactl,
ab9f4fb0
KB
47 ffs_statfs,
48 ffs_sync,
067ae075 49 ffs_vget,
a9013e03
KM
50 ffs_fhtovp,
51 ffs_vptofh,
ab9f4fb0 52 ffs_init,
7188ac27
KM
53};
54
067ae075
KM
55extern u_long nextgennumber;
56
7188ac27 57/*
4ac55ebc 58 * Called by main() when ufs is going to be mounted as root.
7188ac27 59 *
d48157d5 60 * Name is updated by mount(8) after booting.
7188ac27 61 */
8a4911ca 62#define ROOTNAME "root_device"
7188ac27 63
ab9f4fb0 64ffs_mountroot()
71e4e98b 65{
7188ac27 66 extern struct vnode *rootvp;
ab9f4fb0
KB
67 register struct fs *fs;
68 register struct mount *mp;
0eb6f54a 69 struct proc *p = curproc; /* XXX */
7188ac27 70 struct ufsmount *ump;
7188ac27
KM
71 u_int size;
72 int error;
751df505
KM
73
74 /*
75 * Get vnodes for swapdev and rootdev.
76 */
77 if (bdevvp(swapdev, &swapdev_vp) || bdevvp(rootdev, &rootvp))
78 panic("ffs_mountroot: can't setup bdevvp's");
71e4e98b 79
4ac55ebc 80 mp = malloc((u_long)sizeof(struct mount), M_MOUNT, M_WAITOK);
ea301039 81 bzero((char *)mp, (u_long)sizeof(struct mount));
82161bc8
KM
82 mp->mnt_op = &ufs_vfsops;
83 mp->mnt_flag = MNT_RDONLY;
ab9f4fb0
KB
84 if (error = ffs_mountfs(rootvp, mp, p)) {
85 free(mp, M_MOUNT);
7188ac27 86 return (error);
71e4e98b 87 }
d48157d5 88 if (error = vfs_lock(mp)) {
ab9f4fb0
KB
89 (void)ffs_unmount(mp, 0, p);
90 free(mp, M_MOUNT);
7188ac27 91 return (error);
6d07f4cd 92 }
c3627aa8
KM
93 TAILQ_INSERT_TAIL(&mountlist, mp, mnt_list);
94 mp->mnt_flag |= MNT_ROOTFS;
82161bc8 95 mp->mnt_vnodecovered = NULLVP;
7188ac27
KM
96 ump = VFSTOUFS(mp);
97 fs = ump->um_fs;
d45de50d 98 bzero(fs->fs_fsmnt, sizeof(fs->fs_fsmnt));
7188ac27 99 fs->fs_fsmnt[0] = '/';
82161bc8
KM
100 bcopy((caddr_t)fs->fs_fsmnt, (caddr_t)mp->mnt_stat.f_mntonname,
101 MNAMELEN);
102 (void) copystr(ROOTNAME, mp->mnt_stat.f_mntfromname, MNAMELEN - 1,
103 &size);
104 bzero(mp->mnt_stat.f_mntfromname + size, MNAMELEN - size);
ab9f4fb0 105 (void)ffs_statfs(mp, &mp->mnt_stat, p);
7188ac27
KM
106 vfs_unlock(mp);
107 inittodr(fs->fs_time);
108 return (0);
109}
110
111/*
112 * VFS Operations.
113 *
114 * mount system call
115 */
06445aba 116int
ab9f4fb0 117ffs_mount(mp, path, data, ndp, p)
d45de50d 118 register struct mount *mp;
7188ac27
KM
119 char *path;
120 caddr_t data;
121 struct nameidata *ndp;
0eb6f54a 122 struct proc *p;
7188ac27
KM
123{
124 struct vnode *devvp;
125 struct ufs_args args;
126 struct ufsmount *ump;
127 register struct fs *fs;
128 u_int size;
a79eb26d 129 int error, flags;
002e1eb0 130 mode_t accessmode;
7188ac27
KM
131
132 if (error = copyin(data, (caddr_t)&args, sizeof (struct ufs_args)))
133 return (error);
190244fb
MK
134 /*
135 * If updating, check whether changing from read-only to
136 * read/write; if there is no device name, that's all we do.
137 */
138 if (mp->mnt_flag & MNT_UPDATE) {
d48157d5
KM
139 ump = VFSTOUFS(mp);
140 fs = ump->um_fs;
a79eb26d
KM
141 error = 0;
142 if (fs->fs_ronly == 0 && (mp->mnt_flag & MNT_RDONLY)) {
143 flags = WRITECLOSE;
144 if (mp->mnt_flag & MNT_FORCE)
145 flags |= FORCECLOSE;
146 if (vfs_busy(mp))
147 return (EBUSY);
148 error = ffs_flushfiles(mp, flags, p);
149 vfs_unbusy(mp);
150 }
151 if (!error && (mp->mnt_flag & MNT_RELOAD))
152 error = ffs_reload(mp, ndp->ni_cnd.cn_cred, p);
153 if (error)
154 return (error);
002e1eb0
KM
155 if (fs->fs_ronly && (mp->mnt_flag & MNT_WANTRDWR)) {
156 /*
157 * If upgrade to read-write by non-root, then verify
158 * that user has necessary permissions on the device.
159 */
160 if (p->p_ucred->cr_uid != 0) {
161 devvp = ump->um_devvp;
162 VOP_LOCK(devvp);
163 if (error = VOP_ACCESS(devvp, VREAD | VWRITE,
164 p->p_ucred, p)) {
165 VOP_UNLOCK(devvp);
166 return (error);
167 }
168 VOP_UNLOCK(devvp);
169 }
d48157d5 170 fs->fs_ronly = 0;
002e1eb0 171 }
c906fba1
KM
172 if (args.fspec == 0) {
173 /*
174 * Process export requests.
175 */
6e31e5dc 176 return (vfs_export(mp, &ump->um_export, &args.export));
c906fba1 177 }
190244fb
MK
178 }
179 /*
180 * Not an update, or updating the name: look up the name
181 * and verify that it refers to a sensible block device.
182 */
995e59df
KM
183 NDINIT(ndp, LOOKUP, FOLLOW, UIO_USERSPACE, args.fspec, p);
184 if (error = namei(ndp))
190244fb
MK
185 return (error);
186 devvp = ndp->ni_vp;
ab9f4fb0 187
190244fb
MK
188 if (devvp->v_type != VBLK) {
189 vrele(devvp);
190 return (ENOTBLK);
191 }
192 if (major(devvp->v_rdev) >= nblkdev) {
193 vrele(devvp);
194 return (ENXIO);
195 }
002e1eb0
KM
196 /*
197 * If mount by non-root, then verify that user has necessary
198 * permissions on the device.
199 */
200 if (p->p_ucred->cr_uid != 0) {
201 accessmode = VREAD;
202 if ((mp->mnt_flag & MNT_RDONLY) == 0)
203 accessmode |= VWRITE;
204 VOP_LOCK(devvp);
205 if (error = VOP_ACCESS(devvp, accessmode, p->p_ucred, p)) {
206 vput(devvp);
207 return (error);
208 }
209 VOP_UNLOCK(devvp);
210 }
190244fb 211 if ((mp->mnt_flag & MNT_UPDATE) == 0)
ab9f4fb0 212 error = ffs_mountfs(devvp, mp, p);
190244fb 213 else {
d48157d5
KM
214 if (devvp != ump->um_devvp)
215 error = EINVAL; /* needs translation */
2a7dbb09
KM
216 else
217 vrele(devvp);
d48157d5 218 }
7188ac27
KM
219 if (error) {
220 vrele(devvp);
221 return (error);
27d00e76 222 }
7188ac27
KM
223 ump = VFSTOUFS(mp);
224 fs = ump->um_fs;
225 (void) copyinstr(path, fs->fs_fsmnt, sizeof(fs->fs_fsmnt) - 1, &size);
226 bzero(fs->fs_fsmnt + size, sizeof(fs->fs_fsmnt) - size);
82161bc8
KM
227 bcopy((caddr_t)fs->fs_fsmnt, (caddr_t)mp->mnt_stat.f_mntonname,
228 MNAMELEN);
229 (void) copyinstr(args.fspec, mp->mnt_stat.f_mntfromname, MNAMELEN - 1,
230 &size);
231 bzero(mp->mnt_stat.f_mntfromname + size, MNAMELEN - size);
ab9f4fb0 232 (void)ffs_statfs(mp, &mp->mnt_stat, p);
7188ac27 233 return (0);
71e4e98b
SL
234}
235
a79eb26d
KM
236/*
237 * Reload all incore data for a filesystem (used after running fsck on
238 * the root filesystem and finding things to fix). The filesystem must
239 * be mounted read-only.
240 *
241 * Things to do to update the mount:
242 * 1) invalidate all cached meta-data.
243 * 2) re-read superblock from disk.
244 * 3) re-read summary information from disk.
245 * 4) invalidate all inactive vnodes.
246 * 5) invalidate all cached file data.
247 * 6) re-read inode data for all active vnodes.
248 */
249ffs_reload(mountp, cred, p)
250 register struct mount *mountp;
251 struct ucred *cred;
252 struct proc *p;
253{
254 register struct vnode *vp, *nvp, *devvp;
255 struct inode *ip;
a79eb26d
KM
256 struct csum *space;
257 struct buf *bp;
258 struct fs *fs;
259 int i, blks, size, error;
260
261 if ((mountp->mnt_flag & MNT_RDONLY) == 0)
262 return (EINVAL);
263 /*
264 * Step 1: invalidate all cached meta-data.
265 */
266 devvp = VFSTOUFS(mountp)->um_devvp;
646464db 267 if (vinvalbuf(devvp, 0, cred, p, 0, 0))
a79eb26d
KM
268 panic("ffs_reload: dirty1");
269 /*
270 * Step 2: re-read superblock from disk.
271 */
272 if (error = bread(devvp, SBLOCK, SBSIZE, NOCRED, &bp))
273 return (error);
dbb7672a 274 fs = (struct fs *)bp->b_data;
a79eb26d
KM
275 if (fs->fs_magic != FS_MAGIC || fs->fs_bsize > MAXBSIZE ||
276 fs->fs_bsize < sizeof(struct fs)) {
277 brelse(bp);
278 return (EIO); /* XXX needs translation */
279 }
280 fs = VFSTOUFS(mountp)->um_fs;
dbb7672a 281 bcopy(&fs->fs_csp[0], &((struct fs *)bp->b_data)->fs_csp[0],
a79eb26d 282 sizeof(fs->fs_csp));
dbb7672a 283 bcopy(bp->b_data, fs, (u_int)fs->fs_sbsize);
a79eb26d
KM
284 if (fs->fs_sbsize < SBSIZE)
285 bp->b_flags |= B_INVAL;
286 brelse(bp);
3c69c1a2 287 mountp->mnt_maxsymlinklen = fs->fs_maxsymlinklen;
a79eb26d
KM
288 ffs_oldfscompat(fs);
289 /*
290 * Step 3: re-read summary information from disk.
291 */
292 blks = howmany(fs->fs_cssize, fs->fs_fsize);
293 space = fs->fs_csp[0];
294 for (i = 0; i < blks; i += fs->fs_frag) {
295 size = fs->fs_bsize;
296 if (i + fs->fs_frag > blks)
297 size = (blks - i) * fs->fs_fsize;
298 if (error = bread(devvp, fsbtodb(fs, fs->fs_csaddr + i), size,
299 NOCRED, &bp))
300 return (error);
dbb7672a 301 bcopy(bp->b_data, fs->fs_csp[fragstoblks(fs, i)], (u_int)size);
a79eb26d
KM
302 brelse(bp);
303 }
304loop:
c3627aa8
KM
305 for (vp = mountp->mnt_vnodelist.lh_first; vp != NULL; vp = nvp) {
306 nvp = vp->v_mntvnodes.le_next;
a79eb26d
KM
307 /*
308 * Step 4: invalidate all inactive vnodes.
309 */
310 if (vp->v_usecount == 0) {
311 vgone(vp);
312 continue;
313 }
314 /*
315 * Step 5: invalidate all cached file data.
316 */
c3627aa8 317 if (vget(vp, 1))
a79eb26d 318 goto loop;
646464db 319 if (vinvalbuf(vp, 0, cred, p, 0, 0))
a79eb26d
KM
320 panic("ffs_reload: dirty2");
321 /*
322 * Step 6: re-read inode data for all active vnodes.
323 */
324 ip = VTOI(vp);
cf5ef508
KB
325 if (error =
326 bread(devvp, fsbtodb(fs, ino_to_fsba(fs, ip->i_number)),
a79eb26d
KM
327 (int)fs->fs_bsize, NOCRED, &bp)) {
328 vput(vp);
329 return (error);
330 }
cf5ef508
KB
331 ip->i_din = *((struct dinode *)bp->b_data +
332 ino_to_fsbo(fs, ip->i_number));
a79eb26d
KM
333 brelse(bp);
334 vput(vp);
335 if (vp->v_mount != mountp)
336 goto loop;
337 }
338 return (0);
339}
340
7188ac27
KM
341/*
342 * Common code for mount and mountroot
343 */
ab9f4fb0
KB
344int
345ffs_mountfs(devvp, mp, p)
1182ae61 346 register struct vnode *devvp;
7188ac27 347 struct mount *mp;
0eb6f54a 348 struct proc *p;
71e4e98b 349{
6b50a7c5
KM
350 register struct ufsmount *ump;
351 struct buf *bp;
71e4e98b 352 register struct fs *fs;
4867414f 353 dev_t dev;
ec67a3ce
MK
354 struct partinfo dpart;
355 int havepart = 0, blks;
27d00e76 356 caddr_t base, space;
7188ac27 357 int havepart = 0, blks;
2878f11c
KM
358 int error, i, size, ronly;
359 int32_t *lp;
4867414f 360 struct ucred *cred;
1c26e003 361 extern struct vnode *rootvp;
71e4e98b 362
4867414f
KM
363 dev = devvp->v_rdev;
364 cred = p ? p->p_ucred : NOCRED;
1feabdab 365 if (error = VOP_OPEN(devvp, ronly ? FREAD : FREAD|FWRITE, FSCRED, p))
7188ac27 366 return (error);
4867414f 367 if (VOP_IOCTL(devvp, DIOCGPART, (caddr_t)&dpart, FREAD, cred, p) != 0)
609e7cfa 368 size = DEV_BSIZE;
0eb6f54a 369 else {
ec67a3ce
MK
370 havepart = 1;
371 size = dpart.disklab->d_secsize;
7188ac27 372 }
6b50a7c5
KM
373
374 bp = NULL;
375 ump = NULL;
4867414f 376 if (error = bread(devvp, SBLOCK, SBSIZE, cred, &bp))
71e4e98b 377 goto out;
dbb7672a 378 fs = (struct fs *)bp->b_data;
8dc876c1 379 error = EINVAL; /* XXX needs translation */
1c281610
MK
380 goto out;
381 }
ab9f4fb0 382 ump = malloc(sizeof *ump, M_UFSMNT, M_WAITOK);
7bff53ea 383 bzero((caddr_t)ump, sizeof *ump);
b1ca3fbf 384 ump->um_fs = malloc((u_long)fs->fs_sbsize, M_UFSMNT,
5adcb337 385 M_WAITOK);
dbb7672a 386 bcopy(bp->b_data, ump->um_fs, (u_int)fs->fs_sbsize);
5d96a9ad
KM
387 if (fs->fs_sbsize < SBSIZE)
388 bp->b_flags |= B_INVAL;
e018935f
MK
389 brelse(bp);
390 bp = NULL;
7188ac27
KM
391 fs = ump->um_fs;
392 fs->fs_ronly = ronly;
71e4e98b
SL
393 if (ronly == 0)
394 fs->fs_fmod = 1;
ec67a3ce
MK
395#ifdef SECSIZE
396 /*
397 * If we have a disk label, force per-partition
398 * filesystem information to be correct
399 * and set correct current fsbtodb shift.
400 */
401#endif SECSIZE
402 if (havepart) {
403 dpart.part->p_fstype = FS_BSDFFS;
404 dpart.part->p_fsize = fs->fs_fsize;
405 dpart.part->p_frag = fs->fs_frag;
406#ifdef SECSIZE
407#ifdef tahoe
408 /*
409 * Save the original fsbtodb shift to restore on updates.
410 * (Console doesn't understand fsbtodb changes.)
411 */
412 fs->fs_sparecon[0] = fs->fs_fsbtodb;
413#endif
414 i = fs->fs_fsize / size;
415 for (fs->fs_fsbtodb = 0; i > 1; i >>= 1)
416 fs->fs_fsbtodb++;
417#endif SECSIZE
418 fs->fs_dbsize = size;
419 }
71e4e98b 420 blks = howmany(fs->fs_cssize, fs->fs_fsize);
2878f11c
KM
421 size = fs->fs_cssize;
422 if (fs->fs_contigsumsize > 0)
423 size += fs->fs_ncg * sizeof(int32_t);
424 base = space = malloc((u_long)size, M_UFSMNT, M_WAITOK);
71e4e98b
SL
425 for (i = 0; i < blks; i += fs->fs_frag) {
426 size = fs->fs_bsize;
427 if (i + fs->fs_frag > blks)
428 size = (blks - i) * fs->fs_fsize;
ec67a3ce
MK
429#ifdef SECSIZE
430 tp = bread(dev, fsbtodb(fs, fs->fs_csaddr + i), size,
431 fs->fs_dbsize);
432#else SECSIZE
4867414f
KM
433 if (error = bread(devvp, fsbtodb(fs, fs->fs_csaddr + i), size,
434 cred, &bp)) {
b1ca3fbf 435 free(base, M_UFSMNT);
71e4e98b
SL
436 goto out;
437 }
dbb7672a 438 bcopy(bp->b_data, space, (u_int)size);
60f9c9e3 439 fs->fs_csp[fragstoblks(fs, i)] = (struct csum *)space;
71e4e98b 440 space += size;
e018935f
MK
441 brelse(bp);
442 bp = NULL;
71e4e98b 443 }
2878f11c
KM
444 if (fs->fs_contigsumsize > 0) {
445 fs->fs_maxcluster = lp = (int32_t *)space;
446 for (i = 0; i < fs->fs_ncg; i++)
447 *lp++ = fs->fs_contigsumsize;
448 }
82161bc8
KM
449 mp->mnt_data = (qaddr_t)ump;
450 mp->mnt_stat.f_fsid.val[0] = (long)dev;
451 mp->mnt_stat.f_fsid.val[1] = MOUNT_UFS;
ea301039 452 mp->mnt_maxsymlinklen = fs->fs_maxsymlinklen;
82161bc8 453 mp->mnt_flag |= MNT_LOCAL;
7188ac27
KM
454 ump->um_mountp = mp;
455 ump->um_dev = dev;
456 ump->um_devvp = devvp;
3614593e
MS
457 ump->um_nindir = fs->fs_nindir;
458 ump->um_bptrtodb = fs->fs_fsbtodb;
459 ump->um_seqinc = fs->fs_frag;
8dc876c1
KM
460 for (i = 0; i < MAXQUOTAS; i++)
461 ump->um_quotas[i] = NULLVP;
0f93ba7b 462 devvp->v_specflags |= SI_MOUNTEDON;
a79eb26d 463 ffs_oldfscompat(fs);
2878f11c
KM
464 ump->um_savedmaxfilesize = fs->fs_maxfilesize; /* XXX */
465 if (fs->fs_maxfilesize > (quad_t)1 << 39) /* XXX */
466 fs->fs_maxfilesize = (quad_t)1 << 39; /* XXX */
a79eb26d
KM
467 return (0);
468out:
469 if (bp)
470 brelse(bp);
4867414f 471 (void)VOP_CLOSE(devvp, ronly ? FREAD : FREAD|FWRITE, cred, p);
a79eb26d
KM
472 if (ump) {
473 free(ump->um_fs, M_UFSMNT);
474 free(ump, M_UFSMNT);
475 mp->mnt_data = (qaddr_t)0;
476 }
477 return (error);
478}
479
480/*
481 * Sanity checks for old file systems.
482 *
483 * XXX - goes away some day.
484 */
485ffs_oldfscompat(fs)
486 struct fs *fs;
487{
488 int i;
7188ac27 489
2a4eff84
JSP
490 fs->fs_npsect = max(fs->fs_npsect, fs->fs_nsect); /* XXX */
491 fs->fs_interleave = max(fs->fs_interleave, 1); /* XXX */
2af59000
KM
492 if (fs->fs_postblformat == FS_42POSTBLFMT) /* XXX */
493 fs->fs_nrpos = 8; /* XXX */
4605fb61
KM
494 if (fs->fs_inodefmt < FS_44INODEFMT) { /* XXX */
495 quad_t sizepb = fs->fs_bsize; /* XXX */
496 /* XXX */
497 fs->fs_maxfilesize = fs->fs_bsize * NDADDR - 1; /* XXX */
498 for (i = 0; i < NIADDR; i++) { /* XXX */
499 sizepb *= NINDIR(fs); /* XXX */
500 fs->fs_maxfilesize += sizepb; /* XXX */
501 } /* XXX */
502 fs->fs_qbmask = ~fs->fs_bmask; /* XXX */
503 fs->fs_qfmask = ~fs->fs_fmask; /* XXX */
504 } /* XXX */
609e7cfa 505
7188ac27 506 return (0);
71e4e98b
SL
507}
508
7188ac27
KM
509/*
510 * unmount system call
511 */
ab9f4fb0
KB
512int
513ffs_unmount(mp, mntflags, p)
7188ac27 514 struct mount *mp;
8dc876c1 515 int mntflags;
0eb6f54a 516 struct proc *p;
71e4e98b 517{
7188ac27 518 register struct ufsmount *ump;
71e4e98b 519 register struct fs *fs;
de022b87 520 int error, flags;
71e4e98b 521
6b50a7c5 522 flags = 0;
87be6db2 523 if (mntflags & MNT_FORCE) {
c3627aa8 524 if (mp->mnt_flag & MNT_ROOTFS)
87be6db2 525 return (EINVAL);
8dc876c1 526 flags |= FORCECLOSE;
87be6db2 527 }
a79eb26d
KM
528 if (error = ffs_flushfiles(mp, flags, p))
529 return (error);
530 ump = VFSTOUFS(mp);
531 fs = ump->um_fs;
a79eb26d 532 ump->um_devvp->v_specflags &= ~SI_MOUNTEDON;
de022b87 533 error = VOP_CLOSE(ump->um_devvp, fs->fs_ronly ? FREAD : FREAD|FWRITE,
a79eb26d
KM
534 NOCRED, p);
535 vrele(ump->um_devvp);
536 free(fs->fs_csp[0], M_UFSMNT);
537 free(fs, M_UFSMNT);
538 free(ump, M_UFSMNT);
539 mp->mnt_data = (qaddr_t)0;
540 mp->mnt_flag &= ~MNT_LOCAL;
541 return (error);
542}
543
544/*
545 * Flush out all the files in a filesystem.
546 */
547ffs_flushfiles(mp, flags, p)
548 register struct mount *mp;
549 int flags;
550 struct proc *p;
551{
552 extern int doforce;
553 register struct ufsmount *ump;
554 int i, error;
555
556 if (!doforce)
557 flags &= ~FORCECLOSE;
7188ac27 558 ump = VFSTOUFS(mp);
ec67a3ce 559 return (error);
71e4e98b 560#ifdef QUOTA
82161bc8 561 if (mp->mnt_flag & MNT_QUOTA) {
8dc876c1 562 if (error = vflush(mp, NULLVP, SKIPSYSTEM|flags))
6d943995 563 return (error);
8dc876c1
KM
564 for (i = 0; i < MAXQUOTAS; i++) {
565 if (ump->um_quotas[i] == NULLVP)
566 continue;
70a360ba 567 quotaoff(p, mp, i);
8dc876c1 568 }
6d943995 569 /*
8dc876c1
KM
570 * Here we fall through to vflush again to ensure
571 * that we have gotten rid of all the system vnodes.
6d943995 572 */
8dc876c1 573 }
71e4e98b 574#endif
7188ac27
KM
575 * Get file system statistics.
576 */
ab9f4fb0
KB
577int
578ffs_statfs(mp, sbp, p)
7188ac27
KM
579 struct mount *mp;
580 register struct statfs *sbp;
0eb6f54a 581 struct proc *p;
7188ac27
KM
582{
583 register struct ufsmount *ump;
584 register struct fs *fs;
585
586 ump = VFSTOUFS(mp);
587 fs = ump->um_fs;
588 if (fs->fs_magic != FS_MAGIC)
ab9f4fb0 589 panic("ffs_statfs");
7188ac27 590 sbp->f_type = MOUNT_UFS;
06445aba
KM
591 sbp->f_bsize = fs->fs_fsize;
592 sbp->f_iosize = fs->fs_bsize;
7188ac27
KM
593 sbp->f_blocks = fs->fs_dsize;
594 sbp->f_bfree = fs->fs_cstotal.cs_nbfree * fs->fs_frag +
595 fs->fs_cstotal.cs_nffree;
596 sbp->f_bavail = (fs->fs_dsize * (100 - fs->fs_minfree) / 100) -
597 (fs->fs_dsize - sbp->f_bfree);
5c41c19e 598 sbp->f_files = fs->fs_ncg * fs->fs_ipg - ROOTINO;
7188ac27 599 sbp->f_ffree = fs->fs_cstotal.cs_nifree;
82161bc8
KM
600 if (sbp != &mp->mnt_stat) {
601 bcopy((caddr_t)mp->mnt_stat.f_mntonname,
d45de50d 602 (caddr_t)&sbp->f_mntonname[0], MNAMELEN);
82161bc8 603 bcopy((caddr_t)mp->mnt_stat.f_mntfromname,
d45de50d
KM
604 (caddr_t)&sbp->f_mntfromname[0], MNAMELEN);
605 }
7188ac27
KM
606 return (0);
607}
608
7188ac27
KM
609/*
610 * Go through the disk queues to initiate sandbagged IO;
611 * go through the inodes to write those that have been modified;
612 * initiate the writing of the super block if it has been modified.
8dc876c1
KM
613 *
614 * Note: we are always called with the filesystem marked `MPBUSY'.
7188ac27 615 */
ab9f4fb0 616int
6b50a7c5 617ffs_sync(mp, waitfor, cred, p)
71e4e98b 618 struct mount *mp;
7188ac27 619 int waitfor;
6b50a7c5
KM
620 struct ucred *cred;
621 struct proc *p;
71e4e98b 622{
31593ba7 623 register struct vnode *vp;
7188ac27
KM
624 register struct inode *ip;
625 register struct ufsmount *ump = VFSTOUFS(mp);
626 register struct fs *fs;
812b91f3 627 int error, allerror = 0;
7188ac27 628
7188ac27 629 fs = ump->um_fs;
7188ac27
KM
630 /*
631 * Write back modified superblock.
632 * Consistency check that the superblock
633 * is still in the buffer cache.
634 */
635 if (fs->fs_fmod != 0) {
636 if (fs->fs_ronly != 0) { /* XXX */
637 printf("fs = %s\n", fs->fs_fsmnt);
638 panic("update: rofs mod");
639 }
640 fs->fs_fmod = 0;
641 fs->fs_time = time.tv_sec;
ab9f4fb0 642 allerror = ffs_sbupdate(ump, waitfor);
7188ac27
KM
643 }
644 /*
645 * Write back each (modified) inode.
646 */
25b5cf58 647loop:
c3627aa8
KM
648 for (vp = mp->mnt_vnodelist.lh_first;
649 vp != NULL;
650 vp = vp->v_mntvnodes.le_next) {
a242f429
KM
651 /*
652 * If the vnode that we are about to sync is no longer
653 * associated with this mount point, start over.
654 */
655 if (vp->v_mount != mp)
656 goto loop;
d85a9d1b
KM
657 if (VOP_ISLOCKED(vp))
658 continue;
31593ba7 659 ip = VTOI(vp);
dbb7672a 660 if ((ip->i_flag &
cf5ef508 661 (IN_ACCESS | IN_CHANGE | IN_MODIFIED | IN_UPDATE)) == 0 &&
c3627aa8 662 vp->v_dirtyblkhd.lh_first == NULL)
7188ac27 663 continue;
c3627aa8 664 if (vget(vp, 1))
25b5cf58 665 goto loop;
6b50a7c5 666 if (error = VOP_FSYNC(vp, cred, waitfor, p))
812b91f3
KM
667 allerror = error;
668 vput(vp);
7188ac27 669 }
7188ac27 670 /*
5d96a9ad 671 * Force stale file system control information to be flushed.
7188ac27 672 */
6b50a7c5
KM
673 if (error = VOP_FSYNC(ump->um_devvp, cred, waitfor, p))
674 allerror = error;
8dc876c1
KM
675#ifdef QUOTA
676 qsync(mp);
677#endif
812b91f3 678 return (allerror);
7188ac27
KM
679}
680
067ae075 681/*
cf5ef508
KB
682 * Look up a FFS dinode number to find its incore vnode, otherwise read it
683 * in from disk. If it is in core, wait for the lock bit to clear, then
684 * return the inode locked. Detection and handling of mount points must be
685 * done by the calling routine.
067ae075
KM
686 */
687int
688ffs_vget(mp, ino, vpp)
689 struct mount *mp;
690 ino_t ino;
691 struct vnode **vpp;
692{
693 register struct fs *fs;
694 register struct inode *ip;
695 struct ufsmount *ump;
696 struct buf *bp;
067ae075 697 struct vnode *vp;
067ae075
KM
698 dev_t dev;
699 int i, type, error;
700
701 ump = VFSTOUFS(mp);
702 dev = ump->um_dev;
703 if ((*vpp = ufs_ihashget(dev, ino)) != NULL)
704 return (0);
705
706 /* Allocate a new vnode/inode. */
707 if (error = getnewvnode(VT_UFS, mp, ffs_vnodeop_p, &vp)) {
708 *vpp = NULL;
709 return (error);
710 }
711 type = ump->um_devvp->v_tag == VT_MFS ? M_MFSNODE : M_FFSNODE; /* XXX */
712 MALLOC(ip, struct inode *, sizeof(struct inode), type, M_WAITOK);
bd620aaa 713 bzero((caddr_t)ip, sizeof(struct inode));
067ae075
KM
714 vp->v_data = ip;
715 ip->i_vnode = vp;
067ae075
KM
716 ip->i_fs = fs = ump->um_fs;
717 ip->i_dev = dev;
718 ip->i_number = ino;
719#ifdef QUOTA
720 for (i = 0; i < MAXQUOTAS; i++)
721 ip->i_dquot[i] = NODQUOT;
722#endif
723 /*
724 * Put it onto its hash chain and lock it so that other requests for
725 * this inode will block if they arrive while we are sleeping waiting
726 * for old data structures to be purged or for the contents of the
727 * disk portion of this inode to be read.
728 */
729 ufs_ihashins(ip);
730
731 /* Read in the disk contents for the inode, copy into the inode. */
cf5ef508 732 if (error = bread(ump->um_devvp, fsbtodb(fs, ino_to_fsba(fs, ino)),
067ae075
KM
733 (int)fs->fs_bsize, NOCRED, &bp)) {
734 /*
735 * The inode does not contain anything useful, so it would
bd620aaa
KM
736 * be misleading to leave it on its hash chain. With mode
737 * still zero, it will be unlinked and returned to the free
738 * list by vput().
067ae075 739 */
e51f387e 740 vput(vp);
067ae075
KM
741 brelse(bp);
742 *vpp = NULL;
743 return (error);
744 }
cf5ef508 745 ip->i_din = *((struct dinode *)bp->b_data + ino_to_fsbo(fs, ino));
067ae075
KM
746 brelse(bp);
747
748 /*
749 * Initialize the vnode from the inode, check for aliases.
750 * Note that the underlying vnode may have changed.
751 */
752 if (error = ufs_vinit(mp, ffs_specop_p, FFS_FIFOOPS, &vp)) {
e51f387e 753 vput(vp);
067ae075
KM
754 *vpp = NULL;
755 return (error);
756 }
757 /*
758 * Finish inode initialization now that aliasing has been resolved.
759 */
760 ip->i_devvp = ump->um_devvp;
761 VREF(ip->i_devvp);
762 /*
763 * Set up a generation number for this inode if it does not
764 * already have one. This should only happen on old filesystems.
765 */
766 if (ip->i_gen == 0) {
767 if (++nextgennumber < (u_long)time.tv_sec)
768 nextgennumber = time.tv_sec;
769 ip->i_gen = nextgennumber;
770 if ((vp->v_mount->mnt_flag & MNT_RDONLY) == 0)
cf5ef508 771 ip->i_flag |= IN_MODIFIED;
067ae075
KM
772 }
773 /*
774 * Ensure that uid and gid are correct. This is a temporary
775 * fix until fsck has been changed to do the update.
776 */
777 if (fs->fs_inodefmt < FS_44INODEFMT) { /* XXX */
778 ip->i_uid = ip->i_din.di_ouid; /* XXX */
779 ip->i_gid = ip->i_din.di_ogid; /* XXX */
780 } /* XXX */
781
782 *vpp = vp;
783 return (0);
784}
785
a9013e03
KM
786/*
787 * File handle to vnode
788 *
789 * Have to be really careful about stale file handles:
790 * - check that the inode number is valid
791 * - call ffs_vget() to get the locked inode
792 * - check for an unallocated inode (i_mode == 0)
03f3a6e4
KM
793 * - check that the given client host has export rights and return
794 * those rights via. exflagsp and credanonp
a9013e03
KM
795 */
796int
03f3a6e4 797ffs_fhtovp(mp, fhp, nam, vpp, exflagsp, credanonp)
a9013e03
KM
798 register struct mount *mp;
799 struct fid *fhp;
03f3a6e4 800 struct mbuf *nam;
a9013e03 801 struct vnode **vpp;
03f3a6e4
KM
802 int *exflagsp;
803 struct ucred **credanonp;
a9013e03 804{
a9013e03
KM
805 register struct ufid *ufhp;
806 struct fs *fs;
a9013e03
KM
807
808 ufhp = (struct ufid *)fhp;
9e4a3a4a 809 fs = VFSTOUFS(mp)->um_fs;
a9013e03
KM
810 if (ufhp->ufid_ino < ROOTINO ||
811 ufhp->ufid_ino >= fs->fs_ncg * fs->fs_ipg)
03f3a6e4 812 return (ESTALE);
485cf2ee 813 return (ufs_check_export(mp, ufhp, nam, vpp, exflagsp, credanonp));
a9013e03
KM
814}
815
816/*
817 * Vnode pointer to File handle
818 */
819/* ARGSUSED */
820ffs_vptofh(vp, fhp)
821 struct vnode *vp;
822 struct fid *fhp;
823{
824 register struct inode *ip;
825 register struct ufid *ufhp;
826
827 ip = VTOI(vp);
828 ufhp = (struct ufid *)fhp;
829 ufhp->ufid_len = sizeof(struct ufid);
830 ufhp->ufid_ino = ip->i_number;
831 ufhp->ufid_gen = ip->i_gen;
832 return (0);
833}
834
7188ac27
KM
835/*
836 * Write a superblock and associated information back to disk.
837 */
06445aba 838int
ab9f4fb0 839ffs_sbupdate(mp, waitfor)
7188ac27
KM
840 struct ufsmount *mp;
841 int waitfor;
842{
2878f11c 843 register struct fs *dfs, *fs = mp->um_fs;
71e4e98b
SL
844 register struct buf *bp;
845 int blks;
846 caddr_t space;
7188ac27 847 int i, size, error = 0;
71e4e98b 848
ec67a3ce
MK
849#ifdef SECSIZE
850 bp = getblk(mp->m_dev, (daddr_t)fsbtodb(fs, SBOFF / fs->fs_fsize),
851 (int)fs->fs_sbsize, fs->fs_dbsize);
852#else SECSIZE
646464db 853 bp = getblk(mp->um_devvp, SBLOCK, (int)fs->fs_sbsize, 0, 0);
ec67a3ce 854#endif SECSIZE
dbb7672a 855 bcopy((caddr_t)fs, bp->b_data, (u_int)fs->fs_sbsize);
2af59000 856 /* Restore compatibility to old file systems. XXX */
2878f11c 857 dfs = (struct fs *)bp->b_data; /* XXX */
2af59000 858 if (fs->fs_postblformat == FS_42POSTBLFMT) /* XXX */
2878f11c 859 dfs->fs_nrpos = -1; /* XXX */
5eb4cbda
MKM
860 if (fs->fs_inodefmt < FS_44INODEFMT) { /* XXX */
861 long *lp, tmp; /* XXX */
862 /* XXX */
2878f11c 863 lp = (long *)&dfs->fs_qbmask; /* XXX */
5eb4cbda
MKM
864 tmp = lp[4]; /* XXX */
865 for (i = 4; i > 0; i--) /* XXX */
866 lp[i] = lp[i-1]; /* XXX */
867 lp[0] = tmp; /* XXX */
868 } /* XXX */
2878f11c 869 dfs->fs_maxfilesize = mp->um_savedmaxfilesize; /* XXX */
ec67a3ce
MK
870#ifdef SECSIZE
871#ifdef tahoe
872 /* restore standard fsbtodb shift */
873 bp->b_un.b_fs->fs_fsbtodb = fs->fs_sparecon[0];
874 bp->b_un.b_fs->fs_sparecon[0] = 0;
875#endif
876#endif SECSIZE
7188ac27
KM
877 if (waitfor == MNT_WAIT)
878 error = bwrite(bp);
879 else
880 bawrite(bp);
71e4e98b
SL
881 blks = howmany(fs->fs_cssize, fs->fs_fsize);
882 space = (caddr_t)fs->fs_csp[0];
883 for (i = 0; i < blks; i += fs->fs_frag) {
884 size = fs->fs_bsize;
885 if (i + fs->fs_frag > blks)
886 size = (blks - i) * fs->fs_fsize;
ec67a3ce
MK
887#ifdef SECSIZE
888 bp = getblk(mp->m_dev, fsbtodb(fs, fs->fs_csaddr + i), size,
889 fs->fs_dbsize);
890#else SECSIZE
646464db
KM
891 bp = getblk(mp->um_devvp, fsbtodb(fs, fs->fs_csaddr + i),
892 size, 0, 0);
ec67a3ce 893#endif SECSIZE
dbb7672a 894 bcopy(space, bp->b_data, (u_int)size);
71e4e98b 895 space += size;
7188ac27
KM
896 if (waitfor == MNT_WAIT)
897 error = bwrite(bp);
898 else
899 bawrite(bp);
71e4e98b 900 }
7188ac27 901 return (error);
71e4e98b 902}