1 /* $NetBSD: sysvbfs_vnops.c,v 1.17 2008/01/02 11:48:46 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 * 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.17 2008/01/02 11:48:46 ad 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 bool *a_recycle; 576 } */ *a = arg; 577 struct vnode *v = a->a_vp; 578 579 DPRINTF("%s:\n", __func__); 580 *a->a_recycle = true; 581 VOP_UNLOCK(v, 0); 582 583 return 0; 584 } 585 586 int 587 sysvbfs_reclaim(void *v) 588 { 589 extern struct pool sysvbfs_node_pool; 590 struct vop_reclaim_args /* { 591 struct vnode *a_vp; 592 } */ *ap = v; 593 struct vnode *vp = ap->a_vp; 594 struct sysvbfs_node *bnode = vp->v_data; 595 596 DPRINTF("%s:\n", __func__); 597 mutex_enter(&mntvnode_lock); 598 LIST_REMOVE(bnode, link); 599 mutex_exit(&mntvnode_lock); 600 cache_purge(vp); 601 genfs_node_destroy(vp); 602 pool_put(&sysvbfs_node_pool, bnode); 603 vp->v_data = NULL; 604 605 return 0; 606 } 607 608 int 609 sysvbfs_bmap(void *arg) 610 { 611 struct vop_bmap_args /* { 612 struct vnode *a_vp; 613 daddr_t a_bn; 614 struct vnode **a_vpp; 615 daddr_t *a_bnp; 616 int *a_runp; 617 } */ *a = arg; 618 struct vnode *v = a->a_vp; 619 struct sysvbfs_node *bnode = v->v_data; 620 struct sysvbfs_mount *bmp = bnode->bmp; 621 struct bfs_inode *inode = bnode->inode; 622 daddr_t blk; 623 624 DPRINTF("%s:\n", __func__); 625 /* BFS algorithm is contiguous allocation */ 626 blk = inode->start_sector + a->a_bn; 627 628 if (blk * BFS_BSIZE > bmp->bfs->data_end) 629 return ENOSPC; 630 631 *a->a_vpp = bmp->devvp; 632 *a->a_runp = 0; 633 DPRINTF("%s: %d + %lld\n", __func__, inode->start_sector, a->a_bn); 634 635 *a->a_bnp = blk; 636 637 638 return 0; 639 } 640 641 int 642 sysvbfs_strategy(void *arg) 643 { 644 struct vop_strategy_args /* { 645 struct vnode *a_vp; 646 struct buf *a_bp; 647 } */ *a = arg; 648 struct buf *b = a->a_bp; 649 struct vnode *v = a->a_vp; 650 struct sysvbfs_node *bnode = v->v_data; 651 struct sysvbfs_mount *bmp = bnode->bmp; 652 int error; 653 654 DPRINTF("%s:\n", __func__); 655 KDASSERT(v->v_type == VREG); 656 if (b->b_blkno == b->b_lblkno) { 657 error = VOP_BMAP(v, b->b_lblkno, NULL, &b->b_blkno, NULL); 658 if (error) { 659 b->b_error = error; 660 biodone(b); 661 return error; 662 } 663 if ((long)b->b_blkno == -1) 664 clrbuf(b); 665 } 666 if ((long)b->b_blkno == -1) { 667 biodone(b); 668 return 0; 669 } 670 671 return VOP_STRATEGY(bmp->devvp, b); 672 } 673 674 int 675 sysvbfs_print(void *v) 676 { 677 struct vop_print_args /* { 678 struct vnode *a_vp; 679 } */ *ap = v; 680 struct sysvbfs_node *bnode = ap->a_vp->v_data; 681 682 DPRINTF("%s:\n", __func__); 683 bfs_dump(bnode->bmp->bfs); 684 685 return 0; 686 } 687 688 int 689 sysvbfs_advlock(void *v) 690 { 691 struct vop_advlock_args /* { 692 struct vnode *a_vp; 693 void *a_id; 694 int a_op; 695 struct flock *a_fl; 696 int a_flags; 697 } */ *ap = v; 698 struct sysvbfs_node *bnode = ap->a_vp->v_data; 699 700 DPRINTF("%s: op=%d\n", __func__, ap->a_op); 701 702 return lf_advlock(ap, &bnode->lockf, bfs_file_size(bnode->inode)); 703 } 704 705 int 706 sysvbfs_pathconf(void *v) 707 { 708 struct vop_pathconf_args /* { 709 struct vnode *a_vp; 710 int a_name; 711 register_t *a_retval; 712 } */ *ap = v; 713 int err = 0; 714 715 DPRINTF("%s:\n", __func__); 716 717 switch (ap->a_name) { 718 case _PC_LINK_MAX: 719 *ap->a_retval = 1; 720 break;; 721 case _PC_NAME_MAX: 722 *ap->a_retval = BFS_FILENAME_MAXLEN; 723 break;; 724 case _PC_PATH_MAX: 725 *ap->a_retval = BFS_FILENAME_MAXLEN; 726 break;; 727 case _PC_CHOWN_RESTRICTED: 728 *ap->a_retval = 1; 729 break;; 730 case _PC_NO_TRUNC: 731 *ap->a_retval = 0; 732 break;; 733 case _PC_SYNC_IO: 734 *ap->a_retval = 1; 735 break;; 736 case _PC_FILESIZEBITS: 737 *ap->a_retval = 32; 738 break;; 739 default: 740 err = EINVAL; 741 break; 742 } 743 744 return err; 745 } 746 747 int 748 sysvbfs_fsync(void *v) 749 { 750 struct vop_fsync_args /* { 751 struct vnode *a_vp; 752 kauth_cred_t a_cred; 753 int a_flags; 754 off_t offlo; 755 off_t offhi; 756 } */ *ap = v; 757 struct vnode *vp = ap->a_vp; 758 int error, wait; 759 760 if (ap->a_flags & FSYNC_CACHE) { 761 return EOPNOTSUPP; 762 } 763 764 wait = (ap->a_flags & FSYNC_WAIT) != 0; 765 vflushbuf(vp, wait); 766 767 if ((ap->a_flags & FSYNC_DATAONLY) != 0) 768 error = 0; 769 else 770 error = sysvbfs_update(vp, NULL, NULL, wait ? UPDATE_WAIT : 0); 771 772 return error; 773 } 774 775 int 776 sysvbfs_update(struct vnode *vp, const struct timespec *acc, 777 const struct timespec *mod, int flags) 778 { 779 struct sysvbfs_node *bnode = vp->v_data; 780 struct bfs_fileattr attr; 781 782 DPRINTF("%s:\n", __func__); 783 memset(&attr, 0xff, sizeof attr); /* Set VNOVAL all */ 784 if (bnode->update_atime) { 785 attr.atime = acc ? acc->tv_sec : time_second; 786 bnode->update_atime = false; 787 } 788 if (bnode->update_ctime) { 789 attr.ctime = time_second; 790 bnode->update_ctime = false; 791 } 792 if (bnode->update_mtime) { 793 attr.mtime = mod ? mod->tv_sec : time_second; 794 bnode->update_mtime = false; 795 } 796 bfs_inode_set_attr(bnode->bmp->bfs, bnode->inode, &attr); 797 798 return 0; 799 } 800