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
)