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