1 /* $NetBSD: sysvbfs_vnops.c,v 1.25 2010/01/05 13:30:11 mbalmer Exp $ */
4 * Copyright (c) 2004 The NetBSD Foundation, Inc.
7 * This code is derived from software contributed to The NetBSD Foundation
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
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>
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)
56 #define DPRINTF(arg...) ((void)0)
58 #define ROUND_SECTOR(x) (((x) + 511) & ~511)
60 MALLOC_JUSTDEFINE(M_SYSVBFS_VNODE
, "sysvbfs vnode", "sysvbfs vnode structures");
61 MALLOC_DECLARE(M_BFS
);
64 sysvbfs_lookup(void *arg
)
66 struct vop_lookup_args
/* {
69 struct componentname *a_cnp;
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
;
81 bool islastcn
= cnp
->cn_flags
& ISLASTCN
;
83 DPRINTF("%s: %s op=%d %d\n", __func__
, name
, nameiop
,
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] == '.') { /* "." */
95 } else { /* Regular file */
96 if (!bfs_dirent_lookup_by_name(bfs
, cnp
->cn_nameptr
,
98 if (nameiop
!= CREATE
&& nameiop
!= RENAME
) {
99 DPRINTF("%s: no such a file. (1)\n",
103 if ((error
= VOP_ACCESS(v
, VWRITE
, cnp
->cn_cred
)) != 0)
105 cnp
->cn_flags
|= SAVENAME
;
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__
);
117 if (cnp
->cn_nameiop
!= LOOKUP
&& islastcn
)
118 cnp
->cn_flags
|= SAVENAME
;
124 sysvbfs_create(void *arg
)
126 struct vop_create_args
/* {
128 struct vnode **a_vpp;
129 struct componentname *a_cnp;
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
;
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
))
150 DPRINTF("%s: bfs_file_create failed.\n", __func__
);
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__
);
161 bnode
= (*a
->a_vpp
)->v_data
;
162 bnode
->update_ctime
= true;
163 bnode
->update_mtime
= true;
164 bnode
->update_atime
= true;
167 /* unlock parent directory */
168 vput(a
->a_dvp
); /* locked at sysvbfs_lookup(); */
174 sysvbfs_open(void *arg
)
176 struct vop_open_args
/* {
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
))
192 bnode
->update_atime
= true;
193 if ((a
->a_mode
& FWRITE
) && !(a
->a_mode
& O_APPEND
)) {
196 bnode
->size
= bfs_file_size(inode
);
198 bnode
->data_block
= inode
->start_sector
;
204 sysvbfs_close(void *arg
)
206 struct vop_close_args
/* {
207 struct vnodeop_desc *a_desc;
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);
234 sysvbfs_check_possible(struct vnode
*vp
, struct sysvbfs_node
*bnode
,
238 if ((mode
& VWRITE
) && (vp
->v_mount
->mnt_flag
& MNT_RDONLY
))
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
,
255 sysvbfs_access(void *arg
)
257 struct vop_access_args
/* {
262 struct vnode
*vp
= ap
->a_vp
;
263 struct sysvbfs_node
*bnode
= vp
->v_data
;
266 DPRINTF("%s:\n", __func__
);
268 error
= sysvbfs_check_possible(vp
, bnode
, ap
->a_mode
);
272 error
= sysvbfs_check_permitted(vp
, bnode
, ap
->a_mode
, ap
->a_cred
);
278 sysvbfs_getattr(void *v
)
280 struct vop_getattr_args
/* {
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;
309 vap
->va_rdev
= 0; /* No device file */
310 vap
->va_bytes
= vap
->va_size
;
318 sysvbfs_setattr(void *arg
)
320 struct vop_setattr_args
/* {
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
)
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
))
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
);
362 sysvbfs_read(void *arg
)
364 struct vop_read_args
/* {
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
);
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
)
382 while (uio
->uio_resid
> 0) {
383 if ((sz
= MIN(filesz
- uio
->uio_offset
, uio
->uio_resid
)) == 0)
386 err
= ubc_uiomove(&v
->v_uobj
, uio
, sz
, advice
,
387 UBC_READ
| UBC_PARTIALOK
| UBC_UNMAP_FLAG(v
));
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
/* {
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;
414 if (a
->a_vp
->v_type
!= VREG
)
417 if (a
->a_ioflag
& IO_APPEND
)
418 uio
->uio_offset
= bnode
->size
;
420 if (uio
->uio_resid
== 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
);
429 while (uio
->uio_resid
> 0) {
431 err
= ubc_uiomove(&v
->v_uobj
, uio
, sz
, advice
,
432 UBC_WRITE
| UBC_UNMAP_FLAG(v
));
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
+
441 bnode
->update_mtime
= true;
443 VN_KNOTE(v
, NOTE_WRITE
| (extended
? NOTE_EXTEND
: 0));
449 sysvbfs_remove(void *arg
)
451 struct vop_remove_args
/* {
452 struct vnodeop_desc *a_desc;
453 struct vnode * a_dvp;
455 struct componentname * a_cnp;
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
;
464 DPRINTF("%s: delete %s\n", __func__
, ap
->a_cnp
->cn_nameptr
);
466 if (vp
->v_type
== VDIR
)
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
);
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;
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
;
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
))) {
506 printf("cross-device link\n");
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
);
517 vput(ap
->a_tvp
); /* locked on entry */
518 if (ap
->a_tdvp
!= ap
->a_fdvp
)
520 vrele(ap
->a_fvp
); /* unlocked and refcnt is incremented on entry. */
526 sysvbfs_readdir(void *v
)
528 struct vop_readdir_args
/* {
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
;
541 struct bfs_dirent
*file
;
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)
560 if (i
== bfs
->max_dirent
) {
561 DPRINTF("%s: file system inconsistent.\n",
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__
);
578 DPRINTF("%s: %d %d %d\n", __func__
, i
, n
, bfs
->n_dirent
);
579 *ap
->a_eofflag
= (i
== bfs
->n_dirent
);
586 sysvbfs_inactive(void *arg
)
588 struct vop_inactive_args
/* {
592 struct vnode
*v
= a
->a_vp
;
594 DPRINTF("%s:\n", __func__
);
595 *a
->a_recycle
= true;
602 sysvbfs_reclaim(void *v
)
604 extern struct pool sysvbfs_node_pool
;
605 struct vop_reclaim_args
/* {
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
);
616 genfs_node_destroy(vp
);
617 pool_put(&sysvbfs_node_pool
, bnode
);
624 sysvbfs_bmap(void *arg
)
626 struct vop_bmap_args
/* {
629 struct vnode **a_vpp;
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
;
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
)
646 *a
->a_vpp
= bmp
->devvp
;
648 DPRINTF("%s: %d + %lld\n", __func__
, inode
->start_sector
, a
->a_bn
);
657 sysvbfs_strategy(void *arg
)
659 struct vop_strategy_args
/* {
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
;
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
);
678 if ((long)b
->b_blkno
== -1)
681 if ((long)b
->b_blkno
== -1) {
686 return VOP_STRATEGY(bmp
->devvp
, b
);
690 sysvbfs_print(void *v
)
692 struct vop_print_args
/* {
695 struct sysvbfs_node
*bnode
= ap
->a_vp
->v_data
;
697 DPRINTF("%s:\n", __func__
);
698 bfs_dump(bnode
->bmp
->bfs
);
704 sysvbfs_advlock(void *v
)
706 struct vop_advlock_args
/* {
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
/* {
726 register_t *a_retval;
730 DPRINTF("%s:\n", __func__
);
732 switch (ap
->a_name
) {
737 *ap
->a_retval
= BFS_FILENAME_MAXLEN
;
740 *ap
->a_retval
= BFS_FILENAME_MAXLEN
;
742 case _PC_CHOWN_RESTRICTED
:
751 case _PC_FILESIZEBITS
:
763 sysvbfs_fsync(void *v
)
765 struct vop_fsync_args
/* {
772 struct vnode
*vp
= ap
->a_vp
;
775 if (ap
->a_flags
& FSYNC_CACHE
) {
779 wait
= (ap
->a_flags
& FSYNC_WAIT
) != 0;
782 if ((ap
->a_flags
& FSYNC_DATAONLY
) != 0)
785 error
= sysvbfs_update(vp
, NULL
, NULL
, wait
? UPDATE_WAIT
: 0);
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
);