No empty .Rs/.Re
[netbsd-mini2440.git] / sys / fs / sysvbfs / sysvbfs_vnops.c
bloba8b23b197793a820e4ba47c15180957e5c8852fe
1 /* $NetBSD: sysvbfs_vnops.c,v 1.25 2010/01/05 13:30:11 mbalmer Exp $ */
3 /*-
4 * Copyright (c) 2004 The NetBSD Foundation, Inc.
5 * All rights reserved.
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by UCHIYAMA Yasushi.
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.
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.
32 #include <sys/cdefs.h>
33 __KERNEL_RCSID(0, "$NetBSD: sysvbfs_vnops.c,v 1.25 2010/01/05 13:30:11 mbalmer Exp $");
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>
48 #include <miscfs/genfs/genfs.h>
50 #include <fs/sysvbfs/sysvbfs.h>
51 #include <fs/sysvbfs/bfs.h>
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)
60 MALLOC_JUSTDEFINE(M_SYSVBFS_VNODE, "sysvbfs vnode", "sysvbfs vnode structures");
61 MALLOC_DECLARE(M_BFS);
63 int
64 sysvbfs_lookup(void *arg)
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;
83 DPRINTF("%s: %s op=%d %d\n", __func__, name, nameiop,
84 cnp->cn_flags);
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. */
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;
103 if ((error = VOP_ACCESS(v, VWRITE, cnp->cn_cred)) != 0)
104 return error;
105 cnp->cn_flags |= SAVENAME;
106 return EJUSTRETURN;
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;
114 *a->a_vpp = vpp;
117 if (cnp->cn_nameiop != LOOKUP && islastcn)
118 cnp->cn_flags |= SAVENAME;
120 return 0;
124 sysvbfs_create(void *arg)
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;
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;
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;
154 if (!bfs_dirent_lookup_by_name(bfs, a->a_cnp->cn_nameptr, &dirent))
155 panic("no dirent for created file.");
157 if ((err = sysvbfs_vget(mp, dirent->inode, a->a_vpp)) != 0) {
158 DPRINTF("%s: sysvbfs_vget failed.\n", __func__);
159 goto unlock_exit;
161 bnode = (*a->a_vpp)->v_data;
162 bnode->update_ctime = true;
163 bnode->update_mtime = true;
164 bnode->update_atime = true;
166 unlock_exit:
167 /* unlock parent directory */
168 vput(a->a_dvp); /* locked at sysvbfs_lookup(); */
170 return err;
174 sysvbfs_open(void *arg)
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;
187 DPRINTF("%s:\n", __func__);
188 KDASSERT(v->v_type == VREG || v->v_type == VDIR);
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);
198 bnode->data_block = inode->start_sector;
200 return 0;
204 sysvbfs_close(void *arg)
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;
216 DPRINTF("%s:\n", __func__);
217 uvm_vnp_setsize(v, bnode->size);
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);
228 VOP_FSYNC(a->a_vp, a->a_cred, FSYNC_WAIT, 0, 0);
230 return 0;
233 static int
234 sysvbfs_check_possible(struct vnode *vp, struct sysvbfs_node *bnode,
235 mode_t mode)
238 if ((mode & VWRITE) && (vp->v_mount->mnt_flag & MNT_RDONLY))
239 return EROFS;
241 return 0;
244 static int
245 sysvbfs_check_permitted(struct vnode *vp, struct sysvbfs_node *bnode,
246 mode_t mode, kauth_cred_t cred)
248 struct bfs_fileattr *attr = &bnode->inode->attr;
250 return genfs_can_access(vp->v_type, attr->mode, attr->uid, attr->gid,
251 mode, cred);
255 sysvbfs_access(void *arg)
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;
266 DPRINTF("%s:\n", __func__);
268 error = sysvbfs_check_possible(vp, bnode, ap->a_mode);
269 if (error)
270 return error;
272 error = sysvbfs_check_permitted(vp, bnode, ap->a_mode, ap->a_cred);
274 return error;
278 sysvbfs_getattr(void *v)
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;
292 DPRINTF("%s:\n", __func__);
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;
314 return 0;
318 sysvbfs_setattr(void *arg)
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;
333 DPRINTF("%s:\n", __func__);
334 if (vp->v_mount->mnt_flag & MNT_RDONLY)
335 return EROFS;
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;
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;
356 bfs_inode_set_attr(bfs, inode, attr);
358 return 0;
362 sysvbfs_read(void *arg)
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);
378 DPRINTF("%s: type=%d\n", __func__, v->v_type);
379 if (v->v_type != VREG)
380 return EINVAL;
382 while (uio->uio_resid > 0) {
383 if ((sz = MIN(filesz - uio->uio_offset, uio->uio_resid)) == 0)
384 break;
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);
393 return sysvbfs_update(v, NULL, NULL, UPDATE_WAIT);
397 sysvbfs_write(void *arg)
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;
414 if (a->a_vp->v_type != VREG)
415 return EISDIR;
417 if (a->a_ioflag & IO_APPEND)
418 uio->uio_offset = bnode->size;
420 if (uio->uio_resid == 0)
421 return 0;
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;
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);
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;
443 VN_KNOTE(v, NOTE_WRITE | (extended ? NOTE_EXTEND : 0));
445 return err;
449 sysvbfs_remove(void *arg)
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;
464 DPRINTF("%s: delete %s\n", __func__, ap->a_cnp->cn_nameptr);
466 if (vp->v_type == VDIR)
467 return EPERM;
469 if ((err = bfs_file_delete(bfs, ap->a_cnp->cn_nameptr)) != 0)
470 DPRINTF("%s: bfs_file_delete failed.\n", __func__);
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);
480 return err;
484 sysvbfs_rename(void *arg)
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;
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;
510 KDASSERT(fvp->v_type == VREG);
511 KDASSERT(tvp == NULL ? true : tvp->v_type == VREG);
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. */
522 return 0;
526 sysvbfs_readdir(void *v)
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;
544 DPRINTF("%s: offset=%lld residue=%d\n", __func__,
545 uio->uio_offset, uio->uio_resid);
547 KDASSERT(vp->v_type == VDIR);
548 KDASSERT(uio->uio_offset >= 0);
550 dp = malloc(sizeof(struct dirent), M_BFS, M_WAITOK | M_ZERO);
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;
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;
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;
578 DPRINTF("%s: %d %d %d\n", __func__, i, n, bfs->n_dirent);
579 *ap->a_eofflag = (i == bfs->n_dirent);
581 free(dp, M_BFS);
582 return 0;
586 sysvbfs_inactive(void *arg)
588 struct vop_inactive_args /* {
589 struct vnode *a_vp;
590 bool *a_recycle;
591 } */ *a = arg;
592 struct vnode *v = a->a_vp;
594 DPRINTF("%s:\n", __func__);
595 *a->a_recycle = true;
596 VOP_UNLOCK(v, 0);
598 return 0;
602 sysvbfs_reclaim(void *v)
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;
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;
620 return 0;
624 sysvbfs_bmap(void *arg)
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;
639 DPRINTF("%s:\n", __func__);
640 /* BFS algorithm is contiguous allocation */
641 blk = inode->start_sector + a->a_bn;
643 if (blk * BFS_BSIZE > bmp->bfs->data_end)
644 return ENOSPC;
646 *a->a_vpp = bmp->devvp;
647 *a->a_runp = 0;
648 DPRINTF("%s: %d + %lld\n", __func__, inode->start_sector, a->a_bn);
650 *a->a_bnp = blk;
653 return 0;
657 sysvbfs_strategy(void *arg)
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;
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;
678 if ((long)b->b_blkno == -1)
679 clrbuf(b);
681 if ((long)b->b_blkno == -1) {
682 biodone(b);
683 return 0;
686 return VOP_STRATEGY(bmp->devvp, b);
690 sysvbfs_print(void *v)
692 struct vop_print_args /* {
693 struct vnode *a_vp;
694 } */ *ap = v;
695 struct sysvbfs_node *bnode = ap->a_vp->v_data;
697 DPRINTF("%s:\n", __func__);
698 bfs_dump(bnode->bmp->bfs);
700 return 0;
704 sysvbfs_advlock(void *v)
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;
715 DPRINTF("%s: op=%d\n", __func__, ap->a_op);
717 return lf_advlock(ap, &bnode->lockf, bfs_file_size(bnode->inode));
721 sysvbfs_pathconf(void *v)
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;
730 DPRINTF("%s:\n", __func__);
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;
759 return err;
763 sysvbfs_fsync(void *v)
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;
775 if (ap->a_flags & FSYNC_CACHE) {
776 return EOPNOTSUPP;
779 wait = (ap->a_flags & FSYNC_WAIT) != 0;
780 vflushbuf(vp, wait);
782 if ((ap->a_flags & FSYNC_DATAONLY) != 0)
783 error = 0;
784 else
785 error = sysvbfs_update(vp, NULL, NULL, wait ? UPDATE_WAIT : 0);
787 return error;
791 sysvbfs_update(struct vnode *vp, const struct timespec *acc,
792 const struct timespec *mod, int flags)
794 struct sysvbfs_node *bnode = vp->v_data;
795 struct bfs_fileattr attr;
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;
803 if (bnode->update_ctime) {
804 attr.ctime = time_second;
805 bnode->update_ctime = false;
807 if (bnode->update_mtime) {
808 attr.mtime = mod ? mod->tv_sec : time_second;
809 bnode->update_mtime = false;
811 bfs_inode_set_attr(bnode->bmp->bfs, bnode->inode, &attr);
813 return 0;