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