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
);
114 TAILQ_INIT(&mnt
->orphan_list
);
115 mnt
->root_node
= devfs_allocp(Proot
, "", NULL
, mp
, NULL
);
116 KKASSERT(mnt
->root_node
);
117 lockmgr(&devfs_lock
, LK_RELEASE
);
119 vfs_add_vnodeops(mp
, &devfs_vnode_norm_vops
, &mp
->mnt_vn_norm_ops
);
120 vfs_add_vnodeops(mp
, &devfs_vnode_dev_vops
, &mp
->mnt_vn_spec_ops
);
122 devfs_debug(DEVFS_DEBUG_DEBUG
, "calling devfs_mount_add\n");
123 devfs_mount_add(mnt
);
129 * unmount system call
132 devfs_unmount(struct mount
*mp
, int mntflags
)
137 devfs_debug(DEVFS_DEBUG_DEBUG
, "(vfsops) devfs_unmount() called!\n");
139 if (mntflags
& MNT_FORCE
)
142 error
= vflush(mp
, 0, flags
);
146 devfs_tracer_orphan_count(mp
, 1);
147 devfs_mount_del(DEVFS_MNTDATA(mp
));
148 kfree(mp
->mnt_data
, M_DEVFS
);
155 * Sets *vpp to the root procfs vnode, referenced and exclusively locked
158 devfs_root(struct mount
*mp
, struct vnode
**vpp
)
161 devfs_debug(DEVFS_DEBUG_DEBUG
, "(vfsops) devfs_root() called!\n");
162 lockmgr(&devfs_lock
, LK_EXCLUSIVE
);
163 ret
= devfs_allocv(vpp
, DEVFS_MNTDATA(mp
)->root_node
);
164 lockmgr(&devfs_lock
, LK_RELEASE
);
169 * Get file system statistics.
172 devfs_statfs(struct mount
*mp
, struct statfs
*sbp
, struct ucred
*cred
)
174 devfs_debug(DEVFS_DEBUG_DEBUG
, "(vfsops) devfs_stat() called!\n");
175 sbp
->f_bsize
= DEV_BSIZE
;
176 sbp
->f_iosize
= DEV_BSIZE
;
177 sbp
->f_blocks
= 2; /* avoid divide by zero in some df's */
180 sbp
->f_files
= (DEVFS_MNTDATA(mp
))?(DEVFS_MNTDATA(mp
)->file_count
):0;
183 if (sbp
!= &mp
->mnt_stat
) {
184 sbp
->f_type
= mp
->mnt_vfc
->vfc_typenum
;
185 bcopy(&mp
->mnt_stat
.f_fsid
, &sbp
->f_fsid
, sizeof(sbp
->f_fsid
));
186 bcopy(mp
->mnt_stat
.f_mntfromname
, sbp
->f_mntfromname
, MNAMELEN
);
193 devfs_fhtovp(struct mount
*mp
, struct vnode
*rootvp
,
194 struct fid
*fhp
, struct vnode
**vpp
)
197 struct devfs_fid
*dfhp
;
199 dfhp
= (struct devfs_fid
*)fhp
;
201 if (dfhp
->fid_gen
!= boottime
.tv_sec
)
204 vp
= devfs_inode_to_vnode(mp
, dfhp
->fid_ino
);
214 * Vnode pointer to File handle
218 devfs_vptofh(struct vnode
*vp
, struct fid
*fhp
)
220 struct devfs_node
*node
;
221 struct devfs_fid
*dfhp
;
223 if ((node
= DEVFS_NODE(vp
)) != NULL
) {
224 dfhp
= (struct devfs_fid
*)fhp
;
225 dfhp
->fid_len
= sizeof(struct devfs_fid
);
226 dfhp
->fid_ino
= node
->d_dir
.d_ino
;
227 dfhp
->fid_gen
= boottime
.tv_sec
;
236 devfs_vget(struct mount
*mp
, struct vnode
*dvp
, ino_t ino
, struct vnode
**vpp
)
239 vp
= devfs_inode_to_vnode(mp
, ino
);
249 static struct vfsops devfs_vfsops
= {
250 .vfs_mount
= devfs_mount
,
251 .vfs_unmount
= devfs_unmount
,
252 .vfs_root
= devfs_root
,
253 .vfs_statfs
= devfs_statfs
,
254 .vfs_sync
= vfs_stdsync
,
255 .vfs_vget
= devfs_vget
,
256 .vfs_vptofh
= devfs_vptofh
,
257 .vfs_fhtovp
= devfs_fhtovp
260 VFS_SET(devfs_vfsops
, devfs
, VFCF_SYNTHETIC
);
261 MODULE_VERSION(devfs
, 1);