1 /* $NetBSD: nilfs_vnops.c,v 1.3 2010/01/05 13:30:11 mbalmer Exp $ */
4 * Copyright (c) 2008, 2009 Reinoud Zandijk
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 #include <sys/cdefs.h>
31 __KERNEL_RCSID(0, "$NetBSD: nilfs_vnops.c,v 1.3 2010/01/05 13:30:11 mbalmer Exp $");
35 #include <sys/param.h>
36 #include <sys/systm.h>
37 #include <sys/namei.h>
38 #include <sys/resourcevar.h> /* defines plimit structure in proc struct */
39 #include <sys/kernel.h>
40 #include <sys/file.h> /* define FWRITE ... */
44 #include <sys/mount.h>
45 #include <sys/vnode.h>
46 #include <sys/signalvar.h>
47 #include <sys/malloc.h>
48 #include <sys/dirent.h>
49 #include <sys/lockf.h>
50 #include <sys/kauth.h>
52 #include <miscfs/genfs/genfs.h>
53 #include <uvm/uvm_extern.h>
55 #include <fs/nilfs/nilfs_mount.h>
57 #include "nilfs_subr.h"
58 #include "nilfs_bswap.h"
61 #define VTOI(vnode) ((struct nilfs_node *) (vnode)->v_data)
67 /* implementations of vnode functions; table follows at end */
68 /* --------------------------------------------------------------------- */
71 nilfs_inactive(void *v
)
73 struct vop_inactive_args
/* {
77 struct vnode
*vp
= ap
->a_vp
;
78 struct nilfs_node
*nilfs_node
= VTOI(vp
);
80 DPRINTF(NODE
, ("nilfs_inactive called for nilfs_node %p\n", VTOI(vp
)));
82 if (nilfs_node
== NULL
) {
83 DPRINTF(NODE
, ("nilfs_inactive: inactive NULL NILFS node\n"));
89 * Optionally flush metadata to disc. If the file has not been
90 * referenced anymore in a directory we ought to free up the resources
91 * on disc if applicable.
98 /* --------------------------------------------------------------------- */
101 nilfs_reclaim(void *v
)
103 struct vop_reclaim_args
/* {
106 struct vnode
*vp
= ap
->a_vp
;
107 struct nilfs_node
*nilfs_node
= VTOI(vp
);
109 DPRINTF(NODE
, ("nilfs_reclaim called for node %p\n", nilfs_node
));
110 if (prtactive
&& vp
->v_usecount
> 1)
111 vprint("nilfs_reclaim(): pushing active", vp
);
113 if (nilfs_node
== NULL
) {
114 DPRINTF(NODE
, ("nilfs_reclaim(): null nilfsnode\n"));
118 /* update note for closure */
119 nilfs_update(vp
, NULL
, NULL
, NULL
, UPDATE_CLOSE
);
121 /* purge old data from namei */
124 /* dispose all node knowledge */
125 nilfs_dispose_node(&nilfs_node
);
130 /* --------------------------------------------------------------------- */
135 struct vop_read_args
/* {
141 struct vnode
*vp
= ap
->a_vp
;
142 struct uio
*uio
= ap
->a_uio
;
143 int ioflag
= ap
->a_ioflag
;
144 int advice
= IO_ADV_DECODE(ap
->a_ioflag
);
145 struct uvm_object
*uobj
;
146 struct nilfs_node
*nilfs_node
= VTOI(vp
);
152 DPRINTF(READ
, ("nilfs_read called\n"));
154 /* can this happen? some filingsystems have this check */
155 if (uio
->uio_offset
< 0)
157 if (uio
->uio_resid
== 0)
160 /* protect against rogue programs reading raw directories and links */
161 if ((ioflag
& IO_ALTSEMANTICS
) == 0) {
162 if (vp
->v_type
== VDIR
)
164 /* all but regular files just give EINVAL */
165 if (vp
->v_type
!= VREG
)
170 file_size
= nilfs_rw64(nilfs_node
->inode
.i_size
);
172 /* read contents using buffercache */
174 flags
= UBC_WANT_UNMAP(vp
) ? UBC_UNMAP
: 0;
176 while (uio
->uio_resid
> 0) {
178 if (file_size
<= uio
->uio_offset
)
181 /* maximise length to file extremity */
182 len
= MIN(file_size
- uio
->uio_offset
, uio
->uio_resid
);
186 /* ubc, here we come, prepare to trap */
187 error
= ubc_uiomove(uobj
, uio
, len
, advice
,
188 UBC_READ
| UBC_PARTIALOK
| UBC_UNMAP_FLAG(vp
));
193 /* note access time unless not requested */
194 if (!(vp
->v_mount
->mnt_flag
& MNT_NOATIME
)) {
195 nilfs_node
->i_flags
|= IN_ACCESS
;
196 if ((ioflag
& IO_SYNC
) == IO_SYNC
)
197 error
= nilfs_update(vp
, NULL
, NULL
, NULL
, UPDATE_WAIT
);
203 /* --------------------------------------------------------------------- */
208 struct vop_write_args
/* {
214 struct vnode
*vp
= ap
->a_vp
;
215 struct uio
*uio
= ap
->a_uio
;
216 int ioflag
= ap
->a_ioflag
;
217 int advice
= IO_ADV_DECODE(ap
->a_ioflag
);
218 struct uvm_object
*uobj
;
219 struct nilfs_node
*nilfs_node
= VTOI(vp
);
220 uint64_t file_size
, old_size
;
223 int flags
, resid
, extended
;
225 DPRINTF(WRITE
, ("nilfs_write called\n"));
227 /* can this happen? some filingsystems have this check */
228 if (uio
->uio_offset
< 0)
230 if (uio
->uio_resid
== 0)
233 /* protect against rogue programs writing raw directories or links */
234 if ((ioflag
& IO_ALTSEMANTICS
) == 0) {
235 if (vp
->v_type
== VDIR
)
237 /* all but regular files just give EINVAL for now */
238 if (vp
->v_type
!= VREG
)
243 panic("nilfs_write() called\n");
246 /* remember old file size */
248 file_size
= nilfs_rw64(nilfs_node
->inode
.i_size
);
249 old_size
= file_size
;
251 /* if explicitly asked to append, uio_offset can be wrong? */
252 if (ioflag
& IO_APPEND
)
253 uio
->uio_offset
= file_size
;
256 extended
= (uio
->uio_offset
+ uio
->uio_resid
> file_size
);
258 DPRINTF(WRITE
, ("extending file from %"PRIu64
" to %"PRIu64
"\n",
259 file_size
, uio
->uio_offset
+ uio
->uio_resid
));
260 error
= nilfs_grow_node(nilfs_node
, uio
->uio_offset
+ uio
->uio_resid
);
263 file_size
= uio
->uio_offset
+ uio
->uio_resid
;
267 /* write contents using buffercache */
269 flags
= UBC_WANT_UNMAP(vp
) ? UBC_UNMAP
: 0;
270 resid
= uio
->uio_resid
;
273 uvm_vnp_setwritesize(vp
, file_size
);
274 while (uio
->uio_resid
> 0) {
275 /* maximise length to file extremity */
276 len
= MIN(file_size
- uio
->uio_offset
, uio
->uio_resid
);
280 /* ubc, here we come, prepare to trap */
281 error
= ubc_uiomove(uobj
, uio
, len
, advice
,
282 UBC_WRITE
| UBC_UNMAP_FLAG(vp
));
286 uvm_vnp_setsize(vp
, file_size
);
288 /* mark node changed and request update */
289 nilfs_node
->i_flags
|= IN_CHANGE
| IN_UPDATE
;
292 * XXX TODO FFS has code here to reset setuid & setgid when we're not
293 * the superuser as a precaution against tampering.
296 /* if we wrote a thing, note write action on vnode */
297 if (resid
> uio
->uio_resid
)
298 VN_KNOTE(vp
, NOTE_WRITE
| (extended
? NOTE_EXTEND
: 0));
301 /* bring back file size to its former size */
302 /* take notice of its errors? */
303 // (void) nilfs_chsize(vp, (u_quad_t) old_size, NOCRED);
306 uio
->uio_offset
-= resid
- uio
->uio_resid
;
307 uio
->uio_resid
= resid
;
309 /* if we write and we're synchronous, update node */
310 if ((resid
> uio
->uio_resid
) && ((ioflag
& IO_SYNC
) == IO_SYNC
))
311 error
= nilfs_update(vp
, NULL
, NULL
, NULL
, UPDATE_WAIT
);
318 /* --------------------------------------------------------------------- */
321 * `Special' bmap functionality that translates all incomming requests to
322 * translate to vop_strategy() calls with the same blocknumbers effectively
323 * not translating at all.
327 nilfs_trivial_bmap(void *v
)
329 struct vop_bmap_args
/* {
332 struct vnode **a_vpp;
336 struct vnode
*vp
= ap
->a_vp
; /* our node */
337 struct vnode
**vpp
= ap
->a_vpp
; /* return node */
338 daddr_t
*bnp
= ap
->a_bnp
; /* translated */
339 daddr_t bn
= ap
->a_bn
; /* origional */
340 int *runp
= ap
->a_runp
;
341 struct nilfs_node
*node
= VTOI(vp
);
344 DPRINTF(TRANSLATE
, ("nilfs_bmap() called\n"));
345 /* XXX could return `-1' to indicate holes/zero's */
347 blocksize
= node
->nilfsdev
->blocksize
;
354 /* set runlength to maximum */
356 *runp
= MAXPHYS
/ blocksize
;
362 /* --------------------------------------------------------------------- */
365 nilfs_read_filebuf(struct nilfs_node
*node
, struct buf
*bp
)
367 struct nilfs_device
*nilfsdev
= node
->nilfsdev
;
369 uint64_t *l2vmap
, *v2pmap
;
371 uint32_t blocksize
, buf_offset
;
373 int blk2dev
= nilfsdev
->blocksize
/ DEV_BSIZE
;
377 * Translate all the block sectors into a series of buffers to read
378 * asynchronously from the nilfs device. Note that this lookup may
379 * induce readin's too.
382 blocksize
= nilfsdev
->blocksize
;
385 blks
= bp
->b_bcount
/ blocksize
;
387 DPRINTF(READ
, ("\tread in from inode %"PRIu64
" blkno %"PRIu64
" "
388 "+ %"PRIu64
" blocks\n", node
->ino
, from
, blks
));
390 DPRINTF(READ
, ("\t\tblkno %"PRIu64
" "
391 "+ %d bytes\n", bp
->b_blkno
, bp
->b_bcount
));
393 /* get mapping memory */
394 l2vmap
= malloc(sizeof(uint64_t) * blks
, M_TEMP
, M_WAITOK
);
395 v2pmap
= malloc(sizeof(uint64_t) * blks
, M_TEMP
, M_WAITOK
);
397 /* get virtual block numbers for the vnode's buffer span */
398 error
= nilfs_btree_nlookup(node
, from
, blks
, l2vmap
);
402 /* translate virtual block numbers to physical block numbers */
403 error
= nilfs_nvtop(node
, blks
, l2vmap
, v2pmap
);
407 /* issue translated blocks */
408 bp
->b_resid
= bp
->b_bcount
;
409 for (i
= 0; i
< blks
; i
++) {
410 DPRINTF(READ
, ("read_filebuf : ino %"PRIu64
" blk %d -> "
411 "%"PRIu64
" -> %"PRIu64
"\n",
412 node
->ino
, i
, l2vmap
[i
], v2pmap
[i
]));
414 buf_offset
= i
* blocksize
;
415 buf_pos
= (uint8_t *) bp
->b_data
+ buf_offset
;
417 /* note virtual block 0 marks not mapped */
418 if (l2vmap
[i
] == 0) {
419 memset(buf_pos
, 0, blocksize
);
420 nestiobuf_done(bp
, blocksize
, 0);
425 nbp
= getiobuf(NULL
, true);
426 nestiobuf_setup(bp
, nbp
, buf_offset
, blocksize
);
427 KASSERT(nbp
->b_vp
== node
->vnode
);
431 nbp
->b_blkno
= v2pmap
[i
] * blk2dev
; /* in DEV_BSIZE */
432 nbp
->b_rawblkno
= nbp
->b_blkno
;
434 VOP_STRATEGY(nilfsdev
->devvp
, nbp
);
437 if ((bp
->b_flags
& B_ASYNC
) == 0)
441 free(l2vmap
, M_TEMP
);
442 free(v2pmap
, M_TEMP
);
451 nilfs_write_filebuf(struct nilfs_node
*node
, struct buf
*bp
)
453 /* TODO pass on to segment collector */
454 panic("nilfs_strategy writing called\n");
459 nilfs_vfsstrategy(void *v
)
461 struct vop_strategy_args
/* {
465 struct vnode
*vp
= ap
->a_vp
;
466 struct buf
*bp
= ap
->a_bp
;
467 struct nilfs_node
*node
= VTOI(vp
);
469 DPRINTF(STRATEGY
, ("nilfs_strategy called\n"));
471 /* check if we ought to be here */
472 if (vp
->v_type
== VBLK
|| vp
->v_type
== VCHR
)
473 panic("nilfs_strategy: spec");
475 /* translate if needed and pass on */
476 if (bp
->b_flags
& B_READ
) {
477 nilfs_read_filebuf(node
, bp
);
481 /* send to segment collector */
482 nilfs_write_filebuf(node
, bp
);
486 /* --------------------------------------------------------------------- */
489 nilfs_readdir(void *v
)
491 struct vop_readdir_args
/* {
499 struct uio
*uio
= ap
->a_uio
;
500 struct vnode
*vp
= ap
->a_vp
;
501 struct nilfs_node
*node
= VTOI(vp
);
502 struct nilfs_dir_entry
*ndirent
;
503 struct dirent dirent
;
505 uint64_t file_size
, diroffset
, transoffset
, blkoff
;
507 uint32_t blocksize
= node
->nilfsdev
->blocksize
;
508 uint8_t *pos
, name_len
;
511 DPRINTF(READDIR
, ("nilfs_readdir called\n"));
513 if (vp
->v_type
!= VDIR
)
516 file_size
= nilfs_rw64(node
->inode
.i_size
);
518 /* we are called just as long as we keep on pushing data in */
520 if ((uio
->uio_offset
< file_size
) &&
521 (uio
->uio_resid
>= sizeof(struct dirent
))) {
522 diroffset
= uio
->uio_offset
;
523 transoffset
= diroffset
;
525 blocknr
= diroffset
/ blocksize
;
526 blkoff
= diroffset
% blocksize
;
527 error
= nilfs_bread(node
, blocknr
, NOCRED
, 0, &bp
);
530 while (diroffset
< file_size
) {
531 DPRINTF(READDIR
, ("readdir : offset = %"PRIu64
"\n",
533 if (blkoff
>= blocksize
) {
534 blkoff
= 0; blocknr
++;
536 error
= nilfs_bread(node
, blocknr
, NOCRED
, 0,
542 /* read in one dirent */
543 pos
= (uint8_t *) bp
->b_data
+ blkoff
;
544 ndirent
= (struct nilfs_dir_entry
*) pos
;
546 name_len
= ndirent
->name_len
;
547 memset(&dirent
, 0, sizeof(struct dirent
));
548 dirent
.d_fileno
= nilfs_rw64(ndirent
->inode
);
549 dirent
.d_type
= ndirent
->file_type
; /* 1:1 ? */
550 dirent
.d_namlen
= name_len
;
551 strncpy(dirent
.d_name
, ndirent
->name
, name_len
);
552 dirent
.d_reclen
= _DIRENT_SIZE(&dirent
);
553 DPRINTF(READDIR
, ("copying `%*.*s`\n", name_len
,
554 name_len
, dirent
.d_name
));
557 * If there isn't enough space in the uio to return a
558 * whole dirent, break off read
560 if (uio
->uio_resid
< _DIRENT_SIZE(&dirent
))
565 uiomove(&dirent
, _DIRENT_SIZE(&dirent
), uio
);
568 diroffset
+= nilfs_rw16(ndirent
->rec_len
);
569 blkoff
+= nilfs_rw16(ndirent
->rec_len
);
571 /* remember the last entry we transfered */
572 transoffset
= diroffset
;
576 /* pass on last transfered offset */
577 uio
->uio_offset
= transoffset
;
581 *ap
->a_eofflag
= (uio
->uio_offset
>= file_size
);
586 /* --------------------------------------------------------------------- */
589 nilfs_lookup(void *v
)
591 struct vop_lookup_args
/* {
593 struct vnode **a_vpp;
594 struct componentname *a_cnp;
596 struct vnode
*dvp
= ap
->a_dvp
;
597 struct vnode
**vpp
= ap
->a_vpp
;
598 struct componentname
*cnp
= ap
->a_cnp
;
599 struct nilfs_node
*dir_node
, *res_node
;
600 struct nilfs_mount
*ump
;
603 int namelen
, nameiop
, islastcn
, mounted_ro
;
607 dir_node
= VTOI(dvp
);
611 DPRINTF(LOOKUP
, ("nilfs_lookup called\n"));
613 /* simplify/clarification flags */
614 nameiop
= cnp
->cn_nameiop
;
615 islastcn
= cnp
->cn_flags
& ISLASTCN
;
616 mounted_ro
= dvp
->v_mount
->mnt_flag
& MNT_RDONLY
;
618 /* check exec/dirread permissions first */
619 error
= VOP_ACCESS(dvp
, VEXEC
, cnp
->cn_cred
);
623 DPRINTF(LOOKUP
, ("\taccess ok\n"));
626 * If requesting a modify on the last path element on a read-only
627 * filingsystem, reject lookup; XXX why is this repeated in every FS ?
629 if (islastcn
&& mounted_ro
&& (nameiop
== DELETE
|| nameiop
== RENAME
))
632 DPRINTF(LOOKUP
, ("\tlooking up cnp->cn_nameptr '%s'\n",
634 /* look in the nami cache; returns 0 on success!! */
635 error
= cache_lookup(dvp
, vpp
, cnp
);
639 DPRINTF(LOOKUP
, ("\tNOT found in cache\n"));
642 * Obviously, the file is not (anymore) in the namecache, we have to
643 * search for it. There are three basic cases: '.', '..' and others.
645 * Following the guidelines of VOP_LOOKUP manpage and tmpfs.
648 if ((cnp
->cn_namelen
== 1) && (cnp
->cn_nameptr
[0] == '.')) {
649 DPRINTF(LOOKUP
, ("\tlookup '.'\n"));
650 /* special case 1 '.' */
654 } else if (cnp
->cn_flags
& ISDOTDOT
) {
655 /* special case 2 '..' */
656 DPRINTF(LOOKUP
, ("\tlookup '..'\n"));
661 error
= nilfs_lookup_name_in_dir(dvp
, name
, namelen
,
668 /* first unlock parent */
672 DPRINTF(LOOKUP
, ("\tfound '..'\n"));
673 /* try to create/reuse the node */
674 error
= nilfs_get_node(ump
, ino
, &res_node
);
678 ("\tnode retrieved/created OK\n"));
679 *vpp
= res_node
->vnode
;
683 /* try to relock parent */
684 vn_lock(dvp
, LK_EXCLUSIVE
| LK_RETRY
);
686 DPRINTF(LOOKUP
, ("\tlookup file\n"));
687 /* all other files */
688 /* lookup filename in the directory returning its inode */
689 name
= cnp
->cn_nameptr
;
690 namelen
= cnp
->cn_namelen
;
691 error
= nilfs_lookup_name_in_dir(dvp
, name
, namelen
,
696 DPRINTF(LOOKUP
, ("\tNOT found\n"));
698 * UGH, didn't find name. If we're creating or
699 * renaming on the last name this is OK and we ought
700 * to return EJUSTRETURN if its allowed to be created.
704 (nameiop
== CREATE
|| nameiop
== RENAME
))
707 error
= VOP_ACCESS(dvp
, VWRITE
, cnp
->cn_cred
);
709 /* keep the component name */
710 cnp
->cn_flags
|= SAVENAME
;
716 /* try to create/reuse the node */
717 error
= nilfs_get_node(ump
, ino
, &res_node
);
720 * If we are not at the last path component
721 * and found a non-directory or non-link entry
722 * (which may itself be pointing to a
723 * directory), raise an error.
725 vnodetp
= res_node
->vnode
->v_type
;
726 if ((vnodetp
!= VDIR
) && (vnodetp
!= VLNK
)) {
733 *vpp
= res_node
->vnode
;
740 * Store result in the cache if requested. If we are creating a file,
741 * the file might not be found and thus putting it into the namecache
742 * might be seen as negative caching.
744 if ((cnp
->cn_flags
& MAKEENTRY
) && nameiop
!= CREATE
)
745 cache_enter(dvp
, *vpp
, cnp
);
747 DPRINTFIF(LOOKUP
, error
, ("nilfs_lookup returing error %d\n", error
));
752 /* --------------------------------------------------------------------- */
755 nilfs_ctime_to_timespec(struct timespec
*ts
, uint64_t ctime
)
763 nilfs_getattr(void *v
)
765 struct vop_getattr_args
/* {
771 struct vnode
*vp
= ap
->a_vp
;
772 struct vattr
*vap
= ap
->a_vap
;
773 struct nilfs_node
*node
= VTOI(vp
);
774 struct nilfs_inode
*inode
= &node
->inode
;
776 DPRINTF(VFSCALL
, ("nilfs_getattr called\n"));
780 vap
->va_type
= vp
->v_type
;
781 vap
->va_mode
= nilfs_rw16(inode
->i_mode
); /* XXX same? */
782 vap
->va_nlink
= nilfs_rw16(inode
->i_links_count
);
783 vap
->va_uid
= nilfs_rw32(inode
->i_uid
);
784 vap
->va_gid
= nilfs_rw32(inode
->i_gid
);
785 vap
->va_fsid
= vp
->v_mount
->mnt_stat
.f_fsidx
.__fsid_val
[0];
786 vap
->va_fileid
= node
->ino
;
787 vap
->va_size
= nilfs_rw64(inode
->i_size
);
788 vap
->va_blocksize
= node
->nilfsdev
->blocksize
;
791 nilfs_ctime_to_timespec(&vap
->va_atime
, nilfs_rw64(inode
->i_mtime
));
792 nilfs_ctime_to_timespec(&vap
->va_mtime
, nilfs_rw64(inode
->i_mtime
));
793 nilfs_ctime_to_timespec(&vap
->va_ctime
, nilfs_rw64(inode
->i_ctime
));
794 nilfs_ctime_to_timespec(&vap
->va_birthtime
, nilfs_rw64(inode
->i_ctime
));
796 vap
->va_gen
= nilfs_rw32(inode
->i_generation
);
797 vap
->va_flags
= 0; /* vattr flags */
798 vap
->va_bytes
= nilfs_rw64(inode
->i_blocks
) * vap
->va_blocksize
;
799 vap
->va_filerev
= vap
->va_gen
; /* XXX file revision? same as gen? */
800 vap
->va_vaflags
= 0; /* XXX chflags flags */
805 /* --------------------------------------------------------------------- */
809 nilfs_chown(struct vnode
*vp
, uid_t new_uid
, gid_t new_gid
,
817 nilfs_chmod(struct vnode
*vp
, mode_t mode
, kauth_cred_t cred
)
826 nilfs_chsize(struct vnode
*vp
, u_quad_t newsize
, kauth_cred_t cred
)
833 nilfs_chflags(struct vnode
*vp
, mode_t mode
, kauth_cred_t cred
)
840 nilfs_chtimes(struct vnode
*vp
,
841 struct timespec
*atime
, struct timespec
*mtime
,
842 struct timespec
*birthtime
, int setattrflags
,
851 nilfs_setattr(void *v
)
853 struct vop_setattr_args
/* {
859 struct vnode
*vp
= ap
->a_vp
;
862 DPRINTF(VFSCALL
, ("nilfs_setattr called\n"));
866 /* --------------------------------------------------------------------- */
869 * Return POSIX pathconf information for NILFS file systems.
872 nilfs_pathconf(void *v
)
874 struct vop_pathconf_args
/* {
877 register_t *a_retval;
881 DPRINTF(VFSCALL
, ("nilfs_pathconf called\n"));
883 switch (ap
->a_name
) {
885 *ap
->a_retval
= (1<<16)-1; /* 16 bits */
888 *ap
->a_retval
= NAME_MAX
;
891 *ap
->a_retval
= PATH_MAX
;
894 *ap
->a_retval
= PIPE_BUF
;
896 case _PC_CHOWN_RESTRICTED
:
903 *ap
->a_retval
= 0; /* synchronised is off for performance */
905 case _PC_FILESIZEBITS
:
906 /* 64 bit file offsets -> 2+floor(2log(2^64-1)) = 2 + 63 = 65 */
907 bits
= 64; /* XXX ought to deliver 65 */
910 bits
= 64 * vp
->v_mount
->mnt_dev_bshift
;
912 *ap
->a_retval
= bits
;
920 /* --------------------------------------------------------------------- */
925 struct vop_open_args
/* {
933 DPRINTF(VFSCALL
, ("nilfs_open called\n"));
936 * Files marked append-only must be opened for appending.
939 if ((flags
& APPEND
) && (ap
->a_mode
& (FWRITE
| O_APPEND
)) == FWRITE
)
946 /* --------------------------------------------------------------------- */
951 struct vop_close_args
/* {
957 struct vnode
*vp
= ap
->a_vp
;
958 struct nilfs_node
*nilfs_node
= VTOI(vp
);
960 DPRINTF(VFSCALL
, ("nilfs_close called\n"));
961 nilfs_node
= nilfs_node
; /* shut up gcc */
963 mutex_enter(&vp
->v_interlock
);
964 if (vp
->v_usecount
> 1)
965 nilfs_itimes(nilfs_node
, NULL
, NULL
, NULL
);
966 mutex_exit(&vp
->v_interlock
);
972 /* --------------------------------------------------------------------- */
975 nilfs_check_possible(struct vnode
*vp
, struct vattr
*vap
, mode_t mode
)
979 /* check if we are allowed to write */
980 switch (vap
->va_type
) {
985 * normal nodes: check if we're on a read-only mounted
986 * filingsystem and bomb out if we're trying to write.
988 if ((mode
& VWRITE
) && (vp
->v_mount
->mnt_flag
& MNT_RDONLY
))
996 * special nodes: even on read-only mounted filingsystems
997 * these are allowed to be written to if permissions allow.
1001 /* no idea what this is */
1005 /* noone may write immutable files */
1006 /* TODO: get chflags(2) flags */
1008 if ((mode
& VWRITE
) && (flags
& IMMUTABLE
))
1015 nilfs_check_permitted(struct vnode
*vp
, struct vattr
*vap
, mode_t mode
,
1019 /* ask the generic genfs_can_access to advice on security */
1020 return genfs_can_access(vp
->v_type
,
1021 vap
->va_mode
, vap
->va_uid
, vap
->va_gid
,
1026 nilfs_access(void *v
)
1028 struct vop_access_args
/* {
1031 kauth_cred_t a_cred;
1034 struct vnode
*vp
= ap
->a_vp
;
1035 mode_t mode
= ap
->a_mode
;
1036 kauth_cred_t cred
= ap
->a_cred
;
1037 /* struct nilfs_node *nilfs_node = VTOI(vp); */
1041 DPRINTF(VFSCALL
, ("nilfs_access called\n"));
1043 error
= VOP_GETATTR(vp
, &vap
, NULL
);
1047 error
= nilfs_check_possible(vp
, &vap
, mode
);
1051 error
= nilfs_check_permitted(vp
, &vap
, mode
, cred
);
1056 /* --------------------------------------------------------------------- */
1059 nilfs_create(void *v
)
1061 struct vop_create_args
/* {
1062 struct vnode *a_dvp;
1063 struct vnode **a_vpp;
1064 struct componentname *a_cnp;
1065 struct vattr *a_vap;
1067 struct vnode
*dvp
= ap
->a_dvp
;
1068 struct vnode
**vpp
= ap
->a_vpp
;
1069 struct vattr
*vap
= ap
->a_vap
;
1070 struct componentname
*cnp
= ap
->a_cnp
;
1073 DPRINTF(VFSCALL
, ("nilfs_create called\n"));
1074 error
= nilfs_create_node(dvp
, vpp
, vap
, cnp
);
1076 if (error
|| !(cnp
->cn_flags
& SAVESTART
))
1077 PNBUF_PUT(cnp
->cn_pnbuf
);
1082 /* --------------------------------------------------------------------- */
1085 nilfs_mknod(void *v
)
1087 struct vop_mknod_args
/* {
1088 struct vnode *a_dvp;
1089 struct vnode **a_vpp;
1090 struct componentname *a_cnp;
1091 struct vattr *a_vap;
1093 struct vnode
*dvp
= ap
->a_dvp
;
1094 struct vnode
**vpp
= ap
->a_vpp
;
1095 struct vattr
*vap
= ap
->a_vap
;
1096 struct componentname
*cnp
= ap
->a_cnp
;
1099 DPRINTF(VFSCALL
, ("nilfs_mknod called\n"));
1100 error
= nilfs_create_node(dvp
, vpp
, vap
, cnp
);
1102 if (error
|| !(cnp
->cn_flags
& SAVESTART
))
1103 PNBUF_PUT(cnp
->cn_pnbuf
);
1108 /* --------------------------------------------------------------------- */
1111 nilfs_mkdir(void *v
)
1113 struct vop_mkdir_args
/* {
1114 struct vnode *a_dvp;
1115 struct vnode **a_vpp;
1116 struct componentname *a_cnp;
1117 struct vattr *a_vap;
1119 struct vnode
*dvp
= ap
->a_dvp
;
1120 struct vnode
**vpp
= ap
->a_vpp
;
1121 struct vattr
*vap
= ap
->a_vap
;
1122 struct componentname
*cnp
= ap
->a_cnp
;
1125 DPRINTF(VFSCALL
, ("nilfs_mkdir called\n"));
1126 error
= nilfs_create_node(dvp
, vpp
, vap
, cnp
);
1128 if (error
|| !(cnp
->cn_flags
& SAVESTART
))
1129 PNBUF_PUT(cnp
->cn_pnbuf
);
1134 /* --------------------------------------------------------------------- */
1137 nilfs_do_link(struct vnode
*dvp
, struct vnode
*vp
, struct componentname
*cnp
)
1139 struct nilfs_node
*nilfs_node
, *dir_node
;
1143 DPRINTF(VFSCALL
, ("nilfs_link called\n"));
1146 /* some quick checks */
1147 if (vp
->v_type
== VDIR
)
1148 return EPERM
; /* can't link a directory */
1149 if (dvp
->v_mount
!= vp
->v_mount
)
1150 return EXDEV
; /* can't link across devices */
1152 return EPERM
; /* can't be the same */
1155 error
= vn_lock(vp
, LK_EXCLUSIVE
);
1159 /* get attributes */
1160 dir_node
= VTOI(dvp
);
1161 nilfs_node
= VTOI(vp
);
1163 error
= VOP_GETATTR(vp
, &vap
, FSCRED
);
1167 /* check link count overflow */
1168 if (vap
.va_nlink
>= (1<<16)-1) /* uint16_t */
1171 return nilfs_dir_attach(dir_node
->ump
, dir_node
, nilfs_node
, &vap
, cnp
);
1177 struct vop_link_args
/* {
1178 struct vnode *a_dvp;
1180 struct componentname *a_cnp;
1182 struct vnode
*dvp
= ap
->a_dvp
;
1183 struct vnode
*vp
= ap
->a_vp
;
1184 struct componentname
*cnp
= ap
->a_cnp
;
1187 error
= nilfs_do_link(dvp
, vp
, cnp
);
1189 VOP_ABORTOP(dvp
, cnp
);
1191 if ((vp
!= dvp
) && (VOP_ISLOCKED(vp
) == LK_EXCLUSIVE
))
1194 VN_KNOTE(vp
, NOTE_LINK
);
1195 VN_KNOTE(dvp
, NOTE_WRITE
);
1201 /* --------------------------------------------------------------------- */
1204 nilfs_do_symlink(struct nilfs_node
*nilfs_node
, char *target
)
1211 nilfs_symlink(void *v
)
1213 struct vop_symlink_args
/* {
1214 struct vnode *a_dvp;
1215 struct vnode **a_vpp;
1216 struct componentname *a_cnp;
1217 struct vattr *a_vap;
1220 struct vnode
*dvp
= ap
->a_dvp
;
1221 struct vnode
**vpp
= ap
->a_vpp
;
1222 struct vattr
*vap
= ap
->a_vap
;
1223 struct componentname
*cnp
= ap
->a_cnp
;
1224 struct nilfs_node
*dir_node
;
1225 struct nilfs_node
*nilfs_node
;
1228 DPRINTF(VFSCALL
, ("nilfs_symlink called\n"));
1229 DPRINTF(VFSCALL
, ("\tlinking to `%s`\n", ap
->a_target
));
1230 error
= nilfs_create_node(dvp
, vpp
, vap
, cnp
);
1231 KASSERT(((error
== 0) && (*vpp
!= NULL
)) || ((error
&& (*vpp
== NULL
))));
1233 dir_node
= VTOI(dvp
);
1234 nilfs_node
= VTOI(*vpp
);
1235 KASSERT(nilfs_node
);
1236 error
= nilfs_do_symlink(nilfs_node
, ap
->a_target
);
1239 nilfs_shrink_node(nilfs_node
, 0);
1240 nilfs_dir_detach(nilfs_node
->ump
, dir_node
, nilfs_node
, cnp
);
1243 if (error
|| !(cnp
->cn_flags
& SAVESTART
))
1244 PNBUF_PUT(cnp
->cn_pnbuf
);
1249 /* --------------------------------------------------------------------- */
1252 nilfs_readlink(void *v
)
1254 struct vop_readlink_args
/* {
1257 kauth_cred_t a_cred;
1260 struct vnode
*vp
= ap
->a_vp
;
1261 struct uio
*uio
= ap
->a_uio
;
1262 kauth_cred_t cred
= ap
->a_cred
;
1263 struct nilfs_node
*nilfs_node
;
1264 struct pathcomp pathcomp
;
1266 uint8_t *pathbuf
, *targetbuf
, *tmpname
;
1267 uint8_t *pathpos
, *targetpos
;
1269 int pathlen
, targetlen
, namelen
, mntonnamelen
, len
, l_ci
;
1274 DPRINTF(VFSCALL
, ("nilfs_readlink called\n"));
1279 /* --------------------------------------------------------------------- */
1281 /* note: i tried to follow the logics of the tmpfs rename code */
1283 nilfs_rename(void *v
)
1285 struct vop_rename_args
/* {
1286 struct vnode *a_fdvp;
1287 struct vnode *a_fvp;
1288 struct componentname *a_fcnp;
1289 struct vnode *a_tdvp;
1290 struct vnode *a_tvp;
1291 struct componentname *a_tcnp;
1293 struct vnode
*tvp
= ap
->a_tvp
;
1294 struct vnode
*tdvp
= ap
->a_tdvp
;
1295 struct vnode
*fvp
= ap
->a_fvp
;
1296 struct vnode
*fdvp
= ap
->a_fdvp
;
1297 struct componentname
*tcnp
= ap
->a_tcnp
;
1298 struct componentname
*fcnp
= ap
->a_fcnp
;
1299 struct nilfs_node
*fnode
, *fdnode
, *tnode
, *tdnode
;
1300 struct vattr fvap
, tvap
;
1303 DPRINTF(VFSCALL
, ("nilfs_rename called\n"));
1305 /* disallow cross-device renames */
1306 if (fvp
->v_mount
!= tdvp
->v_mount
||
1307 (tvp
!= NULL
&& fvp
->v_mount
!= tvp
->v_mount
)) {
1313 fdnode
= VTOI(fdvp
);
1314 tnode
= (tvp
== NULL
) ? NULL
: VTOI(tvp
);
1315 tdnode
= VTOI(tdvp
);
1317 /* lock our source dir */
1318 if (fdnode
!= tdnode
) {
1319 error
= vn_lock(fdvp
, LK_EXCLUSIVE
| LK_RETRY
);
1324 /* get info about the node to be moved */
1325 error
= VOP_GETATTR(fvp
, &fvap
, FSCRED
);
1326 KASSERT(error
== 0);
1328 /* check when to delete the old already existing entry */
1330 /* get info about the node to be moved to */
1331 error
= VOP_GETATTR(fvp
, &tvap
, FSCRED
);
1332 KASSERT(error
== 0);
1334 /* if both dirs, make sure the destination is empty */
1335 if (fvp
->v_type
== VDIR
&& tvp
->v_type
== VDIR
) {
1336 if (tvap
.va_nlink
> 2) {
1341 /* if moving dir, make sure destination is dir too */
1342 if (fvp
->v_type
== VDIR
&& tvp
->v_type
!= VDIR
) {
1346 /* if we're moving a non-directory, make sure dest is no dir */
1347 if (fvp
->v_type
!= VDIR
&& tvp
->v_type
== VDIR
) {
1353 /* dont allow renaming directories acros directory for now */
1354 if (fdnode
!= tdnode
) {
1355 if (fvp
->v_type
== VDIR
) {
1361 /* remove existing entry if present */
1363 nilfs_dir_detach(tdnode
->ump
, tdnode
, tnode
, tcnp
);
1365 /* create new directory entry for the node */
1366 error
= nilfs_dir_attach(tdnode
->ump
, tdnode
, fnode
, &fvap
, tcnp
);
1370 /* unlink old directory entry for the node, if failing, unattach new */
1371 error
= nilfs_dir_detach(tdnode
->ump
, fdnode
, fnode
, fcnp
);
1373 nilfs_dir_detach(tdnode
->ump
, tdnode
, fnode
, tcnp
);
1376 if (fdnode
!= tdnode
)
1377 VOP_UNLOCK(fdvp
, 0);
1380 VOP_ABORTOP(tdvp
, tcnp
);
1387 VOP_ABORTOP(fdvp
, fcnp
);
1389 /* release source nodes. */
1396 /* --------------------------------------------------------------------- */
1399 nilfs_remove(void *v
)
1401 struct vop_remove_args
/* {
1402 struct vnode *a_dvp;
1404 struct componentname *a_cnp;
1406 struct vnode
*dvp
= ap
->a_dvp
;
1407 struct vnode
*vp
= ap
->a_vp
;
1408 struct componentname
*cnp
= ap
->a_cnp
;
1409 struct nilfs_node
*dir_node
= VTOI(dvp
);
1410 struct nilfs_node
*nilfs_node
= VTOI(vp
);
1411 struct nilfs_mount
*ump
= dir_node
->ump
;
1414 DPRINTF(VFSCALL
, ("nilfs_remove called\n"));
1415 if (vp
->v_type
!= VDIR
) {
1416 error
= nilfs_dir_detach(ump
, dir_node
, nilfs_node
, cnp
);
1417 DPRINTFIF(NODE
, error
, ("\tgot error removing file\n"));
1419 DPRINTF(NODE
, ("\tis a directory: perm. denied\n"));
1424 VN_KNOTE(vp
, NOTE_DELETE
);
1425 VN_KNOTE(dvp
, NOTE_WRITE
);
1437 /* --------------------------------------------------------------------- */
1440 nilfs_rmdir(void *v
)
1442 struct vop_rmdir_args
/* {
1443 struct vnode *a_dvp;
1445 struct componentname *a_cnp;
1447 struct vnode
*vp
= ap
->a_vp
;
1448 struct vnode
*dvp
= ap
->a_dvp
;
1449 struct componentname
*cnp
= ap
->a_cnp
;
1450 struct nilfs_node
*dir_node
= VTOI(dvp
);
1451 struct nilfs_node
*nilfs_node
= VTOI(vp
);
1452 struct nilfs_mount
*ump
= dir_node
->ump
;
1455 DPRINTF(NOTIMPL
, ("nilfs_rmdir called\n"));
1457 /* don't allow '.' to be deleted */
1458 if (dir_node
== nilfs_node
) {
1464 /* check to see if the directory is empty */
1466 refcnt
= 2; /* XXX */
1474 /* detach the node from the directory */
1475 error
= nilfs_dir_detach(ump
, dir_node
, nilfs_node
, cnp
);
1478 // cache_purge(dvp); /* XXX from msdosfs, why? */
1479 VN_KNOTE(vp
, NOTE_DELETE
);
1481 DPRINTFIF(NODE
, error
, ("\tgot error removing file\n"));
1483 /* unput the nodes and exit */
1490 /* --------------------------------------------------------------------- */
1493 nilfs_fsync(void *v
)
1495 struct vop_fsync_args
/* {
1497 kauth_cred_t a_cred;
1503 struct vnode
*vp
= ap
->a_vp
;
1504 // struct nilfs_node *nilfs_node = VTOI(vp);
1505 // int error, flags, wait;
1507 DPRINTF(STRATEGY
, ("nilfs_fsync called : %s, %s\n",
1508 (ap
->a_flags
& FSYNC_WAIT
) ? "wait":"no wait",
1509 (ap
->a_flags
& FSYNC_DATAONLY
) ? "data_only":"complete"));
1515 /* --------------------------------------------------------------------- */
1518 nilfs_advlock(void *v
)
1520 struct vop_advlock_args
/* {
1527 struct vnode
*vp
= ap
->a_vp
;
1528 struct nilfs_node
*nilfs_node
= VTOI(vp
);
1531 DPRINTF(LOCKING
, ("nilfs_advlock called\n"));
1534 file_size
= nilfs_rw64(nilfs_node
->inode
.i_size
);
1536 return lf_advlock(ap
, &nilfs_node
->lockf
, file_size
);
1539 /* --------------------------------------------------------------------- */
1542 /* Global vfs vnode data structures for nilfss */
1543 int (**nilfs_vnodeop_p
) __P((void *));
1545 const struct vnodeopv_entry_desc nilfs_vnodeop_entries
[] = {
1546 { &vop_default_desc
, vn_default_error
},
1547 { &vop_lookup_desc
, nilfs_lookup
}, /* lookup */
1548 { &vop_create_desc
, nilfs_create
}, /* create */
1549 { &vop_mknod_desc
, nilfs_mknod
}, /* mknod */ /* TODO */
1550 { &vop_open_desc
, nilfs_open
}, /* open */
1551 { &vop_close_desc
, nilfs_close
}, /* close */
1552 { &vop_access_desc
, nilfs_access
}, /* access */
1553 { &vop_getattr_desc
, nilfs_getattr
}, /* getattr */
1554 { &vop_setattr_desc
, nilfs_setattr
}, /* setattr */ /* TODO chflags */
1555 { &vop_read_desc
, nilfs_read
}, /* read */
1556 { &vop_write_desc
, nilfs_write
}, /* write */ /* WRITE */
1557 { &vop_fcntl_desc
, genfs_fcntl
}, /* fcntl */ /* TODO? */
1558 { &vop_ioctl_desc
, genfs_enoioctl
}, /* ioctl */ /* TODO? */
1559 { &vop_poll_desc
, genfs_poll
}, /* poll */ /* TODO/OK? */
1560 { &vop_kqfilter_desc
, genfs_kqfilter
}, /* kqfilter */ /* ? */
1561 { &vop_revoke_desc
, genfs_revoke
}, /* revoke */ /* TODO? */
1562 { &vop_mmap_desc
, genfs_mmap
}, /* mmap */ /* OK? */
1563 { &vop_fsync_desc
, nilfs_fsync
}, /* fsync */
1564 { &vop_seek_desc
, genfs_seek
}, /* seek */
1565 { &vop_remove_desc
, nilfs_remove
}, /* remove */
1566 { &vop_link_desc
, nilfs_link
}, /* link */ /* TODO */
1567 { &vop_rename_desc
, nilfs_rename
}, /* rename */ /* TODO */
1568 { &vop_mkdir_desc
, nilfs_mkdir
}, /* mkdir */
1569 { &vop_rmdir_desc
, nilfs_rmdir
}, /* rmdir */
1570 { &vop_symlink_desc
, nilfs_symlink
}, /* symlink */ /* TODO */
1571 { &vop_readdir_desc
, nilfs_readdir
}, /* readdir */
1572 { &vop_readlink_desc
, nilfs_readlink
}, /* readlink */ /* TEST ME */
1573 { &vop_abortop_desc
, genfs_abortop
}, /* abortop */ /* TODO/OK? */
1574 { &vop_inactive_desc
, nilfs_inactive
}, /* inactive */
1575 { &vop_reclaim_desc
, nilfs_reclaim
}, /* reclaim */
1576 { &vop_lock_desc
, genfs_lock
}, /* lock */
1577 { &vop_unlock_desc
, genfs_unlock
}, /* unlock */
1578 { &vop_bmap_desc
, nilfs_trivial_bmap
}, /* bmap */ /* 1:1 bmap */
1579 { &vop_strategy_desc
, nilfs_vfsstrategy
},/* strategy */
1580 /* { &vop_print_desc, nilfs_print }, */ /* print */
1581 { &vop_islocked_desc
, genfs_islocked
}, /* islocked */
1582 { &vop_pathconf_desc
, nilfs_pathconf
}, /* pathconf */
1583 { &vop_advlock_desc
, nilfs_advlock
}, /* advlock */ /* TEST ME */
1584 { &vop_bwrite_desc
, vn_bwrite
}, /* bwrite */ /* ->strategy */
1585 { &vop_getpages_desc
, genfs_getpages
}, /* getpages */
1586 { &vop_putpages_desc
, genfs_putpages
}, /* putpages */
1591 const struct vnodeopv_desc nilfs_vnodeop_opv_desc
= {
1592 &nilfs_vnodeop_p
, nilfs_vnodeop_entries