2 * Copyright (c) 2007 The DragonFly Project. All rights reserved.
4 * This code is derived from software contributed to The DragonFly Project
5 * by Matthew Dillon <dillon@backplane.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 * $DragonFly: src/sys/vfs/userfs/userfs_vfsops.c,v 1.1 2007/08/13 17:49:17 dillon Exp $
37 #include <sys/param.h>
38 #include <sys/systm.h>
39 #include <sys/kernel.h>
40 #include <sys/vnode.h>
41 #include <sys/mount.h>
42 #include <sys/malloc.h>
43 #include <sys/syslink.h>
44 #include <sys/syslink_msg2.h>
45 #include <sys/syslink_vfs.h>
49 * Red-Black tree support - used to index inode numbers
53 user_ino_rb_compare(struct user_inode *ip1, struct user_inode *ip2)
55 if (ip1->inum < ip2->inum)
57 if (ip1->inum > ip2->inum)
62 RB_GENERATE2(userfs_ino_rb_tree, user_inode, rb_node,
63 user_ino_rb_compare, ino_t, inum);
68 static void user_free_ump(struct mount *mp);
70 static int user_vfs_mount(struct mount *mp, char *path, caddr_t data,
72 static int user_vfs_unmount(struct mount *mp, int mntflags);
73 static int user_vfs_root(struct mount *mp, struct vnode **vpp);
74 static int user_vfs_statfs(struct mount *mp, struct statfs *sbp,
76 static int user_vfs_sync(struct mount *mp, int waitfor);
78 static struct vfsops userfs_vfsops = {
79 .vfs_mount = user_vfs_mount,
80 .vfs_unmount = user_vfs_unmount,
81 .vfs_root = user_vfs_root,
82 .vfs_statfs = user_vfs_statfs,
83 .vfs_sync = user_vfs_sync,
84 .vfs_vget = user_vfs_vget
87 static MALLOC_DEFINE(M_USERFSMNT, "userfs-mount", "userfs mount");
89 VFS_SET(userfs_vfsops, userfs, 0);
90 MODULE_VERSION(userfs, 1);
93 user_vfs_mount(struct mount *mp, char *path, caddr_t data, struct ucred *cred)
95 struct userfs_mount_info info;
96 struct user_mount *ump;
99 if ((error = copyin(data, &info, sizeof(info))) != 0)
102 ump = kmalloc(sizeof(*ump), M_USERFSMNT, M_WAITOK | M_ZERO);
103 mp->mnt_data = (qaddr_t)ump;
105 RB_INIT(&ump->rb_root);
107 error = syslink_ukbackend(&info.cfd, &ump->sldesc);
109 error = user_getnewvnode(mp, &ump->rootvp, 0, VDIR);
111 vn_unlock(ump->rootvp);
115 * Allocate the syslink pipe
118 error = copyout(&info, data, sizeof(info));
121 * Setup the rest of the mount or clean up after an error.
126 mp->mnt_iosize_max = MAXPHYS;
127 mp->mnt_kern_flag |= MNTK_FSMID;
128 mp->mnt_stat.f_fsid.val[0] = 0; /* XXX */
129 mp->mnt_stat.f_fsid.val[1] = 0; /* XXX */
130 vfs_getnewfsid(mp); /* XXX */
131 mp->mnt_maxsymlinklen = 255;
132 mp->mnt_flag |= MNT_LOCAL;
134 vfs_add_vnodeops(mp, &userfs_vnode_vops, &mp->mnt_vn_norm_ops);
140 user_vfs_unmount(struct mount *mp, int mntflags)
143 struct user_mount *ump = (void *)mp->mnt_data;
149 * Clean out the vnodes
152 if (mntflags & MNT_FORCE)
154 error = vflush(mp, 1, flags);
159 * Clean up the syslink descriptor
166 user_free_ump(struct mount *mp)
168 struct user_mount *ump = (void *)mp->mnt_data;
175 syslink_kclose(ump->sldesc);
180 kfree(ump, M_USERFSMNT);
184 * VFS_ROOT() is called during the mount sequence and since the process
185 * is stuck in the kernel doing the mount, we will deadlock if we try
186 * to talk to it now. Just allocate and return a vnode.
189 user_vfs_root(struct mount *mp, struct vnode **vpp)
191 struct user_mount *ump = (void *)mp->mnt_data;
196 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
202 user_vfs_statfs(struct mount *mp, struct statfs *sbp, struct ucred *cred)
204 struct user_mount *ump = (void *)mp->mnt_data;
209 slmsg = syslink_kallocmsg();
210 par = sl_msg_init_cmd(slmsg->msg, SMPROTO_BSDVFS, SLVFS_CMD_VFS_STATFS);
211 sl_msg_fini(slmsg->msg);
213 kprintf("userfs_root\n");
214 if ((error = syslink_kdomsg(ump->sldesc, slmsg)) == 0) {
215 par = &slmsg->rep->msg->sm_head;
217 if (par->se_cmd == (SLVFS_CMD_VFS_STATFS|SE_CMDF_REPLY) &&
218 par->se_bytes == sizeof(*par) + sizeof(struct statfs)
220 *sbp = *(struct statfs *)(par + 1);
225 syslink_kfreemsg(ump->sldesc, slmsg);
226 kprintf("error %d\n", error);
231 user_vfs_sync(struct mount *mp, int waitfor)