|
|
1.1 root 1: /*
2: * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
3: *
4: * @APPLE_LICENSE_HEADER_START@
5: *
6: * The contents of this file constitute Original Code as defined in and
7: * are subject to the Apple Public Source License Version 1.1 (the
8: * "License"). You may not use this file except in compliance with the
9: * License. Please obtain a copy of the License at
10: * http://www.apple.com/publicsource and read it before using this file.
11: *
12: * This Original Code and all software distributed under the License are
13: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
14: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
16: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17: * License for the specific language governing rights and limitations
18: * under the License.
19: *
20: * @APPLE_LICENSE_HEADER_END@
21: */
22: /* Copyright (c) 1998 Apple Computer, Inc. All Rights Reserved */
23: /*
24: * Change History:
25: *
26: * 29-May-1998 Pat Dirks Changed to cache pointer to root vnode until unmount.
27: *
28: */
29:
30: #include <sys/param.h>
31: #include <sys/systm.h>
32: #include <sys/namei.h>
33: #include <sys/proc.h>
34: #include <sys/kernel.h>
35: #include <mach/machine/vm_types.h>
36: #include <sys/vnode.h>
37: #include <sys/socket.h>
38: #include <sys/mount.h>
39: #include <sys/buf.h>
40: #include <sys/mbuf.h>
41: #include <sys/file.h>
42: #include <bsd/dev/disk.h>
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:
51: struct vfsops volfs_vfsops = {
52: volfs_mount,
53: volfs_start,
54: volfs_unmount,
55: volfs_root,
56: volfs_quotactl,
57: volfs_statfs,
58: volfs_sync,
59: volfs_vget,
60: volfs_fhtovp,
61: volfs_vptofh,
62: volfs_init,
63: volfs_sysctl
64: };
65:
66: static char volfs_fs_name[MFSNAMELEN] = "volfs";
67: extern struct vnodeopv_desc volfs_vnodeop_opv_desc;
68:
69: /* The following refer to kernel global variables used in the loading/initialization: */
70: extern int maxvfsslots; /* Total number of slots in the system's vfsconf table */
71: extern int maxvfsconf; /* The highest fs type number [old-style ID] in use [dispite its name] */
72: extern int vfs_opv_numops; /* The total number of defined vnode operations */
73: extern int kdp_flag;
74:
75: void
76: volfs_load(int loadArgument) {
77: struct vfsconf *vfsconflistentry;
78: int entriesRemaining;
79: struct vfsconf *newvfsconf = NULL;
80: struct vfsconf *lastentry = NULL;
81: int j;
82: int (***opv_desc_vector_p)();
83: int (**opv_desc_vector)();
84: struct vnodeopv_entry_desc *opve_descp;
85:
86: #pragma unused(loadArgument)
87:
88: /*
89: * This routine is responsible for all the initialization that would
90: * ordinarily be done as part of the system startup; it calls volfs_init
91: * to do the initialization that is strictly volfs-specific.
92: */
93:
94: /*
95: prevvfsconf is supposed to be the entry preceding the new entry.
96: To make sure we can always get hooked in SOMEWHERE in the list,
97: start it out at the first entry of the list. This assumes the
98: first entry in the list will be non-empty and not volfs.
99:
100: This becomes irrelevant when volfs is compiled into the list.
101: */
102: DBG_VOP(("load_volfs: Scanning vfsconf list...\n"));
103: vfsconflistentry = vfsconf;
104: for (entriesRemaining = maxvfsslots; entriesRemaining > 0; --entriesRemaining) {
105: if (vfsconflistentry->vfc_vfsops != NULL) {
106: /*
107: * Check to see if we're reloading a new version of volfs during debugging
108: * and overwrite the previously assigned entry if we find one:
109: */
110: if (strcmp(vfsconflistentry->vfc_name, volfs_fs_name) == 0) {
111: newvfsconf = vfsconflistentry;
112: break;
113: } else {
114: lastentry = vfsconflistentry;
115: };
116: } else {
117: /*
118: * This is at least a POSSIBLE place to insert the new entry...
119: */
120: newvfsconf = vfsconflistentry;
121: };
122: ++vfsconflistentry;
123: };
124:
125: if (newvfsconf) {
126: DBG_VOP(("load_volfs: filling in vfsconf entry at 0x%08lX; lastentry = 0x%08lX.\n", (long)newvfsconf, (long)lastentry));
127: newvfsconf->vfc_vfsops = &volfs_vfsops;
128: strncpy(&newvfsconf->vfc_name[0], "volfs", MFSNAMELEN);
129: newvfsconf->vfc_typenum = maxvfsconf++;
130: newvfsconf->vfc_refcount = 0;
131: newvfsconf->vfc_flags = 0;
132: newvfsconf->vfc_mountroot = NULL; /* Can't mount root of file system [yet] */
133:
134: /* Hook into the list: */
135: newvfsconf->vfc_next = NULL;
136: if (lastentry) {
137: newvfsconf->vfc_next = lastentry->vfc_next;
138: lastentry->vfc_next = newvfsconf;
139: };
140:
141: /* Based on vfs_op_init and ... */
142: opv_desc_vector_p = volfs_vnodeop_opv_desc.opv_desc_vector_p;
143:
144: DBG_VOP(("load_volfs: Allocating and initializing VNode ops vector...\n"));
145:
146: /*
147: * Allocate and init the vector.
148: * Also handle backwards compatibility.
149: */
150: MALLOC(*opv_desc_vector_p, PFI *, vfs_opv_numops*sizeof(PFI), M_TEMP, M_WAITOK);
151:
152: bzero (*opv_desc_vector_p, vfs_opv_numops*sizeof(PFI));
153:
154: opv_desc_vector = *opv_desc_vector_p;
155: for (j=0; volfs_vnodeop_opv_desc.opv_desc_ops[j].opve_op; j++) {
156: opve_descp = &(volfs_vnodeop_opv_desc.opv_desc_ops[j]);
157:
158: /*
159: * Sanity check: is this operation listed
160: * in the list of operations? We check this
161: * by seeing if its offest is zero. Since
162: * the default routine should always be listed
163: * first, it should be the only one with a zero
164: * offset. Any other operation with a zero
165: * offset is probably not listed in
166: * vfs_op_descs, and so is probably an error.
167: *
168: * A panic here means the layer programmer
169: * has committed the all-too common bug
170: * of adding a new operation to the layer's
171: * list of vnode operations but
172: * not adding the operation to the system-wide
173: * list of supported operations.
174: */
175: if (opve_descp->opve_op->vdesc_offset == 0 &&
176: opve_descp->opve_op->vdesc_offset != VOFFSET(vop_default)) {
177: DBG_VOP(("load_volfs: operation %s not listed in %s.\n",
178: opve_descp->opve_op->vdesc_name,
179: "vfs_op_descs"));
180: panic ("load_volfs: bad operation");
181: }
182: /*
183: * Fill in this entry.
184: */
185: opv_desc_vector[opve_descp->opve_op->vdesc_offset] =
186: opve_descp->opve_impl;
187: }
188:
189: /*
190: * Finally, go back and replace unfilled routines
191: * with their default. (Sigh, an O(n^3) algorithm. I
192: * could make it better, but that'd be work, and n is small.)
193: */
194: opv_desc_vector_p = volfs_vnodeop_opv_desc.opv_desc_vector_p;
195:
196: /*
197: * Force every operations vector to have a default routine.
198: */
199: opv_desc_vector = *opv_desc_vector_p;
200: if (opv_desc_vector[VOFFSET(vop_default)]==NULL) {
201: panic("load_vp;fs: operation vector without default routine.");
202: }
203: for (j = 0;j<vfs_opv_numops; j++)
204: if (opv_desc_vector[j] == NULL)
205: opv_desc_vector[j] =
206: opv_desc_vector[VOFFSET(vop_default)];
207:
208: DBG_VOP(("load_volfs: calling volfs_init()...\n"));
209: volfs_init(newvfsconf);
210: };
211: }
212:
213: /*
214: * VFS Operations.
215: *
216: * mount system call
217: */
218: int
219: volfs_mount(mp, path, data, ndp, p)
220: register struct mount *mp;
221: char *path;
222: caddr_t data;
223: struct nameidata *ndp;
224: struct proc *p;
225: {
226: struct volfs_mntdata *priv_mnt_data;
227: struct vnode *root_vp;
228: struct volfs_vndata *priv_vn_data;
229: int error;
230: size_t size;
231:
232: DBG_VOP(("volfs_mount called\n"));
233: MALLOC(priv_mnt_data, struct volfs_mntdata *, sizeof(struct volfs_mntdata),
234: M_VOLFSMNT, M_WAITOK);
235: DBG_VOP(("MALLOC succeeded\n"));
236: LIST_INIT(&priv_mnt_data->volfs_fsvnodes);
237: DBG_VOP(("LIST_INIT succeeded\n"));
238:
239: mp->mnt_data = (void *)priv_mnt_data;
240: strcpy(mp->mnt_stat.f_fstypename, "volfs");
241: (void) copyinstr(path, mp->mnt_stat.f_mntonname, sizeof(mp->mnt_stat.f_mntonname) - 1, &size);
242: strcpy(mp->mnt_stat.f_mntfromname, "<volfs>");
243:
244: /* Set up the root vnode for fast reference in the future.
245: Note that the root is maintained unlocked but with a pos. ref count until unmount. */
246:
247: MALLOC(priv_vn_data, struct volfs_vndata *, sizeof(struct volfs_vndata), M_VOLFSNODE, M_WAITOK);
248: error = getnewvnode(VT_VOLFS, mp, volfs_vnodeop_p, &root_vp);
249: if (error != 0)
250: {
251: FREE(priv_mnt_data, M_VOLFSMNT);
252: FREE(priv_vn_data, M_VOLFSNODE);
253: DBG_VOP(("getnewvnode failed with error code %d\n", error));
254: return(error);
255: }
256: root_vp->v_type = VDIR;
257: root_vp->v_flag = VROOT;
258: lockinit(&priv_vn_data->lock, PINOD, "volfsnode", 0, 0);
259: priv_vn_data->vnode_type = VOLFS_ROOT;
260: priv_vn_data->nodeID = 0;
261: priv_vn_data->fs_mount = mp;
262: root_vp->v_data = priv_vn_data;
263:
264: priv_mnt_data->volfs_rootvp = root_vp;
265:
266: return (0);
267: }
268:
269: int
270: volfs_start(mp, flags, p)
271: struct mount * mp;
272: int flags;
273: struct proc * p;
274: {
275: DBG_VOP(("volfs_start called\n"));
276: return (0);
277: }
278:
279: /*
280: * Return the root of a filesystem. For volfs the root vnode is a directory
281: * containing the list of all filesystems volfs can work with.
282: */
283: int
284: volfs_root(mp, vpp)
285: struct mount *mp;
286: struct vnode **vpp;
287: {
288: struct volfs_mntdata *priv_data;
289: // struct volfs_vndata *priv_vn_data;
290: // int error;
291:
292: DBG_VOP(("volfs_root called\n"));
293: priv_data = (struct volfs_mntdata *)mp->mnt_data;
294:
295: if (priv_data->volfs_rootvp) {
296: vref(priv_data->volfs_rootvp);
297: VOP_LOCK(priv_data->volfs_rootvp, LK_EXCLUSIVE, current_proc());
298: *vpp = priv_data->volfs_rootvp;
299: } else {
300: panic("volfs: root vnode missing!");
301: };
302:
303: DBG_VOP(("volfs_root returned with "));
304: DBG_VOP_PRINT_VNODE_INFO(*vpp);DBG_VOP(("\n"));
305:
306: return(0);
307: }
308:
309: int
310: volfs_quotactl(mp, cmds, uid, arg, p)
311: struct mount *mp;
312: int cmds;
313: uid_t uid;
314: caddr_t arg;
315: struct proc * p;
316: {
317: DBG_VOP(("volfs_quotactl called\n"));
318: return (0);
319: }
320:
321: /*
322: * unmount system call
323: */
324: int
325: volfs_unmount(mp, mntflags, p)
326: struct mount *mp;
327: int mntflags;
328: struct proc *p;
329: {
330: struct volfs_mntdata *priv_data;
331: struct vnode *root_vp;
332: int retval;
333:
334: DBG_VOP(("volfs_unmount called\n"));
335: priv_data = (struct volfs_mntdata *)mp->mnt_data;
336:
337: root_vp = priv_data->volfs_rootvp;
338: retval = vflush(mp, root_vp, 0);
339: if (retval) goto Err_Exit;
340:
341: /* Free the root vnode.
342: Note that there's no need to vget() or vref() it before locking it here:
343: the ref. count has been maintained at +1 ever since mount time. */
344: if (root_vp) {
345: retval = vn_lock(root_vp, LK_EXCLUSIVE, p);
346: if (retval) goto Err_Exit;
347: if (root_vp->v_usecount > 1) {
348: DBG_VOP(("VOLFS ERROR: root vnode = %x, usecount = %d\n", (int)root_vp, priv_data->volfs_rootvp->v_usecount));
349: VOP_UNLOCK(root_vp, 0, p);
350: retval = EBUSY;
351: goto Err_Exit;
352: };
353:
354: priv_data->volfs_rootvp = NULL;
355: vput(root_vp); /* This drops volfs's own refcount */
356: vgone(root_vp);
357: };
358:
359: /* All vnodes should be gone, and no errors, clean up the last */
360: /* XXX DBG_ASSERT(mp->mnt_vnodelist.lh_first == NULL); */
361: /* XXX DBG_ASSERT(retval == 0); */
362:
363: mp->mnt_data = NULL;
364: FREE(priv_data, M_VOLFSMNT);
365:
366: Err_Exit:
367:
368: return(retval);
369: }
370:
371: /*
372: * Get file system statistics.
373: */
374: int
375: volfs_statfs(mp, sbp, p)
376: struct mount *mp;
377: register struct statfs *sbp;
378: struct proc *p;
379: {
380: DBG_VOP(("volfs_statfs called\n"));
381: sbp->f_bsize = 512;
382: sbp->f_iosize = 512;
383: sbp->f_blocks = 1024; // lies, darn lies and virtual file systems
384: sbp->f_bfree = 0; // Nope, can't write here!
385: sbp->f_bavail = 0;
386: sbp->f_files = 0; // Hmmm...maybe later
387: sbp->f_ffree = 0;
388: return (0);
389: }
390:
391: /*
392: * volfs doesn't have any data and you can't write into any of the volfs
393: * structures, so don't do anything
394: */
395: int
396: volfs_sync(mp, waitfor, cred, p)
397: struct mount *mp;
398: int waitfor;
399: struct ucred *cred;
400: struct proc *p;
401: {
402: // DBG_VOP(("volfs_sync called\n"));
403: return 0;
404: }
405: /*
406: * Look up a FFS dinode number to find its incore vnode, otherwise read it
407: * in from disk. If it is in core, wait for the lock bit to clear, then
408: * return the inode locked. Detection and handling of mount points must be
409: * done by the calling routine.
410: */
411: int
412: volfs_vget(mp, ino, vpp)
413: struct mount *mp;
414: void *ino;
415: struct vnode **vpp;
416: {
417: // DBG_VOP(("volfs_vget called\n"));
418: return(0);
419: }
420: /*
421: * File handle to vnode
422: *
423: * Have to be really careful about stale file handles:
424: * - check that the inode number is valid
425: * - call ffs_vget() to get the locked inode
426: * - check for an unallocated inode (i_mode == 0)
427: * - check that the given client host has export rights and return
428: * those rights via. exflagsp and credanonp
429: */
430: int
431: volfs_fhtovp(mp, fhp, nam, vpp, exflagsp, credanonp)
432: register struct mount *mp;
433: struct fid *fhp;
434: struct mbuf *nam;
435: struct vnode **vpp;
436: int *exflagsp;
437: struct ucred **credanonp;
438: {
439: DBG_VOP(("volfs_fhtovp called\n"));
440: return(0);
441: }
442: /*
443: * Vnode pointer to File handle
444: */
445: /* ARGSUSED */
446: int
447: volfs_vptofh(vp, fhp)
448: struct vnode *vp;
449: struct fid *fhp;
450: {
451: DBG_VOP(("volfs_vptofh called\n"));
452: return(0);
453: }
454: /*
455: * Initialize the filesystem
456: */
457: int
458: volfs_init(vfsp)
459: struct vfsconf *vfsp;
460: {
461: DBG_VOP(("volfs_init called\n"));
462: return (0);
463: }
464:
465: /*
466: * fast filesystem related variables.
467: */
468: int
469: volfs_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p)
470: int *name;
471: u_int namelen;
472: void *oldp;
473: size_t *oldlenp;
474: void *newp;
475: size_t newlen;
476: struct proc *p;
477: {
478: DBG_VOP(("volfs_sysctl called\n"));
479: return (EOPNOTSUPP);
480: }
481:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.