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