Annotation of src/sys/fs/nilfs/nilfs_vnops.c, Revision 1.37.10.2
1.37.10.2! martin 1: /* $NetBSD$ */
1.1 reinoud 2:
3: /*
4: * Copyright (c) 2008, 2009 Reinoud Zandijk
5: * All rights reserved.
6: *
7: * Redistribution and use in source and binary forms, with or without
8: * modification, are permitted provided that the following conditions
9: * are met:
10: * 1. Redistributions of source code must retain the above copyright
11: * notice, this list of conditions and the following disclaimer.
12: * 2. Redistributions in binary form must reproduce the above copyright
13: * notice, this list of conditions and the following disclaimer in the
14: * documentation and/or other materials provided with the distribution.
15: *
16: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19: * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20: * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21: * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23: * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25: * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26: *
27: */
28:
29: #include <sys/cdefs.h>
30: #ifndef lint
1.37.10.1 martin 31: __KERNEL_RCSID(0, "$NetBSD$");
1.1 reinoud 32: #endif /* not lint */
33:
34:
35: #include <sys/param.h>
36: #include <sys/systm.h>
37: #include <sys/namei.h>
38: #include <sys/resourcevar.h> /* defines plimit structure in proc struct */
39: #include <sys/kernel.h>
40: #include <sys/file.h> /* define FWRITE ... */
41: #include <sys/stat.h>
42: #include <sys/buf.h>
43: #include <sys/proc.h>
44: #include <sys/mount.h>
45: #include <sys/vnode.h>
46: #include <sys/signalvar.h>
47: #include <sys/malloc.h>
48: #include <sys/dirent.h>
49: #include <sys/lockf.h>
50: #include <sys/kauth.h>
51:
52: #include <miscfs/genfs/genfs.h>
53: #include <uvm/uvm_extern.h>
54:
55: #include <fs/nilfs/nilfs_mount.h>
56: #include "nilfs.h"
57: #include "nilfs_subr.h"
58: #include "nilfs_bswap.h"
59:
60:
61: #define VTOI(vnode) ((struct nilfs_node *) (vnode)->v_data)
62:
63:
64: /* implementations of vnode functions; table follows at end */
65: /* --------------------------------------------------------------------- */
66:
67: int
68: nilfs_inactive(void *v)
69: {
1.34 riastrad 70: struct vop_inactive_v2_args /* {
1.1 reinoud 71: struct vnode *a_vp;
72: bool *a_recycle;
73: } */ *ap = v;
74: struct vnode *vp = ap->a_vp;
75: struct nilfs_node *nilfs_node = VTOI(vp);
76:
77: DPRINTF(NODE, ("nilfs_inactive called for nilfs_node %p\n", VTOI(vp)));
78:
79: if (nilfs_node == NULL) {
80: DPRINTF(NODE, ("nilfs_inactive: inactive NULL NILFS node\n"));
1.7 hannken 81: VOP_UNLOCK(vp);
1.1 reinoud 82: return 0;
83: }
84:
85: /*
86: * Optionally flush metadata to disc. If the file has not been
87: * referenced anymore in a directory we ought to free up the resources
88: * on disc if applicable.
89: */
90:
91: return 0;
92: }
93:
94: /* --------------------------------------------------------------------- */
95:
96: int
97: nilfs_reclaim(void *v)
98: {
1.36 riastrad 99: struct vop_reclaim_v2_args /* {
1.1 reinoud 100: struct vnode *a_vp;
101: } */ *ap = v;
102: struct vnode *vp = ap->a_vp;
103: struct nilfs_node *nilfs_node = VTOI(vp);
104:
1.36 riastrad 105: VOP_UNLOCK(vp);
106:
1.1 reinoud 107: DPRINTF(NODE, ("nilfs_reclaim called for node %p\n", nilfs_node));
108:
109: if (nilfs_node == NULL) {
110: DPRINTF(NODE, ("nilfs_reclaim(): null nilfsnode\n"));
111: return 0;
112: }
113:
114: /* update note for closure */
115: nilfs_update(vp, NULL, NULL, NULL, UPDATE_CLOSE);
116:
117: /* dispose all node knowledge */
1.29 hannken 118: genfs_node_destroy(vp);
1.1 reinoud 119: nilfs_dispose_node(&nilfs_node);
120:
1.29 hannken 121: vp->v_data = NULL;
122:
1.1 reinoud 123: return 0;
124: }
125:
126: /* --------------------------------------------------------------------- */
127:
128: int
129: nilfs_read(void *v)
130: {
131: struct vop_read_args /* {
132: struct vnode *a_vp;
133: struct uio *a_uio;
134: int a_ioflag;
135: kauth_cred_t a_cred;
136: } */ *ap = v;
137: struct vnode *vp = ap->a_vp;
138: struct uio *uio = ap->a_uio;
139: int ioflag = ap->a_ioflag;
140: int advice = IO_ADV_DECODE(ap->a_ioflag);
141: struct uvm_object *uobj;
142: struct nilfs_node *nilfs_node = VTOI(vp);
143: uint64_t file_size;
144: vsize_t len;
145: int error;
146:
147: DPRINTF(READ, ("nilfs_read called\n"));
148:
149: /* can this happen? some filingsystems have this check */
150: if (uio->uio_offset < 0)
151: return EINVAL;
152: if (uio->uio_resid == 0)
153: return 0;
154:
155: /* protect against rogue programs reading raw directories and links */
156: if ((ioflag & IO_ALTSEMANTICS) == 0) {
157: if (vp->v_type == VDIR)
158: return EISDIR;
159: /* all but regular files just give EINVAL */
160: if (vp->v_type != VREG)
161: return EINVAL;
162: }
163:
164: assert(nilfs_node);
165: file_size = nilfs_rw64(nilfs_node->inode.i_size);
166:
167: /* read contents using buffercache */
168: uobj = &vp->v_uobj;
169: error = 0;
170: while (uio->uio_resid > 0) {
171: /* reached end? */
172: if (file_size <= uio->uio_offset)
173: break;
174:
175: /* maximise length to file extremity */
176: len = MIN(file_size - uio->uio_offset, uio->uio_resid);
177: if (len == 0)
178: break;
179:
180: /* ubc, here we come, prepare to trap */
181: error = ubc_uiomove(uobj, uio, len, advice,
182: UBC_READ | UBC_PARTIALOK | UBC_UNMAP_FLAG(vp));
183: if (error)
184: break;
185: }
186:
187: /* note access time unless not requested */
188: if (!(vp->v_mount->mnt_flag & MNT_NOATIME)) {
189: nilfs_node->i_flags |= IN_ACCESS;
190: if ((ioflag & IO_SYNC) == IO_SYNC)
191: error = nilfs_update(vp, NULL, NULL, NULL, UPDATE_WAIT);
192: }
193:
194: return error;
195: }
196:
197: /* --------------------------------------------------------------------- */
198:
199: int
200: nilfs_write(void *v)
201: {
202: struct vop_write_args /* {
203: struct vnode *a_vp;
204: struct uio *a_uio;
205: int a_ioflag;
206: kauth_cred_t a_cred;
207: } */ *ap = v;
208: struct vnode *vp = ap->a_vp;
209: struct uio *uio = ap->a_uio;
210: int ioflag = ap->a_ioflag;
211: int advice = IO_ADV_DECODE(ap->a_ioflag);
212: struct uvm_object *uobj;
213: struct nilfs_node *nilfs_node = VTOI(vp);
1.24 christos 214: uint64_t file_size;
1.1 reinoud 215: vsize_t len;
1.13 rmind 216: int error, resid, extended;
1.1 reinoud 217:
218: DPRINTF(WRITE, ("nilfs_write called\n"));
219:
220: /* can this happen? some filingsystems have this check */
221: if (uio->uio_offset < 0)
222: return EINVAL;
223: if (uio->uio_resid == 0)
224: return 0;
225:
226: /* protect against rogue programs writing raw directories or links */
227: if ((ioflag & IO_ALTSEMANTICS) == 0) {
228: if (vp->v_type == VDIR)
229: return EISDIR;
230: /* all but regular files just give EINVAL for now */
231: if (vp->v_type != VREG)
232: return EINVAL;
233: }
234:
235: assert(nilfs_node);
236: panic("nilfs_write() called\n");
237:
238: /* remember old file size */
239: assert(nilfs_node);
240: file_size = nilfs_rw64(nilfs_node->inode.i_size);
241:
242: /* if explicitly asked to append, uio_offset can be wrong? */
243: if (ioflag & IO_APPEND)
244: uio->uio_offset = file_size;
245:
246: #if 0
247: extended = (uio->uio_offset + uio->uio_resid > file_size);
248: if (extended) {
249: DPRINTF(WRITE, ("extending file from %"PRIu64" to %"PRIu64"\n",
250: file_size, uio->uio_offset + uio->uio_resid));
251: error = nilfs_grow_node(nilfs_node, uio->uio_offset + uio->uio_resid);
252: if (error)
253: return error;
254: file_size = uio->uio_offset + uio->uio_resid;
255: }
256: #endif
257:
258: /* write contents using buffercache */
259: uobj = &vp->v_uobj;
260: resid = uio->uio_resid;
261: error = 0;
262:
263: uvm_vnp_setwritesize(vp, file_size);
264: while (uio->uio_resid > 0) {
265: /* maximise length to file extremity */
266: len = MIN(file_size - uio->uio_offset, uio->uio_resid);
267: if (len == 0)
268: break;
269:
270: /* ubc, here we come, prepare to trap */
271: error = ubc_uiomove(uobj, uio, len, advice,
272: UBC_WRITE | UBC_UNMAP_FLAG(vp));
273: if (error)
274: break;
275: }
276: uvm_vnp_setsize(vp, file_size);
277:
278: /* mark node changed and request update */
279: nilfs_node->i_flags |= IN_CHANGE | IN_UPDATE;
1.16 christos 280: if (vp->v_mount->mnt_flag & MNT_RELATIME)
281: nilfs_node->i_flags |= IN_ACCESS;
1.1 reinoud 282:
283: /*
284: * XXX TODO FFS has code here to reset setuid & setgid when we're not
285: * the superuser as a precaution against tampering.
286: */
287:
288: /* if we wrote a thing, note write action on vnode */
289: if (resid > uio->uio_resid)
290: VN_KNOTE(vp, NOTE_WRITE | (extended ? NOTE_EXTEND : 0));
291:
292: if (error) {
293: /* bring back file size to its former size */
294: /* take notice of its errors? */
295: // (void) nilfs_chsize(vp, (u_quad_t) old_size, NOCRED);
296:
297: /* roll back uio */
298: uio->uio_offset -= resid - uio->uio_resid;
299: uio->uio_resid = resid;
300: } else {
301: /* if we write and we're synchronous, update node */
302: if ((resid > uio->uio_resid) && ((ioflag & IO_SYNC) == IO_SYNC))
303: error = nilfs_update(vp, NULL, NULL, NULL, UPDATE_WAIT);
304: }
305:
306: return error;
307: }
308:
309:
310: /* --------------------------------------------------------------------- */
311:
312: /*
1.6 reinoud 313: * bmap functionality that translates logical block numbers to the virtual
314: * block numbers to be stored on the vnode itself.
1.22 reinoud 315: *
1.23 reinoud 316: * Important alert!
1.22 reinoud 317: *
318: * If runp is not NULL, the number of contiguous blocks __starting from the
319: * next block after the queried block__ will be returned in runp.
1.1 reinoud 320: */
321:
322: int
323: nilfs_trivial_bmap(void *v)
324: {
325: struct vop_bmap_args /* {
326: struct vnode *a_vp;
327: daddr_t a_bn;
328: struct vnode **a_vpp;
329: daddr_t *a_bnp;
330: int *a_runp;
331: } */ *ap = v;
332: struct vnode *vp = ap->a_vp; /* our node */
333: struct vnode **vpp = ap->a_vpp; /* return node */
334: daddr_t *bnp = ap->a_bnp; /* translated */
335: daddr_t bn = ap->a_bn; /* origional */
336: int *runp = ap->a_runp;
337: struct nilfs_node *node = VTOI(vp);
1.6 reinoud 338: uint64_t *l2vmap;
1.1 reinoud 339: uint32_t blocksize;
1.6 reinoud 340: int blks, run, error;
1.1 reinoud 341:
342: DPRINTF(TRANSLATE, ("nilfs_bmap() called\n"));
343: /* XXX could return `-1' to indicate holes/zero's */
344:
345: blocksize = node->nilfsdev->blocksize;
1.6 reinoud 346: blks = MAXPHYS / blocksize;
1.1 reinoud 347:
1.6 reinoud 348: /* get mapping memory */
349: l2vmap = malloc(sizeof(uint64_t) * blks, M_TEMP, M_WAITOK);
350:
351: /* get virtual block numbers for the vnode's buffer span */
352: error = nilfs_btree_nlookup(node, bn, blks, l2vmap);
353: if (error) {
354: free(l2vmap, M_TEMP);
355: return error;
356: }
357:
358: /* store virtual blocks on our own vp */
1.1 reinoud 359: if (vpp)
360: *vpp = vp;
361:
1.6 reinoud 362: /* start at virt[0] */
363: *bnp = l2vmap[0];
364:
365: /* get runlength */
366: run = 1;
367: while ((run < blks) && (l2vmap[run] == *bnp + run))
368: run++;
1.22 reinoud 369: run--; /* see comment at start of function */
370:
1.6 reinoud 371: /* set runlength */
1.1 reinoud 372: if (runp)
1.6 reinoud 373: *runp = run;
374:
375: DPRINTF(TRANSLATE, ("\tstart %"PRIu64" -> %"PRIu64" run %d\n",
376: bn, *bnp, run));
377:
378: /* mark not translated on virtual block number 0 */
379: if (*bnp == 0)
380: *bnp = -1;
1.1 reinoud 381:
382: /* return success */
1.6 reinoud 383: free(l2vmap, M_TEMP);
1.1 reinoud 384: return 0;
385: }
386:
387: /* --------------------------------------------------------------------- */
388:
389: static void
390: nilfs_read_filebuf(struct nilfs_node *node, struct buf *bp)
391: {
392: struct nilfs_device *nilfsdev = node->nilfsdev;
393: struct buf *nbp;
394: uint64_t *l2vmap, *v2pmap;
395: uint64_t from, blks;
396: uint32_t blocksize, buf_offset;
397: uint8_t *buf_pos;
398: int blk2dev = nilfsdev->blocksize / DEV_BSIZE;
399: int i, error;
400:
401: /*
402: * Translate all the block sectors into a series of buffers to read
403: * asynchronously from the nilfs device. Note that this lookup may
404: * induce readin's too.
405: */
406:
407: blocksize = nilfsdev->blocksize;
408:
409: from = bp->b_blkno;
410: blks = bp->b_bcount / blocksize;
411:
412: DPRINTF(READ, ("\tread in from inode %"PRIu64" blkno %"PRIu64" "
413: "+ %"PRIu64" blocks\n", node->ino, from, blks));
414:
415: DPRINTF(READ, ("\t\tblkno %"PRIu64" "
416: "+ %d bytes\n", bp->b_blkno, bp->b_bcount));
417:
418: /* get mapping memory */
419: l2vmap = malloc(sizeof(uint64_t) * blks, M_TEMP, M_WAITOK);
420: v2pmap = malloc(sizeof(uint64_t) * blks, M_TEMP, M_WAITOK);
421:
422: /* get virtual block numbers for the vnode's buffer span */
1.6 reinoud 423: for (i = 0; i < blks; i++)
424: l2vmap[i] = from + i;
1.1 reinoud 425:
426: /* translate virtual block numbers to physical block numbers */
427: error = nilfs_nvtop(node, blks, l2vmap, v2pmap);
428: if (error)
429: goto out;
430:
431: /* issue translated blocks */
432: bp->b_resid = bp->b_bcount;
433: for (i = 0; i < blks; i++) {
434: DPRINTF(READ, ("read_filebuf : ino %"PRIu64" blk %d -> "
435: "%"PRIu64" -> %"PRIu64"\n",
436: node->ino, i, l2vmap[i], v2pmap[i]));
437:
438: buf_offset = i * blocksize;
439: buf_pos = (uint8_t *) bp->b_data + buf_offset;
440:
441: /* note virtual block 0 marks not mapped */
442: if (l2vmap[i] == 0) {
443: memset(buf_pos, 0, blocksize);
444: nestiobuf_done(bp, blocksize, 0);
445: continue;
446: }
447:
448: /* nest iobuf */
449: nbp = getiobuf(NULL, true);
450: nestiobuf_setup(bp, nbp, buf_offset, blocksize);
451: KASSERT(nbp->b_vp == node->vnode);
452: /* nbp is B_ASYNC */
453:
454: nbp->b_lblkno = i;
455: nbp->b_blkno = v2pmap[i] * blk2dev; /* in DEV_BSIZE */
456: nbp->b_rawblkno = nbp->b_blkno;
457:
458: VOP_STRATEGY(nilfsdev->devvp, nbp);
459: }
460:
461: if ((bp->b_flags & B_ASYNC) == 0)
462: biowait(bp);
463:
464: out:
465: free(l2vmap, M_TEMP);
466: free(v2pmap, M_TEMP);
467: if (error) {
468: bp->b_error = EIO;
469: biodone(bp);
470: }
471: }
472:
473:
474: static void
475: nilfs_write_filebuf(struct nilfs_node *node, struct buf *bp)
476: {
477: /* TODO pass on to segment collector */
478: panic("nilfs_strategy writing called\n");
479: }
480:
481:
482: int
483: nilfs_vfsstrategy(void *v)
484: {
485: struct vop_strategy_args /* {
486: struct vnode *a_vp;
487: struct buf *a_bp;
488: } */ *ap = v;
489: struct vnode *vp = ap->a_vp;
490: struct buf *bp = ap->a_bp;
491: struct nilfs_node *node = VTOI(vp);
492:
493: DPRINTF(STRATEGY, ("nilfs_strategy called\n"));
494:
495: /* check if we ought to be here */
496: if (vp->v_type == VBLK || vp->v_type == VCHR)
497: panic("nilfs_strategy: spec");
498:
499: /* translate if needed and pass on */
500: if (bp->b_flags & B_READ) {
501: nilfs_read_filebuf(node, bp);
502: return bp->b_error;
503: }
504:
505: /* send to segment collector */
506: nilfs_write_filebuf(node, bp);
507: return bp->b_error;
508: }
509:
510: /* --------------------------------------------------------------------- */
511:
512: int
513: nilfs_readdir(void *v)
514: {
515: struct vop_readdir_args /* {
516: struct vnode *a_vp;
517: struct uio *a_uio;
518: kauth_cred_t a_cred;
519: int *a_eofflag;
520: off_t **a_cookies;
521: int *a_ncookies;
522: } */ *ap = v;
523: struct uio *uio = ap->a_uio;
524: struct vnode *vp = ap->a_vp;
525: struct nilfs_node *node = VTOI(vp);
526: struct nilfs_dir_entry *ndirent;
527: struct dirent dirent;
528: struct buf *bp;
529: uint64_t file_size, diroffset, transoffset, blkoff;
530: uint64_t blocknr;
531: uint32_t blocksize = node->nilfsdev->blocksize;
532: uint8_t *pos, name_len;
533: int error;
534:
535: DPRINTF(READDIR, ("nilfs_readdir called\n"));
536:
537: if (vp->v_type != VDIR)
538: return ENOTDIR;
539:
540: file_size = nilfs_rw64(node->inode.i_size);
541:
542: /* we are called just as long as we keep on pushing data in */
543: error = 0;
544: if ((uio->uio_offset < file_size) &&
545: (uio->uio_resid >= sizeof(struct dirent))) {
546: diroffset = uio->uio_offset;
547: transoffset = diroffset;
548:
549: blocknr = diroffset / blocksize;
550: blkoff = diroffset % blocksize;
1.31 riastrad 551: error = nilfs_bread(node, blocknr, 0, &bp);
1.1 reinoud 552: if (error)
553: return EIO;
554: while (diroffset < file_size) {
555: DPRINTF(READDIR, ("readdir : offset = %"PRIu64"\n",
556: diroffset));
557: if (blkoff >= blocksize) {
558: blkoff = 0; blocknr++;
559: brelse(bp, BC_AGE);
1.31 riastrad 560: error = nilfs_bread(node, blocknr, 0, &bp);
1.1 reinoud 561: if (error)
562: return EIO;
563: }
564:
565: /* read in one dirent */
566: pos = (uint8_t *) bp->b_data + blkoff;
567: ndirent = (struct nilfs_dir_entry *) pos;
568:
569: name_len = ndirent->name_len;
570: memset(&dirent, 0, sizeof(struct dirent));
571: dirent.d_fileno = nilfs_rw64(ndirent->inode);
572: dirent.d_type = ndirent->file_type; /* 1:1 ? */
573: dirent.d_namlen = name_len;
574: strncpy(dirent.d_name, ndirent->name, name_len);
575: dirent.d_reclen = _DIRENT_SIZE(&dirent);
576: DPRINTF(READDIR, ("copying `%*.*s`\n", name_len,
577: name_len, dirent.d_name));
578:
579: /*
580: * If there isn't enough space in the uio to return a
581: * whole dirent, break off read
582: */
583: if (uio->uio_resid < _DIRENT_SIZE(&dirent))
584: break;
585:
586: /* transfer */
587: if (name_len)
588: uiomove(&dirent, _DIRENT_SIZE(&dirent), uio);
589:
590: /* advance */
591: diroffset += nilfs_rw16(ndirent->rec_len);
592: blkoff += nilfs_rw16(ndirent->rec_len);
593:
1.37.10.1 martin 594: /* remember the last entry we transferred */
1.1 reinoud 595: transoffset = diroffset;
596: }
597: brelse(bp, BC_AGE);
598:
599: /* pass on last transfered offset */
600: uio->uio_offset = transoffset;
601: }
602:
603: if (ap->a_eofflag)
604: *ap->a_eofflag = (uio->uio_offset >= file_size);
605:
606: return error;
607: }
608:
609: /* --------------------------------------------------------------------- */
610:
611: int
612: nilfs_lookup(void *v)
613: {
1.27 hannken 614: struct vop_lookup_v2_args /* {
1.1 reinoud 615: struct vnode *a_dvp;
616: struct vnode **a_vpp;
617: struct componentname *a_cnp;
618: } */ *ap = v;
619: struct vnode *dvp = ap->a_dvp;
620: struct vnode **vpp = ap->a_vpp;
621: struct componentname *cnp = ap->a_cnp;
1.29 hannken 622: struct mount *mp = dvp->v_mount;
1.1 reinoud 623: uint64_t ino;
624: const char *name;
625: int namelen, nameiop, islastcn, mounted_ro;
626: int vnodetp;
627: int error, found;
628:
629: *vpp = NULL;
630:
631: DPRINTF(LOOKUP, ("nilfs_lookup called\n"));
632:
633: /* simplify/clarification flags */
634: nameiop = cnp->cn_nameiop;
635: islastcn = cnp->cn_flags & ISLASTCN;
1.29 hannken 636: mounted_ro = mp->mnt_flag & MNT_RDONLY;
1.1 reinoud 637:
638: /* check exec/dirread permissions first */
639: error = VOP_ACCESS(dvp, VEXEC, cnp->cn_cred);
640: if (error)
641: return error;
642:
643: DPRINTF(LOOKUP, ("\taccess ok\n"));
644:
645: /*
646: * If requesting a modify on the last path element on a read-only
647: * filingsystem, reject lookup; XXX why is this repeated in every FS ?
648: */
649: if (islastcn && mounted_ro && (nameiop == DELETE || nameiop == RENAME))
650: return EROFS;
651:
652: DPRINTF(LOOKUP, ("\tlooking up cnp->cn_nameptr '%s'\n",
653: cnp->cn_nameptr));
1.19 dholland 654: /* look in the namecache */
1.20 dholland 655: if (cache_lookup(dvp, cnp->cn_nameptr, cnp->cn_namelen,
656: cnp->cn_nameiop, cnp->cn_flags, NULL, vpp)) {
1.19 dholland 657: return *vpp == NULLVP ? ENOENT : 0;
658: }
1.1 reinoud 659:
660: DPRINTF(LOOKUP, ("\tNOT found in cache\n"));
661:
662: /*
663: * Obviously, the file is not (anymore) in the namecache, we have to
664: * search for it. There are three basic cases: '.', '..' and others.
665: *
666: * Following the guidelines of VOP_LOOKUP manpage and tmpfs.
667: */
668: error = 0;
669: if ((cnp->cn_namelen == 1) && (cnp->cn_nameptr[0] == '.')) {
670: DPRINTF(LOOKUP, ("\tlookup '.'\n"));
671: /* special case 1 '.' */
1.4 pooka 672: vref(dvp);
1.1 reinoud 673: *vpp = dvp;
674: /* done */
675: } else if (cnp->cn_flags & ISDOTDOT) {
676: /* special case 2 '..' */
677: DPRINTF(LOOKUP, ("\tlookup '..'\n"));
678:
679: /* get our node */
680: name = "..";
681: namelen = 2;
682: error = nilfs_lookup_name_in_dir(dvp, name, namelen,
683: &ino, &found);
684: if (error)
685: goto out;
686: if (!found)
687: error = ENOENT;
688:
689: if (error == 0) {
690: DPRINTF(LOOKUP, ("\tfound '..'\n"));
691: /* try to create/reuse the node */
1.30 hannken 692: error = vcache_get(mp, &ino, sizeof(ino), vpp);
1.1 reinoud 693:
694: if (!error) {
695: DPRINTF(LOOKUP,
696: ("\tnode retrieved/created OK\n"));
697: }
698: }
699: } else {
700: DPRINTF(LOOKUP, ("\tlookup file\n"));
701: /* all other files */
702: /* lookup filename in the directory returning its inode */
703: name = cnp->cn_nameptr;
704: namelen = cnp->cn_namelen;
705: error = nilfs_lookup_name_in_dir(dvp, name, namelen,
706: &ino, &found);
707: if (error)
708: goto out;
709: if (!found) {
710: DPRINTF(LOOKUP, ("\tNOT found\n"));
711: /*
712: * UGH, didn't find name. If we're creating or
713: * renaming on the last name this is OK and we ought
714: * to return EJUSTRETURN if its allowed to be created.
715: */
716: error = ENOENT;
717: if (islastcn &&
718: (nameiop == CREATE || nameiop == RENAME))
719: error = 0;
720: if (!error) {
721: error = VOP_ACCESS(dvp, VWRITE, cnp->cn_cred);
722: if (!error) {
723: error = EJUSTRETURN;
724: }
725: }
726: /* done */
727: } else {
728: /* try to create/reuse the node */
1.30 hannken 729: error = vcache_get(mp, &ino, sizeof(ino), vpp);
1.1 reinoud 730: if (!error) {
731: /*
732: * If we are not at the last path component
733: * and found a non-directory or non-link entry
734: * (which may itself be pointing to a
735: * directory), raise an error.
736: */
1.29 hannken 737: vnodetp = (*vpp)->v_type;
1.1 reinoud 738: if ((vnodetp != VDIR) && (vnodetp != VLNK)) {
1.29 hannken 739: if (!islastcn) {
740: vrele(*vpp);
741: *vpp = NULL;
1.1 reinoud 742: error = ENOTDIR;
1.29 hannken 743: }
1.1 reinoud 744: }
745:
746: }
747: }
748: }
749:
750: out:
751: /*
752: * Store result in the cache if requested. If we are creating a file,
753: * the file might not be found and thus putting it into the namecache
754: * might be seen as negative caching.
755: */
1.29 hannken 756: if (error == 0 && nameiop != CREATE)
1.20 dholland 757: cache_enter(dvp, *vpp, cnp->cn_nameptr, cnp->cn_namelen,
758: cnp->cn_flags);
1.1 reinoud 759:
760: DPRINTFIF(LOOKUP, error, ("nilfs_lookup returing error %d\n", error));
761:
1.27 hannken 762: if (error)
763: return error;
764: return 0;
1.1 reinoud 765: }
766:
767: /* --------------------------------------------------------------------- */
768:
769: static void
770: nilfs_ctime_to_timespec(struct timespec *ts, uint64_t ctime)
771: {
772: ts->tv_sec = ctime;
773: ts->tv_nsec = 0;
774: }
775:
776:
777: int
778: nilfs_getattr(void *v)
779: {
780: struct vop_getattr_args /* {
781: struct vnode *a_vp;
782: struct vattr *a_vap;
783: kauth_cred_t a_cred;
784: struct lwp *a_l;
785: } */ *ap = v;
786: struct vnode *vp = ap->a_vp;
787: struct vattr *vap = ap->a_vap;
788: struct nilfs_node *node = VTOI(vp);
789: struct nilfs_inode *inode = &node->inode;
790:
791: DPRINTF(VFSCALL, ("nilfs_getattr called\n"));
792:
793: /* basic info */
1.4 pooka 794: vattr_null(vap);
1.1 reinoud 795: vap->va_type = vp->v_type;
1.29 hannken 796: vap->va_mode = nilfs_rw16(inode->i_mode) & ALLPERMS;
1.1 reinoud 797: vap->va_nlink = nilfs_rw16(inode->i_links_count);
798: vap->va_uid = nilfs_rw32(inode->i_uid);
799: vap->va_gid = nilfs_rw32(inode->i_gid);
800: vap->va_fsid = vp->v_mount->mnt_stat.f_fsidx.__fsid_val[0];
801: vap->va_fileid = node->ino;
802: vap->va_size = nilfs_rw64(inode->i_size);
803: vap->va_blocksize = node->nilfsdev->blocksize;
804:
805: /* times */
806: nilfs_ctime_to_timespec(&vap->va_atime, nilfs_rw64(inode->i_mtime));
807: nilfs_ctime_to_timespec(&vap->va_mtime, nilfs_rw64(inode->i_mtime));
808: nilfs_ctime_to_timespec(&vap->va_ctime, nilfs_rw64(inode->i_ctime));
809: nilfs_ctime_to_timespec(&vap->va_birthtime, nilfs_rw64(inode->i_ctime));
810:
811: vap->va_gen = nilfs_rw32(inode->i_generation);
812: vap->va_flags = 0; /* vattr flags */
813: vap->va_bytes = nilfs_rw64(inode->i_blocks) * vap->va_blocksize;
814: vap->va_filerev = vap->va_gen; /* XXX file revision? same as gen? */
815: vap->va_vaflags = 0; /* XXX chflags flags */
816:
817: return 0;
818: }
819:
820: /* --------------------------------------------------------------------- */
821:
822: #if 0
823: static int
824: nilfs_chown(struct vnode *vp, uid_t new_uid, gid_t new_gid,
825: kauth_cred_t cred)
826: {
827: return EINVAL;
828: }
829:
830:
831: static int
832: nilfs_chmod(struct vnode *vp, mode_t mode, kauth_cred_t cred)
833: {
834:
835: return EINVAL;
836: }
837:
838:
839: /* exported */
840: int
841: nilfs_chsize(struct vnode *vp, u_quad_t newsize, kauth_cred_t cred)
842: {
843: return EINVAL;
844: }
845:
846:
847: static int
848: nilfs_chflags(struct vnode *vp, mode_t mode, kauth_cred_t cred)
849: {
850: return EINVAL;
851: }
852:
853:
854: static int
855: nilfs_chtimes(struct vnode *vp,
856: struct timespec *atime, struct timespec *mtime,
857: struct timespec *birthtime, int setattrflags,
858: kauth_cred_t cred)
859: {
860: return EINVAL;
861: }
862: #endif
863:
864:
865: int
866: nilfs_setattr(void *v)
867: {
868: struct vop_setattr_args /* {
869: struct vnode *a_vp;
870: struct vattr *a_vap;
871: kauth_cred_t a_cred;
872: struct lwp *a_l;
873: } */ *ap = v;
874: struct vnode *vp = ap->a_vp;
875:
876: vp = vp;
877: DPRINTF(VFSCALL, ("nilfs_setattr called\n"));
878: return EINVAL;
879: }
880:
881: /* --------------------------------------------------------------------- */
882:
883: /*
884: * Return POSIX pathconf information for NILFS file systems.
885: */
886: int
887: nilfs_pathconf(void *v)
888: {
889: struct vop_pathconf_args /* {
890: struct vnode *a_vp;
891: int a_name;
892: register_t *a_retval;
893: } */ *ap = v;
894: uint32_t bits;
895:
896: DPRINTF(VFSCALL, ("nilfs_pathconf called\n"));
897:
898: switch (ap->a_name) {
899: case _PC_LINK_MAX:
900: *ap->a_retval = (1<<16)-1; /* 16 bits */
901: return 0;
902: case _PC_NAME_MAX:
1.14 christos 903: *ap->a_retval = NILFS_MAXNAMLEN;
1.1 reinoud 904: return 0;
905: case _PC_PATH_MAX:
906: *ap->a_retval = PATH_MAX;
907: return 0;
908: case _PC_PIPE_BUF:
909: *ap->a_retval = PIPE_BUF;
910: return 0;
911: case _PC_CHOWN_RESTRICTED:
912: *ap->a_retval = 1;
913: return 0;
914: case _PC_NO_TRUNC:
915: *ap->a_retval = 1;
916: return 0;
917: case _PC_SYNC_IO:
918: *ap->a_retval = 0; /* synchronised is off for performance */
919: return 0;
920: case _PC_FILESIZEBITS:
921: /* 64 bit file offsets -> 2+floor(2log(2^64-1)) = 2 + 63 = 65 */
922: bits = 64; /* XXX ought to deliver 65 */
923: #if 0
924: if (nilfs_node)
925: bits = 64 * vp->v_mount->mnt_dev_bshift;
926: #endif
927: *ap->a_retval = bits;
928: return 0;
929: }
930:
931: return EINVAL;
932: }
933:
934:
935: /* --------------------------------------------------------------------- */
936:
937: int
938: nilfs_open(void *v)
939: {
940: struct vop_open_args /* {
941: struct vnode *a_vp;
942: int a_mode;
943: kauth_cred_t a_cred;
944: struct proc *a_p;
945: } */ *ap = v;
946: int flags;
947:
948: DPRINTF(VFSCALL, ("nilfs_open called\n"));
949:
950: /*
951: * Files marked append-only must be opened for appending.
952: */
953: flags = 0;
954: if ((flags & APPEND) && (ap->a_mode & (FWRITE | O_APPEND)) == FWRITE)
955: return (EPERM);
956:
957: return 0;
958: }
959:
960:
961: /* --------------------------------------------------------------------- */
962:
963: int
964: nilfs_close(void *v)
965: {
966: struct vop_close_args /* {
967: struct vnode *a_vp;
968: int a_fflag;
969: kauth_cred_t a_cred;
970: struct proc *a_p;
971: } */ *ap = v;
972: struct vnode *vp = ap->a_vp;
973: struct nilfs_node *nilfs_node = VTOI(vp);
974:
975: DPRINTF(VFSCALL, ("nilfs_close called\n"));
976: nilfs_node = nilfs_node; /* shut up gcc */
977:
1.12 rmind 978: mutex_enter(vp->v_interlock);
1.37.10.2! martin 979: if (vrefcnt(vp) > 1)
! 980: nilfs_itimes(nilfs_node, NULL, NULL, NULL);
1.12 rmind 981: mutex_exit(vp->v_interlock);
1.1 reinoud 982:
983: return 0;
984: }
985:
986:
987: /* --------------------------------------------------------------------- */
988:
1.2 elad 989: static int
990: nilfs_check_possible(struct vnode *vp, struct vattr *vap, mode_t mode)
1.1 reinoud 991: {
992: int flags;
993:
994: /* check if we are allowed to write */
1.2 elad 995: switch (vap->va_type) {
1.1 reinoud 996: case VDIR:
997: case VLNK:
998: case VREG:
999: /*
1000: * normal nodes: check if we're on a read-only mounted
1001: * filingsystem and bomb out if we're trying to write.
1002: */
1003: if ((mode & VWRITE) && (vp->v_mount->mnt_flag & MNT_RDONLY))
1004: return EROFS;
1005: break;
1006: case VBLK:
1007: case VCHR:
1008: case VSOCK:
1009: case VFIFO:
1010: /*
1011: * special nodes: even on read-only mounted filingsystems
1012: * these are allowed to be written to if permissions allow.
1013: */
1014: break;
1015: default:
1016: /* no idea what this is */
1017: return EINVAL;
1018: }
1019:
1020: /* noone may write immutable files */
1021: /* TODO: get chflags(2) flags */
1022: flags = 0;
1023: if ((mode & VWRITE) && (flags & IMMUTABLE))
1024: return EPERM;
1025:
1.2 elad 1026: return 0;
1027: }
1028:
1029: static int
1030: nilfs_check_permitted(struct vnode *vp, struct vattr *vap, mode_t mode,
1031: kauth_cred_t cred)
1032: {
1033:
1.1 reinoud 1034: /* ask the generic genfs_can_access to advice on security */
1.21 plunky 1035: return kauth_authorize_vnode(cred, KAUTH_ACCESS_ACTION(mode,
1.17 elad 1036: vp->v_type, vap->va_mode), vp, NULL, genfs_can_access(vp->v_type,
1037: vap->va_mode, vap->va_uid, vap->va_gid, mode, cred));
1.1 reinoud 1038: }
1039:
1.2 elad 1040: int
1041: nilfs_access(void *v)
1042: {
1043: struct vop_access_args /* {
1044: struct vnode *a_vp;
1045: int a_mode;
1046: kauth_cred_t a_cred;
1047: struct proc *a_p;
1048: } */ *ap = v;
1049: struct vnode *vp = ap->a_vp;
1050: mode_t mode = ap->a_mode;
1051: kauth_cred_t cred = ap->a_cred;
1052: /* struct nilfs_node *nilfs_node = VTOI(vp); */
1053: struct vattr vap;
1054: int error;
1055:
1056: DPRINTF(VFSCALL, ("nilfs_access called\n"));
1057:
1058: error = VOP_GETATTR(vp, &vap, NULL);
1059: if (error)
1060: return error;
1061:
1062: error = nilfs_check_possible(vp, &vap, mode);
1063: if (error)
1064: return error;
1065:
1066: error = nilfs_check_permitted(vp, &vap, mode, cred);
1067:
1068: return error;
1069: }
1070:
1.1 reinoud 1071: /* --------------------------------------------------------------------- */
1072:
1073: int
1074: nilfs_create(void *v)
1075: {
1.26 hannken 1076: struct vop_create_v3_args /* {
1.1 reinoud 1077: struct vnode *a_dvp;
1078: struct vnode **a_vpp;
1079: struct componentname *a_cnp;
1080: struct vattr *a_vap;
1081: } */ *ap = v;
1082: struct vnode *dvp = ap->a_dvp;
1083: struct vnode **vpp = ap->a_vpp;
1084: struct vattr *vap = ap->a_vap;
1085: struct componentname *cnp = ap->a_cnp;
1086: int error;
1087:
1088: DPRINTF(VFSCALL, ("nilfs_create called\n"));
1089: error = nilfs_create_node(dvp, vpp, vap, cnp);
1090:
1091: return error;
1092: }
1093:
1094: /* --------------------------------------------------------------------- */
1095:
1096: int
1097: nilfs_mknod(void *v)
1098: {
1.26 hannken 1099: struct vop_mknod_v3_args /* {
1.1 reinoud 1100: struct vnode *a_dvp;
1101: struct vnode **a_vpp;
1102: struct componentname *a_cnp;
1103: struct vattr *a_vap;
1104: } */ *ap = v;
1105: struct vnode *dvp = ap->a_dvp;
1106: struct vnode **vpp = ap->a_vpp;
1107: struct vattr *vap = ap->a_vap;
1108: struct componentname *cnp = ap->a_cnp;
1109: int error;
1110:
1111: DPRINTF(VFSCALL, ("nilfs_mknod called\n"));
1112: error = nilfs_create_node(dvp, vpp, vap, cnp);
1113:
1114: return error;
1115: }
1116:
1117: /* --------------------------------------------------------------------- */
1118:
1119: int
1120: nilfs_mkdir(void *v)
1121: {
1.26 hannken 1122: struct vop_mkdir_v3_args /* {
1.1 reinoud 1123: struct vnode *a_dvp;
1124: struct vnode **a_vpp;
1125: struct componentname *a_cnp;
1126: struct vattr *a_vap;
1127: } */ *ap = v;
1128: struct vnode *dvp = ap->a_dvp;
1129: struct vnode **vpp = ap->a_vpp;
1130: struct vattr *vap = ap->a_vap;
1131: struct componentname *cnp = ap->a_cnp;
1132: int error;
1133:
1134: DPRINTF(VFSCALL, ("nilfs_mkdir called\n"));
1135: error = nilfs_create_node(dvp, vpp, vap, cnp);
1136:
1137: return error;
1138: }
1139:
1140: /* --------------------------------------------------------------------- */
1141:
1142: static int
1143: nilfs_do_link(struct vnode *dvp, struct vnode *vp, struct componentname *cnp)
1144: {
1145: struct nilfs_node *nilfs_node, *dir_node;
1146: struct vattr vap;
1147: int error;
1148:
1149: DPRINTF(VFSCALL, ("nilfs_link called\n"));
1.10 rmind 1150: KASSERT(dvp != vp);
1151: KASSERT(vp->v_type != VDIR);
1152: KASSERT(dvp->v_mount == vp->v_mount);
1.1 reinoud 1153:
1154: /* lock node */
1155: error = vn_lock(vp, LK_EXCLUSIVE);
1156: if (error)
1157: return error;
1158:
1159: /* get attributes */
1160: dir_node = VTOI(dvp);
1161: nilfs_node = VTOI(vp);
1162:
1163: error = VOP_GETATTR(vp, &vap, FSCRED);
1.5 hannken 1164: if (error) {
1.7 hannken 1165: VOP_UNLOCK(vp);
1.1 reinoud 1166: return error;
1.5 hannken 1167: }
1.1 reinoud 1168:
1169: /* check link count overflow */
1.5 hannken 1170: if (vap.va_nlink >= (1<<16)-1) { /* uint16_t */
1.7 hannken 1171: VOP_UNLOCK(vp);
1.1 reinoud 1172: return EMLINK;
1.5 hannken 1173: }
1.1 reinoud 1174:
1.5 hannken 1175: error = nilfs_dir_attach(dir_node->ump, dir_node, nilfs_node,
1176: &vap, cnp);
1177: if (error)
1.7 hannken 1178: VOP_UNLOCK(vp);
1.5 hannken 1179: return error;
1.1 reinoud 1180: }
1181:
1182: int
1183: nilfs_link(void *v)
1184: {
1.32 riastrad 1185: struct vop_link_v2_args /* {
1.1 reinoud 1186: struct vnode *a_dvp;
1187: struct vnode *a_vp;
1188: struct componentname *a_cnp;
1189: } */ *ap = v;
1190: struct vnode *dvp = ap->a_dvp;
1191: struct vnode *vp = ap->a_vp;
1192: struct componentname *cnp = ap->a_cnp;
1193: int error;
1194:
1195: error = nilfs_do_link(dvp, vp, cnp);
1196: if (error)
1197: VOP_ABORTOP(dvp, cnp);
1198:
1199: VN_KNOTE(vp, NOTE_LINK);
1200: VN_KNOTE(dvp, NOTE_WRITE);
1201:
1202: return error;
1203: }
1204:
1205: /* --------------------------------------------------------------------- */
1206:
1207: static int
1208: nilfs_do_symlink(struct nilfs_node *nilfs_node, char *target)
1209: {
1210: return EROFS;
1211: }
1212:
1213:
1214: int
1215: nilfs_symlink(void *v)
1216: {
1.26 hannken 1217: struct vop_symlink_v3_args /* {
1.1 reinoud 1218: struct vnode *a_dvp;
1219: struct vnode **a_vpp;
1220: struct componentname *a_cnp;
1221: struct vattr *a_vap;
1222: char *a_target;
1223: } */ *ap = v;
1224: struct vnode *dvp = ap->a_dvp;
1225: struct vnode **vpp = ap->a_vpp;
1226: struct vattr *vap = ap->a_vap;
1227: struct componentname *cnp = ap->a_cnp;
1228: struct nilfs_node *dir_node;
1229: struct nilfs_node *nilfs_node;
1230: int error;
1231:
1232: DPRINTF(VFSCALL, ("nilfs_symlink called\n"));
1233: DPRINTF(VFSCALL, ("\tlinking to `%s`\n", ap->a_target));
1234: error = nilfs_create_node(dvp, vpp, vap, cnp);
1235: KASSERT(((error == 0) && (*vpp != NULL)) || ((error && (*vpp == NULL))));
1236: if (!error) {
1237: dir_node = VTOI(dvp);
1238: nilfs_node = VTOI(*vpp);
1239: KASSERT(nilfs_node);
1240: error = nilfs_do_symlink(nilfs_node, ap->a_target);
1241: if (error) {
1242: /* remove node */
1243: nilfs_shrink_node(nilfs_node, 0);
1244: nilfs_dir_detach(nilfs_node->ump, dir_node, nilfs_node, cnp);
1245: }
1246: }
1247: return error;
1248: }
1249:
1250: /* --------------------------------------------------------------------- */
1251:
1252: int
1253: nilfs_readlink(void *v)
1254: {
1255: struct vop_readlink_args /* {
1256: struct vnode *a_vp;
1257: struct uio *a_uio;
1258: kauth_cred_t a_cred;
1259: } */ *ap = v;
1260: #if 0
1261: struct vnode *vp = ap->a_vp;
1262: struct uio *uio = ap->a_uio;
1263: kauth_cred_t cred = ap->a_cred;
1264: struct nilfs_node *nilfs_node;
1265: struct pathcomp pathcomp;
1266: struct vattr vattr;
1267: uint8_t *pathbuf, *targetbuf, *tmpname;
1268: uint8_t *pathpos, *targetpos;
1269: char *mntonname;
1270: int pathlen, targetlen, namelen, mntonnamelen, len, l_ci;
1271: int first, error;
1272: #endif
1273: ap = ap;
1274:
1275: DPRINTF(VFSCALL, ("nilfs_readlink called\n"));
1276:
1277: return EROFS;
1278: }
1279:
1280: /* --------------------------------------------------------------------- */
1281:
1282: /* note: i tried to follow the logics of the tmpfs rename code */
1283: int
1284: nilfs_rename(void *v)
1285: {
1286: struct vop_rename_args /* {
1287: struct vnode *a_fdvp;
1288: struct vnode *a_fvp;
1289: struct componentname *a_fcnp;
1290: struct vnode *a_tdvp;
1291: struct vnode *a_tvp;
1292: struct componentname *a_tcnp;
1293: } */ *ap = v;
1294: struct vnode *tvp = ap->a_tvp;
1295: struct vnode *tdvp = ap->a_tdvp;
1296: struct vnode *fvp = ap->a_fvp;
1297: struct vnode *fdvp = ap->a_fdvp;
1298: struct componentname *tcnp = ap->a_tcnp;
1299: struct componentname *fcnp = ap->a_fcnp;
1300: struct nilfs_node *fnode, *fdnode, *tnode, *tdnode;
1301: struct vattr fvap, tvap;
1302: int error;
1303:
1304: DPRINTF(VFSCALL, ("nilfs_rename called\n"));
1305:
1306: /* disallow cross-device renames */
1307: if (fvp->v_mount != tdvp->v_mount ||
1308: (tvp != NULL && fvp->v_mount != tvp->v_mount)) {
1309: error = EXDEV;
1310: goto out_unlocked;
1311: }
1312:
1313: fnode = VTOI(fvp);
1314: fdnode = VTOI(fdvp);
1315: tnode = (tvp == NULL) ? NULL : VTOI(tvp);
1316: tdnode = VTOI(tdvp);
1317:
1318: /* lock our source dir */
1319: if (fdnode != tdnode) {
1320: error = vn_lock(fdvp, LK_EXCLUSIVE | LK_RETRY);
1321: if (error != 0)
1322: goto out_unlocked;
1323: }
1324:
1325: /* get info about the node to be moved */
1.15 hannken 1326: vn_lock(fvp, LK_SHARED | LK_RETRY);
1.1 reinoud 1327: error = VOP_GETATTR(fvp, &fvap, FSCRED);
1.15 hannken 1328: VOP_UNLOCK(fvp);
1.1 reinoud 1329: KASSERT(error == 0);
1330:
1331: /* check when to delete the old already existing entry */
1332: if (tvp) {
1333: /* get info about the node to be moved to */
1.15 hannken 1334: error = VOP_GETATTR(tvp, &tvap, FSCRED);
1.1 reinoud 1335: KASSERT(error == 0);
1336:
1337: /* if both dirs, make sure the destination is empty */
1338: if (fvp->v_type == VDIR && tvp->v_type == VDIR) {
1339: if (tvap.va_nlink > 2) {
1340: error = ENOTEMPTY;
1341: goto out;
1342: }
1343: }
1344: /* if moving dir, make sure destination is dir too */
1345: if (fvp->v_type == VDIR && tvp->v_type != VDIR) {
1346: error = ENOTDIR;
1347: goto out;
1348: }
1349: /* if we're moving a non-directory, make sure dest is no dir */
1350: if (fvp->v_type != VDIR && tvp->v_type == VDIR) {
1351: error = EISDIR;
1352: goto out;
1353: }
1354: }
1355:
1356: /* dont allow renaming directories acros directory for now */
1357: if (fdnode != tdnode) {
1358: if (fvp->v_type == VDIR) {
1359: error = EINVAL;
1360: goto out;
1361: }
1362: }
1363:
1364: /* remove existing entry if present */
1365: if (tvp)
1366: nilfs_dir_detach(tdnode->ump, tdnode, tnode, tcnp);
1367:
1368: /* create new directory entry for the node */
1369: error = nilfs_dir_attach(tdnode->ump, tdnode, fnode, &fvap, tcnp);
1370: if (error)
1371: goto out;
1372:
1373: /* unlink old directory entry for the node, if failing, unattach new */
1374: error = nilfs_dir_detach(tdnode->ump, fdnode, fnode, fcnp);
1375: if (error)
1376: nilfs_dir_detach(tdnode->ump, tdnode, fnode, tcnp);
1377:
1378: out:
1379: if (fdnode != tdnode)
1.7 hannken 1380: VOP_UNLOCK(fdvp);
1.1 reinoud 1381:
1382: out_unlocked:
1383: VOP_ABORTOP(tdvp, tcnp);
1384: if (tdvp == tvp)
1385: vrele(tdvp);
1386: else
1387: vput(tdvp);
1388: if (tvp)
1389: vput(tvp);
1390: VOP_ABORTOP(fdvp, fcnp);
1391:
1392: /* release source nodes. */
1393: vrele(fdvp);
1394: vrele(fvp);
1395:
1396: return error;
1397: }
1398:
1399: /* --------------------------------------------------------------------- */
1400:
1401: int
1402: nilfs_remove(void *v)
1403: {
1.35 riastrad 1404: struct vop_remove_v2_args /* {
1.1 reinoud 1405: struct vnode *a_dvp;
1406: struct vnode *a_vp;
1407: struct componentname *a_cnp;
1408: } */ *ap = v;
1409: struct vnode *dvp = ap->a_dvp;
1410: struct vnode *vp = ap->a_vp;
1411: struct componentname *cnp = ap->a_cnp;
1.3 mbalmer 1412: struct nilfs_node *dir_node = VTOI(dvp);
1.1 reinoud 1413: struct nilfs_node *nilfs_node = VTOI(vp);
1414: struct nilfs_mount *ump = dir_node->ump;
1415: int error;
1416:
1417: DPRINTF(VFSCALL, ("nilfs_remove called\n"));
1418: if (vp->v_type != VDIR) {
1419: error = nilfs_dir_detach(ump, dir_node, nilfs_node, cnp);
1420: DPRINTFIF(NODE, error, ("\tgot error removing file\n"));
1421: } else {
1422: DPRINTF(NODE, ("\tis a directory: perm. denied\n"));
1423: error = EPERM;
1424: }
1425:
1426: if (error == 0) {
1427: VN_KNOTE(vp, NOTE_DELETE);
1428: VN_KNOTE(dvp, NOTE_WRITE);
1429: }
1430:
1431: if (dvp == vp)
1432: vrele(vp);
1433: else
1434: vput(vp);
1435:
1436: return error;
1437: }
1438:
1439: /* --------------------------------------------------------------------- */
1440:
1441: int
1442: nilfs_rmdir(void *v)
1443: {
1.35 riastrad 1444: struct vop_rmdir_v2_args /* {
1.1 reinoud 1445: struct vnode *a_dvp;
1446: struct vnode *a_vp;
1447: struct componentname *a_cnp;
1448: } */ *ap = v;
1449: struct vnode *vp = ap->a_vp;
1450: struct vnode *dvp = ap->a_dvp;
1451: struct componentname *cnp = ap->a_cnp;
1.3 mbalmer 1452: struct nilfs_node *dir_node = VTOI(dvp);
1.1 reinoud 1453: struct nilfs_node *nilfs_node = VTOI(vp);
1454: struct nilfs_mount *ump = dir_node->ump;
1455: int refcnt, error;
1456:
1457: DPRINTF(NOTIMPL, ("nilfs_rmdir called\n"));
1458:
1459: /* don't allow '.' to be deleted */
1460: if (dir_node == nilfs_node) {
1.35 riastrad 1461: vrele(vp);
1.1 reinoud 1462: return EINVAL;
1463: }
1464:
1465: /* check to see if the directory is empty */
1466: error = 0;
1467: refcnt = 2; /* XXX */
1468: if (refcnt > 1) {
1469: /* NOT empty */
1470: vput(vp);
1471: return ENOTEMPTY;
1472: }
1473:
1474: /* detach the node from the directory */
1475: error = nilfs_dir_detach(ump, dir_node, nilfs_node, cnp);
1476: if (error == 0) {
1477: cache_purge(vp);
1478: // cache_purge(dvp); /* XXX from msdosfs, why? */
1479: VN_KNOTE(vp, NOTE_DELETE);
1480: }
1481: DPRINTFIF(NODE, error, ("\tgot error removing file\n"));
1482:
1.35 riastrad 1483: /* put the node and exit */
1.1 reinoud 1484: vput(vp);
1485:
1486: return error;
1487: }
1488:
1489: /* --------------------------------------------------------------------- */
1490:
1491: int
1492: nilfs_fsync(void *v)
1493: {
1494: struct vop_fsync_args /* {
1495: struct vnode *a_vp;
1496: kauth_cred_t a_cred;
1497: int a_flags;
1498: off_t offlo;
1499: off_t offhi;
1500: struct proc *a_p;
1501: } */ *ap = v;
1502: struct vnode *vp = ap->a_vp;
1503: // struct nilfs_node *nilfs_node = VTOI(vp);
1504: // int error, flags, wait;
1505:
1506: DPRINTF(STRATEGY, ("nilfs_fsync called : %s, %s\n",
1507: (ap->a_flags & FSYNC_WAIT) ? "wait":"no wait",
1508: (ap->a_flags & FSYNC_DATAONLY) ? "data_only":"complete"));
1509:
1510: vp = vp;
1511: return 0;
1512: }
1513:
1514: /* --------------------------------------------------------------------- */
1515:
1516: int
1517: nilfs_advlock(void *v)
1518: {
1519: struct vop_advlock_args /* {
1520: struct vnode *a_vp;
1521: void *a_id;
1522: int a_op;
1523: struct flock *a_fl;
1524: int a_flags;
1525: } */ *ap = v;
1526: struct vnode *vp = ap->a_vp;
1527: struct nilfs_node *nilfs_node = VTOI(vp);
1528: uint64_t file_size;
1529:
1530: DPRINTF(LOCKING, ("nilfs_advlock called\n"));
1531:
1532: assert(nilfs_node);
1533: file_size = nilfs_rw64(nilfs_node->inode.i_size);
1534:
1535: return lf_advlock(ap, &nilfs_node->lockf, file_size);
1536: }
1537:
1538: /* --------------------------------------------------------------------- */
1539:
1540:
1541: /* Global vfs vnode data structures for nilfss */
1542: int (**nilfs_vnodeop_p) __P((void *));
1543:
1544: const struct vnodeopv_entry_desc nilfs_vnodeop_entries[] = {
1545: { &vop_default_desc, vn_default_error },
1546: { &vop_lookup_desc, nilfs_lookup }, /* lookup */
1547: { &vop_create_desc, nilfs_create }, /* create */
1548: { &vop_mknod_desc, nilfs_mknod }, /* mknod */ /* TODO */
1549: { &vop_open_desc, nilfs_open }, /* open */
1550: { &vop_close_desc, nilfs_close }, /* close */
1551: { &vop_access_desc, nilfs_access }, /* access */
1552: { &vop_getattr_desc, nilfs_getattr }, /* getattr */
1553: { &vop_setattr_desc, nilfs_setattr }, /* setattr */ /* TODO chflags */
1554: { &vop_read_desc, nilfs_read }, /* read */
1555: { &vop_write_desc, nilfs_write }, /* write */ /* WRITE */
1.28 dholland 1556: { &vop_fallocate_desc, genfs_eopnotsupp }, /* fallocate */
1557: { &vop_fdiscard_desc, genfs_eopnotsupp }, /* fdiscard */
1.1 reinoud 1558: { &vop_fcntl_desc, genfs_fcntl }, /* fcntl */ /* TODO? */
1559: { &vop_ioctl_desc, genfs_enoioctl }, /* ioctl */ /* TODO? */
1560: { &vop_poll_desc, genfs_poll }, /* poll */ /* TODO/OK? */
1561: { &vop_kqfilter_desc, genfs_kqfilter }, /* kqfilter */ /* ? */
1562: { &vop_revoke_desc, genfs_revoke }, /* revoke */ /* TODO? */
1563: { &vop_mmap_desc, genfs_mmap }, /* mmap */ /* OK? */
1564: { &vop_fsync_desc, nilfs_fsync }, /* fsync */
1565: { &vop_seek_desc, genfs_seek }, /* seek */
1566: { &vop_remove_desc, nilfs_remove }, /* remove */
1567: { &vop_link_desc, nilfs_link }, /* link */ /* TODO */
1568: { &vop_rename_desc, nilfs_rename }, /* rename */ /* TODO */
1569: { &vop_mkdir_desc, nilfs_mkdir }, /* mkdir */
1570: { &vop_rmdir_desc, nilfs_rmdir }, /* rmdir */
1571: { &vop_symlink_desc, nilfs_symlink }, /* symlink */ /* TODO */
1572: { &vop_readdir_desc, nilfs_readdir }, /* readdir */
1573: { &vop_readlink_desc, nilfs_readlink }, /* readlink */ /* TEST ME */
1574: { &vop_abortop_desc, genfs_abortop }, /* abortop */ /* TODO/OK? */
1575: { &vop_inactive_desc, nilfs_inactive }, /* inactive */
1576: { &vop_reclaim_desc, nilfs_reclaim }, /* reclaim */
1577: { &vop_lock_desc, genfs_lock }, /* lock */
1578: { &vop_unlock_desc, genfs_unlock }, /* unlock */
1579: { &vop_bmap_desc, nilfs_trivial_bmap }, /* bmap */ /* 1:1 bmap */
1580: { &vop_strategy_desc, nilfs_vfsstrategy },/* strategy */
1581: /* { &vop_print_desc, nilfs_print }, */ /* print */
1582: { &vop_islocked_desc, genfs_islocked }, /* islocked */
1583: { &vop_pathconf_desc, nilfs_pathconf }, /* pathconf */
1584: { &vop_advlock_desc, nilfs_advlock }, /* advlock */ /* TEST ME */
1585: { &vop_bwrite_desc, vn_bwrite }, /* bwrite */ /* ->strategy */
1586: { &vop_getpages_desc, genfs_getpages }, /* getpages */
1587: { &vop_putpages_desc, genfs_putpages }, /* putpages */
1588: { NULL, NULL }
1589: };
1590:
1591:
1592: const struct vnodeopv_desc nilfs_vnodeop_opv_desc = {
1593: &nilfs_vnodeop_p, nilfs_vnodeop_entries
1594: };
1595:
CVSweb <webmaster@jp.NetBSD.org>