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 | * |
ad787160 C |
5 | * Redistribution and use in source and binary forms, with or without |
6 | * modification, are permitted provided that the following conditions | |
7 | * are met: | |
8 | * 1. Redistributions of source code must retain the above copyright | |
9 | * notice, this list of conditions and the following disclaimer. | |
10 | * 2. Redistributions in binary form must reproduce the above copyright | |
11 | * notice, this list of conditions and the following disclaimer in the | |
12 | * documentation and/or other materials provided with the distribution. | |
13 | * 3. All advertising materials mentioning features or use of this software | |
14 | * must display the following acknowledgement: | |
15 | * This product includes software developed by the University of | |
16 | * California, Berkeley and its contributors. | |
17 | * 4. Neither the name of the University nor the names of its contributors | |
18 | * may be used to endorse or promote products derived from this software | |
19 | * without specific prior written permission. | |
7188ac27 | 20 | * |
ad787160 C |
21 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND |
22 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
23 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |
24 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE | |
25 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | |
26 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | |
27 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |
28 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | |
29 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | |
30 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |
31 | * SUCH DAMAGE. | |
32 | * | |
fd88f5c5 | 33 | * @(#)lfs_vfsops.c 8.20 (Berkeley) 6/10/95 |
da7c5cc6 | 34 | */ |
71e4e98b | 35 | |
c7e94c3a KB |
36 | #include <sys/param.h> |
37 | #include <sys/systm.h> | |
38 | #include <sys/namei.h> | |
39 | #include <sys/proc.h> | |
40 | #include <sys/kernel.h> | |
41 | #include <sys/vnode.h> | |
c7e94c3a KB |
42 | #include <sys/mount.h> |
43 | #include <sys/buf.h> | |
3a0a9bdc | 44 | #include <sys/mbuf.h> |
c7e94c3a KB |
45 | #include <sys/file.h> |
46 | #include <sys/disklabel.h> | |
47 | #include <sys/ioctl.h> | |
48 | #include <sys/errno.h> | |
49 | #include <sys/malloc.h> | |
3a0a9bdc | 50 | #include <sys/socket.h> |
cff1d696 KM |
51 | |
52 | #include <miscfs/specfs/specdev.h> | |
71e4e98b | 53 | |
d9f5f868 KB |
54 | #include <ufs/ufs/quota.h> |
55 | #include <ufs/ufs/inode.h> | |
56 | #include <ufs/ufs/ufsmount.h> | |
57 | #include <ufs/ufs/ufs_extern.h> | |
c6f5111d | 58 | |
d9f5f868 KB |
59 | #include <ufs/lfs/lfs.h> |
60 | #include <ufs/lfs/lfs_extern.h> | |
275ca4f0 | 61 | |
79a0d4bf | 62 | int lfs_mountfs __P((struct vnode *, struct mount *, struct proc *)); |
0b4d6502 KB |
63 | |
64 | struct vfsops lfs_vfsops = { | |
65 | lfs_mount, | |
5bf9d21f | 66 | ufs_start, |
0b4d6502 | 67 | lfs_unmount, |
52ff95c2 | 68 | ufs_root, |
8dc876c1 | 69 | ufs_quotactl, |
0b4d6502 KB |
70 | lfs_statfs, |
71 | lfs_sync, | |
f7802306 | 72 | lfs_vget, |
b16ed5f4 KM |
73 | lfs_fhtovp, |
74 | lfs_vptofh, | |
c7e94c3a | 75 | lfs_init, |
06ce3734 | 76 | lfs_sysctl, |
7188ac27 KM |
77 | }; |
78 | ||
c4c82039 KM |
79 | /* |
80 | * Called by main() when ufs is going to be mounted as root. | |
81 | */ | |
0b4d6502 | 82 | lfs_mountroot() |
71e4e98b | 83 | { |
c4c82039 KM |
84 | extern struct vnode *rootvp; |
85 | struct fs *fs; | |
86 | struct mount *mp; | |
87 | struct proc *p = curproc; /* XXX */ | |
88 | int error; | |
89 | ||
90 | /* | |
91 | * Get vnodes for swapdev and rootdev. | |
92 | */ | |
8b04865c KM |
93 | if ((error = bdevvp(swapdev, &swapdev_vp)) || |
94 | (error = bdevvp(rootdev, &rootvp))) { | |
95 | printf("lfs_mountroot: can't setup bdevvp's"); | |
96 | return (error); | |
97 | } | |
c4c82039 KM |
98 | if (error = vfs_rootmountalloc("lfs", "root_device", &mp)) |
99 | return (error); | |
100 | if (error = lfs_mountfs(rootvp, mp, p)) { | |
101 | mp->mnt_vfc->vfc_refcount--; | |
9cc53703 | 102 | vfs_unbusy(mp, p); |
c4c82039 KM |
103 | free(mp, M_MOUNT); |
104 | return (error); | |
105 | } | |
9cc53703 | 106 | simple_lock(&mountlist_slock); |
c4c82039 | 107 | CIRCLEQ_INSERT_TAIL(&mountlist, mp, mnt_list); |
9cc53703 | 108 | simple_unlock(&mountlist_slock); |
c4c82039 | 109 | (void)lfs_statfs(mp, &mp->mnt_stat, p); |
9cc53703 | 110 | vfs_unbusy(mp, p); |
c4c82039 | 111 | return (0); |
7188ac27 KM |
112 | } |
113 | ||
114 | /* | |
115 | * VFS Operations. | |
116 | * | |
117 | * mount system call | |
118 | */ | |
0b4d6502 | 119 | lfs_mount(mp, path, data, ndp, p) |
d45de50d | 120 | register struct mount *mp; |
7188ac27 KM |
121 | char *path; |
122 | caddr_t data; | |
123 | struct nameidata *ndp; | |
0eb6f54a | 124 | struct proc *p; |
7188ac27 KM |
125 | { |
126 | struct vnode *devvp; | |
127 | struct ufs_args args; | |
128 | struct ufsmount *ump; | |
d9f5f868 | 129 | register struct lfs *fs; /* LFS */ |
7188ac27 KM |
130 | u_int size; |
131 | int error; | |
38047d55 | 132 | mode_t accessmode; |
7188ac27 KM |
133 | |
134 | if (error = copyin(data, (caddr_t)&args, sizeof (struct ufs_args))) | |
135 | return (error); | |
c7e94c3a KB |
136 | |
137 | /* Until LFS can do NFS right. XXX */ | |
ea7e18a7 | 138 | if (args.export.ex_flags & MNT_EXPORTED) |
c7e94c3a | 139 | return (EINVAL); |
ea7e18a7 | 140 | |
190244fb MK |
141 | /* |
142 | * If updating, check whether changing from read-only to | |
143 | * read/write; if there is no device name, that's all we do. | |
144 | */ | |
145 | if (mp->mnt_flag & MNT_UPDATE) { | |
d48157d5 | 146 | ump = VFSTOUFS(mp); |
38047d55 KM |
147 | if (fs->lfs_ronly && (mp->mnt_flag & MNT_WANTRDWR)) { |
148 | /* | |
149 | * If upgrade to read-write by non-root, then verify | |
150 | * that user has necessary permissions on the device. | |
151 | */ | |
152 | if (p->p_ucred->cr_uid != 0) { | |
4a780c24 KM |
153 | vn_lock(ump->um_devvp, LK_EXCLUSIVE | LK_RETRY, |
154 | p); | |
38047d55 KM |
155 | if (error = VOP_ACCESS(ump->um_devvp, |
156 | VREAD | VWRITE, p->p_ucred, p)) { | |
4a780c24 | 157 | VOP_UNLOCK(ump->um_devvp, 0, p); |
38047d55 KM |
158 | return (error); |
159 | } | |
4a780c24 | 160 | VOP_UNLOCK(ump->um_devvp, 0, p); |
38047d55 | 161 | } |
0b4d6502 | 162 | fs->lfs_ronly = 0; |
38047d55 | 163 | } |
64583792 KM |
164 | if (args.fspec == 0) { |
165 | /* | |
166 | * Process export requests. | |
167 | */ | |
ea7e18a7 | 168 | return (vfs_export(mp, &ump->um_export, &args.export)); |
64583792 | 169 | } |
190244fb MK |
170 | } |
171 | /* | |
172 | * Not an update, or updating the name: look up the name | |
173 | * and verify that it refers to a sensible block device. | |
174 | */ | |
995e59df KM |
175 | NDINIT(ndp, LOOKUP, FOLLOW, UIO_USERSPACE, args.fspec, p); |
176 | if (error = namei(ndp)) | |
190244fb MK |
177 | return (error); |
178 | devvp = ndp->ni_vp; | |
179 | if (devvp->v_type != VBLK) { | |
180 | vrele(devvp); | |
181 | return (ENOTBLK); | |
182 | } | |
183 | if (major(devvp->v_rdev) >= nblkdev) { | |
184 | vrele(devvp); | |
185 | return (ENXIO); | |
186 | } | |
38047d55 KM |
187 | /* |
188 | * If mount by non-root, then verify that user has necessary | |
189 | * permissions on the device. | |
190 | */ | |
191 | if (p->p_ucred->cr_uid != 0) { | |
192 | accessmode = VREAD; | |
193 | if ((mp->mnt_flag & MNT_RDONLY) == 0) | |
194 | accessmode |= VWRITE; | |
4a780c24 | 195 | vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY, p); |
38047d55 KM |
196 | if (error = VOP_ACCESS(devvp, accessmode, p->p_ucred, p)) { |
197 | vput(devvp); | |
198 | return (error); | |
199 | } | |
4a780c24 | 200 | VOP_UNLOCK(devvp, 0, p); |
38047d55 | 201 | } |
190244fb | 202 | if ((mp->mnt_flag & MNT_UPDATE) == 0) |
0b4d6502 | 203 | error = lfs_mountfs(devvp, mp, p); /* LFS */ |
190244fb | 204 | else { |
d48157d5 KM |
205 | if (devvp != ump->um_devvp) |
206 | error = EINVAL; /* needs translation */ | |
2a7dbb09 KM |
207 | else |
208 | vrele(devvp); | |
d48157d5 | 209 | } |
7188ac27 KM |
210 | if (error) { |
211 | vrele(devvp); | |
212 | return (error); | |
27d00e76 | 213 | } |
7188ac27 | 214 | ump = VFSTOUFS(mp); |
0b4d6502 KB |
215 | fs = ump->um_lfs; /* LFS */ |
216 | #ifdef NOTLFS /* LFS */ | |
7188ac27 KM |
217 | (void) copyinstr(path, fs->fs_fsmnt, sizeof(fs->fs_fsmnt) - 1, &size); |
218 | bzero(fs->fs_fsmnt + size, sizeof(fs->fs_fsmnt) - size); | |
82161bc8 KM |
219 | bcopy((caddr_t)fs->fs_fsmnt, (caddr_t)mp->mnt_stat.f_mntonname, |
220 | MNAMELEN); | |
79a0d4bf | 221 | (void) copyinstr(args.fspec, mp->mnt_stat.f_mntfromname, MNAMELEN - 1, |
82161bc8 KM |
222 | &size); |
223 | bzero(mp->mnt_stat.f_mntfromname + size, MNAMELEN - size); | |
0eb6f54a | 224 | (void) ufs_statfs(mp, &mp->mnt_stat, p); |
0b4d6502 KB |
225 | #else |
226 | (void)copyinstr(path, fs->lfs_fsmnt, sizeof(fs->lfs_fsmnt) - 1, &size); | |
227 | bzero(fs->lfs_fsmnt + size, sizeof(fs->lfs_fsmnt) - size); | |
228 | bcopy((caddr_t)fs->lfs_fsmnt, (caddr_t)mp->mnt_stat.f_mntonname, | |
229 | MNAMELEN); | |
79a0d4bf | 230 | (void) copyinstr(args.fspec, mp->mnt_stat.f_mntfromname, MNAMELEN - 1, |
0b4d6502 KB |
231 | &size); |
232 | bzero(mp->mnt_stat.f_mntfromname + size, MNAMELEN - size); | |
233 | (void) lfs_statfs(mp, &mp->mnt_stat, p); | |
234 | #endif | |
7188ac27 | 235 | return (0); |
71e4e98b SL |
236 | } |
237 | ||
7188ac27 KM |
238 | /* |
239 | * Common code for mount and mountroot | |
0b4d6502 | 240 | * LFS specific |
7188ac27 | 241 | */ |
79a0d4bf | 242 | int |
0b4d6502 | 243 | lfs_mountfs(devvp, mp, p) |
1182ae61 | 244 | register struct vnode *devvp; |
7188ac27 | 245 | struct mount *mp; |
0eb6f54a | 246 | struct proc *p; |
71e4e98b | 247 | { |
1c26e003 | 248 | extern struct vnode *rootvp; |
d9f5f868 | 249 | register struct lfs *fs; |
0b4d6502 | 250 | register struct ufsmount *ump; |
0b4d6502 KB |
251 | struct vnode *vp; |
252 | struct buf *bp; | |
253 | struct partinfo dpart; | |
0b4d6502 KB |
254 | dev_t dev; |
255 | int error, i, ronly, size; | |
9f246d5e | 256 | struct ucred *cred; |
71e4e98b | 257 | |
9f246d5e | 258 | cred = p ? p->p_ucred : NOCRED; |
ad787160 C |
259 | /* |
260 | * Disallow multiple mounts of the same device. | |
261 | * Disallow mounting of a device that is currently in use | |
262 | * (except for root, which might share swap device for miniroot). | |
263 | * Flush out any old buffers remaining from a previous use. | |
264 | */ | |
ed554bc5 | 265 | if (error = vfs_mountedon(devvp)) |
ad787160 C |
266 | return (error); |
267 | if (vcount(devvp) > 1 && devvp != rootvp) | |
268 | return (EBUSY); | |
fd88f5c5 | 269 | if (error = vinvalbuf(devvp, V_SAVE, cred, p, 0, 0)) |
ad787160 C |
270 | return (error); |
271 | ||
272 | ronly = (mp->mnt_flag & MNT_RDONLY) != 0; | |
1feabdab | 273 | if (error = VOP_OPEN(devvp, ronly ? FREAD : FREAD|FWRITE, FSCRED, p)) |
7188ac27 | 274 | return (error); |
0b4d6502 | 275 | |
9f246d5e | 276 | if (VOP_IOCTL(devvp, DIOCGPART, (caddr_t)&dpart, FREAD, cred, p) != 0) |
609e7cfa | 277 | size = DEV_BSIZE; |
0eb6f54a | 278 | else { |
ec67a3ce | 279 | size = dpart.disklab->d_secsize; |
0b4d6502 KB |
280 | #ifdef NEVER_USED |
281 | dpart.part->p_fstype = FS_LFS; | |
282 | dpart.part->p_fsize = fs->lfs_fsize; /* frag size */ | |
283 | dpart.part->p_frag = fs->lfs_frag; /* frags per block */ | |
284 | dpart.part->p_cpg = fs->lfs_segshift; /* segment shift */ | |
285 | #endif | |
7188ac27 | 286 | } |
0b4d6502 KB |
287 | |
288 | /* Don't free random space on error. */ | |
289 | bp = NULL; | |
290 | ump = NULL; | |
291 | ||
292 | /* Read in the superblock. */ | |
9f246d5e | 293 | if (error = bread(devvp, LFS_LABELPAD / size, LFS_SBPAD, cred, &bp)) |
71e4e98b | 294 | goto out; |
ed554bc5 | 295 | fs = (struct lfs *)bp->b_data; |
ad787160 C |
296 | |
297 | /* Check the basics. */ | |
298 | if (fs->lfs_magic != LFS_MAGIC || fs->lfs_bsize > MAXBSIZE || | |
299 | fs->lfs_bsize < sizeof(struct lfs)) { | |
8dc876c1 | 300 | error = EINVAL; /* XXX needs translation */ |
1c281610 MK |
301 | goto out; |
302 | } | |
0b4d6502 KB |
303 | |
304 | /* Allocate the mount structure, copy the superblock into it. */ | |
8dc876c1 | 305 | ump = (struct ufsmount *)malloc(sizeof *ump, M_UFSMNT, M_WAITOK); |
0c0b26ec | 306 | fs = ump->um_lfs = malloc(sizeof(struct lfs), M_UFSMNT, M_WAITOK); |
cb84e0ab | 307 | bcopy(bp->b_data, fs, sizeof(struct lfs)); |
d9f5f868 | 308 | if (sizeof(struct lfs) < LFS_SBPAD) /* XXX why? */ |
5d96a9ad | 309 | bp->b_flags |= B_INVAL; |
e018935f MK |
310 | brelse(bp); |
311 | bp = NULL; | |
0b4d6502 | 312 | |
d5075120 KB |
313 | /* Set up the I/O information */ |
314 | fs->lfs_iocount = 0; | |
d5075120 | 315 | |
0c0b26ec | 316 | /* Set up the ifile and lock aflags */ |
3ce71481 KB |
317 | fs->lfs_doifile = 0; |
318 | fs->lfs_writer = 0; | |
319 | fs->lfs_dirops = 0; | |
0c0b26ec | 320 | fs->lfs_seglock = 0; |
3ce71481 | 321 | |
0b4d6502 | 322 | /* Set the file system readonly/modify bits. */ |
0b4d6502 | 323 | fs->lfs_ronly = ronly; |
71e4e98b | 324 | if (ronly == 0) |
0b4d6502 KB |
325 | fs->lfs_fmod = 1; |
326 | ||
327 | /* Initialize the mount structure. */ | |
328 | dev = devvp->v_rdev; | |
82161bc8 KM |
329 | mp->mnt_data = (qaddr_t)ump; |
330 | mp->mnt_stat.f_fsid.val[0] = (long)dev; | |
06ce3734 | 331 | mp->mnt_stat.f_fsid.val[1] = lfs_mount_type; |
b390cbb0 | 332 | mp->mnt_maxsymlinklen = fs->lfs_maxsymlinklen; |
82161bc8 | 333 | mp->mnt_flag |= MNT_LOCAL; |
7188ac27 KM |
334 | ump->um_mountp = mp; |
335 | ump->um_dev = dev; | |
336 | ump->um_devvp = devvp; | |
5e539b49 MS |
337 | ump->um_bptrtodb = 0; |
338 | ump->um_seqinc = 1 << fs->lfs_fsbtodb; | |
339 | ump->um_nindir = fs->lfs_nindir; | |
8dc876c1 KM |
340 | for (i = 0; i < MAXQUOTAS; i++) |
341 | ump->um_quotas[i] = NULLVP; | |
f9c367e8 | 342 | devvp->v_specflags |= SI_MOUNTEDON; |
7188ac27 | 343 | |
f9c367e8 KB |
344 | /* |
345 | * We use the ifile vnode for almost every operation. Instead of | |
346 | * retrieving it from the hash table each time we retrieve it here, | |
347 | * artificially increment the reference count and keep a pointer | |
348 | * to it in the incore copy of the superblock. | |
349 | */ | |
f7802306 | 350 | if (error = VFS_VGET(mp, LFS_IFILE_INUM, &vp)) |
0b4d6502 | 351 | goto out; |
0b4d6502 | 352 | fs->lfs_ivnode = vp; |
f9c367e8 KB |
353 | VREF(vp); |
354 | vput(vp); | |
0b4d6502 | 355 | |
7188ac27 | 356 | return (0); |
71e4e98b | 357 | out: |
c86c9b6e KM |
358 | if (bp) |
359 | brelse(bp); | |
9f246d5e | 360 | (void)VOP_CLOSE(devvp, ronly ? FREAD : FREAD|FWRITE, cred, p); |
8dc876c1 | 361 | if (ump) { |
ece51ee9 | 362 | free(ump->um_lfs, M_UFSMNT); |
d9f5f868 | 363 | free(ump, M_UFSMNT); |
82161bc8 | 364 | mp->mnt_data = (qaddr_t)0; |
27d00e76 | 365 | } |
7188ac27 | 366 | return (error); |
71e4e98b SL |
367 | } |
368 | ||
7188ac27 KM |
369 | /* |
370 | * unmount system call | |
371 | */ | |
0b4d6502 | 372 | lfs_unmount(mp, mntflags, p) |
7188ac27 | 373 | struct mount *mp; |
8dc876c1 | 374 | int mntflags; |
0eb6f54a | 375 | struct proc *p; |
71e4e98b | 376 | { |
d9f5f868 | 377 | extern int doforce; |
7188ac27 | 378 | register struct ufsmount *ump; |
0c0b26ec | 379 | register struct lfs *fs; |
f7802306 | 380 | int i, error, flags, ronly; |
71e4e98b | 381 | |
f7802306 | 382 | flags = 0; |
fe5239dc | 383 | if (mntflags & MNT_FORCE) |
8dc876c1 | 384 | flags |= FORCECLOSE; |
3ce71481 | 385 | |
7188ac27 | 386 | ump = VFSTOUFS(mp); |
3ce71481 | 387 | fs = ump->um_lfs; |
71e4e98b | 388 | #ifdef QUOTA |
82161bc8 | 389 | if (mp->mnt_flag & MNT_QUOTA) { |
3ce71481 | 390 | if (error = vflush(mp, fs->lfs_ivnode, SKIPSYSTEM|flags)) |
6d943995 | 391 | return (error); |
8dc876c1 KM |
392 | for (i = 0; i < MAXQUOTAS; i++) { |
393 | if (ump->um_quotas[i] == NULLVP) | |
394 | continue; | |
70a360ba | 395 | quotaoff(p, mp, i); |
8dc876c1 | 396 | } |
6d943995 | 397 | /* |
8dc876c1 KM |
398 | * Here we fall through to vflush again to ensure |
399 | * that we have gotten rid of all the system vnodes. | |
6d943995 | 400 | */ |
8dc876c1 | 401 | } |
71e4e98b | 402 | #endif |
f7802306 | 403 | if (error = vflush(mp, fs->lfs_ivnode, flags)) |
6d943995 | 404 | return (error); |
0c0b26ec | 405 | fs->lfs_clean = 1; |
f7802306 KB |
406 | if (error = VFS_SYNC(mp, 1, p->p_ucred, p)) |
407 | return (error); | |
eb49bed5 | 408 | if (fs->lfs_ivnode->v_dirtyblkhd.lh_first) |
f7802306 | 409 | panic("lfs_unmount: still dirty blocks on ifile vnode\n"); |
4c9381d8 | 410 | vrele(fs->lfs_ivnode); |
f7802306 KB |
411 | vgone(fs->lfs_ivnode); |
412 | ||
0b4d6502 | 413 | ronly = !fs->lfs_ronly; |
ad787160 C |
414 | ump->um_devvp->v_specflags &= ~SI_MOUNTEDON; |
415 | error = VOP_CLOSE(ump->um_devvp, | |
416 | ronly ? FREAD : FREAD|FWRITE, NOCRED, p); | |
417 | vrele(ump->um_devvp); | |
418 | free(fs, M_UFSMNT); | |
419 | free(ump, M_UFSMNT); | |
420 | mp->mnt_data = (qaddr_t)0; | |
421 | mp->mnt_flag &= ~MNT_LOCAL; | |
422 | return (error); | |
423 | } | |
424 | ||
ad787160 | 425 | /* |
7188ac27 KM |
426 | * Get file system statistics. |
427 | */ | |
0b4d6502 | 428 | lfs_statfs(mp, sbp, p) |
7188ac27 KM |
429 | struct mount *mp; |
430 | register struct statfs *sbp; | |
0eb6f54a | 431 | struct proc *p; |
7188ac27 | 432 | { |
d9f5f868 | 433 | register struct lfs *fs; |
7188ac27 | 434 | register struct ufsmount *ump; |
7188ac27 KM |
435 | |
436 | ump = VFSTOUFS(mp); | |
0b4d6502 KB |
437 | fs = ump->um_lfs; |
438 | if (fs->lfs_magic != LFS_MAGIC) | |
439 | panic("lfs_statfs: magic"); | |
9e8b5f02 | 440 | sbp->f_bsize = fs->lfs_fsize; |
cc173077 | 441 | sbp->f_iosize = fs->lfs_bsize; |
9e8b5f02 MS |
442 | sbp->f_blocks = dbtofrags(fs,fs->lfs_dsize); |
443 | sbp->f_bfree = dbtofrags(fs, fs->lfs_bfree); | |
a50a16b5 KM |
444 | /* |
445 | * To compute the available space. Subtract the minimum free | |
446 | * from the total number of blocks in the file system. Set avail | |
447 | * to the smaller of this number and fs->lfs_bfree. | |
448 | */ | |
449 | sbp->f_bavail = fs->lfs_dsize * (100 - fs->lfs_minfree) / 100; | |
450 | sbp->f_bavail = | |
451 | sbp->f_bavail > fs->lfs_bfree ? fs->lfs_bfree : sbp->f_bavail; | |
9e8b5f02 | 452 | sbp->f_bavail = dbtofrags(fs, sbp->f_bavail); |
0b4d6502 | 453 | sbp->f_files = fs->lfs_nfiles; |
435a74c9 | 454 | sbp->f_ffree = sbp->f_bfree * INOPB(fs); |
82161bc8 | 455 | if (sbp != &mp->mnt_stat) { |
06ce3734 | 456 | sbp->f_type = mp->mnt_vfc->vfc_typenum; |
82161bc8 | 457 | bcopy((caddr_t)mp->mnt_stat.f_mntonname, |
d45de50d | 458 | (caddr_t)&sbp->f_mntonname[0], MNAMELEN); |
82161bc8 | 459 | bcopy((caddr_t)mp->mnt_stat.f_mntfromname, |
d45de50d KM |
460 | (caddr_t)&sbp->f_mntfromname[0], MNAMELEN); |
461 | } | |
7188ac27 KM |
462 | return (0); |
463 | } | |
464 | ||
7188ac27 KM |
465 | /* |
466 | * Go through the disk queues to initiate sandbagged IO; | |
467 | * go through the inodes to write those that have been modified; | |
468 | * initiate the writing of the super block if it has been modified. | |
8dc876c1 KM |
469 | * |
470 | * Note: we are always called with the filesystem marked `MPBUSY'. | |
7188ac27 | 471 | */ |
f7802306 | 472 | lfs_sync(mp, waitfor, cred, p) |
71e4e98b | 473 | struct mount *mp; |
7188ac27 | 474 | int waitfor; |
f7802306 KB |
475 | struct ucred *cred; |
476 | struct proc *p; | |
71e4e98b | 477 | { |
275ca4f0 | 478 | int error; |
7188ac27 | 479 | |
c9cbb645 | 480 | /* All syncs must be checkpoints until roll-forward is implemented. */ |
d2495626 | 481 | error = lfs_segwrite(mp, SEGM_CKP | (waitfor ? SEGM_SYNC : 0)); |
8dc876c1 KM |
482 | #ifdef QUOTA |
483 | qsync(mp); | |
484 | #endif | |
275ca4f0 | 485 | return (error); |
7188ac27 | 486 | } |
b16ed5f4 | 487 | |
f7802306 KB |
488 | /* |
489 | * Look up an LFS dinode number to find its incore vnode. If not already | |
490 | * in core, read it in from the specified device. Return the inode locked. | |
491 | * Detection and handling of mount points must be done by the calling routine. | |
492 | */ | |
493 | int | |
494 | lfs_vget(mp, ino, vpp) | |
495 | struct mount *mp; | |
496 | ino_t ino; | |
497 | struct vnode **vpp; | |
498 | { | |
499 | register struct lfs *fs; | |
500 | register struct inode *ip; | |
501 | struct buf *bp; | |
502 | struct ifile *ifp; | |
503 | struct vnode *vp; | |
504 | struct ufsmount *ump; | |
89e2bb79 | 505 | ufs_daddr_t daddr; |
f7802306 KB |
506 | dev_t dev; |
507 | int error; | |
508 | ||
f7802306 KB |
509 | ump = VFSTOUFS(mp); |
510 | dev = ump->um_dev; | |
511 | if ((*vpp = ufs_ihashget(dev, ino)) != NULL) | |
512 | return (0); | |
513 | ||
514 | /* Translate the inode number to a disk address. */ | |
515 | fs = ump->um_lfs; | |
516 | if (ino == LFS_IFILE_INUM) | |
517 | daddr = fs->lfs_idaddr; | |
518 | else { | |
519 | LFS_IENTRY(ifp, fs, ino, bp); | |
520 | daddr = ifp->if_daddr; | |
521 | brelse(bp); | |
522 | if (daddr == LFS_UNUSED_DADDR) | |
523 | return (ENOENT); | |
524 | } | |
525 | ||
526 | /* Allocate new vnode/inode. */ | |
527 | if (error = lfs_vcreate(mp, ino, &vp)) { | |
528 | *vpp = NULL; | |
529 | return (error); | |
530 | } | |
531 | ||
532 | /* | |
533 | * Put it onto its hash chain and lock it so that other requests for | |
534 | * this inode will block if they arrive while we are sleeping waiting | |
535 | * for old data structures to be purged or for the contents of the | |
536 | * disk portion of this inode to be read. | |
537 | */ | |
538 | ip = VTOI(vp); | |
539 | ufs_ihashins(ip); | |
540 | ||
541 | /* | |
542 | * XXX | |
543 | * This may not need to be here, logically it should go down with | |
544 | * the i_devvp initialization. | |
545 | * Ask Kirk. | |
546 | */ | |
547 | ip->i_lfs = ump->um_lfs; | |
548 | ||
549 | /* Read in the disk contents for the inode, copy into the inode. */ | |
550 | if (error = | |
551 | bread(ump->um_devvp, daddr, (int)fs->lfs_bsize, NOCRED, &bp)) { | |
552 | /* | |
f345d060 KM |
553 | * The inode does not contain anything useful, so it would |
554 | * be misleading to leave it on its hash chain. With mode | |
555 | * still zero, it will be unlinked and returned to the free | |
556 | * list by vput(). | |
f7802306 | 557 | */ |
eca11e88 | 558 | vput(vp); |
f7802306 KB |
559 | brelse(bp); |
560 | *vpp = NULL; | |
561 | return (error); | |
562 | } | |
cb84e0ab | 563 | ip->i_din = *lfs_ifind(fs, ino, (struct dinode *)bp->b_data); |
f7802306 KB |
564 | brelse(bp); |
565 | ||
566 | /* | |
567 | * Initialize the vnode from the inode, check for aliases. In all | |
568 | * cases re-init ip, the underlying vnode/inode may have changed. | |
569 | */ | |
570 | if (error = ufs_vinit(mp, lfs_specop_p, LFS_FIFOOPS, &vp)) { | |
eca11e88 | 571 | vput(vp); |
f7802306 KB |
572 | *vpp = NULL; |
573 | return (error); | |
574 | } | |
575 | /* | |
576 | * Finish inode initialization now that aliasing has been resolved. | |
577 | */ | |
578 | ip->i_devvp = ump->um_devvp; | |
579 | VREF(ip->i_devvp); | |
580 | *vpp = vp; | |
581 | return (0); | |
582 | } | |
583 | ||
b16ed5f4 KM |
584 | /* |
585 | * File handle to vnode | |
586 | * | |
587 | * Have to be really careful about stale file handles: | |
588 | * - check that the inode number is valid | |
589 | * - call lfs_vget() to get the locked inode | |
590 | * - check for an unallocated inode (i_mode == 0) | |
9e4a3a4a KM |
591 | * - check that the given client host has export rights and return |
592 | * those rights via. exflagsp and credanonp | |
b16ed5f4 KM |
593 | * |
594 | * XXX | |
595 | * use ifile to see if inode is allocated instead of reading off disk | |
596 | * what is the relationship between my generational number and the NFS | |
597 | * generational number. | |
598 | */ | |
599 | int | |
3a0a9bdc | 600 | lfs_fhtovp(mp, fhp, nam, vpp, exflagsp, credanonp) |
b16ed5f4 KM |
601 | register struct mount *mp; |
602 | struct fid *fhp; | |
3a0a9bdc | 603 | struct mbuf *nam; |
b16ed5f4 | 604 | struct vnode **vpp; |
3a0a9bdc KM |
605 | int *exflagsp; |
606 | struct ucred **credanonp; | |
b16ed5f4 | 607 | { |
b16ed5f4 | 608 | register struct ufid *ufhp; |
b16ed5f4 KM |
609 | |
610 | ufhp = (struct ufid *)fhp; | |
611 | if (ufhp->ufid_ino < ROOTINO) | |
3a0a9bdc | 612 | return (ESTALE); |
485cf2ee | 613 | return (ufs_check_export(mp, ufhp, nam, vpp, exflagsp, credanonp)); |
b16ed5f4 KM |
614 | } |
615 | ||
616 | /* | |
617 | * Vnode pointer to File handle | |
618 | */ | |
619 | /* ARGSUSED */ | |
620 | lfs_vptofh(vp, fhp) | |
621 | struct vnode *vp; | |
622 | struct fid *fhp; | |
623 | { | |
624 | register struct inode *ip; | |
625 | register struct ufid *ufhp; | |
626 | ||
627 | ip = VTOI(vp); | |
628 | ufhp = (struct ufid *)fhp; | |
629 | ufhp->ufid_len = sizeof(struct ufid); | |
630 | ufhp->ufid_ino = ip->i_number; | |
631 | ufhp->ufid_gen = ip->i_gen; | |
632 | return (0); | |
633 | } | |
06ce3734 KM |
634 | |
635 | /* | |
636 | * Initialize the filesystem, most work done by ufs_init. | |
637 | */ | |
638 | int lfs_mount_type; | |
639 | ||
640 | int | |
641 | lfs_init(vfsp) | |
642 | struct vfsconf *vfsp; | |
643 | { | |
644 | ||
645 | lfs_mount_type = vfsp->vfc_typenum; | |
646 | return (ufs_init(vfsp)); | |
647 | } |