NFS - create nfsm_subs.c, clean up externs
[dragonfly.git] / sys / vfs / userfs / userfs_vfsops.c
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:
10  * 
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.
20  * 
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.
33  * 
34  * $DragonFly: src/sys/vfs/userfs/userfs_vfsops.c,v 1.1 2007/08/13 17:49:17 dillon Exp $
35  */
36
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"
47
48 /*
49  * Red-Black tree support - used to index inode numbers
50  */
51
52 static int
53 user_ino_rb_compare(struct user_inode *ip1, struct user_inode *ip2)
54 {
55         if (ip1->inum < ip2->inum)
56                 return(-1);
57         if (ip1->inum > ip2->inum)
58                 return(1);
59         return(0);
60 }
61
62 RB_GENERATE2(userfs_ino_rb_tree, user_inode, rb_node,
63              user_ino_rb_compare, ino_t, inum);
64
65 /*
66  * VFS ABI
67  */
68 static void     user_free_ump(struct mount *mp);
69
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);
77
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
85 };
86
87 static MALLOC_DEFINE(M_USERFSMNT, "userfs-mount", "userfs mount");
88
89 VFS_SET(userfs_vfsops, userfs, 0);
90 MODULE_VERSION(userfs, 1);
91
92 static int
93 user_vfs_mount(struct mount *mp, char *path, caddr_t data, struct ucred *cred)
94 {
95         struct userfs_mount_info info;
96         struct user_mount *ump;
97         int error;
98
99         if ((error = copyin(data, &info, sizeof(info))) != 0)
100                 return (error);
101
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);
106
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);
112         }
113
114         /*
115          * Allocate the syslink pipe
116          */
117         if (error == 0)
118                 error = copyout(&info, data, sizeof(info));
119
120         /*
121          * Setup the rest of the mount or clean up after an error.
122          */
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;
133
134                 vfs_add_vnodeops(mp, &userfs_vnode_vops, &mp->mnt_vn_norm_ops);
135         }
136         return (error);
137 }
138
139 static int
140 user_vfs_unmount(struct mount *mp, int mntflags)
141 {
142 #if 0
143         struct user_mount *ump = (void *)mp->mnt_data;
144 #endif
145         int flags;
146         int error;
147
148         /*
149          * Clean out the vnodes
150          */
151         flags = 0;
152         if (mntflags & MNT_FORCE)
153                 flags |= FORCECLOSE;
154         error = vflush(mp, 1, flags);
155         if (error)
156                 return (error);
157
158         /*
159          * Clean up the syslink descriptor
160          */
161         user_free_ump(mp);
162         return(0);
163 }
164
165 static void
166 user_free_ump(struct mount *mp)
167 {
168         struct user_mount *ump = (void *)mp->mnt_data;
169
170         if (ump->rootvp) {
171                 vrele(ump->rootvp);
172                 ump->rootvp = NULL;
173         }
174         if (ump->sldesc) {
175                 syslink_kclose(ump->sldesc);
176                 ump->sldesc = NULL;
177         }
178         mp->mnt_data = NULL;
179         ump->mp = NULL;
180         kfree(ump, M_USERFSMNT);
181 }
182
183 /*
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.
187  */
188 static int
189 user_vfs_root(struct mount *mp, struct vnode **vpp)
190 {
191         struct user_mount *ump = (void *)mp->mnt_data;
192         struct vnode *vp;
193
194         vp = ump->rootvp;
195         vref(vp);
196         vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
197         *vpp = vp;
198         return (0);
199 }
200
201 static int
202 user_vfs_statfs(struct mount *mp, struct statfs *sbp, struct ucred *cred)
203 {
204         struct user_mount *ump = (void *)mp->mnt_data;
205         struct slmsg *slmsg;
206         syslink_elm_t par;
207         int error;
208
209         slmsg = syslink_kallocmsg();
210         par = sl_msg_init_cmd(slmsg->msg, SMPROTO_BSDVFS, SLVFS_CMD_VFS_STATFS);
211         sl_msg_fini(slmsg->msg);
212
213         kprintf("userfs_root\n");
214         if ((error = syslink_kdomsg(ump->sldesc, slmsg)) == 0) {
215                 par = &slmsg->rep->msg->sm_head;
216
217                 if (par->se_cmd == (SLVFS_CMD_VFS_STATFS|SE_CMDF_REPLY) &&
218                     par->se_bytes == sizeof(*par) + sizeof(struct statfs)
219                 ) {
220                         *sbp = *(struct statfs *)(par + 1);
221                 } else {
222                         error = EBADRPC;
223                 }
224         }
225         syslink_kfreemsg(ump->sldesc, slmsg);
226         kprintf("error %d\n", error);
227         return(error);
228 }
229
230 static int
231 user_vfs_sync(struct mount *mp, int waitfor)
232 {
233         return(0);
234 }
235