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