General userfs fleshing out work. Abstract out construction and
[dragonfly.git] / sys / vfs / userfs / userfs_vfsops.c
blobb3f7e297c1a21e34c2e70189d6171b822426a19d
1 /*
2 * Copyright (c) 2007 The DragonFly Project. All rights reserved.
3 *
4 * This code is derived from software contributed to The DragonFly Project
5 * by Matthew Dillon <dillon@backplane.com>
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
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
16 * distribution.
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
32 * SUCH DAMAGE.
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>
46 #include "userfs.h"
49 * Red-Black tree support - used to index inode numbers
52 static int
53 user_ino_rb_compare(struct user_inode *ip1, struct user_inode *ip2)
55 if (ip1->inum < ip2->inum)
56 return(-1);
57 if (ip1->inum > ip2->inum)
58 return(1);
59 return(0);
62 RB_GENERATE2(userfs_ino_rb_tree, user_inode, rb_node,
63 user_ino_rb_compare, ino_t, inum);
66 * VFS ABI
68 static void user_free_ump(struct mount *mp);
70 static int user_vfs_mount(struct mount *mp, char *path, caddr_t data,
71 struct ucred *cred);
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,
75 struct ucred *cred);
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);
92 static int
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;
97 int error;
99 if ((error = copyin(data, &info, sizeof(info))) != 0)
100 return (error);
102 ump = kmalloc(sizeof(*ump), M_USERFSMNT, M_WAITOK | M_ZERO);
103 mp->mnt_data = (qaddr_t)ump;
104 ump->mp = mp;
105 RB_INIT(&ump->rb_root);
107 error = syslink_ukbackend(&info.cfd, &ump->sldesc);
108 if (error == 0) {
109 error = user_getnewvnode(mp, &ump->rootvp, 0, VDIR);
110 if (ump->rootvp)
111 vn_unlock(ump->rootvp);
115 * Allocate the syslink pipe
117 if (error == 0)
118 error = copyout(&info, data, sizeof(info));
121 * Setup the rest of the mount or clean up after an error.
123 if (error) {
124 user_free_ump(mp);
125 } else {
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);
136 return (error);
139 static int
140 user_vfs_unmount(struct mount *mp, int mntflags)
142 #if 0
143 struct user_mount *ump = (void *)mp->mnt_data;
144 #endif
145 int flags;
146 int error;
149 * Clean out the vnodes
151 flags = 0;
152 if (mntflags & MNT_FORCE)
153 flags |= FORCECLOSE;
154 error = vflush(mp, 1, flags);
155 if (error)
156 return (error);
159 * Clean up the syslink descriptor
161 user_free_ump(mp);
162 return(0);
165 static void
166 user_free_ump(struct mount *mp)
168 struct user_mount *ump = (void *)mp->mnt_data;
170 if (ump->rootvp) {
171 vrele(ump->rootvp);
172 ump->rootvp = NULL;
174 if (ump->sldesc) {
175 syslink_kclose(ump->sldesc);
176 ump->sldesc = NULL;
178 mp->mnt_data = NULL;
179 ump->mp = NULL;
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.
188 static int
189 user_vfs_root(struct mount *mp, struct vnode **vpp)
191 struct user_mount *ump = (void *)mp->mnt_data;
192 struct vnode *vp;
194 vp = ump->rootvp;
195 vref(vp);
196 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
197 *vpp = vp;
198 return (0);
201 static int
202 user_vfs_statfs(struct mount *mp, struct statfs *sbp, struct ucred *cred)
204 struct user_mount *ump = (void *)mp->mnt_data;
205 struct slmsg *slmsg;
206 syslink_elm_t par;
207 int error;
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);
221 } else {
222 error = EBADRPC;
225 syslink_kfreemsg(ump->sldesc, slmsg);
226 kprintf("error %d\n", error);
227 return(error);
230 static int
231 user_vfs_sync(struct mount *mp, int waitfor)
233 return(0);