1 /* $NetBSD: sysvbfs_vnops.c,v 1.14 2007/09/24 00:42:14 rumble Exp $ */ 2 3 /*- 4 * Copyright (c) 2004 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by UCHIYAMA Yasushi. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 3. All advertising materials mentioning features or use of this software 19 * must display the following acknowledgement: 20 * This product includes software developed by the NetBSD 21 * Foundation, Inc. and its contributors. 22 * 4. Neither the name of The NetBSD Foundation nor the names of its 23 * contributors may be used to endorse or promote products derived 24 * from this software without specific prior written permission. 25 * 26 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 27 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 28 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 29 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 30 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 31 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 32 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 33 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 34 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 35 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 36 * POSSIBILITY OF SUCH DAMAGE. 37 */ 38 39 #include <sys/cdefs.h> 40 __KERNEL_RCSID(0, "$NetBSD: sysvbfs_vnops.c,v 1.14 2007/09/24 00:42:14 rumble Exp $"); 41 42 #include <sys/param.h> 43 #include <sys/kernel.h> 44 #include <sys/resource.h> 45 #include <sys/vnode.h> 46 #include <sys/namei.h> 47 #include <sys/dirent.h> 48 #include <sys/malloc.h> 49 #include <sys/lockf.h> 50 #include <sys/unistd.h> 51 #include <sys/fcntl.h> 52 #include <sys/kauth.h> 53 54 #include <fs/sysvbfs/sysvbfs.h> 55 #include <fs/sysvbfs/bfs.h> 56 57 #ifdef SYSVBFS_VNOPS_DEBUG 58 #define DPRINTF(fmt, args...) printf(fmt, ##args) 59 #else 60 #define DPRINTF(arg...) ((void)0) 61 #endif 62 #define ROUND_SECTOR(x) (((x) + 511) & ~511) 63 64 MALLOC_JUSTDEFINE(M_SYSVBFS_VNODE, "sysvbfs vnode", "sysvbfs vnode structures"); 65 MALLOC_DECLARE(M_BFS); 66 67 int 68 sysvbfs_lookup(void *arg) 69 { 70 struct vop_lookup_args /* { 71 struct vnode *a_dvp; 72 struct vnode **a_vpp; 73 struct componentname *a_cnp; 74 } */ *a = arg; 75 struct vnode *v = a->a_dvp; 76 struct sysvbfs_node *bnode = v->v_data; 77 struct bfs *bfs = bnode->bmp->bfs; /* my filesystem */ 78 struct vnode *vpp = NULL; 79 struct bfs_dirent *dirent = NULL; 80 struct componentname *cnp = a->a_cnp; 81 int nameiop = cnp->cn_nameiop; 82 const char *name = cnp->cn_nameptr; 83 int namelen = cnp->cn_namelen; 84 int error; 85 bool islastcn = cnp->cn_flags & ISLASTCN; 86 87 DPRINTF("%s: %s op=%d %ld\n", __FUNCTION__, name, nameiop, 88 cnp->cn_flags); 89 90 KASSERT((cnp->cn_flags & ISDOTDOT) == 0); 91 if ((error = VOP_ACCESS(a->a_dvp, VEXEC, cnp->cn_cred, 92 cnp->cn_lwp)) != 0) { 93 return error; /* directory permittion. */ 94 } 95 96 97 if (namelen == 1 && name[0] == '.') { /* "." */ 98 VREF(v); 99 *a->a_vpp = v; 100 } else { /* Regular file */ 101 if (!bfs_dirent_lookup_by_name(bfs, cnp->cn_nameptr, 102 &dirent)) { 103 if (nameiop != CREATE && nameiop != RENAME) { 104 DPRINTF("%s: no such a file. (1)\n", 105 __FUNCTION__); 106 return ENOENT; 107 } 108 if ((error = VOP_ACCESS(v, VWRITE, cnp->cn_cred, 109 cnp->cn_lwp)) != 0) 110 return error; 111 cnp->cn_flags |= SAVENAME; 112 return EJUSTRETURN; 113 } 114 115 /* Allocate v-node */ 116 if ((error = sysvbfs_vget(v->v_mount, dirent->inode, &vpp)) != 0) { 117 DPRINTF("%s: can't get vnode.\n", __FUNCTION__); 118 return error; 119 } 120 *a->a_vpp = vpp; 121 } 122 123 if (cnp->cn_nameiop != LOOKUP && islastcn) 124 cnp->cn_flags |= SAVENAME; 125 126 return 0; 127 } 128 129 int 130 sysvbfs_create(void *arg) 131 { 132 struct vop_create_args /* { 133 struct vnode *a_dvp; 134 struct vnode **a_vpp; 135 struct componentname *a_cnp; 136 struct vattr *a_vap; 137 } */ *a = arg; 138 struct sysvbfs_node *bnode = a->a_dvp->v_data; 139 struct sysvbfs_mount *bmp = bnode->bmp; 140 struct bfs *bfs = bmp->bfs; 141 struct mount *mp = bmp->mountp; 142 struct bfs_dirent *dirent; 143 struct bfs_fileattr attr; 144 struct vattr *va = a->a_vap; 145 kauth_cred_t cr = a->a_cnp->cn_cred; 146 int err = 0; 147 148 DPRINTF("%s: %s\n", __FUNCTION__, a->a_cnp->cn_nameptr); 149 KDASSERT(a->a_vap->va_type == VREG); 150 attr.uid = kauth_cred_geteuid(cr); 151 attr.gid = kauth_cred_getegid(cr); 152 attr.mode = va->va_mode; 153 154 if ((err = bfs_file_create(bfs, a->a_cnp->cn_nameptr, 0, 0, &attr)) 155 != 0) { 156 DPRINTF("%s: bfs_file_create failed.\n", __FUNCTION__); 157 goto unlock_exit; 158 } 159 160 if (!bfs_dirent_lookup_by_name(bfs, a->a_cnp->cn_nameptr, &dirent)) 161 panic("no dirent for created file."); 162 163 if ((err = sysvbfs_vget(mp, dirent->inode, a->a_vpp)) != 0) { 164 DPRINTF("%s: sysvbfs_vget failed.\n", __FUNCTION__); 165 goto unlock_exit; 166 } 167 bnode = (*a->a_vpp)->v_data; 168 bnode->update_ctime = true; 169 bnode->update_mtime = true; 170 bnode->update_atime = true; 171 172 unlock_exit: 173 /* unlock parent directory */ 174 vput(a->a_dvp); /* locked at sysvbfs_lookup(); */ 175 176 return err; 177 } 178 179 int 180 sysvbfs_open(void *arg) 181 { 182 struct vop_open_args /* { 183 struct vnode *a_vp; 184 int a_mode; 185 kauth_cred_t a_cred; 186 struct lwp *a_l; 187 } */ *a = arg; 188 struct vnode *v = a->a_vp; 189 struct sysvbfs_node *bnode = v->v_data; 190 struct bfs_inode *inode = bnode->inode; 191 struct bfs *bfs = bnode->bmp->bfs; 192 struct bfs_dirent *dirent; 193 194 DPRINTF("%s:\n", __FUNCTION__); 195 KDASSERT(v->v_type == VREG || v->v_type == VDIR); 196 197 if (!bfs_dirent_lookup_by_inode(bfs, inode->number, &dirent)) 198 return ENOENT; 199 bnode->update_atime = true; 200 if ((a->a_mode & FWRITE) && !(a->a_mode & O_APPEND)) { 201 bnode->size = 0; 202 } else { 203 bnode->size = bfs_file_size(inode); 204 } 205 bnode->data_block = inode->start_sector; 206 207 return 0; 208 } 209 210 int 211 sysvbfs_close(void *arg) 212 { 213 struct vop_close_args /* { 214 struct vnodeop_desc *a_desc; 215 struct vnode *a_vp; 216 int a_fflag; 217 kauth_cred_t a_cred; 218 struct lwp *a_l; 219 } */ *a = arg; 220 struct vnode *v = a->a_vp; 221 struct sysvbfs_node *bnode = v->v_data; 222 struct bfs_fileattr attr; 223 224 DPRINTF("%s:\n", __FUNCTION__); 225 uvm_vnp_setsize(v, bnode->size); 226 227 memset(&attr, 0xff, sizeof attr); /* Set VNOVAL all */ 228 if (bnode->update_atime) 229 attr.atime = time_second; 230 if (bnode->update_ctime) 231 attr.ctime = time_second; 232 if (bnode->update_mtime) 233 attr.mtime = time_second; 234 bfs_inode_set_attr(bnode->bmp->bfs, bnode->inode, &attr); 235 236 VOP_FSYNC(a->a_vp, a->a_cred, FSYNC_WAIT, 0, 0, a->a_l); 237 238 return 0; 239 } 240 241 int 242 sysvbfs_access(void *arg) 243 { 244 struct vop_access_args /* { 245 struct vnode *a_vp; 246 int a_mode; 247 kauth_cred_t a_cred; 248 struct lwp *a_l; 249 } */ *ap = arg; 250 struct vnode *vp = ap->a_vp; 251 struct sysvbfs_node *bnode = vp->v_data; 252 struct bfs_fileattr *attr = &bnode->inode->attr; 253 254 DPRINTF("%s:\n", __FUNCTION__); 255 if ((ap->a_mode & VWRITE) && (vp->v_mount->mnt_flag & MNT_RDONLY)) 256 return EROFS; 257 258 return vaccess(vp->v_type, attr->mode, attr->uid, attr->gid, 259 ap->a_mode, ap->a_cred); 260 } 261 262 int 263 sysvbfs_getattr(void *v) 264 { 265 struct vop_getattr_args /* { 266 struct vnode *a_vp; 267 struct vattr *a_vap; 268 kauth_cred_t a_cred; 269 struct lwp *a_l; 270 } */ *ap = v; 271 struct vnode *vp = ap->a_vp; 272 struct sysvbfs_node *bnode = vp->v_data; 273 struct bfs_inode *inode = bnode->inode; 274 struct bfs_fileattr *attr = &inode->attr; 275 struct sysvbfs_mount *bmp = bnode->bmp; 276 struct vattr *vap = ap->a_vap; 277 278 DPRINTF("%s:\n", __FUNCTION__); 279 280 vap->va_type = vp->v_type; 281 vap->va_mode = attr->mode; 282 vap->va_nlink = attr->nlink; 283 vap->va_uid = attr->uid; 284 vap->va_gid = attr->gid; 285 vap->va_fsid = bmp->devvp->v_rdev; 286 vap->va_fileid = inode->number; 287 vap->va_size = bfs_file_size(inode); 288 vap->va_blocksize = BFS_BSIZE; 289 vap->va_atime.tv_sec = attr->atime; 290 vap->va_mtime.tv_sec = attr->mtime; 291 vap->va_ctime.tv_sec = attr->ctime; 292 vap->va_birthtime.tv_sec = 0; 293 vap->va_gen = 1; 294 vap->va_flags = 0; 295 vap->va_rdev = 0; /* No device file */ 296 vap->va_bytes = vap->va_size; 297 vap->va_filerev = 0; 298 vap->va_vaflags = 0; 299 300 return 0; 301 } 302 303 int 304 sysvbfs_setattr(void *arg) 305 { 306 struct vop_setattr_args /* { 307 struct vnode *a_vp; 308 struct vattr *a_vap; 309 kauth_cred_t a_cred; 310 struct proc *p; 311 } */ *ap = arg; 312 struct vnode *vp = ap->a_vp; 313 struct vattr *vap = ap->a_vap; 314 struct sysvbfs_node *bnode = vp->v_data; 315 struct bfs_inode *inode = bnode->inode; 316 struct bfs_fileattr *attr = &inode->attr; 317 struct bfs *bfs = bnode->bmp->bfs; 318 319 DPRINTF("%s:\n", __FUNCTION__); 320 if (vp->v_mount->mnt_flag & MNT_RDONLY) 321 return EROFS; 322 323 if ((vap->va_type != VNON) || (vap->va_nlink != VNOVAL) || 324 (vap->va_fsid != VNOVAL) || (vap->va_fileid != VNOVAL) || 325 (vap->va_blocksize != VNOVAL) || (vap->va_rdev != VNOVAL) || 326 ((int)vap->va_bytes != VNOVAL) || (vap->va_gen != VNOVAL)) 327 return EINVAL; 328 329 if (vap->va_uid != (uid_t)VNOVAL) 330 attr->uid = vap->va_uid; 331 if (vap->va_gid != (uid_t)VNOVAL) 332 attr->gid = vap->va_gid; 333 if (vap->va_mode != (mode_t)VNOVAL) 334 attr->mode = vap->va_mode; 335 if (vap->va_atime.tv_sec != VNOVAL) 336 attr->atime = vap->va_atime.tv_sec; 337 if (vap->va_mtime.tv_sec != VNOVAL) 338 attr->mtime = vap->va_mtime.tv_sec; 339 if (vap->va_ctime.tv_sec != VNOVAL) 340 attr->ctime = vap->va_ctime.tv_sec; 341 342 bfs_inode_set_attr(bfs, inode, attr); 343 344 return 0; 345 } 346 347 int 348 sysvbfs_read(void *arg) 349 { 350 struct vop_read_args /* { 351 struct vnode *a_vp; 352 struct uio *a_uio; 353 int a_ioflag; 354 kauth_cred_t a_cred; 355 } */ *a = arg; 356 struct vnode *v = a->a_vp; 357 struct uio *uio = a->a_uio; 358 struct sysvbfs_node *bnode = v->v_data; 359 struct bfs_inode *inode = bnode->inode; 360 vsize_t sz, filesz = bfs_file_size(inode); 361 int err; 362 void *win; 363 const int advice = IO_ADV_DECODE(a->a_ioflag); 364 365 DPRINTF("%s: type=%d\n", __FUNCTION__, v->v_type); 366 if (v->v_type != VREG) 367 return EINVAL; 368 369 while (uio->uio_resid > 0) { 370 if ((sz = MIN(filesz - uio->uio_offset, uio->uio_resid)) == 0) 371 break; 372 373 win = ubc_alloc(&v->v_uobj, uio->uio_offset, &sz, advice, 374 UBC_READ); 375 err = uiomove(win, sz, uio); 376 ubc_release(win, 0); 377 if (err) 378 break; 379 DPRINTF("%s: read %ldbyte\n", __FUNCTION__, sz); 380 } 381 382 return sysvbfs_update(v, NULL, NULL, UPDATE_WAIT); 383 } 384 385 int 386 sysvbfs_write(void *arg) 387 { 388 struct vop_write_args /* { 389 struct vnode *a_vp; 390 struct uio *a_uio; 391 int a_ioflag; 392 kauth_cred_t a_cred; 393 } */ *a = arg; 394 struct vnode *v = a->a_vp; 395 struct uio *uio = a->a_uio; 396 struct sysvbfs_node *bnode = v->v_data; 397 struct bfs_inode *inode = bnode->inode; 398 bool extended = false; 399 vsize_t sz; 400 void *win; 401 int err = 0; 402 403 if (a->a_vp->v_type != VREG) 404 return EISDIR; 405 406 if (a->a_ioflag & IO_APPEND) 407 uio->uio_offset = bnode->size; 408 409 if (uio->uio_resid == 0) 410 return 0; 411 412 if (bnode->size < uio->uio_offset + uio->uio_resid) { 413 bnode->size = uio->uio_offset + uio->uio_resid; 414 uvm_vnp_setsize(v, bnode->size); 415 extended = true; 416 } 417 418 while (uio->uio_resid > 0) { 419 sz = uio->uio_resid; 420 win = ubc_alloc(&v->v_uobj, uio->uio_offset, &sz, 421 UVM_ADV_NORMAL, UBC_WRITE); 422 err = uiomove(win, sz, uio); 423 ubc_release(win, 0); 424 if (err) 425 break; 426 DPRINTF("%s: write %ldbyte\n", __FUNCTION__, sz); 427 } 428 inode->end_sector = bnode->data_block + 429 (ROUND_SECTOR(bnode->size) >> DEV_BSHIFT) - 1; 430 inode->eof_offset_byte = bnode->data_block * DEV_BSIZE + 431 bnode->size - 1; 432 bnode->update_mtime = true; 433 434 VN_KNOTE(v, NOTE_WRITE | (extended ? NOTE_EXTEND : 0)); 435 436 return err; 437 } 438 439 int 440 sysvbfs_remove(void *arg) 441 { 442 struct vop_remove_args /* { 443 struct vnodeop_desc *a_desc; 444 struct vnode * a_dvp; 445 struct vnode * a_vp; 446 struct componentname * a_cnp; 447 } */ *ap = arg; 448 struct vnode *vp = ap->a_vp; 449 struct vnode *dvp = ap->a_dvp; 450 struct sysvbfs_node *bnode = vp->v_data; 451 struct sysvbfs_mount *bmp = bnode->bmp; 452 struct bfs *bfs = bmp->bfs; 453 int err; 454 455 DPRINTF("%s: delete %s\n", __FUNCTION__, ap->a_cnp->cn_nameptr); 456 457 if (vp->v_type == VDIR) 458 return EPERM; 459 460 if ((err = bfs_file_delete(bfs, ap->a_cnp->cn_nameptr)) != 0) 461 DPRINTF("%s: bfs_file_delete failed.\n", __FUNCTION__); 462 463 VN_KNOTE(ap->a_vp, NOTE_DELETE); 464 VN_KNOTE(ap->a_dvp, NOTE_WRITE); 465 if (dvp == vp) 466 vrele(vp); 467 else 468 vput(vp); 469 vput(dvp); 470 471 return err; 472 } 473 474 int 475 sysvbfs_rename(void *arg) 476 { 477 struct vop_rename_args /* { 478 struct vnode *a_fdvp; from parent-directory v-node 479 struct vnode *a_fvp; from file v-node 480 struct componentname *a_fcnp; 481 struct vnode *a_tdvp; to parent-directory 482 struct vnode *a_tvp; to file v-node 483 struct componentname *a_tcnp; 484 } */ *ap = arg; 485 struct vnode *fvp = ap->a_fvp; 486 struct vnode *tvp = ap->a_tvp; 487 struct sysvbfs_node *bnode = fvp->v_data; 488 struct bfs *bfs = bnode->bmp->bfs; 489 const char *from_name = ap->a_fcnp->cn_nameptr; 490 const char *to_name = ap->a_tcnp->cn_nameptr; 491 int error; 492 493 DPRINTF("%s: %s->%s\n", __FUNCTION__, from_name, to_name); 494 if ((fvp->v_mount != ap->a_tdvp->v_mount) || 495 (tvp && (fvp->v_mount != tvp->v_mount))) { 496 error = EXDEV; 497 printf("cross-device link\n"); 498 goto out; 499 } 500 501 KDASSERT(fvp->v_type == VREG); 502 KDASSERT(tvp == NULL ? true : tvp->v_type == VREG); 503 504 error = bfs_file_rename(bfs, from_name, to_name); 505 out: 506 vput(ap->a_tdvp); 507 if (tvp) 508 vput(ap->a_tvp); /* locked on entry */ 509 if (ap->a_tdvp != ap->a_fdvp) 510 vrele(ap->a_fdvp); 511 vrele(ap->a_fvp); /* unlocked and refcnt is incremented on entry. */ 512 513 return 0; 514 } 515 516 int 517 sysvbfs_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 sysvbfs_node *bnode = vp->v_data; 530 struct bfs *bfs = bnode->bmp->bfs; 531 struct dirent *dp; 532 struct bfs_dirent *file; 533 int i, n, error; 534 535 DPRINTF("%s: offset=%lld residue=%d\n", __FUNCTION__, 536 uio->uio_offset, uio->uio_resid); 537 538 KDASSERT(vp->v_type == VDIR); 539 KDASSERT(uio->uio_offset >= 0); 540 541 dp = malloc(sizeof(struct dirent), M_BFS, M_WAITOK | M_ZERO); 542 543 i = uio->uio_offset / sizeof(struct dirent); 544 n = uio->uio_resid / sizeof(struct dirent); 545 if ((i + n) > bfs->n_dirent) 546 n = bfs->n_dirent - i; 547 548 for (file = &bfs->dirent[i]; i < n; file++) { 549 if (file->inode == 0) 550 continue; 551 if (i == bfs->max_dirent) { 552 DPRINTF("%s: file system inconsistent.\n", 553 __FUNCTION__); 554 break; 555 } 556 i++; 557 memset(dp, 0, sizeof(struct dirent)); 558 dp->d_fileno = file->inode; 559 dp->d_type = file->inode == BFS_ROOT_INODE ? DT_DIR : DT_REG; 560 dp->d_namlen = strlen(file->name); 561 strncpy(dp->d_name, file->name, BFS_FILENAME_MAXLEN); 562 dp->d_reclen = sizeof(struct dirent); 563 if ((error = uiomove(dp, dp->d_reclen, uio)) != 0) { 564 DPRINTF("%s: uiomove failed.\n", __FUNCTION__); 565 free(dp, M_BFS); 566 return error; 567 } 568 } 569 DPRINTF("%s: %d %d %d\n", __FUNCTION__, i, n, bfs->n_dirent); 570 *ap->a_eofflag = (i == bfs->n_dirent); 571 572 free(dp, M_BFS); 573 return 0; 574 } 575 576 int 577 sysvbfs_inactive(void *arg) 578 { 579 struct vop_inactive_args /* { 580 struct vnode *a_vp; 581 struct lwp *a_l; 582 } */ *a = arg; 583 struct vnode *v = a->a_vp; 584 struct lwp *l = a->a_l; 585 586 DPRINTF("%s:\n", __FUNCTION__); 587 VOP_UNLOCK(v, 0); 588 vrecycle(v, NULL, l); 589 590 return 0; 591 } 592 593 int 594 sysvbfs_reclaim(void *v) 595 { 596 extern struct pool sysvbfs_node_pool; 597 struct vop_reclaim_args /* { 598 struct vnode *a_vp; 599 } */ *ap = v; 600 struct vnode *vp = ap->a_vp; 601 struct sysvbfs_node *bnode = vp->v_data; 602 603 DPRINTF("%s:\n", __FUNCTION__); 604 simple_lock(&mntvnode_slock); 605 LIST_REMOVE(bnode, link); 606 simple_unlock(&mntvnode_slock); 607 cache_purge(vp); 608 genfs_node_destroy(vp); 609 pool_put(&sysvbfs_node_pool, bnode); 610 vp->v_data = NULL; 611 612 return 0; 613 } 614 615 int 616 sysvbfs_bmap(void *arg) 617 { 618 struct vop_bmap_args /* { 619 struct vnode *a_vp; 620 daddr_t a_bn; 621 struct vnode **a_vpp; 622 daddr_t *a_bnp; 623 int *a_runp; 624 } */ *a = arg; 625 struct vnode *v = a->a_vp; 626 struct sysvbfs_node *bnode = v->v_data; 627 struct sysvbfs_mount *bmp = bnode->bmp; 628 struct bfs_inode *inode = bnode->inode; 629 daddr_t blk; 630 631 DPRINTF("%s:\n", __FUNCTION__); 632 /* BFS algorithm is contiguous allocation */ 633 blk = inode->start_sector + a->a_bn; 634 635 if (blk * BFS_BSIZE > bmp->bfs->data_end) 636 return ENOSPC; 637 638 *a->a_vpp = bmp->devvp; 639 *a->a_runp = 0; 640 DPRINTF("%s: %d + %lld\n", __FUNCTION__, inode->start_sector, a->a_bn); 641 642 *a->a_bnp = blk; 643 644 645 return 0; 646 } 647 648 int 649 sysvbfs_strategy(void *arg) 650 { 651 struct vop_strategy_args /* { 652 struct vnode *a_vp; 653 struct buf *a_bp; 654 } */ *a = arg; 655 struct buf *b = a->a_bp; 656 struct vnode *v = a->a_vp; 657 struct sysvbfs_node *bnode = v->v_data; 658 struct sysvbfs_mount *bmp = bnode->bmp; 659 int error; 660 661 DPRINTF("%s:\n", __FUNCTION__); 662 KDASSERT(v->v_type == VREG); 663 if (b->b_blkno == b->b_lblkno) { 664 error = VOP_BMAP(v, b->b_lblkno, NULL, &b->b_blkno, NULL); 665 if (error) { 666 b->b_error = error; 667 biodone(b); 668 return error; 669 } 670 if ((long)b->b_blkno == -1) 671 clrbuf(b); 672 } 673 if ((long)b->b_blkno == -1) { 674 biodone(b); 675 return 0; 676 } 677 678 return VOP_STRATEGY(bmp->devvp, b); 679 } 680 681 int 682 sysvbfs_print(void *v) 683 { 684 struct vop_print_args /* { 685 struct vnode *a_vp; 686 } */ *ap = v; 687 struct sysvbfs_node *bnode = ap->a_vp->v_data; 688 689 DPRINTF("%s:\n", __FUNCTION__); 690 bfs_dump(bnode->bmp->bfs); 691 692 return 0; 693 } 694 695 int 696 sysvbfs_advlock(void *v) 697 { 698 struct vop_advlock_args /* { 699 struct vnode *a_vp; 700 void *a_id; 701 int a_op; 702 struct flock *a_fl; 703 int a_flags; 704 } */ *ap = v; 705 struct sysvbfs_node *bnode = ap->a_vp->v_data; 706 707 DPRINTF("%s: op=%d\n", __FUNCTION__, ap->a_op); 708 709 return lf_advlock(ap, &bnode->lockf, bfs_file_size(bnode->inode)); 710 } 711 712 int 713 sysvbfs_pathconf(void *v) 714 { 715 struct vop_pathconf_args /* { 716 struct vnode *a_vp; 717 int a_name; 718 register_t *a_retval; 719 } */ *ap = v; 720 int err = 0; 721 722 DPRINTF("%s:\n", __FUNCTION__); 723 724 switch (ap->a_name) { 725 case _PC_LINK_MAX: 726 *ap->a_retval = 1; 727 break;; 728 case _PC_NAME_MAX: 729 *ap->a_retval = BFS_FILENAME_MAXLEN; 730 break;; 731 case _PC_PATH_MAX: 732 *ap->a_retval = BFS_FILENAME_MAXLEN; 733 break;; 734 case _PC_CHOWN_RESTRICTED: 735 *ap->a_retval = 1; 736 break;; 737 case _PC_NO_TRUNC: 738 *ap->a_retval = 0; 739 break;; 740 case _PC_SYNC_IO: 741 *ap->a_retval = 1; 742 break;; 743 case _PC_FILESIZEBITS: 744 *ap->a_retval = 32; 745 break;; 746 default: 747 err = EINVAL; 748 break; 749 } 750 751 return err; 752 } 753 754 int 755 sysvbfs_fsync(void *v) 756 { 757 struct vop_fsync_args /* { 758 struct vnode *a_vp; 759 kauth_cred_t a_cred; 760 int a_flags; 761 off_t offlo; 762 off_t offhi; 763 struct lwp *a_l; 764 } */ *ap = v; 765 struct vnode *vp = ap->a_vp; 766 int error, wait; 767 768 if (ap->a_flags & FSYNC_CACHE) { 769 return EOPNOTSUPP; 770 } 771 772 wait = (ap->a_flags & FSYNC_WAIT) != 0; 773 vflushbuf(vp, wait); 774 775 if ((ap->a_flags & FSYNC_DATAONLY) != 0) 776 error = 0; 777 else 778 error = sysvbfs_update(vp, NULL, NULL, wait ? UPDATE_WAIT : 0); 779 780 return error; 781 } 782 783 int 784 sysvbfs_update(struct vnode *vp, const struct timespec *acc, 785 const struct timespec *mod, int flags) 786 { 787 struct sysvbfs_node *bnode = vp->v_data; 788 struct bfs_fileattr attr; 789 790 DPRINTF("%s:\n", __FUNCTION__); 791 memset(&attr, 0xff, sizeof attr); /* Set VNOVAL all */ 792 if (bnode->update_atime) { 793 attr.atime = acc ? acc->tv_sec : time_second; 794 bnode->update_atime = false; 795 } 796 if (bnode->update_ctime) { 797 attr.ctime = time_second; 798 bnode->update_ctime = false; 799 } 800 if (bnode->update_mtime) { 801 attr.mtime = mod ? mod->tv_sec : time_second; 802 bnode->update_mtime = false; 803 } 804 bfs_inode_set_attr(bnode->bmp->bfs, bnode->inode, &attr); 805 806 return 0; 807 } 808