]> git.saurik.com Git - apple/xnu.git/blame - bsd/miscfs/synthfs/synthfs_vfsops.c
xnu-792.25.20.tar.gz
[apple/xnu.git] / bsd / miscfs / synthfs / synthfs_vfsops.c
CommitLineData
1c79356b 1/*
5d5c5d0d
A
2 * Copyright (c) 2000-2004 Apple Computer, Inc. All rights reserved.
3 *
6601e61a 4 * @APPLE_LICENSE_HEADER_START@
1c79356b 5 *
6601e61a
A
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.
8f6c56a5 11 *
6601e61a
A
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
8f6c56a5
A
14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
6601e61a
A
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.
8f6c56a5 19 *
6601e61a 20 * @APPLE_LICENSE_HEADER_END@
1c79356b
A
21 */
22/* Copyright (c) 1998 Apple Computer, Inc. All Rights Reserved */
23/*
24 * Change History:
25 *
26 * 17-Aug-1999 Pat Dirks New today.
27 *
28 */
29
30#include <sys/param.h>
31#include <sys/systm.h>
32#include <sys/namei.h>
33#include <sys/filedesc.h>
91447636 34#include <sys/proc_internal.h>
1c79356b
A
35#include <sys/kernel.h>
36#include <mach/machine/vm_types.h>
91447636 37#include <sys/vnode_internal.h>
1c79356b 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 <sys/attr.h>
91447636 47#include <sys/uio_internal.h>
1c79356b
A
48
49#include <miscfs/specfs/specdev.h>
50
51#include "synthfs.h"
52
53#define LOADABLE_FS 0
54
55typedef int (*PFI)();
56
57struct vfsops synthfs_vfsops = {
58 synthfs_mount,
59 synthfs_start,
60 synthfs_unmount,
61 synthfs_root,
91447636
A
62 NULL, /* quotactl */
63 synthfs_vfs_getattr,
1c79356b
A
64 synthfs_sync,
65 synthfs_vget,
66 synthfs_fhtovp,
67 synthfs_vptofh,
68 synthfs_init,
69 synthfs_sysctl
70};
71
72#define ROOTMPMODE 0755
73#define ROOTPLACEHOLDERMODE 0700
91447636 74static char synthfs_fs_name[MFSTYPENAMELEN] = "synthfs";
1c79356b
A
75static char synthfs_fake_mntfromname[] = "<synthfs>";
76
77
78extern struct vnodeopv_desc synthfs_vnodeop_opv_desc;
79
80/* The following refer to kernel global variables used in the loading/initialization: */
81extern int maxvfsslots; /* Total number of slots in the system's vfsconf table */
82extern int maxvfsconf; /* The highest fs type number [old-style ID] in use [dispite its name] */
83extern int vfs_opv_numops; /* The total number of defined vnode operations */
84
85int vn_mkdir(struct proc *p, char *path, int mode);
86int vn_symlink(struct proc *p, char *path, char *link);
87
88
89
90
91#if LOADABLE_FS
92void
93synthfs_load(int loadArgument) {
91447636 94 /* Should use vfs_fsadd kpi */
1c79356b
A
95}
96
97
98
99int synthfs_unload(void) {
1c79356b 100
91447636 101 /* should use fs_fsremove kpi */
1c79356b
A
102 return 0;
103}
104#endif
105
106
107
108/*
109 * VFS Operations.
110 *
111 * mount system call
112 */
113int
91447636 114synthfs_mount_fs(struct mount *mp, vnode_t devvp, __unused user_addr_t data, struct proc *p)
1c79356b
A
115{
116 struct synthfs_mntdata *priv_mnt_data;
117 int error;
118 size_t size;
119
120 DBG_VOP(("synthfs_mount_fs called.\n"));
121 MALLOC(priv_mnt_data, struct synthfs_mntdata *, sizeof(struct synthfs_mntdata), M_SYNTHFS, M_WAITOK);
122 DBG_VOP(("MALLOC succeeded...\n"));
123
91447636
A
124 strncpy(mp->mnt_vfsstat.f_fstypename, synthfs_fs_name, sizeof(mp->mnt_vfsstat.f_fstypename));
125 strncpy(mp->mnt_vfsstat.f_mntfromname, synthfs_fake_mntfromname, sizeof(mp->mnt_vfsstat.f_mntfromname));
1c79356b
A
126 priv_mnt_data->synthfs_mounteddev = (dev_t)0;
127 priv_mnt_data->synthfs_nextid = FIRST_SYNTHFS_ID;
128 priv_mnt_data->synthfs_filecount = 0;
129 priv_mnt_data->synthfs_dircount = 0;
130 priv_mnt_data->synthfs_encodingsused = 0x00000001;
131
132 /*
133 Set up the root vnode for fast reference in the future.
134 Note that synthfs_new_directory() returns the vnode with a refcount of +2.
135 The root vnode's refcount is maintained unlocked but with a pos. ref count until unmount.
136 */
137 error = synthfs_new_directory(mp, NULL, "", ROOT_DIRID, (S_IRWXU|S_IRWXG|S_IROTH|S_IXOTH), p, &priv_mnt_data->synthfs_rootvp);
138 if (error) {
139 DBG_VOP(("Attempt to create root directory failed with error %d.\n", error));
140 return error;
141 };
142 priv_mnt_data->synthfs_rootvp->v_flag |= VROOT;
143
144 priv_mnt_data->synthfs_mp = mp;
145 mp->mnt_data = (void *)priv_mnt_data;
146
147 /* Drop the freshly acquired reference on the root, leaving v_usecount=1 to prevent
148 the vnode from beeing freed: */
91447636 149 vnode_put(priv_mnt_data->synthfs_rootvp);
1c79356b
A
150
151 return (0);
152}
153
154
155
156int
91447636 157synthfs_mount(mp, devvp, data, context)
1c79356b 158 register struct mount *mp;
91447636
A
159 vnode_t devvp;
160 user_addr_t data;
161 vfs_context_t context;
1c79356b
A
162{
163 size_t size;
164
91447636 165 return (synthfs_mount_fs(mp, devvp, data, vfs_context_proc(context)));
1c79356b
A
166}
167
168
169
170
171
172
173/*
174 * Initialize the filesystem
175 */
176int
177synthfs_init(vfsp)
178 struct vfsconf *vfsp;
179{
180 DBG_VOP(("synthfs_init called.\n"));
181 return 0;
182}
183
184int
91447636 185synthfs_start(mp, flags, context)
1c79356b
A
186struct mount * mp;
187int flags;
91447636 188vfs_context_t context;
1c79356b
A
189{
190 DBG_VOP(("synthfs_start called.\n"));
191 return 0;
192}
193
194/*
195 * Return the root of a filesystem.
196 */
197int
91447636 198synthfs_root(mp, vpp, context)
1c79356b
A
199 struct mount *mp;
200 struct vnode **vpp;
91447636 201 vfs_context_t context;
1c79356b
A
202{
203 unsigned long root_nodeid = ROOT_DIRID;
204
205 DBG_VOP(("synthfs_root called.\n"));
206
207 *vpp = VFSTOSFS(mp)->synthfs_rootvp;
91447636 208 return vnode_get(VFSTOSFS(mp)->synthfs_rootvp);
1c79356b
A
209}
210
211/*
212 * unmount system call
213 */
214int
91447636 215synthfs_unmount(mp, mntflags, context)
1c79356b
A
216 struct mount *mp;
217 int mntflags;
91447636 218 vfs_context_t context;
1c79356b
A
219{
220 struct synthfs_mntdata *synth;
221 struct vnode *root_vp;
222 int retval;
223
224 DBG_VOP(("synthfs_unmount called.\n"));
225 synth = (struct synthfs_mntdata *)mp->mnt_data;
226
227 root_vp = synth->synthfs_rootvp;
228 retval = vflush(mp, root_vp, (mntflags & MNT_FORCE) ? FORCECLOSE : 0);
229 if (retval && ((mntflags & MNT_FORCE) == 0)) goto Err_Exit;
230
231 /* Free the root vnode.
1c79356b
A
232 the ref. count has been maintained at +1 ever since mount time. */
233 if (root_vp) {
1c79356b
A
234 if ((mntflags & MNT_FORCE) == 0) {
235 if (retval) goto Err_Exit;
236
237 if (root_vp->v_usecount > 1) {
238 DBG_VOP(("synthfs ERROR: root vnode = %x, usecount = %d\n", (int)root_vp, synth->synthfs_rootvp->v_usecount));
1c79356b
A
239 retval = EBUSY;
240 goto Err_Exit;
241 };
242 };
243
244 synth->synthfs_rootvp = NULL;
245
246 if (retval == 0) {
91447636
A
247 vnode_get(root_vp);
248 vnode_rele(root_vp);
249 vnode_recycle(root_vp);
250 vnode_put(root_vp); /* This drops synthfs's own refcount */
1c79356b
A
251 };
252 };
253
254 /* All vnodes should be gone, and no errors, clean up the last */
255
256 mp->mnt_data = NULL;
257 FREE(synth, M_SYNTHFS);
258
259Err_Exit:
260
261 if (mntflags & MNT_FORCE) retval = 0;
262
263 return(retval);
264}
265
266/*
267 * Get file system statistics.
268 */
269int
91447636 270synthfs_vfs_getattr(mount_t mp, struct vfs_attr *fsap, vfs_context_t context)
1c79356b 271{
91447636
A
272 struct synthfs_mntdata *synthfs_mp = VFSTOSFS(mp);
273 DBG_VOP(("synthfs_vfs_getattr called.\n"));
274
275 VFSATTR_RETURN(fsap, f_bsize, 512);
276 VFSATTR_RETURN(fsap, f_iosize, 512);
277 VFSATTR_RETURN(fsap, f_blocks, 1024);
278 VFSATTR_RETURN(fsap, f_bfree, 0);
279 VFSATTR_RETURN(fsap, f_bavail, 0);
280 VFSATTR_RETURN(fsap, f_bused, 1024);
281 VFSATTR_RETURN(fsap, f_files, synthfs_mp->synthfs_filecount + synthfs_mp->synthfs_dircount);
282 VFSATTR_RETURN(fsap, f_ffree, 0);
283 VFSATTR_RETURN(fsap, f_fssubtype, 0);
284
285 return 0;
1c79356b
A
286}
287
288/*
289 * synthfs doesn't have any data or backing store and you can't write into any of the synthfs
290 * structures, so don't do anything
291 */
292int
91447636 293synthfs_sync(mp, waitfor, context)
1c79356b
A
294 struct mount *mp;
295 int waitfor;
91447636 296 vfs_context_t context;
1c79356b
A
297{
298// DBG_VOP(("synthfs_sync called\n"));
299 return 0;
300}
301/*
302 * Look up a synthfs node by node number.
303 */
304int
91447636 305synthfs_vget(mp, ino, vpp, context)
1c79356b 306 struct mount *mp;
91447636 307 ino64_t ino;
1c79356b 308 struct vnode **vpp;
91447636 309 vfs_context_t context;
1c79356b
A
310{
311 struct vnode *vp;
91447636 312 int vid = 0;
1c79356b
A
313
314// DBG_VOP(("synthfs_vget called\n"));
315
316 /* Check for unmount in progress */
317 if (mp->mnt_kern_flag & MNTK_UNMOUNT) {
318 *vpp = NULL;
319 return (EPERM);
320 }
321
322loop:
91447636
A
323 TAILQ_FOREACH(vp, &mp->mnt_vnodelist, v_mntvnodes) {
324 if (VTOS(vp)->s_nodeid == (unsigned long)ino) {
325 /*
326 * doing a vnode_getwithvid isn't technically
327 * necessary since synthfs is an unsafe filesystem
328 * and we're running behind a funnel at this point
329 * however, vnode_get always succeeds, which isn't
330 * what we want if this vnode is in the process of
331 * being terminated
332 */
333 vid = vnode_vid(vp);
334
335 if (vnode_getwithvid(vp, vid) != 0) {
336 goto loop;
337 };
1c79356b
A
338 *vpp = vp;
339 return 0;
340 };
341 };
342 *vpp = NULL;
343 return -1;
344}
345
346/*
347 * fast filesystem related variables.
348 */
349int
91447636
A
350synthfs_sysctl(int *name, u_int namelen, user_addr_t oldp, size_t *oldlenp,
351 user_addr_t newp, size_t newlen, vfs_context_t context)
1c79356b
A
352{
353 DBG_VOP(("synthfs_sysctl called.\n"));
91447636 354 return (ENOTSUP);
1c79356b
A
355}
356
357/*
358 * File handle to vnode
359 *
360 */
361int
91447636 362synthfs_fhtovp(mp, fhlen, fhp, vpp, context)
1c79356b 363 register struct mount *mp;
91447636
A
364 int fhlen;
365 unsigned char *fhp;
1c79356b 366 struct vnode **vpp;
91447636 367 vfs_context_t context;
1c79356b
A
368{
369 DBG_VOP(("synthfs_fhtovp called.\n"));
91447636 370 return ENOTSUP;
1c79356b
A
371}
372
373/*
374 * Vnode pointer to File handle
375 */
376/* ARGSUSED */
377int
91447636 378synthfs_vptofh(vp, fhlenp, fhp, context)
1c79356b 379 struct vnode *vp;
91447636
A
380 int *fhlenp;
381 unsigned char *fhp;
382 vfs_context_t context;
1c79356b
A
383{
384 DBG_VOP(("synthfs_vptofh called.\n"));
91447636 385 return ENOTSUP;
1c79356b
A
386}
387
388
389
390
391
392
393int
91447636
A
394vn_mkdir(struct proc *p, char *path, int mode)
395{
1c79356b
A
396 struct nameidata nd;
397 struct vnode *vp;
91447636
A
398 struct vnode_attr va;
399 struct vfs_context context;
1c79356b
A
400 int error;
401
91447636 402 context.vc_proc = p;
0c530ab8 403 context.vc_ucred = kauth_cred_proc_ref(p); /* XXX kauth_cred_get() ??? proxy */
91447636
A
404
405 NDINIT(&nd, CREATE, LOCKPARENT, UIO_SYSSPACE32, CAST_USER_ADDR_T(path), &context);
406 error = namei(&nd);
407 if (error) {
1c79356b 408 DBG_VOP(("vn_mkdir: error from namei, error = %d.\n", error));
0c530ab8 409 kauth_cred_unref(&context.vc_ucred);
1c79356b
A
410 return (error);
411 };
412 vp = nd.ni_vp;
91447636
A
413
414 if (vp == NULL) {
415 VATTR_INIT(&va);
416 VATTR_SET(&va, va_type, VDIR);
417 VATTR_SET(&va, va_mode, (mode & ACCESSPERMS) &~ p->p_fd->fd_cmask);
418
419 error = vn_create(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &va, 0, &context);
420 if (error)
421 DBG_VOP(("vn_mkdir: error from vnop_mkdir (%d).\n", error));
422 } else {
1c79356b 423 DBG_VOP(("vn_mkdir: target already exists; returning EEXIST.\n"));
91447636 424 error = EEXIST;
1c79356b 425 }
91447636
A
426 vnode_put(nd.ni_dvp);
427 if (nd.ni_vp)
428 vnode_put(nd.ni_vp);
429 nameidone(&nd);
430
0c530ab8 431 kauth_cred_unref(&context.vc_ucred);
1c79356b
A
432 return (error);
433}
434
435
436
437int
438vn_symlink(struct proc *p, char *path, char *link) {
439 struct nameidata nd;
91447636
A
440 struct vnode_attr va;
441 struct vfs_context context;
1c79356b
A
442 int error;
443
91447636 444 context.vc_proc = p;
0c530ab8 445 context.vc_ucred = kauth_cred_proc_ref(p); /* XXX kauth_cred_get() ??? proxy */
91447636
A
446
447 NDINIT(&nd, CREATE, LOCKPARENT, UIO_SYSSPACE32, CAST_USER_ADDR_T(link), &context);
0c530ab8
A
448 if ((error = namei(&nd))) {
449 kauth_cred_unref(&context.vc_ucred);
450 return error;
451 }
91447636
A
452
453 if (nd.ni_vp == NULL) {
454 VATTR_INIT(&va);
455 VATTR_SET(&va, va_type, VLNK);
456 VATTR_SET(&va, va_mode, ACCESSPERMS &~ p->p_fd->fd_cmask);
457
458 error = VNOP_SYMLINK(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &va, path, &context);
459 } else
460 error = EEXIST;
461
462 vnode_put(nd.ni_dvp);
463 if (nd.ni_vp)
464 vnode_put(nd.ni_vp);
465 nameidone(&nd);
466
0c530ab8 467 kauth_cred_unref(&context.vc_ucred);
91447636 468 return (error);
1c79356b
A
469}
470
471