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