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