4 * Copyright (c) 2009 The DragonFly Project. All rights reserved.
6 * This code is derived from software contributed to The DragonFly Project
7 * by Alex Hornung <ahornung@gmail.com>
9 * Redistribution and use in source and binary forms, with or without
10 * 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
17 * the documentation and/or other materials provided with the
19 * 3. Neither the name of The DragonFly Project nor the names of its
20 * contributors may be used to endorse or promote products derived
21 * from this software without specific, prior written permission.
23 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
24 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
25 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
26 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
27 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
28 * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
29 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
31 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
32 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
33 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36 #include <sys/param.h>
37 #include <sys/systm.h>
38 #include <sys/kernel.h>
39 #include <sys/mount.h>
40 #include <sys/namecache.h>
41 #include <sys/vnode.h>
44 #include <sys/devfs.h>
46 MALLOC_DECLARE(M_DEVFS
);
48 extern struct vop_ops devfs_vnode_norm_vops
;
49 extern struct vop_ops devfs_vnode_dev_vops
;
50 extern struct lock devfs_lock
;
52 static int devfs_vfs_mount (struct mount
*mp
, char *path
, caddr_t data
,
54 static int devfs_vfs_statfs (struct mount
*mp
, struct statfs
*sbp
,
56 static int devfs_vfs_unmount (struct mount
*mp
, int mntflags
);
57 int devfs_vfs_root(struct mount
*mp
, struct vnode
**vpp
);
58 static int devfs_vfs_vget(struct mount
*mp
, struct vnode
*dvp
,
59 ino_t ino
, struct vnode
**vpp
);
60 static int devfs_vfs_fhtovp(struct mount
*mp
, struct vnode
*rootvp
,
61 struct fid
*fhp
, struct vnode
**vpp
);
62 static int devfs_vfs_vptofh(struct vnode
*vp
, struct fid
*fhp
);
71 devfs_vfs_mount(struct mount
*mp
, char *path
, caddr_t data
, struct ucred
*cred
)
73 struct devfs_mount_info info
;
74 struct devfs_mnt_data
*mnt
;
78 devfs_debug(DEVFS_DEBUG_DEBUG
, "(vfsops) devfs_mount() called!\n");
80 if (mp
->mnt_flag
& MNT_UPDATE
)
84 bzero(&info
, sizeof(info
));
86 if ((error
= copyin(data
, &info
, sizeof(info
))) != 0)
90 mp
->mnt_flag
|= MNT_LOCAL
;
91 mp
->mnt_kern_flag
|= MNTK_NOSTKMNT
| MNTK_ALL_MPSAFE
;
95 size
= sizeof("devfs") - 1;
96 bcopy("devfs", mp
->mnt_stat
.f_mntfromname
, size
);
97 bzero(mp
->mnt_stat
.f_mntfromname
+ size
, MNAMELEN
- size
);
98 copyinstr(path
, mp
->mnt_stat
.f_mntonname
,
99 sizeof(mp
->mnt_stat
.f_mntonname
) -1, &size
);
100 devfs_vfs_statfs(mp
, &mp
->mnt_stat
, cred
);
103 * XXX: save other mount info passed from userland or so.
105 mnt
= kmalloc(sizeof(*mnt
), M_DEVFS
, M_WAITOK
| M_ZERO
);
107 lockmgr(&devfs_lock
, LK_EXCLUSIVE
);
108 mp
->mnt_data
= (qaddr_t
)mnt
;
110 if (info
.flags
& DEVFS_MNT_JAIL
)
113 mnt
->jailed
= jailed(cred
);
118 TAILQ_INIT(&mnt
->orphan_list
);
119 mnt
->root_node
= devfs_allocp(Nroot
, "", NULL
, mp
, NULL
);
120 KKASSERT(mnt
->root_node
);
121 lockmgr(&devfs_lock
, LK_RELEASE
);
123 vfs_add_vnodeops(mp
, &devfs_vnode_norm_vops
, &mp
->mnt_vn_norm_ops
);
124 vfs_add_vnodeops(mp
, &devfs_vnode_dev_vops
, &mp
->mnt_vn_spec_ops
);
126 devfs_debug(DEVFS_DEBUG_DEBUG
, "calling devfs_mount_add\n");
127 devfs_mount_add(mnt
);
133 * unmount system call
136 devfs_vfs_unmount(struct mount
*mp
, int mntflags
)
141 devfs_debug(DEVFS_DEBUG_DEBUG
, "(vfsops) devfs_unmount() called!\n");
143 if (mntflags
& MNT_FORCE
)
146 error
= vflush(mp
, 0, flags
);
150 lockmgr(&devfs_lock
, LK_EXCLUSIVE
);
151 devfs_tracer_orphan_count(mp
, 1);
152 lockmgr(&devfs_lock
, LK_RELEASE
);
153 devfs_mount_del(DEVFS_MNTDATA(mp
));
154 kfree(mp
->mnt_data
, M_DEVFS
);
161 * Sets *vpp to the root procfs vnode, referenced and exclusively locked
164 devfs_vfs_root(struct mount
*mp
, struct vnode
**vpp
)
168 devfs_debug(DEVFS_DEBUG_DEBUG
, "(vfsops) devfs_root() called!\n");
169 lockmgr(&devfs_lock
, LK_EXCLUSIVE
);
170 ret
= devfs_allocv(vpp
, DEVFS_MNTDATA(mp
)->root_node
);
171 lockmgr(&devfs_lock
, LK_RELEASE
);
177 * Get file system statistics.
180 devfs_vfs_statfs(struct mount
*mp
, struct statfs
*sbp
, struct ucred
*cred
)
182 devfs_debug(DEVFS_DEBUG_DEBUG
, "(vfsops) devfs_stat() called!\n");
183 sbp
->f_bsize
= DEV_BSIZE
;
184 sbp
->f_iosize
= DEV_BSIZE
;
185 sbp
->f_blocks
= 2; /* avoid divide by zero in some df's */
188 sbp
->f_files
= (DEVFS_MNTDATA(mp
))?(DEVFS_MNTDATA(mp
)->file_count
):0;
191 if (sbp
!= &mp
->mnt_stat
) {
192 sbp
->f_type
= mp
->mnt_vfc
->vfc_typenum
;
193 bcopy(&mp
->mnt_stat
.f_fsid
, &sbp
->f_fsid
, sizeof(sbp
->f_fsid
));
194 bcopy(mp
->mnt_stat
.f_mntfromname
, sbp
->f_mntfromname
, MNAMELEN
);
201 devfs_vfs_fhtovp(struct mount
*mp
, struct vnode
*rootvp
,
202 struct fid
*fhp
, struct vnode
**vpp
)
205 struct devfs_fid
*dfhp
;
207 dfhp
= (struct devfs_fid
*)fhp
;
209 if (dfhp
->fid_gen
!= boottime
.tv_sec
)
212 vp
= devfs_inode_to_vnode(mp
, dfhp
->fid_ino
);
222 * Vnode pointer to File handle
225 devfs_vfs_vptofh(struct vnode
*vp
, struct fid
*fhp
)
227 struct devfs_node
*node
;
228 struct devfs_fid
*dfhp
;
230 if ((node
= DEVFS_NODE(vp
)) != NULL
) {
231 dfhp
= (struct devfs_fid
*)fhp
;
232 dfhp
->fid_len
= sizeof(struct devfs_fid
);
233 dfhp
->fid_ino
= node
->d_dir
.d_ino
;
234 dfhp
->fid_gen
= boottime
.tv_sec
;
243 devfs_vfs_vget(struct mount
*mp
, struct vnode
*dvp
,
244 ino_t ino
, struct vnode
**vpp
)
247 vp
= devfs_inode_to_vnode(mp
, ino
);
257 devfs_vfs_ncpgen_set(struct mount
*mp
, struct namecache
*ncp
)
259 ncp
->nc_namecache_gen
= mp
->mnt_namecache_gen
;
263 devfs_vfs_ncpgen_test(struct mount
*mp
, struct namecache
*ncp
)
265 return (ncp
->nc_namecache_gen
!= mp
->mnt_namecache_gen
);
268 static struct vfsops devfs_vfsops
= {
269 .vfs_mount
= devfs_vfs_mount
,
270 .vfs_unmount
= devfs_vfs_unmount
,
271 .vfs_root
= devfs_vfs_root
,
272 .vfs_statfs
= devfs_vfs_statfs
,
273 .vfs_vget
= devfs_vfs_vget
,
274 .vfs_vptofh
= devfs_vfs_vptofh
,
275 .vfs_fhtovp
= devfs_vfs_fhtovp
,
276 .vfs_ncpgen_set
= devfs_vfs_ncpgen_set
,
277 .vfs_ncpgen_test
= devfs_vfs_ncpgen_test
280 VFS_SET(devfs_vfsops
, devfs
, VFCF_SYNTHETIC
| VFCF_MPSAFE
);
281 MODULE_VERSION(devfs
, 1);