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