1 /* $NetBSD: sysvbfs_vfsops.c,v 1.30 2009/06/29 05:08:17 dholland 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_vfsops.c,v 1.30 2009/06/29 05:08:17 dholland Exp $");
35 #include <sys/types.h>
36 #include <sys/param.h>
37 #include <sys/systm.h>
40 #include <sys/ucred.h>
41 #include <sys/mount.h>
42 #include <sys/disklabel.h>
43 #include <sys/fcntl.h>
44 #include <sys/malloc.h>
45 #include <sys/kauth.h>
49 #include <sys/namei.h>
50 #include <sys/vnode.h>
54 #include <fs/sysvbfs/sysvbfs.h> /* external interface */
55 #include <fs/sysvbfs/bfs.h> /* internal interface */
57 #ifdef SYSVBFS_VNOPS_DEBUG
58 #define DPRINTF(fmt, args...) printf(fmt, ##args)
60 #define DPRINTF(arg...) ((void)0)
63 MALLOC_JUSTDEFINE(M_SYSVBFS_VFS
, "sysvbfs vfs", "sysvbfs vfs structures");
65 struct pool sysvbfs_node_pool
;
67 int sysvbfs_mountfs(struct vnode
*, struct mount
*, struct lwp
*);
70 sysvbfs_mount(struct mount
*mp
, const char *path
, void *data
, size_t *data_len
)
72 struct lwp
*l
= curlwp
;
73 struct sysvbfs_args
*args
= data
;
74 struct sysvbfs_mount
*bmp
= NULL
;
75 struct vnode
*devvp
= NULL
;
79 DPRINTF("%s: mnt_flag=%x\n", __func__
, mp
->mnt_flag
);
81 if (*data_len
< sizeof *args
)
84 if (mp
->mnt_flag
& MNT_GETARGS
) {
85 if ((bmp
= (void *)mp
->mnt_data
) == NULL
)
88 *data_len
= sizeof *args
;
93 DPRINTF("%s: args->fspec=%s\n", __func__
, args
->fspec
);
94 update
= mp
->mnt_flag
& MNT_UPDATE
;
95 if (args
->fspec
== NULL
) {
100 if (args
->fspec
!= NULL
) {
101 /* Look up the name and verify that it's sane. */
102 error
= namei_simple_user(args
->fspec
,
103 NSM_FOLLOW_NOEMULROOT
, &devvp
);
109 * Be sure this is a valid block device
111 if (devvp
->v_type
!= VBLK
)
113 else if (bdevsw_lookup(devvp
->v_rdev
) == NULL
)
117 * Be sure we're still naming the same device
118 * used for our initial mount
120 if (devvp
!= bmp
->devvp
)
126 * If mount by non-root, then verify that user has necessary
127 * permissions on the device.
129 * Permission to update a mount is checked higher, so here we presume
130 * updating the mount is okay (for example, as far as securelevel goes)
131 * which leaves us with the normal check.
134 int accessmode
= VREAD
;
136 (mp
->mnt_iflag
& IMNT_WANTRDWR
) != 0 :
137 (mp
->mnt_flag
& MNT_RDONLY
) == 0)
138 accessmode
|= VWRITE
;
140 error
= genfs_can_mount(devvp
, accessmode
, l
->l_cred
);
149 if ((error
= sysvbfs_mountfs(devvp
, mp
, l
)) != 0) {
153 } else if (mp
->mnt_flag
& MNT_RDONLY
) {
154 /* XXX: r/w -> read only */
157 return set_statvfs_info(path
, UIO_USERSPACE
, args
->fspec
, UIO_USERSPACE
,
158 mp
->mnt_op
->vfs_name
, mp
, l
);
162 sysvbfs_mountfs(struct vnode
*devvp
, struct mount
*mp
, struct lwp
*l
)
164 kauth_cred_t cred
= l
->l_cred
;
165 struct sysvbfs_mount
*bmp
;
166 struct partinfo dpart
;
168 bool devopen
= false;
170 vn_lock(devvp
, LK_EXCLUSIVE
| LK_RETRY
);
171 error
= vinvalbuf(devvp
, V_SAVE
, cred
, l
, 0, 0);
175 /* Open block device */
177 if ((mp
->mnt_flag
& MNT_RDONLY
) == 0)
179 if ((error
= VOP_OPEN(devvp
, oflags
, NOCRED
)) != 0)
183 /* Get partition information */
184 if ((error
= VOP_IOCTL(devvp
, DIOCGPART
, &dpart
, FREAD
, cred
)) != 0) {
188 bmp
= malloc(sizeof(struct sysvbfs_mount
), M_SYSVBFS_VFS
, M_WAITOK
);
195 if ((error
= sysvbfs_bfs_init(&bmp
->bfs
, devvp
)) != 0) {
196 free(bmp
, M_SYSVBFS_VFS
);
199 LIST_INIT(&bmp
->bnode_head
);
202 mp
->mnt_stat
.f_fsidx
.__fsid_val
[0] = (long)devvp
->v_rdev
;
203 mp
->mnt_stat
.f_fsidx
.__fsid_val
[1] = makefstype(MOUNT_SYSVBFS
);
204 mp
->mnt_stat
.f_fsid
= mp
->mnt_stat
.f_fsidx
.__fsid_val
[0];
205 mp
->mnt_flag
|= MNT_LOCAL
;
206 mp
->mnt_dev_bshift
= BFS_BSHIFT
;
207 mp
->mnt_fs_bshift
= BFS_BSHIFT
;
209 DPRINTF("fstype=%d dtype=%d bsize=%d\n", dpart
.part
->p_fstype
,
210 dpart
.disklab
->d_type
, dpart
.disklab
->d_secsize
);
213 if (devopen
&& error
)
214 VOP_CLOSE(devvp
, oflags
, NOCRED
);
215 VOP_UNLOCK(devvp
, 0);
220 sysvbfs_start(struct mount
*mp
, int flags
)
223 DPRINTF("%s:\n", __func__
);
229 sysvbfs_unmount(struct mount
*mp
, int mntflags
)
231 struct sysvbfs_mount
*bmp
= (void *)mp
->mnt_data
;
234 DPRINTF("%s: %p\n", __func__
, bmp
);
236 if ((error
= vflush(mp
, NULLVP
,
237 mntflags
& MNT_FORCE
? FORCECLOSE
: 0)) != 0)
240 vn_lock(bmp
->devvp
, LK_EXCLUSIVE
| LK_RETRY
);
241 error
= VOP_CLOSE(bmp
->devvp
, FREAD
, NOCRED
);
244 sysvbfs_bfs_fini(bmp
->bfs
);
246 free(bmp
, M_SYSVBFS_VFS
);
248 mp
->mnt_flag
&= ~MNT_LOCAL
;
254 sysvbfs_root(struct mount
*mp
, struct vnode
**vpp
)
259 DPRINTF("%s:\n", __func__
);
260 if ((error
= VFS_VGET(mp
, BFS_ROOT_INODE
, &vp
)) != 0)
268 sysvbfs_statvfs(struct mount
*mp
, struct statvfs
*f
)
270 struct sysvbfs_mount
*bmp
= mp
->mnt_data
;
271 struct bfs
*bfs
= bmp
->bfs
;
275 data_block
= (bfs
->data_end
- bfs
->data_start
) >> BFS_BSHIFT
;
276 if (bfs_inode_alloc(bfs
, 0, 0, &free_block
) != 0)
279 free_block
= (bfs
->data_end
>> BFS_BSHIFT
) - free_block
;
281 DPRINTF("%s: %d %d %d\n", __func__
, bfs
->data_start
,
282 bfs
->data_end
, free_block
);
284 f
->f_bsize
= BFS_BSIZE
;
285 f
->f_frsize
= BFS_BSIZE
;
286 f
->f_iosize
= BFS_BSIZE
;
287 f
->f_blocks
= data_block
;
288 f
->f_bfree
= free_block
;
289 f
->f_bavail
= f
->f_bfree
;
291 f
->f_files
= bfs
->n_inode
;
292 f
->f_ffree
= bfs
->max_inode
- f
->f_files
;
293 f
->f_favail
= f
->f_ffree
;
295 copy_statvfs_info(f
, mp
);
301 sysvbfs_sync(struct mount
*mp
, int waitfor
, kauth_cred_t cred
)
303 struct sysvbfs_mount
*bmp
= mp
->mnt_data
;
304 struct sysvbfs_node
*bnode
;
308 DPRINTF("%s:\n", __func__
);
310 mutex_enter(&mntvnode_lock
);
311 for (bnode
= LIST_FIRST(&bmp
->bnode_head
); bnode
!= NULL
;
312 bnode
= LIST_NEXT(bnode
, link
)) {
314 mutex_enter(&v
->v_interlock
);
315 mutex_exit(&mntvnode_lock
);
316 err
= vget(v
, LK_EXCLUSIVE
| LK_NOWAIT
| LK_INTERLOCK
);
318 err
= VOP_FSYNC(v
, cred
, FSYNC_WAIT
, 0, 0);
323 mutex_enter(&mntvnode_lock
);
325 mutex_exit(&mntvnode_lock
);
331 sysvbfs_vget(struct mount
*mp
, ino_t ino
, struct vnode
**vpp
)
333 struct sysvbfs_mount
*bmp
= mp
->mnt_data
;
334 struct bfs
*bfs
= bmp
->bfs
;
336 struct sysvbfs_node
*bnode
;
337 struct bfs_inode
*inode
;
340 DPRINTF("%s: i-node=%lld\n", __func__
, (long long)ino
);
341 /* Lookup requested i-node */
342 if (!bfs_inode_lookup(bfs
, ino
, &inode
)) {
343 DPRINTF("bfs_inode_lookup failed.\n");
348 mutex_enter(&mntvnode_lock
);
349 for (bnode
= LIST_FIRST(&bmp
->bnode_head
); bnode
!= NULL
;
350 bnode
= LIST_NEXT(bnode
, link
)) {
351 if (bnode
->inode
->number
== ino
) {
353 mutex_enter(&vp
->v_interlock
);
354 mutex_exit(&mntvnode_lock
);
355 if (vget(vp
, LK_EXCLUSIVE
|LK_RETRY
|LK_INTERLOCK
) == 0) {
363 mutex_exit(&mntvnode_lock
);
365 /* Allocate v-node. */
366 if ((error
= getnewvnode(VT_SYSVBFS
, mp
, sysvbfs_vnodeop_p
, &vp
)) !=
368 DPRINTF("%s: getnewvnode error.\n", __func__
);
371 /* Lock vnode here */
372 vn_lock(vp
, LK_EXCLUSIVE
| LK_RETRY
);
374 /* Allocate i-node */
375 vp
->v_data
= pool_get(&sysvbfs_node_pool
, PR_WAITOK
);
376 memset(vp
->v_data
, 0, sizeof(struct sysvbfs_node
));
378 mutex_enter(&mntvnode_lock
);
379 LIST_INSERT_HEAD(&bmp
->bnode_head
, bnode
, link
);
380 mutex_exit(&mntvnode_lock
);
383 bnode
->inode
= inode
;
384 bnode
->lockf
= NULL
; /* advlock */
386 if (ino
== BFS_ROOT_INODE
) { /* BFS is flat filesystem */
388 vp
->v_vflag
|= VV_ROOT
;
393 genfs_node_init(vp
, &sysvbfs_genfsops
);
394 uvm_vnp_setsize(vp
, bfs_file_size(inode
));
401 sysvbfs_fhtovp(struct mount
*mp
, struct fid
*fid
, struct vnode
**vpp
)
404 DPRINTF("%s:\n", __func__
);
410 sysvbfs_vptofh(struct vnode
*vpp
, struct fid
*fid
, size_t *fh_size
)
413 DPRINTF("%s:\n", __func__
);
418 MALLOC_DECLARE(M_BFS
);
419 MALLOC_DECLARE(M_SYSVBFS_VNODE
);
425 DPRINTF("%s:\n", __func__
);
426 malloc_type_attach(M_SYSVBFS_VFS
);
427 malloc_type_attach(M_BFS
);
428 malloc_type_attach(M_SYSVBFS_VNODE
);
429 pool_init(&sysvbfs_node_pool
, sizeof(struct sysvbfs_node
), 0, 0, 0,
430 "sysvbfs_node_pool", &pool_allocator_nointr
, IPL_NONE
);
438 DPRINTF("%s:\n", __func__
);
445 DPRINTF("%s:\n", __func__
);
446 pool_destroy(&sysvbfs_node_pool
);
447 malloc_type_detach(M_BFS
);
448 malloc_type_detach(M_SYSVBFS_VFS
);
449 malloc_type_detach(M_SYSVBFS_VNODE
);
453 sysvbfs_gop_alloc(struct vnode
*vp
, off_t off
, off_t len
, int flags
,