Commit | Line | Data |
---|---|---|
da7c5cc6 | 1 | /* |
52ff95c2 | 2 | * Copyright (c) 1989, 1991, 1993, 1994 |
ad0f93d2 | 3 | * The Regents of the University of California. All rights reserved. |
da7c5cc6 | 4 | * |
b702c21d | 5 | * %sccs.include.redist.c% |
7188ac27 | 6 | * |
89e2bb79 | 7 | * @(#)lfs_vfsops.c 8.11 (Berkeley) %G% |
da7c5cc6 | 8 | */ |
71e4e98b | 9 | |
c7e94c3a 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> | |
c7e94c3a KB |
16 | #include <sys/mount.h> |
17 | #include <sys/buf.h> | |
3a0a9bdc | 18 | #include <sys/mbuf.h> |
c7e94c3a KB |
19 | #include <sys/file.h> |
20 | #include <sys/disklabel.h> | |
21 | #include <sys/ioctl.h> | |
22 | #include <sys/errno.h> | |
23 | #include <sys/malloc.h> | |
3a0a9bdc | 24 | #include <sys/socket.h> |
cff1d696 KM |
25 | |
26 | #include <miscfs/specfs/specdev.h> | |
609e7cfa MK |
27 | #include "ioctl.h" |
28 | #include "disklabel.h" | |
29 | #include "stat.h" | |
71e4e98b | 30 | |
d9f5f868 KB |
31 | #include <ufs/ufs/quota.h> |
32 | #include <ufs/ufs/inode.h> | |
33 | #include <ufs/ufs/ufsmount.h> | |
34 | #include <ufs/ufs/ufs_extern.h> | |
c6f5111d | 35 | |
d9f5f868 KB |
36 | #include <ufs/lfs/lfs.h> |
37 | #include <ufs/lfs/lfs_extern.h> | |
275ca4f0 | 38 | |
79a0d4bf | 39 | int lfs_mountfs __P((struct vnode *, struct mount *, struct proc *)); |
0b4d6502 KB |
40 | |
41 | struct vfsops lfs_vfsops = { | |
42 | lfs_mount, | |
5bf9d21f | 43 | ufs_start, |
0b4d6502 | 44 | lfs_unmount, |
52ff95c2 | 45 | ufs_root, |
8dc876c1 | 46 | ufs_quotactl, |
0b4d6502 KB |
47 | lfs_statfs, |
48 | lfs_sync, | |
f7802306 | 49 | lfs_vget, |
b16ed5f4 KM |
50 | lfs_fhtovp, |
51 | lfs_vptofh, | |
c7e94c3a | 52 | lfs_init, |
7188ac27 KM |
53 | }; |
54 | ||
c7e94c3a | 55 | int |
0b4d6502 | 56 | lfs_mountroot() |
71e4e98b | 57 | { |
c7e94c3a | 58 | panic("lfs_mountroot"); /* XXX -- implement */ |
7188ac27 KM |
59 | } |
60 | ||
61 | /* | |
62 | * VFS Operations. | |
63 | * | |
64 | * mount system call | |
65 | */ | |
0b4d6502 | 66 | lfs_mount(mp, path, data, ndp, p) |
d45de50d | 67 | register struct mount *mp; |
7188ac27 KM |
68 | char *path; |
69 | caddr_t data; | |
70 | struct nameidata *ndp; | |
0eb6f54a | 71 | struct proc *p; |
7188ac27 KM |
72 | { |
73 | struct vnode *devvp; | |
74 | struct ufs_args args; | |
75 | struct ufsmount *ump; | |
d9f5f868 | 76 | register struct lfs *fs; /* LFS */ |
7188ac27 KM |
77 | u_int size; |
78 | int error; | |
38047d55 | 79 | mode_t accessmode; |
7188ac27 KM |
80 | |
81 | if (error = copyin(data, (caddr_t)&args, sizeof (struct ufs_args))) | |
82 | return (error); | |
c7e94c3a KB |
83 | |
84 | /* Until LFS can do NFS right. XXX */ | |
ea7e18a7 | 85 | if (args.export.ex_flags & MNT_EXPORTED) |
c7e94c3a | 86 | return (EINVAL); |
ea7e18a7 | 87 | |
190244fb MK |
88 | /* |
89 | * If updating, check whether changing from read-only to | |
90 | * read/write; if there is no device name, that's all we do. | |
91 | */ | |
92 | if (mp->mnt_flag & MNT_UPDATE) { | |
d48157d5 | 93 | ump = VFSTOUFS(mp); |
38047d55 KM |
94 | if (fs->lfs_ronly && (mp->mnt_flag & MNT_WANTRDWR)) { |
95 | /* | |
96 | * If upgrade to read-write by non-root, then verify | |
97 | * that user has necessary permissions on the device. | |
98 | */ | |
99 | if (p->p_ucred->cr_uid != 0) { | |
100 | VOP_LOCK(ump->um_devvp); | |
101 | if (error = VOP_ACCESS(ump->um_devvp, | |
102 | VREAD | VWRITE, p->p_ucred, p)) { | |
103 | VOP_UNLOCK(ump->um_devvp); | |
104 | return (error); | |
105 | } | |
106 | VOP_UNLOCK(ump->um_devvp); | |
107 | } | |
0b4d6502 | 108 | fs->lfs_ronly = 0; |
38047d55 | 109 | } |
64583792 KM |
110 | if (args.fspec == 0) { |
111 | /* | |
112 | * Process export requests. | |
113 | */ | |
ea7e18a7 | 114 | return (vfs_export(mp, &ump->um_export, &args.export)); |
64583792 | 115 | } |
190244fb MK |
116 | } |
117 | /* | |
118 | * Not an update, or updating the name: look up the name | |
119 | * and verify that it refers to a sensible block device. | |
120 | */ | |
995e59df KM |
121 | NDINIT(ndp, LOOKUP, FOLLOW, UIO_USERSPACE, args.fspec, p); |
122 | if (error = namei(ndp)) | |
190244fb MK |
123 | return (error); |
124 | devvp = ndp->ni_vp; | |
125 | if (devvp->v_type != VBLK) { | |
126 | vrele(devvp); | |
127 | return (ENOTBLK); | |
128 | } | |
129 | if (major(devvp->v_rdev) >= nblkdev) { | |
130 | vrele(devvp); | |
131 | return (ENXIO); | |
132 | } | |
38047d55 KM |
133 | /* |
134 | * If mount by non-root, then verify that user has necessary | |
135 | * permissions on the device. | |
136 | */ | |
137 | if (p->p_ucred->cr_uid != 0) { | |
138 | accessmode = VREAD; | |
139 | if ((mp->mnt_flag & MNT_RDONLY) == 0) | |
140 | accessmode |= VWRITE; | |
141 | VOP_LOCK(devvp); | |
142 | if (error = VOP_ACCESS(devvp, accessmode, p->p_ucred, p)) { | |
143 | vput(devvp); | |
144 | return (error); | |
145 | } | |
146 | VOP_UNLOCK(devvp); | |
147 | } | |
190244fb | 148 | if ((mp->mnt_flag & MNT_UPDATE) == 0) |
0b4d6502 | 149 | error = lfs_mountfs(devvp, mp, p); /* LFS */ |
190244fb | 150 | else { |
d48157d5 KM |
151 | if (devvp != ump->um_devvp) |
152 | error = EINVAL; /* needs translation */ | |
2a7dbb09 KM |
153 | else |
154 | vrele(devvp); | |
d48157d5 | 155 | } |
7188ac27 KM |
156 | if (error) { |
157 | vrele(devvp); | |
158 | return (error); | |
27d00e76 | 159 | } |
7188ac27 | 160 | ump = VFSTOUFS(mp); |
0b4d6502 KB |
161 | fs = ump->um_lfs; /* LFS */ |
162 | #ifdef NOTLFS /* LFS */ | |
7188ac27 KM |
163 | (void) copyinstr(path, fs->fs_fsmnt, sizeof(fs->fs_fsmnt) - 1, &size); |
164 | bzero(fs->fs_fsmnt + size, sizeof(fs->fs_fsmnt) - size); | |
82161bc8 KM |
165 | bcopy((caddr_t)fs->fs_fsmnt, (caddr_t)mp->mnt_stat.f_mntonname, |
166 | MNAMELEN); | |
79a0d4bf | 167 | (void) copyinstr(args.fspec, mp->mnt_stat.f_mntfromname, MNAMELEN - 1, |
82161bc8 KM |
168 | &size); |
169 | bzero(mp->mnt_stat.f_mntfromname + size, MNAMELEN - size); | |
0eb6f54a | 170 | (void) ufs_statfs(mp, &mp->mnt_stat, p); |
0b4d6502 KB |
171 | #else |
172 | (void)copyinstr(path, fs->lfs_fsmnt, sizeof(fs->lfs_fsmnt) - 1, &size); | |
173 | bzero(fs->lfs_fsmnt + size, sizeof(fs->lfs_fsmnt) - size); | |
174 | bcopy((caddr_t)fs->lfs_fsmnt, (caddr_t)mp->mnt_stat.f_mntonname, | |
175 | MNAMELEN); | |
79a0d4bf | 176 | (void) copyinstr(args.fspec, mp->mnt_stat.f_mntfromname, MNAMELEN - 1, |
0b4d6502 KB |
177 | &size); |
178 | bzero(mp->mnt_stat.f_mntfromname + size, MNAMELEN - size); | |
179 | (void) lfs_statfs(mp, &mp->mnt_stat, p); | |
180 | #endif | |
7188ac27 | 181 | return (0); |
71e4e98b SL |
182 | } |
183 | ||
7188ac27 KM |
184 | /* |
185 | * Common code for mount and mountroot | |
0b4d6502 | 186 | * LFS specific |
7188ac27 | 187 | */ |
79a0d4bf | 188 | int |
0b4d6502 | 189 | lfs_mountfs(devvp, mp, p) |
1182ae61 | 190 | register struct vnode *devvp; |
7188ac27 | 191 | struct mount *mp; |
0eb6f54a | 192 | struct proc *p; |
71e4e98b | 193 | { |
1c26e003 | 194 | extern struct vnode *rootvp; |
d9f5f868 | 195 | register struct lfs *fs; |
0b4d6502 | 196 | register struct ufsmount *ump; |
0b4d6502 KB |
197 | struct vnode *vp; |
198 | struct buf *bp; | |
199 | struct partinfo dpart; | |
0b4d6502 KB |
200 | dev_t dev; |
201 | int error, i, ronly, size; | |
9f246d5e | 202 | struct ucred *cred; |
71e4e98b | 203 | |
9f246d5e | 204 | cred = p ? p->p_ucred : NOCRED; |
1feabdab | 205 | if (error = VOP_OPEN(devvp, ronly ? FREAD : FREAD|FWRITE, FSCRED, p)) |
7188ac27 | 206 | return (error); |
0b4d6502 | 207 | |
9f246d5e | 208 | if (VOP_IOCTL(devvp, DIOCGPART, (caddr_t)&dpart, FREAD, cred, p) != 0) |
609e7cfa | 209 | size = DEV_BSIZE; |
0eb6f54a | 210 | else { |
ec67a3ce | 211 | size = dpart.disklab->d_secsize; |
0b4d6502 KB |
212 | #ifdef NEVER_USED |
213 | dpart.part->p_fstype = FS_LFS; | |
214 | dpart.part->p_fsize = fs->lfs_fsize; /* frag size */ | |
215 | dpart.part->p_frag = fs->lfs_frag; /* frags per block */ | |
216 | dpart.part->p_cpg = fs->lfs_segshift; /* segment shift */ | |
217 | #endif | |
7188ac27 | 218 | } |
0b4d6502 KB |
219 | |
220 | /* Don't free random space on error. */ | |
221 | bp = NULL; | |
222 | ump = NULL; | |
223 | ||
224 | /* Read in the superblock. */ | |
9f246d5e | 225 | if (error = bread(devvp, LFS_LABELPAD / size, LFS_SBPAD, cred, &bp)) |
71e4e98b | 226 | goto out; |
8dc876c1 | 227 | error = EINVAL; /* XXX needs translation */ |
1c281610 MK |
228 | goto out; |
229 | } | |
0b4d6502 KB |
230 | |
231 | /* Allocate the mount structure, copy the superblock into it. */ | |
8dc876c1 | 232 | ump = (struct ufsmount *)malloc(sizeof *ump, M_UFSMNT, M_WAITOK); |
0c0b26ec | 233 | fs = ump->um_lfs = malloc(sizeof(struct lfs), M_UFSMNT, M_WAITOK); |
cb84e0ab | 234 | bcopy(bp->b_data, fs, sizeof(struct lfs)); |
d9f5f868 | 235 | if (sizeof(struct lfs) < LFS_SBPAD) /* XXX why? */ |
5d96a9ad | 236 | bp->b_flags |= B_INVAL; |
e018935f MK |
237 | brelse(bp); |
238 | bp = NULL; | |
0b4d6502 | 239 | |
d5075120 KB |
240 | /* Set up the I/O information */ |
241 | fs->lfs_iocount = 0; | |
d5075120 | 242 | |
0c0b26ec | 243 | /* Set up the ifile and lock aflags */ |
3ce71481 KB |
244 | fs->lfs_doifile = 0; |
245 | fs->lfs_writer = 0; | |
246 | fs->lfs_dirops = 0; | |
0c0b26ec | 247 | fs->lfs_seglock = 0; |
3ce71481 | 248 | |
0b4d6502 | 249 | /* Set the file system readonly/modify bits. */ |
0b4d6502 | 250 | fs->lfs_ronly = ronly; |
71e4e98b | 251 | if (ronly == 0) |
0b4d6502 KB |
252 | fs->lfs_fmod = 1; |
253 | ||
254 | /* Initialize the mount structure. */ | |
255 | dev = devvp->v_rdev; | |
82161bc8 KM |
256 | mp->mnt_data = (qaddr_t)ump; |
257 | mp->mnt_stat.f_fsid.val[0] = (long)dev; | |
79a0d4bf | 258 | mp->mnt_stat.f_fsid.val[1] = MOUNT_LFS; |
b390cbb0 | 259 | mp->mnt_maxsymlinklen = fs->lfs_maxsymlinklen; |
82161bc8 | 260 | mp->mnt_flag |= MNT_LOCAL; |
7188ac27 KM |
261 | ump->um_mountp = mp; |
262 | ump->um_dev = dev; | |
263 | ump->um_devvp = devvp; | |
5e539b49 MS |
264 | ump->um_bptrtodb = 0; |
265 | ump->um_seqinc = 1 << fs->lfs_fsbtodb; | |
266 | ump->um_nindir = fs->lfs_nindir; | |
8dc876c1 KM |
267 | for (i = 0; i < MAXQUOTAS; i++) |
268 | ump->um_quotas[i] = NULLVP; | |
f9c367e8 | 269 | devvp->v_specflags |= SI_MOUNTEDON; |
7188ac27 | 270 | |
f9c367e8 KB |
271 | /* |
272 | * We use the ifile vnode for almost every operation. Instead of | |
273 | * retrieving it from the hash table each time we retrieve it here, | |
274 | * artificially increment the reference count and keep a pointer | |
275 | * to it in the incore copy of the superblock. | |
276 | */ | |
f7802306 | 277 | if (error = VFS_VGET(mp, LFS_IFILE_INUM, &vp)) |
0b4d6502 | 278 | goto out; |
0b4d6502 | 279 | fs->lfs_ivnode = vp; |
f9c367e8 KB |
280 | VREF(vp); |
281 | vput(vp); | |
0b4d6502 | 282 | |
609e7cfa | 283 | |
7188ac27 | 284 | return (0); |
71e4e98b | 285 | out: |
c86c9b6e KM |
286 | if (bp) |
287 | brelse(bp); | |
9f246d5e | 288 | (void)VOP_CLOSE(devvp, ronly ? FREAD : FREAD|FWRITE, cred, p); |
8dc876c1 | 289 | if (ump) { |
ece51ee9 | 290 | free(ump->um_lfs, M_UFSMNT); |
d9f5f868 | 291 | free(ump, M_UFSMNT); |
82161bc8 | 292 | mp->mnt_data = (qaddr_t)0; |
27d00e76 | 293 | } |
7188ac27 | 294 | return (error); |
71e4e98b SL |
295 | } |
296 | ||
7188ac27 KM |
297 | /* |
298 | * unmount system call | |
299 | */ | |
0b4d6502 | 300 | lfs_unmount(mp, mntflags, p) |
7188ac27 | 301 | struct mount *mp; |
8dc876c1 | 302 | int mntflags; |
0eb6f54a | 303 | struct proc *p; |
71e4e98b | 304 | { |
d9f5f868 | 305 | extern int doforce; |
7188ac27 | 306 | register struct ufsmount *ump; |
0c0b26ec | 307 | register struct lfs *fs; |
f7802306 | 308 | int i, error, flags, ronly; |
71e4e98b | 309 | |
f7802306 | 310 | flags = 0; |
87be6db2 | 311 | if (mntflags & MNT_FORCE) { |
eb49bed5 | 312 | if (!doforce || (mp->mnt_flag & MNT_ROOTFS)) |
87be6db2 | 313 | return (EINVAL); |
8dc876c1 | 314 | flags |= FORCECLOSE; |
87be6db2 | 315 | } |
3ce71481 | 316 | |
7188ac27 | 317 | ump = VFSTOUFS(mp); |
3ce71481 | 318 | fs = ump->um_lfs; |
ec67a3ce | 319 | return (error); |
71e4e98b | 320 | #ifdef QUOTA |
82161bc8 | 321 | if (mp->mnt_flag & MNT_QUOTA) { |
3ce71481 | 322 | if (error = vflush(mp, fs->lfs_ivnode, SKIPSYSTEM|flags)) |
6d943995 | 323 | return (error); |
8dc876c1 KM |
324 | for (i = 0; i < MAXQUOTAS; i++) { |
325 | if (ump->um_quotas[i] == NULLVP) | |
326 | continue; | |
70a360ba | 327 | quotaoff(p, mp, i); |
8dc876c1 | 328 | } |
6d943995 | 329 | /* |
8dc876c1 KM |
330 | * Here we fall through to vflush again to ensure |
331 | * that we have gotten rid of all the system vnodes. | |
6d943995 | 332 | */ |
8dc876c1 | 333 | } |
71e4e98b | 334 | #endif |
f7802306 | 335 | if (error = vflush(mp, fs->lfs_ivnode, flags)) |
6d943995 | 336 | return (error); |
0c0b26ec | 337 | fs->lfs_clean = 1; |
f7802306 KB |
338 | if (error = VFS_SYNC(mp, 1, p->p_ucred, p)) |
339 | return (error); | |
eb49bed5 | 340 | if (fs->lfs_ivnode->v_dirtyblkhd.lh_first) |
f7802306 | 341 | panic("lfs_unmount: still dirty blocks on ifile vnode\n"); |
4c9381d8 | 342 | vrele(fs->lfs_ivnode); |
f7802306 KB |
343 | vgone(fs->lfs_ivnode); |
344 | ||
0b4d6502 | 345 | ronly = !fs->lfs_ronly; |
7188ac27 KM |
346 | * Get file system statistics. |
347 | */ | |
0b4d6502 | 348 | lfs_statfs(mp, sbp, p) |
7188ac27 KM |
349 | struct mount *mp; |
350 | register struct statfs *sbp; | |
0eb6f54a | 351 | struct proc *p; |
7188ac27 | 352 | { |
d9f5f868 | 353 | register struct lfs *fs; |
7188ac27 | 354 | register struct ufsmount *ump; |
7188ac27 KM |
355 | |
356 | ump = VFSTOUFS(mp); | |
0b4d6502 KB |
357 | fs = ump->um_lfs; |
358 | if (fs->lfs_magic != LFS_MAGIC) | |
359 | panic("lfs_statfs: magic"); | |
360 | sbp->f_type = MOUNT_LFS; | |
0b4d6502 | 361 | sbp->f_bsize = fs->lfs_bsize; |
cc173077 | 362 | sbp->f_iosize = fs->lfs_bsize; |
4d3cf006 | 363 | sbp->f_blocks = dbtofsb(fs,fs->lfs_dsize); |
435a74c9 | 364 | sbp->f_bfree = dbtofsb(fs, fs->lfs_bfree); |
0b4d6502 | 365 | sbp->f_bavail = (fs->lfs_dsize * (100 - fs->lfs_minfree) / 100) - |
76353702 | 366 | (fs->lfs_dsize - fs->lfs_bfree); |
4d3cf006 | 367 | sbp->f_bavail = dbtofsb(fs, sbp->f_bavail); |
0b4d6502 | 368 | sbp->f_files = fs->lfs_nfiles; |
435a74c9 | 369 | sbp->f_ffree = sbp->f_bfree * INOPB(fs); |
82161bc8 KM |
370 | if (sbp != &mp->mnt_stat) { |
371 | bcopy((caddr_t)mp->mnt_stat.f_mntonname, | |
d45de50d | 372 | (caddr_t)&sbp->f_mntonname[0], MNAMELEN); |
82161bc8 | 373 | bcopy((caddr_t)mp->mnt_stat.f_mntfromname, |
d45de50d KM |
374 | (caddr_t)&sbp->f_mntfromname[0], MNAMELEN); |
375 | } | |
7188ac27 KM |
376 | return (0); |
377 | } | |
378 | ||
7188ac27 KM |
379 | /* |
380 | * Go through the disk queues to initiate sandbagged IO; | |
381 | * go through the inodes to write those that have been modified; | |
382 | * initiate the writing of the super block if it has been modified. | |
8dc876c1 KM |
383 | * |
384 | * Note: we are always called with the filesystem marked `MPBUSY'. | |
7188ac27 | 385 | */ |
f7802306 | 386 | lfs_sync(mp, waitfor, cred, p) |
71e4e98b | 387 | struct mount *mp; |
7188ac27 | 388 | int waitfor; |
f7802306 KB |
389 | struct ucred *cred; |
390 | struct proc *p; | |
71e4e98b | 391 | { |
275ca4f0 | 392 | int error; |
7188ac27 | 393 | |
c9cbb645 | 394 | /* All syncs must be checkpoints until roll-forward is implemented. */ |
d2495626 | 395 | error = lfs_segwrite(mp, SEGM_CKP | (waitfor ? SEGM_SYNC : 0)); |
8dc876c1 KM |
396 | #ifdef QUOTA |
397 | qsync(mp); | |
398 | #endif | |
275ca4f0 | 399 | return (error); |
7188ac27 | 400 | } |
b16ed5f4 | 401 | |
f7802306 KB |
402 | /* |
403 | * Look up an LFS dinode number to find its incore vnode. If not already | |
404 | * in core, read it in from the specified device. Return the inode locked. | |
405 | * Detection and handling of mount points must be done by the calling routine. | |
406 | */ | |
407 | int | |
408 | lfs_vget(mp, ino, vpp) | |
409 | struct mount *mp; | |
410 | ino_t ino; | |
411 | struct vnode **vpp; | |
412 | { | |
413 | register struct lfs *fs; | |
414 | register struct inode *ip; | |
415 | struct buf *bp; | |
416 | struct ifile *ifp; | |
417 | struct vnode *vp; | |
418 | struct ufsmount *ump; | |
89e2bb79 | 419 | ufs_daddr_t daddr; |
f7802306 KB |
420 | dev_t dev; |
421 | int error; | |
422 | ||
f7802306 KB |
423 | ump = VFSTOUFS(mp); |
424 | dev = ump->um_dev; | |
425 | if ((*vpp = ufs_ihashget(dev, ino)) != NULL) | |
426 | return (0); | |
427 | ||
428 | /* Translate the inode number to a disk address. */ | |
429 | fs = ump->um_lfs; | |
430 | if (ino == LFS_IFILE_INUM) | |
431 | daddr = fs->lfs_idaddr; | |
432 | else { | |
433 | LFS_IENTRY(ifp, fs, ino, bp); | |
434 | daddr = ifp->if_daddr; | |
435 | brelse(bp); | |
436 | if (daddr == LFS_UNUSED_DADDR) | |
437 | return (ENOENT); | |
438 | } | |
439 | ||
440 | /* Allocate new vnode/inode. */ | |
441 | if (error = lfs_vcreate(mp, ino, &vp)) { | |
442 | *vpp = NULL; | |
443 | return (error); | |
444 | } | |
445 | ||
446 | /* | |
447 | * Put it onto its hash chain and lock it so that other requests for | |
448 | * this inode will block if they arrive while we are sleeping waiting | |
449 | * for old data structures to be purged or for the contents of the | |
450 | * disk portion of this inode to be read. | |
451 | */ | |
452 | ip = VTOI(vp); | |
453 | ufs_ihashins(ip); | |
454 | ||
455 | /* | |
456 | * XXX | |
457 | * This may not need to be here, logically it should go down with | |
458 | * the i_devvp initialization. | |
459 | * Ask Kirk. | |
460 | */ | |
461 | ip->i_lfs = ump->um_lfs; | |
462 | ||
463 | /* Read in the disk contents for the inode, copy into the inode. */ | |
464 | if (error = | |
465 | bread(ump->um_devvp, daddr, (int)fs->lfs_bsize, NOCRED, &bp)) { | |
466 | /* | |
f345d060 KM |
467 | * The inode does not contain anything useful, so it would |
468 | * be misleading to leave it on its hash chain. With mode | |
469 | * still zero, it will be unlinked and returned to the free | |
470 | * list by vput(). | |
f7802306 | 471 | */ |
eca11e88 | 472 | vput(vp); |
f7802306 KB |
473 | brelse(bp); |
474 | *vpp = NULL; | |
475 | return (error); | |
476 | } | |
cb84e0ab | 477 | ip->i_din = *lfs_ifind(fs, ino, (struct dinode *)bp->b_data); |
f7802306 KB |
478 | brelse(bp); |
479 | ||
480 | /* | |
481 | * Initialize the vnode from the inode, check for aliases. In all | |
482 | * cases re-init ip, the underlying vnode/inode may have changed. | |
483 | */ | |
484 | if (error = ufs_vinit(mp, lfs_specop_p, LFS_FIFOOPS, &vp)) { | |
eca11e88 | 485 | vput(vp); |
f7802306 KB |
486 | *vpp = NULL; |
487 | return (error); | |
488 | } | |
489 | /* | |
490 | * Finish inode initialization now that aliasing has been resolved. | |
491 | */ | |
492 | ip->i_devvp = ump->um_devvp; | |
493 | VREF(ip->i_devvp); | |
494 | *vpp = vp; | |
495 | return (0); | |
496 | } | |
497 | ||
b16ed5f4 KM |
498 | /* |
499 | * File handle to vnode | |
500 | * | |
501 | * Have to be really careful about stale file handles: | |
502 | * - check that the inode number is valid | |
503 | * - call lfs_vget() to get the locked inode | |
504 | * - check for an unallocated inode (i_mode == 0) | |
9e4a3a4a KM |
505 | * - check that the given client host has export rights and return |
506 | * those rights via. exflagsp and credanonp | |
b16ed5f4 KM |
507 | * |
508 | * XXX | |
509 | * use ifile to see if inode is allocated instead of reading off disk | |
510 | * what is the relationship between my generational number and the NFS | |
511 | * generational number. | |
512 | */ | |
513 | int | |
3a0a9bdc | 514 | lfs_fhtovp(mp, fhp, nam, vpp, exflagsp, credanonp) |
b16ed5f4 KM |
515 | register struct mount *mp; |
516 | struct fid *fhp; | |
3a0a9bdc | 517 | struct mbuf *nam; |
b16ed5f4 | 518 | struct vnode **vpp; |
3a0a9bdc KM |
519 | int *exflagsp; |
520 | struct ucred **credanonp; | |
b16ed5f4 | 521 | { |
b16ed5f4 | 522 | register struct ufid *ufhp; |
b16ed5f4 KM |
523 | |
524 | ufhp = (struct ufid *)fhp; | |
525 | if (ufhp->ufid_ino < ROOTINO) | |
3a0a9bdc | 526 | return (ESTALE); |
485cf2ee | 527 | return (ufs_check_export(mp, ufhp, nam, vpp, exflagsp, credanonp)); |
b16ed5f4 KM |
528 | } |
529 | ||
530 | /* | |
531 | * Vnode pointer to File handle | |
532 | */ | |
533 | /* ARGSUSED */ | |
534 | lfs_vptofh(vp, fhp) | |
535 | struct vnode *vp; | |
536 | struct fid *fhp; | |
537 | { | |
538 | register struct inode *ip; | |
539 | register struct ufid *ufhp; | |
540 | ||
541 | ip = VTOI(vp); | |
542 | ufhp = (struct ufid *)fhp; | |
543 | ufhp->ufid_len = sizeof(struct ufid); | |
544 | ufhp->ufid_ino = ip->i_number; | |
545 | ufhp->ufid_gen = ip->i_gen; | |
546 | return (0); | |
547 | } |