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