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