Annotation of src/sys/adosfs/advfsops.c, Revision 1.56
1.56 ! mycroft 1: /* $NetBSD: advfsops.c,v 1.55 2002/09/21 18:10:04 christos Exp $ */
1.4 cgd 2:
1.1 chopps 3: /*
4: * Copyright (c) 1994 Christian E. Hopps
1.17 mhitch 5: * Copyright (c) 1996 Matthias Scheler
1.1 chopps 6: * All rights reserved.
7: *
8: * Redistribution and use in source and binary forms, with or without
9: * modification, are permitted provided that the following conditions
10: * are met:
11: * 1. Redistributions of source code must retain the above copyright
12: * notice, this list of conditions and the following disclaimer.
13: * 2. Redistributions in binary form must reproduce the above copyright
14: * notice, this list of conditions and the following disclaimer in the
15: * documentation and/or other materials provided with the distribution.
16: * 3. All advertising materials mentioning features or use of this software
17: * must display the following acknowledgement:
18: * This product includes software developed by Christian E. Hopps.
19: * 4. The name of the author may not be used to endorse or promote products
20: * derived from this software without specific prior written permission
21: *
22: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
23: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
24: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
25: * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
26: * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
27: * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29: * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
31: * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32: */
1.50 lukem 33:
34: #include <sys/cdefs.h>
1.56 ! mycroft 35: __KERNEL_RCSID(0, "$NetBSD: advfsops.c,v 1.55 2002/09/21 18:10:04 christos Exp $");
1.29 jonathan 36:
1.46 mrg 37: #if defined(_KERNEL_OPT)
1.29 jonathan 38: #include "opt_compat_netbsd.h"
39: #endif
40:
1.1 chopps 41: #include <sys/param.h>
42: #include <sys/systm.h>
43: #include <sys/vnode.h>
44: #include <sys/mount.h>
1.2 chopps 45: #include <sys/proc.h>
1.1 chopps 46: #include <sys/time.h>
47: #include <sys/malloc.h>
1.31 thorpej 48: #include <sys/pool.h>
1.1 chopps 49: #include <sys/disklabel.h>
50: #include <miscfs/specfs/specdev.h> /* XXX */
51: #include <sys/fcntl.h>
52: #include <sys/namei.h>
53: #include <sys/ioctl.h>
54: #include <sys/queue.h>
55: #include <sys/buf.h>
1.54 gehenna 56: #include <sys/conf.h>
1.1 chopps 57: #include <adosfs/adosfs.h>
58:
1.16 christos 59: void adosfs_init __P((void));
1.47 chs 60: void adosfs_reinit __P((void));
1.42 jdolecek 61: void adosfs_done __P((void));
1.24 cgd 62: int adosfs_mount __P((struct mount *, const char *, void *, struct nameidata *,
1.16 christos 63: struct proc *));
64: int adosfs_start __P((struct mount *, int, struct proc *));
65: int adosfs_unmount __P((struct mount *, int, struct proc *));
66: int adosfs_root __P((struct mount *, struct vnode **));
67: int adosfs_quotactl __P((struct mount *, int, uid_t, caddr_t, struct proc *));
68: int adosfs_statfs __P((struct mount *, struct statfs *, struct proc *));
69: int adosfs_sync __P((struct mount *, int, struct ucred *, struct proc *));
70: int adosfs_vget __P((struct mount *, ino_t, struct vnode **));
1.35 wrstuden 71: int adosfs_fhtovp __P((struct mount *, struct fid *, struct vnode **));
72: int adosfs_checkexp __P((struct mount *, struct mbuf *, int *,
73: struct ucred **));
1.16 christos 74: int adosfs_vptofh __P((struct vnode *, struct fid *));
75:
76: int adosfs_mountfs __P((struct vnode *, struct mount *, struct proc *));
1.17 mhitch 77: int adosfs_loadbitmap __P((struct adosfsmount *));
1.28 fvdl 78: int adosfs_sysctl __P((int *, u_int, void *, size_t *, void *, size_t,
79: struct proc *));
80:
81: struct simplelock adosfs_hashlock;
1.16 christos 82:
1.31 thorpej 83: struct pool adosfs_node_pool;
84:
1.49 chs 85: struct genfs_ops adosfs_genfsops = {
86: genfs_size,
87: };
1.52 matt 88:
89: int (**adosfs_vnodeop_p) __P((void *));
1.49 chs 90:
1.1 chopps 91: int
92: adosfs_mount(mp, path, data, ndp, p)
93: struct mount *mp;
1.24 cgd 94: const char *path;
95: void *data;
1.1 chopps 96: struct nameidata *ndp;
97: struct proc *p;
98: {
1.9 mycroft 99: struct vnode *devvp;
1.1 chopps 100: struct adosfs_args args;
1.9 mycroft 101: struct adosfsmount *amp;
1.12 mycroft 102: size_t size;
1.1 chopps 103: int error;
1.9 mycroft 104: mode_t accessmode;
1.1 chopps 105:
1.55 christos 106: if (mp->mnt_flag & MNT_GETARGS) {
107: amp = VFSTOADOSFS(mp);
108: if (amp == NULL)
109: return EIO;
110: args.uid = amp->uid;
111: args.gid = amp->gid;
112: args.mask = amp->mask;
113: args.fspec = NULL;
1.56 ! mycroft 114: vfs_showexport(mp, &args.export, &->export);
1.55 christos 115: return copyout(&args, data, sizeof(args));
116: }
1.16 christos 117: error = copyin(data, (caddr_t)&args, sizeof(struct adosfs_args));
118: if (error)
1.1 chopps 119: return(error);
120:
1.9 mycroft 121: if ((mp->mnt_flag & MNT_RDONLY) == 0)
122: return (EROFS);
123: /*
1.14 chopps 124: * If updating, check whether changing from read-only to
125: * read/write; if there is no device name, that's all we do.
126: */
127: if (mp->mnt_flag & MNT_UPDATE) {
128: amp = VFSTOADOSFS(mp);
129: if (args.fspec == 0)
130: return (vfs_export(mp, &->export, &args.export));
131: }
132: /*
1.9 mycroft 133: * Not an update, or updating the name: look up the name
134: * and verify that it refers to a sensible block device.
1.1 chopps 135: */
1.2 chopps 136: NDINIT(ndp, LOOKUP, FOLLOW, UIO_USERSPACE, args.fspec, p);
1.16 christos 137: if ((error = namei(ndp)) != 0)
1.2 chopps 138: return (error);
1.9 mycroft 139: devvp = ndp->ni_vp;
1.2 chopps 140:
1.9 mycroft 141: if (devvp->v_type != VBLK) {
142: vrele(devvp);
1.2 chopps 143: return (ENOTBLK);
1.1 chopps 144: }
1.54 gehenna 145: if (bdevsw_lookup(devvp->v_rdev) == NULL) {
1.9 mycroft 146: vrele(devvp);
1.2 chopps 147: return (ENXIO);
1.1 chopps 148: }
1.9 mycroft 149: /*
150: * If mount by non-root, then verify that user has necessary
151: * permissions on the device.
152: */
153: if (p->p_ucred->cr_uid != 0) {
154: accessmode = VREAD;
155: if ((mp->mnt_flag & MNT_RDONLY) == 0)
156: accessmode |= VWRITE;
1.28 fvdl 157: vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY);
1.16 christos 158: error = VOP_ACCESS(devvp, accessmode, p->p_ucred, p);
159: if (error) {
1.9 mycroft 160: vput(devvp);
161: return (error);
162: }
1.28 fvdl 163: VOP_UNLOCK(devvp, 0);
1.9 mycroft 164: }
1.14 chopps 165: /* MNT_UPDATE? */
1.16 christos 166: if ((error = adosfs_mountfs(devvp, mp, p)) != 0) {
1.9 mycroft 167: vrele(devvp);
168: return (error);
169: }
170: amp = VFSTOADOSFS(mp);
171: amp->uid = args.uid;
172: amp->gid = args.gid;
173: amp->mask = args.mask;
174: (void) copyinstr(path, mp->mnt_stat.f_mntonname, MNAMELEN - 1, &size);
1.30 perry 175: memset(mp->mnt_stat.f_mntonname + size, 0, MNAMELEN - size);
1.9 mycroft 176: (void) copyinstr(args.fspec, mp->mnt_stat.f_mntfromname, MNAMELEN - 1,
177: &size);
1.30 perry 178: memset(mp->mnt_stat.f_mntfromname + size, 0, MNAMELEN - size);
1.9 mycroft 179: return (0);
1.1 chopps 180: }
181:
182: int
1.9 mycroft 183: adosfs_mountfs(devvp, mp, p)
184: struct vnode *devvp;
1.1 chopps 185: struct mount *mp;
186: struct proc *p;
187: {
188: struct disklabel dl;
189: struct partition *parp;
1.10 mycroft 190: struct adosfsmount *amp;
1.17 mhitch 191: struct buf *bp;
1.2 chopps 192: struct vnode *rvp;
1.11 cgd 193: int error, part, i;
1.1 chopps 194:
1.9 mycroft 195: part = DISKPART(devvp->v_rdev);
1.2 chopps 196: amp = NULL;
1.9 mycroft 197:
1.1 chopps 198: /*
1.9 mycroft 199: * Disallow multiple mounts of the same device.
200: * Disallow mounting of a device that is currently in use
201: * (except for root, which might share swap device for miniroot).
202: * Flush out any old buffers remaining from a previous use.
1.1 chopps 203: */
1.16 christos 204: if ((error = vfs_mountedon(devvp)) != 0)
1.2 chopps 205: return (error);
1.9 mycroft 206: if (vcount(devvp) > 1 && devvp != rootvp)
1.2 chopps 207: return (EBUSY);
1.16 christos 208: if ((error = vinvalbuf(devvp, V_SAVE, p->p_ucred, p, 0, 0)) != 0)
1.2 chopps 209: return (error);
1.1 chopps 210:
211: /*
1.2 chopps 212: * open blkdev and read root block
1.1 chopps 213: */
1.16 christos 214: if ((error = VOP_OPEN(devvp, FREAD, NOCRED, p)) != 0)
1.2 chopps 215: return (error);
1.16 christos 216: error = VOP_IOCTL(devvp, DIOCGDINFO,(caddr_t)&dl, FREAD, NOCRED, p);
217: if (error)
1.1 chopps 218: goto fail;
219:
220: parp = &dl.d_partitions[part];
1.10 mycroft 221: amp = malloc(sizeof(struct adosfsmount), M_ADOSFSMNT, M_WAITOK);
1.30 perry 222: memset((char *)amp, 0, (u_long)sizeof(struct adosfsmount));
1.1 chopps 223: amp->mp = mp;
1.17 mhitch 224: if (dl.d_type == DTYPE_FLOPPY) {
225: amp->bsize = dl.d_secsize;
226: amp->secsperblk = 1;
227: }
228: else {
229: amp->bsize = parp->p_fsize * parp->p_frag;
230: amp->secsperblk = parp->p_frag;
231: }
1.43 jdolecek 232:
233: /* invalid fs ? */
234: if (amp->secsperblk == 0) {
235: error = EINVAL;
236: goto fail;
237: }
1.17 mhitch 238:
239: bp = NULL;
240: if ((error = bread(devvp, (daddr_t)BBOFF,
1.32 bouyer 241: amp->bsize, NOCRED, &bp)) != 0) {
242: brelse(bp);
1.17 mhitch 243: goto fail;
1.32 bouyer 244: }
1.17 mhitch 245: amp->dostype = adoswordn(bp, 0);
246: brelse(bp);
247:
1.43 jdolecek 248: /* basic sanity checks */
1.17 mhitch 249: if (amp->dostype < 0x444f5300 || amp->dostype > 0x444f5305) {
250: error = EINVAL;
251: goto fail;
252: }
1.43 jdolecek 253:
254: amp->rootb = (parp->p_size / amp->secsperblk - 1 + parp->p_cpg) >> 1;
255: amp->numblks = parp->p_size / amp->secsperblk - parp->p_cpg;
1.17 mhitch 256:
1.1 chopps 257: amp->nwords = amp->bsize >> 2;
1.17 mhitch 258: amp->dbsize = amp->bsize - (IS_FFS(amp) ? 0 : OFS_DATA_OFFSET);
1.9 mycroft 259: amp->devvp = devvp;
1.1 chopps 260:
1.53 soren 261: mp->mnt_data = amp;
1.9 mycroft 262: mp->mnt_stat.f_fsid.val[0] = (long)devvp->v_rdev;
1.1 chopps 263: mp->mnt_stat.f_fsid.val[1] = makefstype(MOUNT_ADOSFS);
1.45 chs 264: mp->mnt_fs_bshift = ffs(amp->bsize) - 1;
265: mp->mnt_dev_bshift = DEV_BSHIFT; /* XXX */
1.9 mycroft 266: mp->mnt_flag |= MNT_LOCAL;
1.1 chopps 267:
268: /*
269: * init anode table.
270: */
271: for (i = 0; i < ANODEHASHSZ; i++)
272: LIST_INIT(&->anodetab[i]);
273:
274: /*
275: * get the root anode, if not a valid fs this will fail.
276: */
1.16 christos 277: if ((error = VFS_ROOT(mp, &rvp)) != 0)
1.1 chopps 278: goto fail;
1.17 mhitch 279: /* allocate and load bitmap, set free space */
280: amp->bitmap = malloc(((amp->numblks + 31) / 32) * sizeof(*amp->bitmap),
281: M_ADOSFSBITMAP, M_WAITOK);
282: if (amp->bitmap)
283: adosfs_loadbitmap(amp);
284: if (mp->mnt_flag & MNT_RDONLY && amp->bitmap) {
285: /*
286: * Don't need the bitmap any more if it's read-only.
287: */
288: free(amp->bitmap, M_ADOSFSBITMAP);
289: amp->bitmap = NULL;
290: }
1.2 chopps 291: vput(rvp);
292:
1.1 chopps 293: return(0);
1.9 mycroft 294:
1.1 chopps 295: fail:
1.38 wrstuden 296: vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY);
1.9 mycroft 297: (void) VOP_CLOSE(devvp, FREAD, NOCRED, p);
1.38 wrstuden 298: VOP_UNLOCK(devvp, 0);
1.17 mhitch 299: if (amp && amp->bitmap)
300: free(amp->bitmap, M_ADOSFSBITMAP);
1.2 chopps 301: if (amp)
302: free(amp, M_ADOSFSMNT);
1.9 mycroft 303: return (error);
1.1 chopps 304: }
305:
306: int
307: adosfs_start(mp, flags, p)
308: struct mount *mp;
309: int flags;
310: struct proc *p;
311: {
1.9 mycroft 312:
313: return (0);
1.1 chopps 314: }
315:
316: int
1.9 mycroft 317: adosfs_unmount(mp, mntflags, p)
1.1 chopps 318: struct mount *mp;
1.9 mycroft 319: int mntflags;
1.1 chopps 320: struct proc *p;
321: {
1.10 mycroft 322: struct adosfsmount *amp;
1.9 mycroft 323: int error, flags;
1.1 chopps 324:
1.9 mycroft 325: flags = 0;
326: if (mntflags & MNT_FORCE)
327: flags |= FORCECLOSE;
1.16 christos 328: if ((error = vflush(mp, NULLVP, flags)) != 0)
1.9 mycroft 329: return (error);
1.1 chopps 330: amp = VFSTOADOSFS(mp);
1.39 enami 331: if (amp->devvp->v_type != VBAD)
1.41 tron 332: amp->devvp->v_specmountpoint = NULL;
1.37 wrstuden 333: vn_lock(amp->devvp, LK_EXCLUSIVE | LK_RETRY);
1.9 mycroft 334: error = VOP_CLOSE(amp->devvp, FREAD, NOCRED, p);
1.37 wrstuden 335: vput(amp->devvp);
1.17 mhitch 336: if (amp->bitmap)
337: free(amp->bitmap, M_ADOSFSBITMAP);
1.1 chopps 338: free(amp, M_ADOSFSMNT);
1.53 soren 339: mp->mnt_data = NULL;
1.2 chopps 340: mp->mnt_flag &= ~MNT_LOCAL;
341: return (error);
1.1 chopps 342: }
343:
344: int
345: adosfs_root(mp, vpp)
346: struct mount *mp;
347: struct vnode **vpp;
348: {
1.2 chopps 349: struct vnode *nvp;
350: int error;
1.1 chopps 351:
1.16 christos 352: if ((error = VFS_VGET(mp, (ino_t)VFSTOADOSFS(mp)->rootb, &nvp)) != 0)
1.2 chopps 353: return (error);
1.17 mhitch 354: /* XXX verify it's a root block? */
1.2 chopps 355: *vpp = nvp;
356: return (0);
1.1 chopps 357: }
358:
359: int
360: adosfs_statfs(mp, sbp, p)
361: struct mount *mp;
362: struct statfs *sbp;
363: struct proc *p;
364: {
1.10 mycroft 365: struct adosfsmount *amp;
1.9 mycroft 366:
1.1 chopps 367: amp = VFSTOADOSFS(mp);
1.28 fvdl 368: #ifdef COMPAT_09
369: sbp->f_type = 16;
370: #else
1.1 chopps 371: sbp->f_type = 0;
1.28 fvdl 372: #endif
1.1 chopps 373: sbp->f_bsize = amp->bsize;
1.17 mhitch 374: sbp->f_iosize = amp->dbsize;
375: sbp->f_blocks = amp->numblks;
376: sbp->f_bfree = amp->freeblks;
377: sbp->f_bavail = amp->freeblks;
1.1 chopps 378: sbp->f_files = 0; /* who knows */
379: sbp->f_ffree = 0; /* " " */
380: if (sbp != &mp->mnt_stat) {
1.30 perry 381: memcpy(sbp->f_mntonname, mp->mnt_stat.f_mntonname, MNAMELEN);
382: memcpy(sbp->f_mntfromname, mp->mnt_stat.f_mntfromname, MNAMELEN);
1.1 chopps 383: }
384: strncpy(sbp->f_fstypename, mp->mnt_op->vfs_name, MFSNAMELEN);
1.9 mycroft 385: return (0);
1.1 chopps 386: }
387:
1.2 chopps 388: /*
389: * lookup an anode, check mount's hash table if not found, create
390: * return locked and referenced al la vget(vp, 1);
391: */
1.1 chopps 392: int
1.2 chopps 393: adosfs_vget(mp, an, vpp)
1.1 chopps 394: struct mount *mp;
1.2 chopps 395: ino_t an;
396: struct vnode **vpp;
1.1 chopps 397: {
1.10 mycroft 398: struct adosfsmount *amp;
1.2 chopps 399: struct vnode *vp;
400: struct anode *ap;
401: struct buf *bp;
402: char *nam, *tmp;
1.17 mhitch 403: int namlen, error;
1.2 chopps 404:
405: error = 0;
406: amp = VFSTOADOSFS(mp);
407: bp = NULL;
408:
409: /*
410: * check hash table. we are done if found
411: */
1.16 christos 412: if ((*vpp = adosfs_ahashget(mp, an)) != NULL)
1.2 chopps 413: return (0);
414:
1.16 christos 415: error = getnewvnode(VT_ADOSFS, mp, adosfs_vnodeop_p, &vp);
416: if (error)
1.2 chopps 417: return (error);
418:
419: /*
420: * setup, insert in hash, and lock before io.
421: */
1.31 thorpej 422: vp->v_data = ap = pool_get(&adosfs_node_pool, PR_WAITOK);
1.30 perry 423: memset(ap, 0, sizeof(struct anode));
1.2 chopps 424: ap->vp = vp;
425: ap->amp = amp;
426: ap->block = an;
427: ap->nwords = amp->nwords;
428: adosfs_ainshash(amp, ap);
429:
1.36 is 430: if ((error = bread(amp->devvp, an * amp->bsize / DEV_BSIZE,
1.17 mhitch 431: amp->bsize, NOCRED, &bp)) != 0) {
1.32 bouyer 432: brelse(bp);
1.2 chopps 433: vput(vp);
434: return (error);
435: }
436:
437: /*
438: * get type and fill rest in based on that.
439: */
440: switch (ap->type = adosfs_getblktype(amp, bp)) {
441: case AROOT:
442: vp->v_type = VDIR;
443: vp->v_flag |= VROOT;
444: ap->mtimev.days = adoswordn(bp, ap->nwords - 10);
445: ap->mtimev.mins = adoswordn(bp, ap->nwords - 9);
446: ap->mtimev.ticks = adoswordn(bp, ap->nwords - 8);
447: ap->created.days = adoswordn(bp, ap->nwords - 7);
448: ap->created.mins = adoswordn(bp, ap->nwords - 6);
449: ap->created.ticks = adoswordn(bp, ap->nwords - 5);
450: break;
451: case ALDIR:
452: case ADIR:
453: vp->v_type = VDIR;
454: break;
455: case ALFILE:
456: case AFILE:
457: vp->v_type = VREG;
458: ap->fsize = adoswordn(bp, ap->nwords - 47);
459: break;
460: case ASLINK: /* XXX soft link */
461: vp->v_type = VLNK;
462: /*
463: * convert from BCPL string and
464: * from: "part:dir/file" to: "/part/dir/file"
465: */
466: nam = bp->b_data + (6 * sizeof(long));
1.17 mhitch 467: namlen = strlen(nam);
1.2 chopps 468: tmp = nam;
1.17 mhitch 469: while (*tmp && *tmp != ':')
1.2 chopps 470: tmp++;
471: if (*tmp == 0) {
472: ap->slinkto = malloc(namlen + 1, M_ANODE, M_WAITOK);
1.30 perry 473: memcpy(ap->slinkto, nam, namlen);
1.2 chopps 474: } else if (*nam == ':') {
475: ap->slinkto = malloc(namlen + 1, M_ANODE, M_WAITOK);
1.30 perry 476: memcpy(ap->slinkto, nam, namlen);
1.2 chopps 477: ap->slinkto[0] = '/';
478: } else {
479: ap->slinkto = malloc(namlen + 2, M_ANODE, M_WAITOK);
480: ap->slinkto[0] = '/';
1.30 perry 481: memcpy(&ap->slinkto[1], nam, namlen);
1.2 chopps 482: ap->slinkto[tmp - nam + 1] = '/';
483: namlen++;
484: }
485: ap->slinkto[namlen] = 0;
1.19 mhitch 486: ap->fsize = namlen;
1.2 chopps 487: break;
488: default:
489: brelse(bp);
490: vput(vp);
491: return (EINVAL);
492: }
1.17 mhitch 493:
494: /*
495: * Get appropriate data from this block; hard link needs
496: * to get other data from the "real" block.
497: */
498:
499: /*
500: * copy in name (from original block)
501: */
1.20 thorpej 502: nam = bp->b_data + (ap->nwords - 20) * sizeof(u_int32_t);
1.17 mhitch 503: namlen = *(u_char *)nam++;
504: if (namlen > 30) {
505: #ifdef DIAGNOSTIC
1.23 christos 506: printf("adosfs: aget: name length too long blk %d\n", an);
1.17 mhitch 507: #endif
508: brelse(bp);
509: vput(vp);
510: return (EINVAL);
511: }
1.30 perry 512: memcpy(ap->name, nam, namlen);
1.17 mhitch 513: ap->name[namlen] = 0;
514:
1.2 chopps 515: /*
516: * if dir alloc hash table and copy it in
517: */
518: if (vp->v_type == VDIR) {
519: int i;
520:
521: ap->tab = malloc(ANODETABSZ(ap) * 2, M_ANODE, M_WAITOK);
522: ap->ntabent = ANODETABENT(ap);
523: ap->tabi = (int *)&ap->tab[ap->ntabent];
1.30 perry 524: memset(ap->tabi, 0, ANODETABSZ(ap));
1.2 chopps 525: for (i = 0; i < ap->ntabent; i++)
526: ap->tab[i] = adoswordn(bp, i + 6);
527: }
528:
529: /*
530: * misc.
531: */
532: ap->pblock = adoswordn(bp, ap->nwords - 3);
533: ap->hashf = adoswordn(bp, ap->nwords - 4);
534: ap->linknext = adoswordn(bp, ap->nwords - 10);
535: ap->linkto = adoswordn(bp, ap->nwords - 11);
1.5 chopps 536:
537: /*
538: * setup last indirect block cache.
539: */
540: ap->lastlindblk = 0;
1.17 mhitch 541: if (ap->type == AFILE) {
1.5 chopps 542: ap->lastindblk = ap->block;
1.17 mhitch 543: if (adoswordn(bp, ap->nwords - 10))
544: ap->linkto = ap->block;
545: } else if (ap->type == ALFILE) {
1.5 chopps 546: ap->lastindblk = ap->linkto;
1.17 mhitch 547: brelse(bp);
548: bp = NULL;
1.36 is 549: error = bread(amp->devvp, ap->linkto * amp->bsize / DEV_BSIZE,
1.17 mhitch 550: amp->bsize, NOCRED, &bp);
1.32 bouyer 551: if (error) {
552: brelse(bp);
553: vput(vp);
554: return (error);
555: }
1.17 mhitch 556: ap->fsize = adoswordn(bp, ap->nwords - 47);
557: /*
558: * Should ap->block be set to the real file header block?
559: */
560: ap->block = ap->linkto;
561: }
1.5 chopps 562:
1.8 chopps 563: if (ap->type == AROOT) {
1.17 mhitch 564: ap->adprot = 15;
1.8 chopps 565: ap->uid = amp->uid;
566: ap->gid = amp->gid;
567: } else {
1.17 mhitch 568: ap->adprot = adoswordn(bp, ap->nwords - 48) ^ 15;
1.25 kleink 569: /*
570: * ADOS directories do not have a `x' protection bit as
571: * it is known in VFS; this functionality is fulfilled
572: * by the ADOS `r' bit.
573: *
574: * To retain the ADOS behaviour, fake execute permissions
575: * in that case.
576: */
1.26 kleink 577: if ((ap->type == ADIR || ap->type == ALDIR) &&
578: (ap->adprot & 0x00000008) == 0)
579: ap->adprot &= ~0x00000002;
1.25 kleink 580:
1.8 chopps 581: /*
582: * Get uid/gid from extensions in file header
583: * (really need to know if this is a muFS partition)
584: */
585: ap->uid = (adoswordn(bp, ap->nwords - 49) >> 16) & 0xffff;
586: ap->gid = adoswordn(bp, ap->nwords - 49) & 0xffff;
587: if (ap->uid || ap->gid) {
588: if (ap->uid == 0xffff)
589: ap->uid = 0;
590: if (ap->gid == 0xffff)
591: ap->gid = 0;
592: ap->adprot |= 0x40000000; /* Kludge */
593: }
594: else {
595: /*
596: * uid & gid extension don't exist,
597: * so use the mount-point uid/gid
598: */
599: ap->uid = amp->uid;
600: ap->gid = amp->gid;
601: }
602: }
1.2 chopps 603: ap->mtime.days = adoswordn(bp, ap->nwords - 23);
604: ap->mtime.mins = adoswordn(bp, ap->nwords - 22);
605: ap->mtime.ticks = adoswordn(bp, ap->nwords - 21);
606:
1.49 chs 607: genfs_node_init(vp, &adosfs_genfsops);
1.48 chs 608: *vpp = vp;
609: brelse(bp);
610: vp->v_size = ap->fsize;
1.17 mhitch 611: return (0);
612: }
613:
614: /*
615: * Load the bitmap into memory, and count the number of available
616: * blocks.
617: * The bitmap will be released if the filesystem is read-only; it's
618: * only needed to find the free space.
619: */
620: int
621: adosfs_loadbitmap(amp)
622: struct adosfsmount *amp;
623: {
624: struct buf *bp, *mapbp;
625: u_long bn;
626: int blkix, endix, mapix;
627: int bmsize;
628: int error;
629:
630: bp = mapbp = NULL;
631: bn = amp->rootb;
1.36 is 632: if ((error = bread(amp->devvp, bn * amp->bsize / DEV_BSIZE, amp->bsize,
1.32 bouyer 633: NOCRED, &bp)) != 0) {
634: brelse(bp);
1.17 mhitch 635: return (error);
1.32 bouyer 636: }
1.17 mhitch 637: blkix = amp->nwords - 49;
638: endix = amp->nwords - 24;
639: mapix = 0;
640: bmsize = (amp->numblks + 31) / 32;
641: while (mapix < bmsize) {
642: int n;
643: u_long bits;
644:
645: if (adoswordn(bp, blkix) == 0)
646: break;
647: if (mapbp != NULL)
648: brelse(mapbp);
649: if ((error = bread(amp->devvp,
1.36 is 650: adoswordn(bp, blkix) * amp->bsize / DEV_BSIZE, amp->bsize,
1.17 mhitch 651: NOCRED, &mapbp)) != 0)
652: break;
653: if (adoscksum(mapbp, amp->nwords)) {
1.2 chopps 654: #ifdef DIAGNOSTIC
1.23 christos 655: printf("adosfs: loadbitmap - cksum of blk %d failed\n",
1.21 christos 656: adoswordn(bp, blkix));
1.1 chopps 657: #endif
1.17 mhitch 658: /* XXX Force read-only? Set free space 0? */
659: break;
660: }
661: n = 1;
662: while (n < amp->nwords && mapix < bmsize) {
663: amp->bitmap[mapix++] = bits = adoswordn(mapbp, n);
664: ++n;
665: if (mapix == bmsize && amp->numblks & 31)
666: bits &= ~(0xffffffff << (amp->numblks & 31));
667: while (bits) {
668: if (bits & 1)
669: ++amp->freeblks;
670: bits >>= 1;
671: }
672: }
673: ++blkix;
674: if (mapix < bmsize && blkix == endix) {
675: bn = adoswordn(bp, blkix);
676: brelse(bp);
1.36 is 677: if ((error = bread(amp->devvp, bn * amp->bsize / DEV_BSIZE,
1.17 mhitch 678: amp->bsize, NOCRED, &bp)) != 0)
679: break;
680: /*
681: * Why is there no checksum on these blocks?
682: */
683: blkix = 0;
684: endix = amp->nwords - 1;
685: }
686: }
687: if (bp)
1.2 chopps 688: brelse(bp);
1.17 mhitch 689: if (mapbp)
690: brelse(mapbp);
691: return (error);
1.1 chopps 692: }
693:
1.14 chopps 694:
695: /*
696: * File handle to vnode
697: *
698: * Have to be really careful about stale file handles:
699: * - check that the inode number is in range
700: * - call iget() to get the locked inode
701: * - check for an unallocated inode (i_mode == 0)
702: * - check that the generation number matches
703: */
704:
705: struct ifid {
706: ushort ifid_len;
707: ushort ifid_pad;
708: int ifid_ino;
709: long ifid_start;
710: };
711:
1.1 chopps 712: int
1.35 wrstuden 713: adosfs_fhtovp(mp, fhp, vpp)
1.1 chopps 714: struct mount *mp;
715: struct fid *fhp;
716: struct vnode **vpp;
717: {
1.14 chopps 718: struct ifid *ifhp = (struct ifid *)fhp;
1.16 christos 719: #if 0
1.14 chopps 720: struct anode *ap;
1.16 christos 721: #endif
1.14 chopps 722: struct vnode *nvp;
723: int error;
724:
1.1 chopps 725: #ifdef ADOSFS_DIAGNOSTIC
1.23 christos 726: printf("adfhtovp(%x, %x, %x)\n", mp, fhp, vpp);
1.1 chopps 727: #endif
1.14 chopps 728:
1.16 christos 729: if ((error = VFS_VGET(mp, ifhp->ifid_ino, &nvp)) != 0) {
1.14 chopps 730: *vpp = NULLVP;
731: return (error);
732: }
733: #if 0
734: ap = VTOA(nvp);
735: if (ap->inode.iso_mode == 0) {
736: vput(nvp);
737: *vpp = NULLVP;
738: return (ESTALE);
739: }
740: #endif
741: *vpp = nvp;
1.35 wrstuden 742: return(0);
743: }
744:
745: int
746: adosfs_checkexp(mp, nam, exflagsp, credanonp)
747: struct mount *mp;
748: struct mbuf *nam;
749: int *exflagsp;
750: struct ucred **credanonp;
751: {
752: struct adosfsmount *amp = VFSTOADOSFS(mp);
753: #if 0
754: struct anode *ap;
755: #endif
756: struct netcred *np;
757:
758: #ifdef ADOSFS_DIAGNOSTIC
759: printf("adcheckexp(%x, %x, %x)\n", mp, nam, exflagsp);
760: #endif
761:
762: /*
763: * Get the export permission structure for this <mp, client> tuple.
764: */
765: np = vfs_export_lookup(mp, &->export, nam);
766: if (np == NULL)
767: return (EACCES);
768:
1.14 chopps 769: *exflagsp = np->netc_exflags;
770: *credanonp = &np->netc_anon;
1.1 chopps 771: return(0);
772: }
773:
774: int
775: adosfs_vptofh(vp, fhp)
776: struct vnode *vp;
777: struct fid *fhp;
778: {
1.14 chopps 779: struct anode *ap = VTOA(vp);
780: struct ifid *ifhp;
781:
782: ifhp = (struct ifid *)fhp;
783: ifhp->ifid_len = sizeof(struct ifid);
784:
785: ifhp->ifid_ino = ap->block;
786: ifhp->ifid_start = ap->block;
787:
1.1 chopps 788: #ifdef ADOSFS_DIAGNOSTIC
1.23 christos 789: printf("advptofh(%x, %x)\n", vp, fhp);
1.1 chopps 790: #endif
791: return(0);
792: }
793:
794: int
1.2 chopps 795: adosfs_quotactl(mp, cmds, uid, arg, p)
796: struct mount *mp;
797: int cmds;
798: uid_t uid;
799: caddr_t arg;
800: struct proc *p;
801: {
802: return(EOPNOTSUPP);
803: }
804:
805: int
1.16 christos 806: adosfs_sync(mp, waitfor, uc, p)
1.2 chopps 807: struct mount *mp;
808: int waitfor;
1.16 christos 809: struct ucred *uc;
810: struct proc *p;
1.1 chopps 811: {
812: #ifdef ADOSFS_DIAGNOSTIC
1.23 christos 813: printf("ad_sync(%x, %x)\n", mp, waitfor);
1.1 chopps 814: #endif
815: return(0);
816: }
817:
1.16 christos 818: void
1.2 chopps 819: adosfs_init()
820: {
1.28 fvdl 821: simple_lock_init(&adosfs_hashlock);
1.31 thorpej 822:
823: pool_init(&adosfs_node_pool, sizeof(struct anode), 0, 0, 0,
1.51 thorpej 824: "adosndpl", &pool_allocator_nointr);
1.28 fvdl 825: }
826:
1.42 jdolecek 827: void
828: adosfs_done()
829: {
830: pool_destroy(&adosfs_node_pool);
831: }
832:
1.28 fvdl 833: int
834: adosfs_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p)
835: int *name;
836: u_int namelen;
837: void *oldp;
838: size_t *oldlenp;
839: void *newp;
840: size_t newlen;
841: struct proc *p;
842: {
843: return (EOPNOTSUPP);
1.2 chopps 844: }
845:
1.1 chopps 846: /*
847: * vfs generic function call table
848: */
1.27 thorpej 849:
1.44 jdolecek 850: extern const struct vnodeopv_desc adosfs_vnodeop_opv_desc;
1.27 thorpej 851:
1.44 jdolecek 852: const struct vnodeopv_desc *adosfs_vnodeopv_descs[] = {
1.27 thorpej 853: &adosfs_vnodeop_opv_desc,
854: NULL,
855: };
856:
1.1 chopps 857: struct vfsops adosfs_vfsops = {
858: MOUNT_ADOSFS,
859: adosfs_mount,
860: adosfs_start,
861: adosfs_unmount,
862: adosfs_root,
863: adosfs_quotactl,
864: adosfs_statfs,
865: adosfs_sync,
1.2 chopps 866: adosfs_vget,
1.1 chopps 867: adosfs_fhtovp,
868: adosfs_vptofh,
869: adosfs_init,
1.47 chs 870: NULL,
1.42 jdolecek 871: adosfs_done,
1.28 fvdl 872: adosfs_sysctl,
1.27 thorpej 873: NULL, /* vfs_mountroot */
1.35 wrstuden 874: adosfs_checkexp,
1.27 thorpej 875: adosfs_vnodeopv_descs,
876: };
CVSweb <webmaster@jp.NetBSD.org>