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