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