123400Smckusick /*
266805Sbostic * Copyright (c) 1989, 1991, 1993, 1994
363375Sbostic * The Regents of the University of California. All rights reserved.
423400Smckusick *
544539Sbostic * %sccs.include.redist.c%
637737Smckusick *
7*69813Smargo * @(#)lfs_vfsops.c 8.20 (Berkeley) 06/10/95
823400Smckusick */
912795Ssam
1051483Sbostic #include <sys/param.h>
1151483Sbostic #include <sys/systm.h>
1251483Sbostic #include <sys/namei.h>
1351483Sbostic #include <sys/proc.h>
1451483Sbostic #include <sys/kernel.h>
1551483Sbostic #include <sys/vnode.h>
1651483Sbostic #include <sys/mount.h>
1751483Sbostic #include <sys/buf.h>
1854734Smckusick #include <sys/mbuf.h>
1951483Sbostic #include <sys/file.h>
2051483Sbostic #include <sys/disklabel.h>
2151483Sbostic #include <sys/ioctl.h>
2251483Sbostic #include <sys/errno.h>
2351483Sbostic #include <sys/malloc.h>
2454734Smckusick #include <sys/socket.h>
2512795Ssam
2655047Smckusick #include <miscfs/specfs/specdev.h>
2755047Smckusick
2851501Sbostic #include <ufs/ufs/quota.h>
2951501Sbostic #include <ufs/ufs/inode.h>
3051501Sbostic #include <ufs/ufs/ufsmount.h>
3151501Sbostic #include <ufs/ufs/ufs_extern.h>
3247571Skarels
3351501Sbostic #include <ufs/lfs/lfs.h>
3451501Sbostic #include <ufs/lfs/lfs_extern.h>
3551155Sbostic
3651991Sbostic int lfs_mountfs __P((struct vnode *, struct mount *, struct proc *));
3751215Sbostic
3851155Sbostic struct vfsops lfs_vfsops = {
3951155Sbostic lfs_mount,
4039043Smckusick ufs_start,
4151155Sbostic lfs_unmount,
4266805Sbostic ufs_root,
4341314Smckusick ufs_quotactl,
4451155Sbostic lfs_statfs,
4551155Sbostic lfs_sync,
4654693Sbostic lfs_vget,
4751559Smckusick lfs_fhtovp,
4851559Smckusick lfs_vptofh,
4951483Sbostic lfs_init,
5068676Smckusick lfs_sysctl,
5137737Smckusick };
5237737Smckusick
5369369Smckusick /*
5469369Smckusick * Called by main() when ufs is going to be mounted as root.
5569369Smckusick */
lfs_mountroot()5651155Sbostic lfs_mountroot()
5712795Ssam {
5869369Smckusick extern struct vnode *rootvp;
5969369Smckusick struct fs *fs;
6069369Smckusick struct mount *mp;
6169369Smckusick struct proc *p = curproc; /* XXX */
6269369Smckusick int error;
6369369Smckusick
6469369Smckusick /*
6569369Smckusick * Get vnodes for swapdev and rootdev.
6669369Smckusick */
6769373Smckusick if ((error = bdevvp(swapdev, &swapdev_vp)) ||
6869373Smckusick (error = bdevvp(rootdev, &rootvp))) {
6969373Smckusick printf("lfs_mountroot: can't setup bdevvp's");
7069373Smckusick return (error);
7169373Smckusick }
7269369Smckusick if (error = vfs_rootmountalloc("lfs", "root_device", &mp))
7369369Smckusick return (error);
7469369Smckusick if (error = lfs_mountfs(rootvp, mp, p)) {
7569369Smckusick mp->mnt_vfc->vfc_refcount--;
7669582Smckusick vfs_unbusy(mp, p);
7769369Smckusick free(mp, M_MOUNT);
7869369Smckusick return (error);
7969369Smckusick }
8069582Smckusick simple_lock(&mountlist_slock);
8169369Smckusick CIRCLEQ_INSERT_TAIL(&mountlist, mp, mnt_list);
8269582Smckusick simple_unlock(&mountlist_slock);
8369369Smckusick (void)lfs_statfs(mp, &mp->mnt_stat, p);
8469582Smckusick vfs_unbusy(mp, p);
8569369Smckusick return (0);
8637737Smckusick }
8737737Smckusick
8837737Smckusick /*
8937737Smckusick * VFS Operations.
9037737Smckusick *
9137737Smckusick * mount system call
9237737Smckusick */
lfs_mount(mp,path,data,ndp,p)9351155Sbostic lfs_mount(mp, path, data, ndp, p)
9440346Smckusick register struct mount *mp;
9537737Smckusick char *path;
9637737Smckusick caddr_t data;
9737737Smckusick struct nameidata *ndp;
9848036Smckusick struct proc *p;
9937737Smckusick {
10037737Smckusick struct vnode *devvp;
10137737Smckusick struct ufs_args args;
10237737Smckusick struct ufsmount *ump;
10351501Sbostic register struct lfs *fs; /* LFS */
10437737Smckusick u_int size;
10537737Smckusick int error;
10667533Smckusick mode_t accessmode;
10737737Smckusick
10837737Smckusick if (error = copyin(data, (caddr_t)&args, sizeof (struct ufs_args)))
10937737Smckusick return (error);
11051483Sbostic
11151483Sbostic /* Until LFS can do NFS right. XXX */
11265674Shibler if (args.export.ex_flags & MNT_EXPORTED)
11351483Sbostic return (EINVAL);
11465674Shibler
11540371Smckusick /*
11650264Skarels * If updating, check whether changing from read-only to
11750264Skarels * read/write; if there is no device name, that's all we do.
11850264Skarels */
11950264Skarels if (mp->mnt_flag & MNT_UPDATE) {
12039336Smckusick ump = VFSTOUFS(mp);
12167533Smckusick if (fs->lfs_ronly && (mp->mnt_flag & MNT_WANTRDWR)) {
12267533Smckusick /*
12367533Smckusick * If upgrade to read-write by non-root, then verify
12467533Smckusick * that user has necessary permissions on the device.
12567533Smckusick */
12667533Smckusick if (p->p_ucred->cr_uid != 0) {
12769421Smckusick vn_lock(ump->um_devvp, LK_EXCLUSIVE | LK_RETRY,
12869421Smckusick p);
12967533Smckusick if (error = VOP_ACCESS(ump->um_devvp,
13067533Smckusick VREAD | VWRITE, p->p_ucred, p)) {
13169421Smckusick VOP_UNLOCK(ump->um_devvp, 0, p);
13267533Smckusick return (error);
13367533Smckusick }
13469421Smckusick VOP_UNLOCK(ump->um_devvp, 0, p);
13567533Smckusick }
13651155Sbostic fs->lfs_ronly = 0;
13767533Smckusick }
13852175Smckusick if (args.fspec == 0) {
13952175Smckusick /*
14052175Smckusick * Process export requests.
14152175Smckusick */
14265674Shibler return (vfs_export(mp, &ump->um_export, &args.export));
14352175Smckusick }
14450264Skarels }
14550264Skarels /*
14650264Skarels * Not an update, or updating the name: look up the name
14750264Skarels * and verify that it refers to a sensible block device.
14850264Skarels */
14952333Smckusick NDINIT(ndp, LOOKUP, FOLLOW, UIO_USERSPACE, args.fspec, p);
15052333Smckusick if (error = namei(ndp))
15150264Skarels return (error);
15250264Skarels devvp = ndp->ni_vp;
15350264Skarels if (devvp->v_type != VBLK) {
15450264Skarels vrele(devvp);
15550264Skarels return (ENOTBLK);
15650264Skarels }
15750264Skarels if (major(devvp->v_rdev) >= nblkdev) {
15850264Skarels vrele(devvp);
15950264Skarels return (ENXIO);
16050264Skarels }
16167533Smckusick /*
16267533Smckusick * If mount by non-root, then verify that user has necessary
16367533Smckusick * permissions on the device.
16467533Smckusick */
16567533Smckusick if (p->p_ucred->cr_uid != 0) {
16667533Smckusick accessmode = VREAD;
16767533Smckusick if ((mp->mnt_flag & MNT_RDONLY) == 0)
16867533Smckusick accessmode |= VWRITE;
16969421Smckusick vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY, p);
17067533Smckusick if (error = VOP_ACCESS(devvp, accessmode, p->p_ucred, p)) {
17167533Smckusick vput(devvp);
17267533Smckusick return (error);
17367533Smckusick }
17469421Smckusick VOP_UNLOCK(devvp, 0, p);
17567533Smckusick }
17650264Skarels if ((mp->mnt_flag & MNT_UPDATE) == 0)
17751155Sbostic error = lfs_mountfs(devvp, mp, p); /* LFS */
17850264Skarels else {
17939336Smckusick if (devvp != ump->um_devvp)
18039336Smckusick error = EINVAL; /* needs translation */
18142858Smckusick else
18242858Smckusick vrele(devvp);
18339336Smckusick }
18437737Smckusick if (error) {
18537737Smckusick vrele(devvp);
18637737Smckusick return (error);
18732721Smckusick }
18837737Smckusick ump = VFSTOUFS(mp);
18951155Sbostic fs = ump->um_lfs; /* LFS */
19051155Sbostic #ifdef NOTLFS /* LFS */
19137737Smckusick (void) copyinstr(path, fs->fs_fsmnt, sizeof(fs->fs_fsmnt) - 1, &size);
19237737Smckusick bzero(fs->fs_fsmnt + size, sizeof(fs->fs_fsmnt) - size);
19341397Smckusick bcopy((caddr_t)fs->fs_fsmnt, (caddr_t)mp->mnt_stat.f_mntonname,
19441397Smckusick MNAMELEN);
19551991Sbostic (void) copyinstr(args.fspec, mp->mnt_stat.f_mntfromname, MNAMELEN - 1,
19641397Smckusick &size);
19741397Smckusick bzero(mp->mnt_stat.f_mntfromname + size, MNAMELEN - size);
19848036Smckusick (void) ufs_statfs(mp, &mp->mnt_stat, p);
19951155Sbostic #else
20051155Sbostic (void)copyinstr(path, fs->lfs_fsmnt, sizeof(fs->lfs_fsmnt) - 1, &size);
20151155Sbostic bzero(fs->lfs_fsmnt + size, sizeof(fs->lfs_fsmnt) - size);
20251155Sbostic bcopy((caddr_t)fs->lfs_fsmnt, (caddr_t)mp->mnt_stat.f_mntonname,
20351155Sbostic MNAMELEN);
20451991Sbostic (void) copyinstr(args.fspec, mp->mnt_stat.f_mntfromname, MNAMELEN - 1,
20551155Sbostic &size);
20651155Sbostic bzero(mp->mnt_stat.f_mntfromname + size, MNAMELEN - size);
20751155Sbostic (void) lfs_statfs(mp, &mp->mnt_stat, p);
20851155Sbostic #endif
20937737Smckusick return (0);
21012795Ssam }
21112795Ssam
21237737Smckusick /*
21337737Smckusick * Common code for mount and mountroot
21451155Sbostic * LFS specific
21537737Smckusick */
21651991Sbostic int
lfs_mountfs(devvp,mp,p)21751155Sbostic lfs_mountfs(devvp, mp, p)
21840376Smckusick register struct vnode *devvp;
21937737Smckusick struct mount *mp;
22048036Smckusick struct proc *p;
22112795Ssam {
22251155Sbostic extern struct vnode *rootvp;
22351501Sbostic register struct lfs *fs;
22451155Sbostic register struct ufsmount *ump;
22551155Sbostic struct vnode *vp;
22651155Sbostic struct buf *bp;
22730749Skarels struct partinfo dpart;
22851155Sbostic dev_t dev;
22951155Sbostic int error, i, ronly, size;
23067949Smckusick struct ucred *cred;
23112795Ssam
23267949Smckusick cred = p ? p->p_ucred : NOCRED;
23340376Smckusick /*
23440376Smckusick * Disallow multiple mounts of the same device.
23545652Smckusick * Disallow mounting of a device that is currently in use
23645652Smckusick * (except for root, which might share swap device for miniroot).
23740376Smckusick * Flush out any old buffers remaining from a previous use.
23840376Smckusick */
23965674Shibler if (error = vfs_mountedon(devvp))
24040376Smckusick return (error);
24145652Smckusick if (vcount(devvp) > 1 && devvp != rootvp)
24240376Smckusick return (EBUSY);
24367949Smckusick if (error = vinvalbuf(devvp, V_SAVE, cred, p, 0, 0))
24454693Sbostic return (error);
24551155Sbostic
24651155Sbostic ronly = (mp->mnt_flag & MNT_RDONLY) != 0;
24759473Smckusick if (error = VOP_OPEN(devvp, ronly ? FREAD : FREAD|FWRITE, FSCRED, p))
24837737Smckusick return (error);
24951155Sbostic
25067949Smckusick if (VOP_IOCTL(devvp, DIOCGPART, (caddr_t)&dpart, FREAD, cred, p) != 0)
25137737Smckusick size = DEV_BSIZE;
25248036Smckusick else {
25330749Skarels size = dpart.disklab->d_secsize;
25451155Sbostic #ifdef NEVER_USED
25551155Sbostic dpart.part->p_fstype = FS_LFS;
25651155Sbostic dpart.part->p_fsize = fs->lfs_fsize; /* frag size */
25751155Sbostic dpart.part->p_frag = fs->lfs_frag; /* frags per block */
25851155Sbostic dpart.part->p_cpg = fs->lfs_segshift; /* segment shift */
25951155Sbostic #endif
26037737Smckusick }
26151155Sbostic
26251155Sbostic /* Don't free random space on error. */
26351155Sbostic bp = NULL;
26451155Sbostic ump = NULL;
26551155Sbostic
26651155Sbostic /* Read in the superblock. */
26767949Smckusick if (error = bread(devvp, LFS_LABELPAD / size, LFS_SBPAD, cred, &bp))
26812795Ssam goto out;
26964523Sbostic fs = (struct lfs *)bp->b_data;
27051155Sbostic
27151155Sbostic /* Check the basics. */
27251155Sbostic if (fs->lfs_magic != LFS_MAGIC || fs->lfs_bsize > MAXBSIZE ||
27351501Sbostic fs->lfs_bsize < sizeof(struct lfs)) {
27441314Smckusick error = EINVAL; /* XXX needs translation */
27516639Skarels goto out;
27616639Skarels }
27751155Sbostic
27851155Sbostic /* Allocate the mount structure, copy the superblock into it. */
27941314Smckusick ump = (struct ufsmount *)malloc(sizeof *ump, M_UFSMNT, M_WAITOK);
28055548Sbostic fs = ump->um_lfs = malloc(sizeof(struct lfs), M_UFSMNT, M_WAITOK);
28164523Sbostic bcopy(bp->b_data, fs, sizeof(struct lfs));
28251501Sbostic if (sizeof(struct lfs) < LFS_SBPAD) /* XXX why? */
28339675Smckusick bp->b_flags |= B_INVAL;
28434421Skarels brelse(bp);
28534421Skarels bp = NULL;
28651155Sbostic
28751183Sbostic /* Set up the I/O information */
28851183Sbostic fs->lfs_iocount = 0;
28951183Sbostic
29055548Sbostic /* Set up the ifile and lock aflags */
29154264Sbostic fs->lfs_doifile = 0;
29254264Sbostic fs->lfs_writer = 0;
29354264Sbostic fs->lfs_dirops = 0;
29455548Sbostic fs->lfs_seglock = 0;
29554264Sbostic
29651155Sbostic /* Set the file system readonly/modify bits. */
29751155Sbostic fs->lfs_ronly = ronly;
29812795Ssam if (ronly == 0)
29951155Sbostic fs->lfs_fmod = 1;
30051155Sbostic
30151155Sbostic /* Initialize the mount structure. */
30251155Sbostic dev = devvp->v_rdev;
30341397Smckusick mp->mnt_data = (qaddr_t)ump;
30441397Smckusick mp->mnt_stat.f_fsid.val[0] = (long)dev;
30568676Smckusick mp->mnt_stat.f_fsid.val[1] = lfs_mount_type;
30667395Smkm mp->mnt_maxsymlinklen = fs->lfs_maxsymlinklen;
30741397Smckusick mp->mnt_flag |= MNT_LOCAL;
30837737Smckusick ump->um_mountp = mp;
30937737Smckusick ump->um_dev = dev;
31037737Smckusick ump->um_devvp = devvp;
31156475Smargo ump->um_bptrtodb = 0;
31256475Smargo ump->um_seqinc = 1 << fs->lfs_fsbtodb;
31356475Smargo ump->um_nindir = fs->lfs_nindir;
31441314Smckusick for (i = 0; i < MAXQUOTAS; i++)
31541314Smckusick ump->um_quotas[i] = NULLVP;
31652221Sbostic devvp->v_specflags |= SI_MOUNTEDON;
31751155Sbostic
31852221Sbostic /*
31952221Sbostic * We use the ifile vnode for almost every operation. Instead of
32052221Sbostic * retrieving it from the hash table each time we retrieve it here,
32152221Sbostic * artificially increment the reference count and keep a pointer
32252221Sbostic * to it in the incore copy of the superblock.
32352221Sbostic */
32454693Sbostic if (error = VFS_VGET(mp, LFS_IFILE_INUM, &vp))
32551155Sbostic goto out;
32651155Sbostic fs->lfs_ivnode = vp;
32752221Sbostic VREF(vp);
32852221Sbostic vput(vp);
32951155Sbostic
33037737Smckusick return (0);
33112795Ssam out:
33240872Smckusick if (bp)
33340872Smckusick brelse(bp);
33467949Smckusick (void)VOP_CLOSE(devvp, ronly ? FREAD : FREAD|FWRITE, cred, p);
33541314Smckusick if (ump) {
33651989Smckusick free(ump->um_lfs, M_UFSMNT);
33751501Sbostic free(ump, M_UFSMNT);
33841397Smckusick mp->mnt_data = (qaddr_t)0;
33932721Smckusick }
34037737Smckusick return (error);
34112795Ssam }
34212795Ssam
34339043Smckusick /*
34437737Smckusick * unmount system call
34537737Smckusick */
34651155Sbostic lfs_unmount(mp, mntflags, p)
34737737Smckusick struct mount *mp;
34841314Smckusick int mntflags;
34948036Smckusick struct proc *p;
35012795Ssam {
35151501Sbostic extern int doforce;
35237737Smckusick register struct ufsmount *ump;
35355548Sbostic register struct lfs *fs;
35454693Sbostic int i, error, flags, ronly;
35512795Ssam
35654693Sbostic flags = 0;
35769344Smckusick if (mntflags & MNT_FORCE)
35841314Smckusick flags |= FORCECLOSE;
35954264Sbostic
36054264Sbostic ump = VFSTOUFS(mp);
36154264Sbostic fs = ump->um_lfs;
36212795Ssam #ifdef QUOTA
36341397Smckusick if (mp->mnt_flag & MNT_QUOTA) {
36454264Sbostic if (error = vflush(mp, fs->lfs_ivnode, SKIPSYSTEM|flags))
36539898Smckusick return (error);
36641314Smckusick for (i = 0; i < MAXQUOTAS; i++) {
36741314Smckusick if (ump->um_quotas[i] == NULLVP)
36841314Smckusick continue;
36950114Smckusick quotaoff(p, mp, i);
37041314Smckusick }
37139898Smckusick /*
37241314Smckusick * Here we fall through to vflush again to ensure
37341314Smckusick * that we have gotten rid of all the system vnodes.
37439898Smckusick */
37541314Smckusick }
37612795Ssam #endif
37754693Sbostic if (error = vflush(mp, fs->lfs_ivnode, flags))
37839898Smckusick return (error);
37955548Sbostic fs->lfs_clean = 1;
38054693Sbostic if (error = VFS_SYNC(mp, 1, p->p_ucred, p))
38154693Sbostic return (error);
38265240Smckusick if (fs->lfs_ivnode->v_dirtyblkhd.lh_first)
38354693Sbostic panic("lfs_unmount: still dirty blocks on ifile vnode\n");
38455806Sbostic vrele(fs->lfs_ivnode);
38554693Sbostic vgone(fs->lfs_ivnode);
38654693Sbostic
38751155Sbostic ronly = !fs->lfs_ronly;
38840653Smckusick ump->um_devvp->v_specflags &= ~SI_MOUNTEDON;
38954693Sbostic error = VOP_CLOSE(ump->um_devvp,
39054693Sbostic ronly ? FREAD : FREAD|FWRITE, NOCRED, p);
39137737Smckusick vrele(ump->um_devvp);
39251989Smckusick free(fs, M_UFSMNT);
39351501Sbostic free(ump, M_UFSMNT);
39441397Smckusick mp->mnt_data = (qaddr_t)0;
39541397Smckusick mp->mnt_flag &= ~MNT_LOCAL;
39630749Skarels return (error);
39712795Ssam }
39812795Ssam
39937737Smckusick /*
40037737Smckusick * Get file system statistics.
40137737Smckusick */
40251155Sbostic lfs_statfs(mp, sbp, p)
40337737Smckusick struct mount *mp;
40437737Smckusick register struct statfs *sbp;
40548036Smckusick struct proc *p;
40637737Smckusick {
40751501Sbostic register struct lfs *fs;
40837737Smckusick register struct ufsmount *ump;
40937737Smckusick
41037737Smckusick ump = VFSTOUFS(mp);
41151155Sbostic fs = ump->um_lfs;
41251155Sbostic if (fs->lfs_magic != LFS_MAGIC)
41351155Sbostic panic("lfs_statfs: magic");
414*69813Smargo sbp->f_bsize = fs->lfs_fsize;
41551943Smckusick sbp->f_iosize = fs->lfs_bsize;
416*69813Smargo sbp->f_blocks = dbtofrags(fs,fs->lfs_dsize);
417*69813Smargo sbp->f_bfree = dbtofrags(fs, fs->lfs_bfree);
41869293Smckusick /*
41969293Smckusick * To compute the available space. Subtract the minimum free
42069293Smckusick * from the total number of blocks in the file system. Set avail
42169293Smckusick * to the smaller of this number and fs->lfs_bfree.
42269293Smckusick */
42369293Smckusick sbp->f_bavail = fs->lfs_dsize * (100 - fs->lfs_minfree) / 100;
42469293Smckusick sbp->f_bavail =
42569293Smckusick sbp->f_bavail > fs->lfs_bfree ? fs->lfs_bfree : sbp->f_bavail;
426*69813Smargo sbp->f_bavail = dbtofrags(fs, sbp->f_bavail);
42751155Sbostic sbp->f_files = fs->lfs_nfiles;
42855588Sbostic sbp->f_ffree = sbp->f_bfree * INOPB(fs);
42941397Smckusick if (sbp != &mp->mnt_stat) {
43068676Smckusick sbp->f_type = mp->mnt_vfc->vfc_typenum;
43141397Smckusick bcopy((caddr_t)mp->mnt_stat.f_mntonname,
43240346Smckusick (caddr_t)&sbp->f_mntonname[0], MNAMELEN);
43341397Smckusick bcopy((caddr_t)mp->mnt_stat.f_mntfromname,
43440346Smckusick (caddr_t)&sbp->f_mntfromname[0], MNAMELEN);
43540346Smckusick }
43637737Smckusick return (0);
43737737Smckusick }
43837737Smckusick
43937737Smckusick /*
44037737Smckusick * Go through the disk queues to initiate sandbagged IO;
44137737Smckusick * go through the inodes to write those that have been modified;
44237737Smckusick * initiate the writing of the super block if it has been modified.
44341314Smckusick *
44441314Smckusick * Note: we are always called with the filesystem marked `MPBUSY'.
44537737Smckusick */
44654693Sbostic lfs_sync(mp, waitfor, cred, p)
44737737Smckusick struct mount *mp;
44837737Smckusick int waitfor;
44954693Sbostic struct ucred *cred;
45054693Sbostic struct proc *p;
45137737Smckusick {
45251215Sbostic int error;
45337737Smckusick
45451310Sbostic /* All syncs must be checkpoints until roll-forward is implemented. */
45557068Smargo error = lfs_segwrite(mp, SEGM_CKP | (waitfor ? SEGM_SYNC : 0));
45641314Smckusick #ifdef QUOTA
45741314Smckusick qsync(mp);
45841314Smckusick #endif
45951215Sbostic return (error);
46037737Smckusick }
46151559Smckusick
46251559Smckusick /*
46354693Sbostic * Look up an LFS dinode number to find its incore vnode. If not already
46454693Sbostic * in core, read it in from the specified device. Return the inode locked.
46554693Sbostic * Detection and handling of mount points must be done by the calling routine.
46654693Sbostic */
46754693Sbostic int
lfs_vget(mp,ino,vpp)46854693Sbostic lfs_vget(mp, ino, vpp)
46954693Sbostic struct mount *mp;
47054693Sbostic ino_t ino;
47154693Sbostic struct vnode **vpp;
47254693Sbostic {
47354693Sbostic register struct lfs *fs;
47454693Sbostic register struct inode *ip;
47554693Sbostic struct buf *bp;
47654693Sbostic struct ifile *ifp;
47754693Sbostic struct vnode *vp;
47854693Sbostic struct ufsmount *ump;
47968550Smckusick ufs_daddr_t daddr;
48054693Sbostic dev_t dev;
48154693Sbostic int error;
48254693Sbostic
48354693Sbostic ump = VFSTOUFS(mp);
48454693Sbostic dev = ump->um_dev;
48554693Sbostic if ((*vpp = ufs_ihashget(dev, ino)) != NULL)
48654693Sbostic return (0);
48754693Sbostic
48854693Sbostic /* Translate the inode number to a disk address. */
48954693Sbostic fs = ump->um_lfs;
49054693Sbostic if (ino == LFS_IFILE_INUM)
49154693Sbostic daddr = fs->lfs_idaddr;
49254693Sbostic else {
49354693Sbostic LFS_IENTRY(ifp, fs, ino, bp);
49454693Sbostic daddr = ifp->if_daddr;
49554693Sbostic brelse(bp);
49654693Sbostic if (daddr == LFS_UNUSED_DADDR)
49754693Sbostic return (ENOENT);
49854693Sbostic }
49954693Sbostic
50054693Sbostic /* Allocate new vnode/inode. */
50154693Sbostic if (error = lfs_vcreate(mp, ino, &vp)) {
50254693Sbostic *vpp = NULL;
50354693Sbostic return (error);
50454693Sbostic }
50554693Sbostic
50654693Sbostic /*
50754693Sbostic * Put it onto its hash chain and lock it so that other requests for
50854693Sbostic * this inode will block if they arrive while we are sleeping waiting
50954693Sbostic * for old data structures to be purged or for the contents of the
51054693Sbostic * disk portion of this inode to be read.
51154693Sbostic */
51254693Sbostic ip = VTOI(vp);
51354693Sbostic ufs_ihashins(ip);
51454693Sbostic
51554693Sbostic /*
51654693Sbostic * XXX
51754693Sbostic * This may not need to be here, logically it should go down with
51854693Sbostic * the i_devvp initialization.
51954693Sbostic * Ask Kirk.
52054693Sbostic */
52154693Sbostic ip->i_lfs = ump->um_lfs;
52254693Sbostic
52354693Sbostic /* Read in the disk contents for the inode, copy into the inode. */
52454693Sbostic if (error =
52554693Sbostic bread(ump->um_devvp, daddr, (int)fs->lfs_bsize, NOCRED, &bp)) {
52654693Sbostic /*
52759820Smckusick * The inode does not contain anything useful, so it would
52859820Smckusick * be misleading to leave it on its hash chain. With mode
52959820Smckusick * still zero, it will be unlinked and returned to the free
53059820Smckusick * list by vput().
53154693Sbostic */
53256799Smckusick vput(vp);
53354693Sbostic brelse(bp);
53454693Sbostic *vpp = NULL;
53554693Sbostic return (error);
53654693Sbostic }
53764523Sbostic ip->i_din = *lfs_ifind(fs, ino, (struct dinode *)bp->b_data);
53854693Sbostic brelse(bp);
53954693Sbostic
54054693Sbostic /*
54154693Sbostic * Initialize the vnode from the inode, check for aliases. In all
54254693Sbostic * cases re-init ip, the underlying vnode/inode may have changed.
54354693Sbostic */
54454693Sbostic if (error = ufs_vinit(mp, lfs_specop_p, LFS_FIFOOPS, &vp)) {
54556799Smckusick vput(vp);
54654693Sbostic *vpp = NULL;
54754693Sbostic return (error);
54854693Sbostic }
54954693Sbostic /*
55054693Sbostic * Finish inode initialization now that aliasing has been resolved.
55154693Sbostic */
55254693Sbostic ip->i_devvp = ump->um_devvp;
55354693Sbostic VREF(ip->i_devvp);
55454693Sbostic *vpp = vp;
55554693Sbostic return (0);
55654693Sbostic }
55754693Sbostic
55854693Sbostic /*
55951559Smckusick * File handle to vnode
56051559Smckusick *
56151559Smckusick * Have to be really careful about stale file handles:
56251559Smckusick * - check that the inode number is valid
56351559Smckusick * - call lfs_vget() to get the locked inode
56451559Smckusick * - check for an unallocated inode (i_mode == 0)
56555891Smckusick * - check that the given client host has export rights and return
56655891Smckusick * those rights via. exflagsp and credanonp
56751559Smckusick *
56851559Smckusick * XXX
56951559Smckusick * use ifile to see if inode is allocated instead of reading off disk
57051559Smckusick * what is the relationship between my generational number and the NFS
57151559Smckusick * generational number.
57251559Smckusick */
57351559Smckusick int
lfs_fhtovp(mp,fhp,nam,vpp,exflagsp,credanonp)57454734Smckusick lfs_fhtovp(mp, fhp, nam, vpp, exflagsp, credanonp)
57551559Smckusick register struct mount *mp;
57651559Smckusick struct fid *fhp;
57754734Smckusick struct mbuf *nam;
57851559Smckusick struct vnode **vpp;
57954734Smckusick int *exflagsp;
58054734Smckusick struct ucred **credanonp;
58151559Smckusick {
58251559Smckusick register struct ufid *ufhp;
58351559Smckusick
58451559Smckusick ufhp = (struct ufid *)fhp;
58551559Smckusick if (ufhp->ufid_ino < ROOTINO)
58654734Smckusick return (ESTALE);
58756246Smckusick return (ufs_check_export(mp, ufhp, nam, vpp, exflagsp, credanonp));
58851559Smckusick }
58951559Smckusick
59051559Smckusick /*
59151559Smckusick * Vnode pointer to File handle
59251559Smckusick */
59351559Smckusick /* ARGSUSED */
59451559Smckusick lfs_vptofh(vp, fhp)
59551559Smckusick struct vnode *vp;
59651559Smckusick struct fid *fhp;
59751559Smckusick {
59851559Smckusick register struct inode *ip;
59951559Smckusick register struct ufid *ufhp;
60051559Smckusick
60151559Smckusick ip = VTOI(vp);
60251559Smckusick ufhp = (struct ufid *)fhp;
60351559Smckusick ufhp->ufid_len = sizeof(struct ufid);
60451559Smckusick ufhp->ufid_ino = ip->i_number;
60551559Smckusick ufhp->ufid_gen = ip->i_gen;
60651559Smckusick return (0);
60751559Smckusick }
60868676Smckusick
60968676Smckusick /*
61068676Smckusick * Initialize the filesystem, most work done by ufs_init.
61168676Smckusick */
61268676Smckusick int lfs_mount_type;
61368676Smckusick
61468676Smckusick int
lfs_init(vfsp)61568676Smckusick lfs_init(vfsp)
61668676Smckusick struct vfsconf *vfsp;
61768676Smckusick {
61868676Smckusick
61968676Smckusick lfs_mount_type = vfsp->vfc_typenum;
62068676Smckusick return (ufs_init(vfsp));
62168676Smckusick }
622