]> git.saurik.com Git - apple/xnu.git/blame - bsd/miscfs/volfs/volfs_vfsops.c
xnu-792.12.6.tar.gz
[apple/xnu.git] / bsd / miscfs / volfs / volfs_vfsops.c
CommitLineData
1c79356b 1/*
91447636 2 * Copyright (c) 1998-2004 Apple Computer, Inc. All rights reserved.
1c79356b 3 *
8ad349bb 4 * @APPLE_LICENSE_OSREFERENCE_HEADER_START@
1c79356b 5 *
8ad349bb
A
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the
10 * License may not be used to create, or enable the creation or
11 * redistribution of, unlawful or unlicensed copies of an Apple operating
12 * system, or to circumvent, violate, or enable the circumvention or
13 * violation of, any terms of an Apple operating system software license
14 * agreement.
15 *
16 * Please obtain a copy of the License at
17 * http://www.opensource.apple.com/apsl/ and read it before using this
18 * file.
19 *
20 * The Original Code and all software distributed under the License are
21 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
22 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
23 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
24 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
25 * Please see the License for the specific language governing rights and
26 * limitations under the License.
27 *
28 * @APPLE_LICENSE_OSREFERENCE_HEADER_END@
1c79356b 29 */
1c79356b
A
30
31#include <sys/param.h>
32#include <sys/systm.h>
33#include <sys/namei.h>
34#include <sys/proc.h>
35#include <sys/kernel.h>
36#include <mach/machine/vm_types.h>
37#include <sys/vnode.h>
38#include <sys/socket.h>
91447636 39#include <sys/mount_internal.h>
1c79356b
A
40#include <sys/mbuf.h>
41#include <sys/file.h>
55e303ae 42#include <sys/disk.h>
1c79356b
A
43#include <sys/ioctl.h>
44#include <sys/errno.h>
45#include <sys/malloc.h>
46#include <dev/ldd.h>
47
48#include <miscfs/specfs/specdev.h>
49#include "volfs.h"
50
91447636
A
51static int volfs_mount(struct mount *, vnode_t , user_addr_t, vfs_context_t);
52static int volfs_start(struct mount *, int, vfs_context_t);
53static int volfs_unmount(struct mount *, int, vfs_context_t);
54static int volfs_root(struct mount *, struct vnode **, vfs_context_t);
55static int volfs_vfs_getattr(mount_t mp, struct vfs_attr *fsap, vfs_context_t context);
56static int volfs_sync(struct mount *, int, vfs_context_t);
57static int volfs_vget(struct mount *, ino64_t, struct vnode **, vfs_context_t);
58static int volfs_fhtovp(struct mount *, int, unsigned char *, struct vnode **, vfs_context_t);
59static int volfs_vptofh(struct vnode *, int *, unsigned char *, vfs_context_t);
60static int volfs_init(struct vfsconf *);
61static int volfs_sysctl(int *, u_int, user_addr_t, size_t *, user_addr_t, size_t, vfs_context_t);
62void volfs_load(int loadArgument);
63
64
1c79356b
A
65struct vfsops volfs_vfsops = {
66 volfs_mount,
67 volfs_start,
68 volfs_unmount,
69 volfs_root,
91447636
A
70 NULL, /* quotactl */
71 volfs_vfs_getattr,
1c79356b
A
72 volfs_sync,
73 volfs_vget,
74 volfs_fhtovp,
75 volfs_vptofh,
76 volfs_init,
77 volfs_sysctl
78};
79
91447636 80// static char volfs_fs_name[MFSNAMELEN] = "volfs";
1c79356b
A
81extern struct vnodeopv_desc volfs_vnodeop_opv_desc;
82
91447636
A
83extern int (**volfs_vnodeop_p)(void *);
84
1c79356b 85/* The following refer to kernel global variables used in the loading/initialization: */
1c79356b
A
86extern int vfs_opv_numops; /* The total number of defined vnode operations */
87extern int kdp_flag;
88
89void
91447636
A
90volfs_load(__unused int loadArgument)
91{
92#if 0
1c79356b
A
93 struct vfsconf *vfsconflistentry;
94 int entriesRemaining;
95 struct vfsconf *newvfsconf = NULL;
96 struct vfsconf *lastentry = NULL;
97 int j;
98 int (***opv_desc_vector_p)();
99 int (**opv_desc_vector)();
100 struct vnodeopv_entry_desc *opve_descp;
91447636 101
1c79356b
A
102 /*
103 * This routine is responsible for all the initialization that would
104 * ordinarily be done as part of the system startup; it calls volfs_init
105 * to do the initialization that is strictly volfs-specific.
106 */
107
108 /*
109 prevvfsconf is supposed to be the entry preceding the new entry.
110 To make sure we can always get hooked in SOMEWHERE in the list,
111 start it out at the first entry of the list. This assumes the
112 first entry in the list will be non-empty and not volfs.
113
114 This becomes irrelevant when volfs is compiled into the list.
115 */
1c79356b
A
116 vfsconflistentry = vfsconf;
117 for (entriesRemaining = maxvfsslots; entriesRemaining > 0; --entriesRemaining) {
118 if (vfsconflistentry->vfc_vfsops != NULL) {
119 /*
120 * Check to see if we're reloading a new version of volfs during debugging
121 * and overwrite the previously assigned entry if we find one:
122 */
123 if (strcmp(vfsconflistentry->vfc_name, volfs_fs_name) == 0) {
124 newvfsconf = vfsconflistentry;
125 break;
126 } else {
127 lastentry = vfsconflistentry;
128 };
129 } else {
130 /*
131 * This is at least a POSSIBLE place to insert the new entry...
132 */
133 newvfsconf = vfsconflistentry;
134 };
135 ++vfsconflistentry;
136 };
137
138 if (newvfsconf) {
91447636 139 newvfsconf->vfc_vfsops = &volfs_vfsops;
1c79356b
A
140 strncpy(&newvfsconf->vfc_name[0], "volfs", MFSNAMELEN);
141 newvfsconf->vfc_typenum = maxvfsconf++;
142 newvfsconf->vfc_refcount = 0;
143 newvfsconf->vfc_flags = 0;
144 newvfsconf->vfc_mountroot = NULL; /* Can't mount root of file system [yet] */
145
146 /* Hook into the list: */
147 newvfsconf->vfc_next = NULL;
148 if (lastentry) {
149 newvfsconf->vfc_next = lastentry->vfc_next;
150 lastentry->vfc_next = newvfsconf;
151 };
152
153 /* Based on vfs_op_init and ... */
154 opv_desc_vector_p = volfs_vnodeop_opv_desc.opv_desc_vector_p;
155
1c79356b
A
156 /*
157 * Allocate and init the vector.
158 * Also handle backwards compatibility.
159 */
160 MALLOC(*opv_desc_vector_p, PFI *, vfs_opv_numops*sizeof(PFI), M_TEMP, M_WAITOK);
161
162 bzero (*opv_desc_vector_p, vfs_opv_numops*sizeof(PFI));
163
164 opv_desc_vector = *opv_desc_vector_p;
165 for (j=0; volfs_vnodeop_opv_desc.opv_desc_ops[j].opve_op; j++) {
166 opve_descp = &(volfs_vnodeop_opv_desc.opv_desc_ops[j]);
167
168 /*
169 * Sanity check: is this operation listed
170 * in the list of operations? We check this
171 * by seeing if its offest is zero. Since
172 * the default routine should always be listed
173 * first, it should be the only one with a zero
174 * offset. Any other operation with a zero
175 * offset is probably not listed in
176 * vfs_op_descs, and so is probably an error.
177 *
178 * A panic here means the layer programmer
179 * has committed the all-too common bug
180 * of adding a new operation to the layer's
181 * list of vnode operations but
182 * not adding the operation to the system-wide
183 * list of supported operations.
184 */
185 if (opve_descp->opve_op->vdesc_offset == 0 &&
91447636 186 opve_descp->opve_op->vdesc_offset != VOFFSET(vnop_default)) {
1c79356b
A
187 panic ("load_volfs: bad operation");
188 }
189 /*
190 * Fill in this entry.
191 */
192 opv_desc_vector[opve_descp->opve_op->vdesc_offset] =
193 opve_descp->opve_impl;
194 }
195
196 /*
197 * Finally, go back and replace unfilled routines
198 * with their default. (Sigh, an O(n^3) algorithm. I
199 * could make it better, but that'd be work, and n is small.)
200 */
201 opv_desc_vector_p = volfs_vnodeop_opv_desc.opv_desc_vector_p;
202
203 /*
204 * Force every operations vector to have a default routine.
205 */
206 opv_desc_vector = *opv_desc_vector_p;
91447636 207 if (opv_desc_vector[VOFFSET(vnop_default)]==NULL) {
1c79356b
A
208 panic("load_vp;fs: operation vector without default routine.");
209 }
210 for (j = 0;j<vfs_opv_numops; j++)
211 if (opv_desc_vector[j] == NULL)
212 opv_desc_vector[j] =
91447636 213 opv_desc_vector[VOFFSET(vnop_default)];
1c79356b 214
91447636 215 volfs_init(newvfsconf);
1c79356b 216 };
91447636
A
217#else
218 panic("volfs load not ported");
219#endif
1c79356b
A
220}
221
222/*
223 * VFS Operations.
224 *
225 * mount system call
226 */
91447636
A
227static int
228volfs_mount(struct mount *mp, __unused vnode_t devvp, __unused user_addr_t data, __unused vfs_context_t context)
1c79356b
A
229{
230 struct volfs_mntdata *priv_mnt_data;
91447636
A
231 struct vnode *root_vp;
232 struct volfs_vndata *priv_vn_data;
233 int error;
234 struct vnode_fsparam vfsp;
1c79356b 235
1c79356b
A
236 MALLOC(priv_mnt_data, struct volfs_mntdata *, sizeof(struct volfs_mntdata),
237 M_VOLFSMNT, M_WAITOK);
1c79356b
A
238
239 mp->mnt_data = (void *)priv_mnt_data;
91447636
A
240 strcpy(mp->mnt_vfsstat.f_fstypename, "volfs");
241 strcpy(mp->mnt_vfsstat.f_mntfromname, "<volfs>");
1c79356b
A
242
243 /* Set up the root vnode for fast reference in the future.
244 Note that the root is maintained unlocked but with a pos. ref count until unmount. */
245
91447636
A
246 MALLOC(priv_vn_data, struct volfs_vndata *, sizeof(struct volfs_vndata), M_VOLFSNODE, M_WAITOK);
247
248 priv_vn_data->vnode_type = VOLFS_ROOT;
249 priv_vn_data->nodeID = ROOT_DIRID;
250 priv_vn_data->fs_mount = mp;
251 priv_vn_data->fs_fsid = mp->mnt_vfsstat.f_fsid;
252
253 vfsp.vnfs_mp = mp;
254 vfsp.vnfs_vtype = VDIR;
255 vfsp.vnfs_str = "volfs";
256 vfsp.vnfs_dvp = 0;
257 vfsp.vnfs_fsnode = priv_vn_data;
258 vfsp.vnfs_cnp = 0;
259 vfsp.vnfs_vops = volfs_vnodeop_p;
260 vfsp.vnfs_rdev = 0;
261 vfsp.vnfs_filesize = 0;
262 vfsp.vnfs_flags = VNFS_NOCACHE | VNFS_CANTCACHE;
263 vfsp.vnfs_marksystem = 0;
264 vfsp.vnfs_markroot = 1;
265
266 error = vnode_create(VNCREATE_FLAVOR, VCREATESIZE, &vfsp, &root_vp);
267 if (error != 0) {
1c79356b
A
268 FREE(priv_mnt_data, M_VOLFSMNT);
269 FREE(priv_vn_data, M_VOLFSNODE);
1c79356b
A
270 return(error);
271 }
91447636
A
272 vnode_ref(root_vp);
273 vnode_put(root_vp);
274
275 /* obtain a new fsid for the mount point */
276 vfs_getnewfsid(mp);
277
278 vnode_settag(root_vp, VT_VOLFS);
55e303ae 279
91447636
A
280 priv_mnt_data->volfs_rootvp = root_vp;
281 mp->mnt_flag &= ~MNT_RDONLY;
282
283 mp->mnt_vtable->vfc_threadsafe = TRUE;
1c79356b 284
91447636 285 return (0);
1c79356b
A
286}
287
91447636
A
288static int
289volfs_start(__unused struct mount * mp, __unused int flags, __unused vfs_context_t context)
1c79356b 290{
1c79356b
A
291 return (0);
292}
293
294/*
295 * Return the root of a filesystem. For volfs the root vnode is a directory
296 * containing the list of all filesystems volfs can work with.
297 */
91447636
A
298static int
299volfs_root(struct mount *mp, struct vnode **vpp, __unused vfs_context_t context)
1c79356b
A
300{
301 struct volfs_mntdata *priv_data;
1c79356b 302
1c79356b
A
303 priv_data = (struct volfs_mntdata *)mp->mnt_data;
304
91447636
A
305 if (priv_data->volfs_rootvp) {
306 vnode_get(priv_data->volfs_rootvp);
1c79356b
A
307 *vpp = priv_data->volfs_rootvp;
308 } else {
309 panic("volfs: root vnode missing!");
91447636 310 };
1c79356b 311
91447636 312 return(0);
1c79356b
A
313}
314
315/*
316 * unmount system call
317 */
91447636
A
318static int
319volfs_unmount(struct mount *mp, __unused int mntflags, __unused vfs_context_t context)
1c79356b
A
320{
321 struct volfs_mntdata *priv_data;
322 struct vnode *root_vp;
323 int retval;
324
1c79356b
A
325 priv_data = (struct volfs_mntdata *)mp->mnt_data;
326
327 root_vp = priv_data->volfs_rootvp;
328 retval = vflush(mp, root_vp, 0);
329 if (retval) goto Err_Exit;
330
331 /* Free the root vnode.
332 Note that there's no need to vget() or vref() it before locking it here:
333 the ref. count has been maintained at +1 ever since mount time. */
334 if (root_vp) {
91447636
A
335 if (vnode_isinuse(root_vp, 1)) {
336 retval = EBUSY;
1c79356b
A
337 goto Err_Exit;
338 };
339
340 priv_data->volfs_rootvp = NULL;
91447636
A
341 vnode_rele(root_vp); /* This drops volfs's own refcount */
342 vnode_reclaim(root_vp);
1c79356b
A
343 };
344
345 /* All vnodes should be gone, and no errors, clean up the last */
1c79356b
A
346
347 mp->mnt_data = NULL;
348 FREE(priv_data, M_VOLFSMNT);
349
350Err_Exit:
351
352 return(retval);
353}
354
355/*
356 * Get file system statistics.
357 */
91447636
A
358static int
359volfs_vfs_getattr(mount_t mp, struct vfs_attr *fsap, vfs_context_t context)
1c79356b 360{
91447636
A
361 VFSATTR_RETURN(fsap, f_bsize, 512);
362 VFSATTR_RETURN(fsap, f_iosize, 512);
363 VFSATTR_RETURN(fsap, f_blocks, 1024);
364 VFSATTR_RETURN(fsap, f_bfree, 0);
365 VFSATTR_RETURN(fsap, f_bavail, 0);
366 VFSATTR_RETURN(fsap, f_bused, 1024);
367 VFSATTR_RETURN(fsap, f_files, 0);
368 VFSATTR_RETURN(fsap, f_ffree, 0);
369 VFSATTR_RETURN(fsap, f_fssubtype, 0);
370 return 0;
1c79356b
A
371}
372
373/*
374 * volfs doesn't have any data and you can't write into any of the volfs
375 * structures, so don't do anything
376 */
91447636
A
377static int
378volfs_sync(__unused struct mount *mp, __unused int waitfor, __unused vfs_context_t context)
1c79356b 379{
1c79356b
A
380 return 0;
381}
91447636 382
1c79356b 383/*
91447636 384 *
1c79356b 385 */
91447636
A
386static int
387volfs_vget(__unused struct mount *mp, __unused ino64_t ino,
388 __unused struct vnode **vpp, __unused vfs_context_t context)
1c79356b 389{
91447636 390 return(ENOTSUP);
1c79356b 391}
91447636 392
1c79356b
A
393/*
394 * File handle to vnode
1c79356b 395 */
91447636
A
396static int
397volfs_fhtovp(__unused struct mount *mp, __unused int fhlen,
398 __unused unsigned char *fhp, __unused struct vnode **vpp,
399 __unused vfs_context_t context)
1c79356b 400{
91447636 401 return(ENOTSUP);
1c79356b 402}
91447636 403
1c79356b
A
404/*
405 * Vnode pointer to File handle
406 */
91447636
A
407static int
408volfs_vptofh(__unused struct vnode *vp, __unused int *fhlenp, __unused unsigned char *fhp, __unused vfs_context_t context)
1c79356b 409{
91447636 410 return(ENOTSUP);
1c79356b 411}
91447636 412
1c79356b
A
413/*
414 * Initialize the filesystem
415 */
91447636
A
416static int
417volfs_init(__unused struct vfsconf *vfsp)
418{
1c79356b
A
419 return (0);
420}
421
422/*
423 * fast filesystem related variables.
424 */
91447636
A
425static int
426volfs_sysctl(__unused int *name, __unused u_int namelen, __unused user_addr_t oldp,
427 __unused size_t *oldlenp, __unused user_addr_t newp, __unused size_t newlen,
428 __unused vfs_context_t context)
1c79356b 429{
91447636 430 return (ENOTSUP);
1c79356b
A
431}
432