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