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