2 * Copyright (c) 2009 The DragonFly Project. All rights reserved.
4 * This code is derived from software contributed to The DragonFly Project
5 * by Alex Hornung <ahornung@gmail.com>
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in
15 * the documentation and/or other materials provided with the
17 * 3. Neither the name of The DragonFly Project nor the names of its
18 * contributors may be used to endorse or promote products derived
19 * from this software without specific, prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26 * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
27 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
29 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
30 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
31 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 #include <sys/param.h>
35 #include <sys/systm.h>
36 #include <sys/kernel.h>
37 #include <sys/mount.h>
38 #include <sys/vnode.h>
41 #include <sys/devfs.h>
43 MALLOC_DECLARE(M_DEVFS
);
45 extern struct vop_ops devfs_vnode_norm_vops
;
46 extern struct vop_ops devfs_vnode_dev_vops
;
47 extern struct lock devfs_lock
;
49 static int devfs_mount (struct mount
*mp
, char *path
, caddr_t data
,
51 static int devfs_statfs (struct mount
*mp
, struct statfs
*sbp
,
53 static int devfs_unmount (struct mount
*mp
, int mntflags
);
54 int devfs_root(struct mount
*mp
, struct vnode
**vpp
);
55 static int devfs_vget(struct mount
*mp
, struct vnode
*dvp
,
56 ino_t ino
, struct vnode
**vpp
);
57 static int devfs_fhtovp(struct mount
*mp
, struct vnode
*rootvp
,
58 struct fid
*fhp
, struct vnode
**vpp
);
59 static int devfs_vptofh(struct vnode
*vp
, struct fid
*fhp
);
69 devfs_mount(struct mount
*mp
, char *path
, caddr_t data
, struct ucred
*cred
)
71 struct devfs_mount_info info
;
72 struct devfs_mnt_data
*mnt
;
76 devfs_debug(DEVFS_DEBUG_DEBUG
, "(vfsops) devfs_mount() called!\n");
78 if (mp
->mnt_flag
& MNT_UPDATE
)
82 bzero(&info
, sizeof(info
));
84 if ((error
= copyin(data
, &info
, sizeof(info
))) != 0)
88 mp
->mnt_flag
|= MNT_LOCAL
;
89 mp
->mnt_kern_flag
|= MNTK_NOSTKMNT
;
93 size
= sizeof("devfs") - 1;
94 bcopy("devfs", mp
->mnt_stat
.f_mntfromname
, size
);
95 bzero(mp
->mnt_stat
.f_mntfromname
+ size
, MNAMELEN
- size
);
96 devfs_statfs(mp
, &mp
->mnt_stat
, cred
);
99 * XXX: save other mount info passed from userland or so.
101 mnt
= kmalloc(sizeof(*mnt
), M_DEVFS
, M_WAITOK
| M_ZERO
);
103 lockmgr(&devfs_lock
, LK_EXCLUSIVE
);
104 mp
->mnt_data
= (qaddr_t
)mnt
;
106 if (info
.flags
& DEVFS_MNT_JAIL
)
109 mnt
->jailed
= jailed(cred
);
113 TAILQ_INIT(&mnt
->orphan_list
);
114 mnt
->root_node
= devfs_allocp(Proot
, "", NULL
, mp
, NULL
);
115 KKASSERT(mnt
->root_node
);
116 lockmgr(&devfs_lock
, LK_RELEASE
);
118 vfs_add_vnodeops(mp
, &devfs_vnode_norm_vops
, &mp
->mnt_vn_norm_ops
);
119 vfs_add_vnodeops(mp
, &devfs_vnode_dev_vops
, &mp
->mnt_vn_spec_ops
);
121 devfs_debug(DEVFS_DEBUG_DEBUG
, "calling devfs_mount_add\n");
122 devfs_mount_add(mnt
);
128 * unmount system call
131 devfs_unmount(struct mount
*mp
, int mntflags
)
136 devfs_debug(DEVFS_DEBUG_DEBUG
, "(vfsops) devfs_unmount() called!\n");
138 if (mntflags
& MNT_FORCE
)
141 error
= vflush(mp
, 0, flags
);
145 devfs_tracer_orphan_count(mp
, 1);
146 devfs_mount_del(DEVFS_MNTDATA(mp
));
147 kfree(mp
->mnt_data
, M_DEVFS
);
154 * Sets *vpp to the root procfs vnode, referenced and exclusively locked
157 devfs_root(struct mount
*mp
, struct vnode
**vpp
)
160 devfs_debug(DEVFS_DEBUG_DEBUG
, "(vfsops) devfs_root() called!\n");
161 lockmgr(&devfs_lock
, LK_EXCLUSIVE
);
162 ret
= devfs_allocv(vpp
, DEVFS_MNTDATA(mp
)->root_node
);
163 lockmgr(&devfs_lock
, LK_RELEASE
);
168 * Get file system statistics.
171 devfs_statfs(struct mount
*mp
, struct statfs
*sbp
, struct ucred
*cred
)
173 devfs_debug(DEVFS_DEBUG_DEBUG
, "(vfsops) devfs_stat() called!\n");
174 sbp
->f_bsize
= DEV_BSIZE
;
175 sbp
->f_iosize
= DEV_BSIZE
;
176 sbp
->f_blocks
= 2; /* avoid divide by zero in some df's */
182 if (sbp
!= &mp
->mnt_stat
) {
183 sbp
->f_type
= mp
->mnt_vfc
->vfc_typenum
;
184 bcopy(&mp
->mnt_stat
.f_fsid
, &sbp
->f_fsid
, sizeof(sbp
->f_fsid
));
185 bcopy(mp
->mnt_stat
.f_mntfromname
, sbp
->f_mntfromname
, MNAMELEN
);
192 devfs_fhtovp(struct mount
*mp
, struct vnode
*rootvp
,
193 struct fid
*fhp
, struct vnode
**vpp
)
196 struct devfs_fid
*dfhp
;
198 dfhp
= (struct devfs_fid
*)fhp
;
200 if (dfhp
->fid_gen
!= boottime
.tv_sec
)
203 vp
= devfs_inode_to_vnode(mp
, dfhp
->fid_ino
);
213 * Vnode pointer to File handle
217 devfs_vptofh(struct vnode
*vp
, struct fid
*fhp
)
219 struct devfs_node
*node
;
220 struct devfs_fid
*dfhp
;
222 if ((node
= DEVFS_NODE(vp
)) != NULL
) {
223 dfhp
= (struct devfs_fid
*)fhp
;
224 dfhp
->fid_len
= sizeof(struct devfs_fid
);
225 dfhp
->fid_ino
= node
->d_dir
.d_ino
;
226 dfhp
->fid_gen
= boottime
.tv_sec
;
235 devfs_vget(struct mount
*mp
, struct vnode
*dvp
, ino_t ino
, struct vnode
**vpp
)
238 vp
= devfs_inode_to_vnode(mp
, ino
);
248 static struct vfsops devfs_vfsops
= {
249 .vfs_mount
= devfs_mount
,
250 .vfs_unmount
= devfs_unmount
,
251 .vfs_root
= devfs_root
,
252 .vfs_statfs
= devfs_statfs
,
253 .vfs_sync
= vfs_stdsync
,
254 .vfs_vget
= devfs_vget
,
255 .vfs_vptofh
= devfs_vptofh
,
256 .vfs_fhtovp
= devfs_fhtovp
259 VFS_SET(devfs_vfsops
, devfs
, VFCF_SYNTHETIC
);
260 MODULE_VERSION(devfs
, 1);