Annotation of src/sys/adosfs/advnops.c, Revision 1.32
1.32 ! christos 1: /* $NetBSD: advnops.c,v 1.31 1996/10/10 17:47:32 christos Exp $ */
1.8 cgd 2:
1.1 chopps 3: /*
4: * Copyright (c) 1994 Christian E. Hopps
1.27 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: */
33: #include <sys/param.h>
1.13 cgd 34: #include <sys/systm.h>
1.1 chopps 35: #include <sys/vnode.h>
36: #include <sys/mount.h>
37: #include <sys/time.h>
38: #include <sys/queue.h>
39: #include <sys/namei.h>
40: #include <sys/buf.h>
41: #include <sys/dirent.h>
1.6 chopps 42: #include <sys/malloc.h>
1.1 chopps 43: #include <sys/stat.h>
1.6 chopps 44: #include <sys/unistd.h>
1.25 christos 45: #include <sys/proc.h>
1.29 mycroft 46:
47: #include <miscfs/genfs/genfs.h>
1.1 chopps 48: #include <miscfs/specfs/specdev.h>
49: #include <adosfs/adosfs.h>
50:
51: extern struct vnodeops adosfs_vnodeops;
52:
1.29 mycroft 53: #define adosfs_open genfs_nullop
1.25 christos 54: int adosfs_getattr __P((void *));
55: int adosfs_read __P((void *));
56: int adosfs_write __P((void *));
57: int adosfs_ioctl __P((void *));
1.30 mycroft 58: #define adosfs_poll genfs_poll
1.25 christos 59: int adosfs_strategy __P((void *));
1.26 christos 60: int adosfs_link __P((void *));
61: int adosfs_symlink __P((void *));
1.29 mycroft 62: #define adosfs_abortop genfs_abortop
1.25 christos 63: int adosfs_lock __P((void *));
64: int adosfs_unlock __P((void *));
65: int adosfs_bmap __P((void *));
66: int adosfs_print __P((void *));
67: int adosfs_readdir __P((void *));
68: int adosfs_access __P((void *));
69: int adosfs_readlink __P((void *));
70: int adosfs_inactive __P((void *));
71: int adosfs_islocked __P((void *));
72: int adosfs_reclaim __P((void *));
73: int adosfs_pathconf __P((void *));
74:
1.29 mycroft 75: #define adosfs_close genfs_nullop
76: #define adosfs_fsync genfs_nullop
1.25 christos 77: #ifdef NFSSERVER
78: int lease_check __P((void *));
1.29 mycroft 79: #define adosfs_lease_check lease_check
1.25 christos 80: #else
1.29 mycroft 81: #define adosfs_lease_check genfs_nullop
1.25 christos 82: #endif
1.29 mycroft 83: #define adosfs_seek genfs_nullop
84: #define adosfs_vfree genfs_nullop
1.25 christos 85:
1.29 mycroft 86: #define adosfs_advlock genfs_eopnotsupp
87: #define adosfs_blkatoff genfs_eopnotsupp
88: #define adosfs_bwrite genfs_eopnotsupp
89: #define adosfs_create genfs_eopnotsupp
90: #define adosfs_mkdir genfs_eopnotsupp
91: #define adosfs_mknod genfs_eopnotsupp
92: #define adosfs_mmap genfs_eopnotsupp
93: #define adosfs_remove genfs_eopnotsupp
94: #define adosfs_rename genfs_eopnotsupp
95: #define adosfs_rmdir genfs_eopnotsupp
96: #define adosfs_setattr genfs_eopnotsupp
97: #define adosfs_truncate genfs_eopnotsupp
98: #define adosfs_update genfs_nullop
99: #define adosfs_valloc genfs_eopnotsupp
1.25 christos 100:
101: struct vnodeopv_entry_desc adosfs_vnodeop_entries[] = {
1.29 mycroft 102: { &vop_default_desc, vn_default_error },
103: { &vop_lookup_desc, adosfs_lookup }, /* lookup */
104: { &vop_create_desc, adosfs_create }, /* create */
105: { &vop_mknod_desc, adosfs_mknod }, /* mknod */
106: { &vop_open_desc, adosfs_open }, /* open */
107: { &vop_close_desc, adosfs_close }, /* close */
108: { &vop_access_desc, adosfs_access }, /* access */
109: { &vop_getattr_desc, adosfs_getattr }, /* getattr */
110: { &vop_setattr_desc, adosfs_setattr }, /* setattr */
111: { &vop_read_desc, adosfs_read }, /* read */
112: { &vop_write_desc, adosfs_write }, /* write */
113: { &vop_lease_desc, adosfs_lease_check }, /* lease */
114: { &vop_ioctl_desc, adosfs_ioctl }, /* ioctl */
1.30 mycroft 115: { &vop_poll_desc, adosfs_poll }, /* poll */
1.29 mycroft 116: { &vop_mmap_desc, adosfs_mmap }, /* mmap */
117: { &vop_fsync_desc, adosfs_fsync }, /* fsync */
118: { &vop_seek_desc, adosfs_seek }, /* seek */
119: { &vop_remove_desc, adosfs_remove }, /* remove */
120: { &vop_link_desc, adosfs_link }, /* link */
121: { &vop_rename_desc, adosfs_rename }, /* rename */
122: { &vop_mkdir_desc, adosfs_mkdir }, /* mkdir */
123: { &vop_rmdir_desc, adosfs_rmdir }, /* rmdir */
124: { &vop_symlink_desc, adosfs_symlink }, /* symlink */
125: { &vop_readdir_desc, adosfs_readdir }, /* readdir */
126: { &vop_readlink_desc, adosfs_readlink }, /* readlink */
127: { &vop_abortop_desc, adosfs_abortop }, /* abortop */
128: { &vop_inactive_desc, adosfs_inactive }, /* inactive */
129: { &vop_reclaim_desc, adosfs_reclaim }, /* reclaim */
130: { &vop_lock_desc, adosfs_lock }, /* lock */
131: { &vop_unlock_desc, adosfs_unlock }, /* unlock */
132: { &vop_bmap_desc, adosfs_bmap }, /* bmap */
133: { &vop_strategy_desc, adosfs_strategy }, /* strategy */
134: { &vop_print_desc, adosfs_print }, /* print */
135: { &vop_islocked_desc, adosfs_islocked }, /* islocked */
136: { &vop_pathconf_desc, adosfs_pathconf }, /* pathconf */
137: { &vop_advlock_desc, adosfs_advlock }, /* advlock */
138: { &vop_blkatoff_desc, adosfs_blkatoff }, /* blkatoff */
139: { &vop_valloc_desc, adosfs_valloc }, /* valloc */
140: { &vop_vfree_desc, adosfs_vfree }, /* vfree */
141: { &vop_truncate_desc, adosfs_truncate }, /* truncate */
142: { &vop_update_desc, adosfs_update }, /* update */
143: { &vop_bwrite_desc, adosfs_bwrite }, /* bwrite */
1.25 christos 144: { (struct vnodeop_desc*)NULL, (int(*) __P((void *)))NULL }
145: };
146:
147: struct vnodeopv_desc adosfs_vnodeop_opv_desc =
148: { &adosfs_vnodeop_p, adosfs_vnodeop_entries };
149:
1.1 chopps 150: int
1.25 christos 151: adosfs_getattr(v)
152: void *v;
153: {
1.6 chopps 154: struct vop_getattr_args /* {
155: struct vnode *a_vp;
156: struct vattr *a_vap;
157: struct ucred *a_cred;
158: struct proc *a_p;
1.25 christos 159: } */ *sp = v;
1.1 chopps 160: struct vattr *vap;
1.20 mycroft 161: struct adosfsmount *amp;
1.1 chopps 162: struct anode *ap;
1.2 chopps 163: u_long fblks;
1.1 chopps 164:
165: #ifdef ADOSFS_DIAGNOSTIC
1.6 chopps 166: advopprint(sp);
1.1 chopps 167: #endif
1.6 chopps 168: vap = sp->a_vap;
169: ap = VTOA(sp->a_vp);
1.1 chopps 170: amp = ap->amp;
171: vattr_null(vap);
1.18 chopps 172: vap->va_uid = ap->uid;
173: vap->va_gid = ap->gid;
1.6 chopps 174: vap->va_fsid = sp->a_vp->v_mount->mnt_stat.f_fsid.val[0];
1.23 jtc 175: vap->va_atime.tv_sec = vap->va_mtime.tv_sec = vap->va_ctime.tv_sec =
1.18 chopps 176: ap->mtime.days * 24 * 60 * 60 + ap->mtime.mins * 60 +
177: ap->mtime.ticks / 50 + (8 * 365 + 2) * 24 * 60 * 60;
1.23 jtc 178: vap->va_atime.tv_nsec = vap->va_mtime.tv_nsec = vap->va_ctime.tv_nsec = 0;
1.1 chopps 179: vap->va_gen = 0;
180: vap->va_flags = 0;
1.2 chopps 181: vap->va_rdev = NODEV;
182: vap->va_fileid = ap->block;
1.6 chopps 183: vap->va_type = sp->a_vp->v_type;
1.2 chopps 184: vap->va_mode = amp->mask & adunixprot(ap->adprot);
1.6 chopps 185: if (sp->a_vp->v_type == VDIR) {
1.3 chopps 186: vap->va_nlink = 1; /* XXX bogus, oh well */
1.1 chopps 187: vap->va_bytes = amp->bsize;
188: vap->va_size = amp->bsize;
1.2 chopps 189: } else {
190: /*
191: * XXX actually we can track this if we were to walk the list
192: * of links if it exists.
1.27 mhitch 193: * XXX for now, just set nlink to 2 if this is a hard link
194: * to a file, or a file with a hard link.
1.2 chopps 195: */
1.27 mhitch 196: vap->va_nlink = 1 + (ap->linkto != 0);
1.2 chopps 197: /*
198: * round up to nearest blocks add number of file list
199: * blocks needed and mutiply by number of bytes per block.
200: */
1.27 mhitch 201: fblks = howmany(ap->fsize, amp->dbsize);
1.2 chopps 202: fblks += howmany(fblks, ANODENDATBLKENT(ap));
1.27 mhitch 203: vap->va_bytes = fblks * amp->dbsize;
1.2 chopps 204: vap->va_size = ap->fsize;
1.21 chopps 205:
1.27 mhitch 206: vap->va_blocksize = amp->dbsize;
1.1 chopps 207: }
208: #ifdef ADOSFS_DIAGNOSTIC
1.32 ! christos 209: printf(" 0)");
1.1 chopps 210: #endif
211: return(0);
212: }
213: /*
214: * are things locked??? they need to be to avoid this being
215: * deleted or changed (data block pointer blocks moving about.)
216: */
217: int
1.25 christos 218: adosfs_read(v)
219: void *v;
220: {
1.6 chopps 221: struct vop_read_args /* {
222: struct vnode *a_vp;
223: struct uio *a_uio;
224: int a_ioflag;
225: struct ucred *a_cred;
1.25 christos 226: } */ *sp = v;
1.20 mycroft 227: struct adosfsmount *amp;
1.1 chopps 228: struct anode *ap;
1.6 chopps 229: struct uio *uio;
230: struct buf *bp;
1.25 christos 231: daddr_t lbn;
1.1 chopps 232: int size, diff, error;
233: long n, on;
234:
235: #ifdef ADOSFS_DIAGNOSTIC
1.6 chopps 236: advopprint(sp);
1.1 chopps 237: #endif
238: error = 0;
1.6 chopps 239: uio = sp->a_uio;
240: ap = VTOA(sp->a_vp);
1.1 chopps 241: amp = ap->amp;
242: /*
243: * Return EOF for character devices, EIO for others
244: */
1.6 chopps 245: if (sp->a_vp->v_type != VREG) {
1.1 chopps 246: error = EIO;
247: goto reterr;
248: }
249: if (uio->uio_resid == 0)
250: goto reterr;
251: if (uio->uio_offset < 0) {
252: error = EINVAL;
253: goto reterr;
254: }
255:
256: /*
257: * to expensive to let general algorithm figure out that
258: * we are beyond the file. Do it now.
259: */
260: if (uio->uio_offset >= ap->fsize)
261: goto reterr;
262:
263: /*
264: * taken from ufs_read()
265: */
266: do {
267: /*
268: * we are only supporting ADosFFS currently
1.27 mhitch 269: * (which have data blocks without headers)
1.1 chopps 270: */
1.27 mhitch 271: size = amp->dbsize;
1.1 chopps 272: lbn = uio->uio_offset / size;
273: on = uio->uio_offset % size;
1.4 chopps 274: n = min((u_int)(size - on), uio->uio_resid);
1.1 chopps 275: diff = ap->fsize - uio->uio_offset;
276: /*
277: * check for EOF
278: */
279: if (diff <= 0)
280: return(0);
281: if (diff < n)
282: n = diff;
283: /*
284: * read ahead could possibly be worth something
285: * but not much as ados makes little attempt to
286: * make things contigous
287: */
1.27 mhitch 288: error = bread(sp->a_vp, lbn * amp->secsperblk,
289: amp->bsize, NOCRED, &bp);
1.6 chopps 290: sp->a_vp->v_lastr = lbn;
1.27 mhitch 291:
292: if (!IS_FFS(amp)) {
293: if (bp->b_resid > 0)
294: error = EIO; /* OFS needs the complete block */
295: else if (adoswordn(bp, 0) != BPT_DATA) {
296: #ifdef DIAGNOSTIC
1.32 ! christos 297: printf("adosfs: bad primary type blk %ld\n",
1.31 christos 298: bp->b_blkno / amp->secsperblk);
1.27 mhitch 299: #endif
300: error=EINVAL;
301: }
302: else if ( adoscksum(bp, ap->nwords)) {
303: #ifdef DIAGNOSTIC
1.32 ! christos 304: printf("adosfs: blk %ld failed cksum.\n",
1.31 christos 305: bp->b_blkno / amp->secsperblk);
1.27 mhitch 306: #endif
307: error=EINVAL;
308: }
309: }
310:
1.1 chopps 311: if (error) {
312: brelse(bp);
313: goto reterr;
314: }
315: #ifdef ADOSFS_DIAGNOSTIC
1.32 ! christos 316: printf(" %d+%d-%d+%d", lbn, on, lbn, n);
1.1 chopps 317: #endif
1.27 mhitch 318: n = min(n, (u_int)size - bp->b_resid);
319: error = uiomove(bp->b_un.b_addr + on +
320: amp->bsize - amp->dbsize, (int)n, uio);
1.1 chopps 321: brelse(bp);
322: } while (error == 0 && uio->uio_resid > 0 && n != 0);
323: reterr:
324: #ifdef ADOSFS_DIAGNOSTIC
1.32 ! christos 325: printf(" %d)", error);
1.1 chopps 326: #endif
327: return(error);
328: }
329:
330: int
1.25 christos 331: adosfs_write(v)
332: void *v;
333: {
334: #ifdef ADOSFS_DIAGNOSTIC
1.6 chopps 335: struct vop_write_args /* {
336: struct vnode *a_vp;
337: struct uio *a_uio;
338: int a_ioflag;
339: struct ucred *a_cred;
1.25 christos 340: } */ *sp = v;
1.6 chopps 341: advopprint(sp);
1.32 ! christos 342: printf(" EOPNOTSUPP)");
1.1 chopps 343: #endif
344: return(EOPNOTSUPP);
345: }
346:
347: /*
348: * Device ioctl operation.
349: */
350: /* ARGSUSED */
351: int
1.25 christos 352: adosfs_ioctl(v)
353: void *v;
354: {
355: #ifdef ADOSFS_DIAGNOSTIC
1.6 chopps 356: struct vop_ioctl_args /* {
357: struct vnode *a_vp;
1.14 cgd 358: u_long a_command;
1.6 chopps 359: caddr_t a_data;
360: int a_fflag;
361: struct ucred *a_cred;
362: struct proc *a_p;
1.25 christos 363: } */ *sp = v;
1.6 chopps 364: advopprint(sp);
1.32 ! christos 365: printf(" ENOTTY)");
1.1 chopps 366: #endif
367: return(ENOTTY);
368: }
369:
370: /*
371: * Just call the device strategy routine
372: */
373: int
1.25 christos 374: adosfs_strategy(v)
375: void *v;
376: {
1.6 chopps 377: struct vop_strategy_args /* {
378: struct buf *a_bp;
1.25 christos 379: } */ *sp = v;
1.1 chopps 380: struct buf *bp;
381: struct anode *ap;
382: struct vnode *vp;
383: int error;
384:
385: #ifdef ADOSFS_DIAGNOSTIC
1.6 chopps 386: advopprint(sp);
1.1 chopps 387: #endif
388: error = 0;
1.6 chopps 389: bp = sp->a_bp;
1.1 chopps 390: if (bp->b_vp == NULL) {
391: bp->b_flags |= B_ERROR;
392: biodone(bp);
393: error = EIO;
394: goto reterr;
395: }
396: vp = bp->b_vp;
397: ap = VTOA(vp);
1.6 chopps 398: if (bp->b_blkno == bp->b_lblkno) {
1.25 christos 399: error = VOP_BMAP(vp, bp->b_lblkno, NULL, &bp->b_blkno, NULL);
400: if (error) {
1.1 chopps 401: bp->b_flags |= B_ERROR;
402: biodone(bp);
403: goto reterr;
404: }
1.6 chopps 405: }
406: if ((long)bp->b_blkno == -1) {
407: biodone(bp);
408: error = 0;
409: goto reterr;
410: }
1.1 chopps 411: vp = ap->amp->devvp;
412: bp->b_dev = vp->v_rdev;
1.6 chopps 413: VOCALL(vp->v_op, VOFFSET(vop_strategy), sp);
1.1 chopps 414: reterr:
415: #ifdef ADOSFS_DIAGNOSTIC
1.32 ! christos 416: printf(" %d)", error);
1.1 chopps 417: #endif
418: return(error);
419: }
420:
1.24 mycroft 421: int
1.25 christos 422: adosfs_link(v)
423: void *v;
424: {
1.24 mycroft 425: struct vop_link_args /* {
426: struct vnode *a_dvp;
427: struct vnode *a_vp;
428: struct componentname *a_cnp;
1.25 christos 429: } */ *ap = v;
1.24 mycroft 430:
431: VOP_ABORTOP(ap->a_dvp, ap->a_cnp);
432: vput(ap->a_dvp);
433: return (EROFS);
434: }
435:
436: int
1.25 christos 437: adosfs_symlink(v)
438: void *v;
439: {
1.24 mycroft 440: struct vop_symlink_args /* {
441: struct vnode *a_dvp;
442: struct vnode **a_vpp;
443: struct componentname *a_cnp;
444: struct vattr *a_vap;
445: char *a_target;
1.25 christos 446: } */ *ap = v;
1.24 mycroft 447:
448: VOP_ABORTOP(ap->a_dvp, ap->a_cnp);
449: vput(ap->a_dvp);
450: return (EROFS);
451: }
452:
1.1 chopps 453: /*
1.6 chopps 454: * lock the anode
1.1 chopps 455: */
456: int
1.25 christos 457: adosfs_lock(v)
458: void *v;
459: {
1.6 chopps 460: struct vop_lock_args /* {
461: struct vnode *a_vp;
1.25 christos 462: } */ *sp = v;
1.1 chopps 463: struct vnode *vp;
1.6 chopps 464: struct anode *ap;
465:
1.1 chopps 466: #ifdef ADOSFS_DIAGNOSTIC
1.6 chopps 467: advopprint(sp);
1.1 chopps 468: #endif
1.6 chopps 469: vp = sp->a_vp;
470: start:
471: while (vp->v_flag & VXLOCK) {
472: vp->v_flag |= VXWANT;
473: tsleep(vp, PINOD, "adosfs_lock vp", 0);
474: }
475: if (vp->v_tag == VT_NON)
476: return (ENOENT);
477: ap = VTOA(vp);
478: if (ap->flags & ALOCKED) {
479: ap->flags |= AWANT;
480: tsleep(ap, PINOD, "adosfs_lock ap", 0);
481: goto start;
482: }
483: ap->flags |= ALOCKED;
1.1 chopps 484: #ifdef ADOSFS_DIAGNOSTIC
1.32 ! christos 485: printf(" 0)");
1.1 chopps 486: #endif
487: return(0);
488: }
489:
1.6 chopps 490: /*
491: * unlock an anode
492: */
1.1 chopps 493: int
1.25 christos 494: adosfs_unlock(v)
495: void *v;
496: {
1.6 chopps 497: struct vop_unlock_args /* {
498: struct vnode *a_vp;
1.25 christos 499: } */ *sp = v;
1.6 chopps 500: struct anode *ap;
501:
1.1 chopps 502: #ifdef ADOSFS_DIAGNOSTIC
1.6 chopps 503: advopprint(sp);
1.1 chopps 504: #endif
1.6 chopps 505: ap = VTOA(sp->a_vp);
506: ap->flags &= ~ALOCKED;
507: if (ap->flags & AWANT) {
508: ap->flags &= ~AWANT;
509: wakeup(ap);
510: }
1.1 chopps 511:
512: #ifdef ADOSFS_DIAGNOSTIC
1.32 ! christos 513: printf(" 0)");
1.1 chopps 514: #endif
515: return(0);
516: }
517:
518:
519: /*
520: * Wait until the vnode has finished changing state.
521: */
522: int
1.25 christos 523: adosfs_bmap(v)
524: void *v;
525: {
1.6 chopps 526: struct vop_bmap_args /* {
527: struct vnode *a_vp;
528: daddr_t a_bn;
529: struct vnode **a_vpp;
530: daddr_t *a_bnp;
531: int *a_runp;
1.25 christos 532: } */ *sp = v;
1.1 chopps 533: struct anode *ap;
534: struct buf *flbp;
1.9 chopps 535: long nb, flblk, flblkoff, fcnt;
1.6 chopps 536: daddr_t *bnp;
537: daddr_t bn;
1.1 chopps 538: int error;
539:
540: #ifdef ADOSFS_DIAGNOSTIC
1.6 chopps 541: advopprint(sp);
1.1 chopps 542: #endif
1.27 mhitch 543: ap = VTOA(sp->a_vp);
544: bn = sp->a_bn / ap->amp->secsperblk;
1.6 chopps 545: bnp = sp->a_bnp;
1.1 chopps 546: error = 0;
547:
1.6 chopps 548: if (sp->a_vpp != NULL)
549: *sp->a_vpp = ap->amp->devvp;
550: if (bnp == NULL)
551: goto reterr;
1.1 chopps 552: if (bn < 0) {
553: error = EFBIG;
554: goto reterr;
555: }
1.6 chopps 556: if (sp->a_vp->v_type != VREG) {
1.1 chopps 557: error = EINVAL;
558: goto reterr;
559: }
560:
561: /*
562: * walk the chain of file list blocks until we find
563: * the one that will yield the block pointer we need.
564: */
565: if (ap->type == AFILE)
566: nb = ap->block; /* pointer to ourself */
567: else if (ap->type == ALFILE)
568: nb = ap->linkto; /* pointer to real file */
569: else {
570: error = EINVAL;
571: goto reterr;
572: }
573:
574: flblk = bn / ANODENDATBLKENT(ap);
575: flbp = NULL;
1.9 chopps 576:
577: /*
578: * check last indirect block cache
579: */
1.18 chopps 580: if (flblk < ap->lastlindblk)
1.9 chopps 581: fcnt = 0;
582: else {
583: flblk -= ap->lastlindblk;
584: fcnt = ap->lastlindblk;
585: nb = ap->lastindblk;
586: }
1.1 chopps 587: while (flblk >= 0) {
588: if (flbp)
589: brelse(flbp);
590: if (nb == 0) {
591: #ifdef DIAGNOSTIC
1.32 ! christos 592: printf("adosfs: bad file list chain.\n");
1.1 chopps 593: #endif
594: error = EINVAL;
595: goto reterr;
596: }
1.27 mhitch 597: error = bread(ap->amp->devvp, nb * ap->amp->secsperblk,
598: ap->amp->bsize, NOCRED, &flbp);
1.25 christos 599: if (error)
1.1 chopps 600: goto reterr;
601: if (adoscksum(flbp, ap->nwords)) {
602: #ifdef DIAGNOSTIC
1.32 ! christos 603: printf("adosfs: blk %ld failed cksum.\n", nb);
1.1 chopps 604: #endif
605: brelse(flbp);
606: error = EINVAL;
607: goto reterr;
608: }
1.9 chopps 609: /*
610: * update last indirect block cache
611: */
612: ap->lastlindblk = fcnt++;
613: ap->lastindblk = nb;
614:
1.1 chopps 615: nb = adoswordn(flbp, ap->nwords - 2);
616: flblk--;
617: }
618: /*
619: * calculate offset of block number in table. The table starts
620: * at nwords - 51 and goes to offset 6 or less if indicated by the
621: * valid table entries stored at offset ADBI_NBLKTABENT.
622: */
623: flblkoff = bn % ANODENDATBLKENT(ap);
624: if (flblkoff < adoswordn(flbp, 2 /* ADBI_NBLKTABENT */)) {
625: flblkoff = (ap->nwords - 51) - flblkoff;
1.27 mhitch 626: *bnp = adoswordn(flbp, flblkoff) * ap->amp->secsperblk;
1.1 chopps 627: } else {
628: #ifdef DIAGNOSTIC
1.32 ! christos 629: printf("flblk offset %ld too large in lblk %ld blk %d\n",
1.27 mhitch 630: flblkoff, bn / ap->amp->secsperblk , flbp->b_blkno);
1.1 chopps 631: #endif
632: error = EINVAL;
633: }
634: brelse(flbp);
635: reterr:
636: #ifdef ADOSFS_DIAGNOSTIC
637: if (error == 0 && bnp)
1.32 ! christos 638: printf(" %d => %d", bn, *bnp);
! 639: printf(" %d)", error);
1.1 chopps 640: #endif
641: return(error);
642: }
643:
644: /*
645: * Print out the contents of a adosfs vnode.
646: */
647: /* ARGSUSED */
648: int
1.25 christos 649: adosfs_print(v)
650: void *v;
651: {
652: #if 0
1.6 chopps 653: struct vop_print_args /* {
654: struct vnode *a_vp;
1.25 christos 655: } */ *sp = v;
656: #endif
1.1 chopps 657: return(0);
658: }
659:
660: struct adirent {
661: u_long fileno;
662: u_short reclen;
1.6 chopps 663: char type;
664: char namlen;
1.1 chopps 665: char name[32]; /* maxlen of 30 plus 2 NUL's */
666: };
667:
668: int
1.25 christos 669: adosfs_readdir(v)
670: void *v;
671: {
1.6 chopps 672: struct vop_readdir_args /* {
673: struct vnode *a_vp;
674: struct uio *a_uio;
675: struct ucred *a_cred;
676: int *a_eofflag;
677: u_long *a_cookies;
678: int a_ncookies;
1.25 christos 679: } */ *sp = v;
1.1 chopps 680: int error, useri, chainc, hashi, scanned, uavail;
681: struct adirent ad, *adp;
682: struct anode *pap, *ap;
1.20 mycroft 683: struct adosfsmount *amp;
1.6 chopps 684: struct vnode *vp;
685: struct uio *uio;
1.25 christos 686: u_long nextbn;
1.1 chopps 687: off_t uoff;
688:
689: #ifdef ADOSFS_DIAGNOSTIC
1.6 chopps 690: advopprint(sp);
1.1 chopps 691: #endif
1.6 chopps 692: if (sp->a_vp->v_type != VDIR) {
1.1 chopps 693: error = ENOTDIR;
694: goto reterr;
695: }
1.6 chopps 696: uio = sp->a_uio;
1.1 chopps 697: uoff = uio->uio_offset;
698: if (uoff < 0) {
699: error = EINVAL;
700: goto reterr;
701: }
702:
1.6 chopps 703: pap = VTOA(sp->a_vp);
1.1 chopps 704: amp = pap->amp;
705: adp = &ad;
706: error = nextbn = hashi = chainc = scanned = 0;
707: uavail = uio->uio_resid / sizeof(ad);
708: useri = uoff / sizeof(ad);
709:
1.2 chopps 710: /*
711: * if no slots available or offset requested is not on a slot boundry
712: */
713: if (uavail < 1 || uoff % sizeof(ad)) {
714: error = EINVAL;
715: goto reterr;
716: }
717:
1.6 chopps 718: while (uavail && (sp->a_cookies == NULL || sp->a_ncookies > 0)) {
1.1 chopps 719: if (hashi == pap->ntabent) {
1.6 chopps 720: *sp->a_eofflag = 1;
1.1 chopps 721: break;
722: }
723: if (pap->tab[hashi] == 0) {
724: hashi++;
725: continue;
726: }
1.2 chopps 727: if (nextbn == 0)
1.1 chopps 728: nextbn = pap->tab[hashi];
729:
730: /*
731: * first determine if we can skip this chain
732: */
733: if (chainc == 0) {
734: int skip;
735:
736: skip = useri - scanned;
737: if (pap->tabi[hashi] > 0 && pap->tabi[hashi] <= skip) {
738: scanned += pap->tabi[hashi];
739: hashi++;
1.2 chopps 740: nextbn = 0;
1.1 chopps 741: continue;
742: }
743: }
744:
745: /*
746: * now [continue to] walk the chain
747: */
748: ap = NULL;
749: do {
1.25 christos 750: error = VFS_VGET(amp->mp, (ino_t)nextbn, &vp);
751: if (error)
1.1 chopps 752: goto reterr;
1.6 chopps 753: ap = VTOA(vp);
1.1 chopps 754: scanned++;
755: chainc++;
756: nextbn = ap->hashf;
757:
758: /*
759: * check for end of chain.
760: */
761: if (nextbn == 0) {
762: pap->tabi[hashi] = chainc;
763: hashi++;
1.2 chopps 764: chainc = 0;
1.1 chopps 765: } else if (pap->tabi[hashi] <= 0 &&
766: -chainc < pap->tabi[hashi])
767: pap->tabi[hashi] = -chainc;
768:
1.2 chopps 769: if (useri >= scanned) {
1.6 chopps 770: vput(vp);
1.1 chopps 771: ap = NULL;
772: }
773: } while (ap == NULL && nextbn != 0);
774:
775: /*
776: * we left the loop but without a result so do main over.
777: */
778: if (ap == NULL)
779: continue;
780: /*
781: * Fill in dirent record
782: */
783: bzero(adp, sizeof(struct adirent));
784: adp->fileno = ap->block;
1.6 chopps 785: /*
786: * this deserves an function in kern/vfs_subr.c
787: */
788: switch (ATOV(ap)->v_type) {
789: case VREG:
790: adp->type = DT_REG;
791: break;
792: case VDIR:
793: adp->type = DT_DIR;
794: break;
795: case VLNK:
796: adp->type = DT_LNK;
797: break;
798: default:
799: adp->type = DT_UNKNOWN;
800: break;
801: }
1.1 chopps 802: adp->reclen = sizeof(struct adirent);
803: adp->namlen = strlen(ap->name);
804: bcopy(ap->name, adp->name, adp->namlen);
1.6 chopps 805: vput(vp);
1.1 chopps 806:
1.25 christos 807: error = uiomove((caddr_t) adp, sizeof(struct adirent), uio);
1.1 chopps 808: if (error)
809: break;
1.6 chopps 810: if (sp->a_cookies) {
811: *sp->a_cookies++ = uoff;
812: sp->a_ncookies--;
1.1 chopps 813: }
814: uoff += sizeof(struct adirent);
815: useri++;
816: uavail--;
817: }
1.2 chopps 818: #if doesnt_uiomove_handle_this
1.1 chopps 819: uio->uio_offset = uoff;
1.2 chopps 820: #endif
1.1 chopps 821: reterr:
822: #ifdef ADOSFS_DIAGNOSTIC
1.32 ! christos 823: printf(" %d)", error);
1.1 chopps 824: #endif
825: return(error);
826: }
827:
828:
829: int
1.25 christos 830: adosfs_access(v)
831: void *v;
832: {
1.6 chopps 833: struct vop_access_args /* {
834: struct vnode *a_vp;
835: int a_mode;
836: struct ucred *a_cred;
837: struct proc *a_p;
1.25 christos 838: } */ *sp = v;
1.1 chopps 839: struct anode *ap;
1.19 chopps 840: int error;
1.1 chopps 841:
842: #ifdef ADOSFS_DIAGNOSTIC
1.6 chopps 843: advopprint(sp);
1.1 chopps 844: #endif
845:
1.6 chopps 846: ap = VTOA(sp->a_vp);
1.1 chopps 847: #ifdef DIAGNOSTIC
1.6 chopps 848: if (!VOP_ISLOCKED(sp->a_vp)) {
849: vprint("adosfs_access: not locked", sp->a_vp);
1.1 chopps 850: panic("adosfs_access: not locked");
851: }
852: #endif
853: #ifdef QUOTA
854: #endif
1.18 chopps 855: error = vaccess(adunixprot(ap->adprot) & ap->amp->mask, ap->uid,
1.19 chopps 856: ap->gid, sp->a_mode, sp->a_cred);
1.1 chopps 857: #ifdef ADOSFS_DIAGNOSTIC
1.32 ! christos 858: printf(" %d)", error);
1.1 chopps 859: #endif
860: return(error);
861: }
862:
863: /*ARGSUSED*/
864: int
1.25 christos 865: adosfs_readlink(v)
866: void *v;
867: {
1.6 chopps 868: struct vop_readlink_args /* {
869: struct vnode *a_vp;
870: struct uio *a_uio;
871: struct ucred *a_cred;
1.25 christos 872: } */ *sp = v;
1.6 chopps 873: struct anode *ap;
874: int error;
875:
1.1 chopps 876: #ifdef ADOSFS_DIAGNOSTIC
1.6 chopps 877: advopprint(sp);
1.1 chopps 878: #endif
1.6 chopps 879: error = 0;
880: ap = VTOA(sp->a_vp);
881: if (ap->type != ASLINK)
882: error = EBADF;
883: /*
884: * XXX Should this be NULL terminated?
885: */
886: if (error == 0)
887: error = uiomove(ap->slinkto, strlen(ap->slinkto)+1, sp->a_uio);
1.1 chopps 888: #ifdef ADOSFS_DIAGNOSTIC
1.32 ! christos 889: printf(" %d)", error);
1.1 chopps 890: #endif
1.6 chopps 891: return(error);
1.1 chopps 892: }
893:
894: /*ARGSUSED*/
895: int
1.25 christos 896: adosfs_inactive(v)
897: void *v;
898: {
1.6 chopps 899: struct vop_inactive_args /* {
900: struct vnode *a_vp;
1.25 christos 901: } */ *sp = v;
1.1 chopps 902: #ifdef ADOSFS_DIAGNOSTIC
1.6 chopps 903: advopprint(sp);
1.1 chopps 904: #endif
1.6 chopps 905: if (sp->a_vp->v_usecount == 0 /* && check for file gone? */)
906: vgone(sp->a_vp);
1.1 chopps 907:
908: #ifdef ADOSFS_DIAGNOSTIC
1.32 ! christos 909: printf(" 0)");
1.1 chopps 910: #endif
911: return(0);
912: }
1.25 christos 913:
1.1 chopps 914: int
1.25 christos 915: adosfs_islocked(v)
916: void *v;
917: {
1.6 chopps 918: struct vop_islocked_args /* {
919: struct vnode *a_vp;
1.25 christos 920: } */ *sp = v;
1.6 chopps 921: int locked;
1.1 chopps 922:
923: #ifdef ADOSFS_DIAGNOSTIC
1.6 chopps 924: advopprint(sp);
1.1 chopps 925: #endif
926:
1.6 chopps 927: locked = (VTOA(sp->a_vp)->flags & ALOCKED) == ALOCKED;
1.1 chopps 928:
929: #ifdef ADOSFS_DIAGNOSTIC
1.32 ! christos 930: printf(" %d)", locked);
1.1 chopps 931: #endif
1.6 chopps 932: return(locked);
1.1 chopps 933: }
934:
1.6 chopps 935: /*
936: * the kernel wants its vnode back.
937: * no lock needed we are being called from vclean()
938: */
1.1 chopps 939: int
1.25 christos 940: adosfs_reclaim(v)
941: void *v;
942: {
1.6 chopps 943: struct vop_reclaim_args /* {
944: struct vnode *a_vp;
1.25 christos 945: } */ *sp = v;
1.1 chopps 946: struct vnode *vp;
947: struct anode *ap;
948:
949: #ifdef ADOSFS_DIAGNOSTIC
1.32 ! christos 950: printf("(reclaim 0)");
1.1 chopps 951: #endif
1.6 chopps 952: vp = sp->a_vp;
1.1 chopps 953: ap = VTOA(vp);
1.6 chopps 954: LIST_REMOVE(ap, link);
955: cache_purge(vp);
956: if (vp->v_type == VDIR && ap->tab)
957: free(ap->tab, M_ANODE);
958: else if (vp->v_type == VLNK && ap->slinkto)
959: free(ap->slinkto, M_ANODE);
960: free(ap, M_ANODE);
961: vp->v_data = NULL;
962: return(0);
1.1 chopps 963: }
964:
965:
1.6 chopps 966: /*
967: * POSIX pathconf info, grabbed from kern/u fs, probably need to
968: * investigate exactly what each return type means as they are probably
969: * not valid currently
970: */
1.25 christos 971: int
972: adosfs_pathconf(v)
973: void *v;
974: {
1.6 chopps 975: struct vop_pathconf_args /* {
976: struct vnode *a_vp;
977: int a_name;
1.12 cgd 978: register_t *a_retval;
1.25 christos 979: } */ *sp = v;
1.1 chopps 980:
1.6 chopps 981: switch (sp->a_name) {
982: case _PC_LINK_MAX:
983: *sp->a_retval = LINK_MAX;
984: return (0);
985: case _PC_MAX_CANON:
986: *sp->a_retval = MAX_CANON;
987: return (0);
988: case _PC_MAX_INPUT:
989: *sp->a_retval = MAX_INPUT;
990: return (0);
991: case _PC_PIPE_BUF:
992: *sp->a_retval = PIPE_BUF;
993: return (0);
994: case _PC_CHOWN_RESTRICTED:
995: *sp->a_retval = 1;
996: return (0);
997: case _PC_VDISABLE:
998: *sp->a_retval = _POSIX_VDISABLE;
999: return (0);
1000: default:
1001: return (EINVAL);
1002: }
1003: /* NOTREACHED */
1.1 chopps 1004: }
CVSweb <webmaster@jp.NetBSD.org>