Merge 1.8.0~pre4 packaging into master
[pkg-k5-afs_openafs.git] / src / afs / DARWIN / osi_vfsops.c
blob064410decb5297c31ddc464ac1780bc3c50126ba
1 /*
2 * Portions Copyright (c) 2003 Apple Computer, Inc. All rights reserved.
3 */
4 #include <afsconfig.h>
5 #include <afs/param.h>
8 #include <afs/sysincludes.h> /* Standard vendor system headers */
9 #include <afsincludes.h> /* Afs-based standard headers */
10 #include <afs/afs_stats.h> /* statistics */
11 #include <sys/malloc.h>
12 #include <sys/namei.h>
13 #include <sys/conf.h>
14 #ifndef AFS_DARWIN80_ENV
15 #include <sys/syscall.h>
16 #endif
17 #include <sys/sysctl.h>
18 #include "../afs/sysctl.h"
20 #ifndef M_UFSMNT
21 #define M_UFSMNT M_TEMP /* DARWIN80 MALLOC doesn't look at the type anyway */
22 #endif
24 struct vcache *afs_globalVp = 0;
25 struct mount *afs_globalVFS = 0;
26 int afs_vfs_typenum;
28 int
29 afs_quotactl()
31 return ENOTSUP;
34 int
35 afs_fhtovp(struct mount *mp, struct fid *fhp, struct vnode **vpp)
37 return (EINVAL);
40 int
41 afs_vptofh(struct vnode *vp, struct fid *fhp)
43 return (EINVAL);
46 #ifdef AFS_DARWIN80_ENV
47 #define CTX_TYPE vfs_context_t
48 #define CTX_PROC_CONVERT(C) vfs_context_proc((C))
49 #define STATFS_TYPE struct vfsstatfs
50 #else
51 #define CTX_TYPE struct proc *
52 #define CTX_PROC_CONVERT(C) (C)
53 #define STATFS_TYPE struct statfs
54 #define vfs_statfs(VFS) &(VFS)->mnt_stat
55 #endif
56 #define PROC_DECL(out,in) struct proc *out = CTX_PROC_CONVERT(in)
58 int
59 afs_start(struct mount *mp, int flags, CTX_TYPE p)
61 return (0); /* nothing to do. ? */
64 int
65 afs_statfs(struct mount *mp, STATFS_TYPE *abp, CTX_TYPE ctx);
66 #ifdef AFS_DARWIN80_ENV
67 int
68 afs_mount(struct mount *mp, vnode_t *devvp, user_addr_t data, vfs_context_t ctx)
69 #else
70 int
71 afs_mount(struct mount *mp, char *path, caddr_t data, struct nameidata *ndp, CTX_TYPE ctx)
72 #endif
74 /* ndp contains the mounted-from device. Just ignore it.
75 * we also don't care about our proc struct. */
76 size_t size;
77 int error;
78 #ifdef AFS_DARWIN80_ENV
79 struct vfsioattr ioattr;
80 /* vfs_statfs advertised as RO, but isn't */
81 /* new api will be needed to initialize this information (nfs needs to
82 set mntfromname too) */
83 #endif
84 STATFS_TYPE *mnt_stat = vfs_statfs(mp);
86 if (vfs_isupdate(mp))
87 return EINVAL;
89 AFS_GLOCK();
90 AFS_STATCNT(afs_mount);
92 if (data == 0 && afs_globalVFS) { /* Don't allow remounts. */
93 AFS_GUNLOCK();
94 return (EBUSY);
97 afs_globalVFS = mp;
98 #ifdef AFS_DARWIN80_ENV
99 vfs_ioattr(mp, &ioattr);
100 ioattr.io_devblocksize = (16 * 32768);
101 vfs_setioattr(mp, &ioattr);
102 /* f_iosize is handled in VFS_GETATTR */
103 #else
104 mp->vfs_bsize = 8192;
105 mp->mnt_stat.f_iosize = 8192;
106 #endif
107 vfs_getnewfsid(mp);
109 #ifndef AFS_DARWIN80_ENV
110 (void)copyinstr(path, mp->mnt_stat.f_mntonname, MNAMELEN - 1, &size);
111 memset(mp->mnt_stat.f_mntonname + size, 0, MNAMELEN - size);
112 #endif
113 memset(mnt_stat->f_mntfromname, 0, MNAMELEN);
115 if (data == 0) {
116 strcpy(mnt_stat->f_mntfromname, "AFS");
117 /* null terminated string "AFS" will fit, just leave it be. */
118 vfs_setfsprivate(mp, NULL);
119 } else {
120 struct VenusFid *rootFid = NULL;
121 struct volume *tvp;
122 char volName[MNAMELEN];
124 (void)copyinstr(data, volName, MNAMELEN - 1, &size);
125 memset(volName + size, 0, MNAMELEN - size);
127 if (volName[0] == 0) {
128 strcpy(mnt_stat->f_mntfromname, "AFS");
129 vfs_setfsprivate(mp, &afs_rootFid);
130 } else {
131 struct cell *localcell = afs_GetPrimaryCell(READ_LOCK);
132 if (localcell == NULL) {
133 AFS_GUNLOCK();
134 return ENODEV;
137 /* Set the volume identifier to "AFS:volume.name" */
138 snprintf(mnt_stat->f_mntfromname, MNAMELEN - 1, "AFS:%s",
139 volName);
140 tvp =
141 afs_GetVolumeByName(volName, localcell->cellNum, 1,
142 (struct vrequest *)0, READ_LOCK);
144 if (tvp) {
145 int volid = (tvp->roVol ? tvp->roVol : tvp->volume);
146 MALLOC(rootFid, struct VenusFid *, sizeof(*rootFid), M_UFSMNT,
147 M_WAITOK);
148 rootFid->Cell = localcell->cellNum;
149 rootFid->Fid.Volume = volid;
150 rootFid->Fid.Vnode = 1;
151 rootFid->Fid.Unique = 1;
152 } else {
153 AFS_GUNLOCK();
154 return ENODEV;
157 vfs_setfsprivate(mp, &rootFid);
160 #ifdef AFS_DARWIN80_ENV
161 afs_vfs_typenum=vfs_typenum(mp);
162 vfs_setauthopaque(mp);
163 vfs_setauthopaqueaccess(mp);
164 #else
165 strcpy(mp->mnt_stat.f_fstypename, "afs");
166 #endif
167 AFS_GUNLOCK();
168 (void)afs_statfs(mp, mnt_stat, ctx);
169 return 0;
173 afs_unmount(struct mount *mp, int flags, CTX_TYPE ctx)
175 void *mdata = vfs_fsprivate(mp);
176 AFS_GLOCK();
177 AFS_STATCNT(afs_unmount);
179 if (mdata != (qaddr_t) - 1) {
180 if (mdata != NULL) {
181 vfs_setfsprivate(mp, (qaddr_t) - 1);
182 FREE(mdata, M_UFSMNT);
183 } else {
184 if (flags & MNT_FORCE) {
185 if (afs_globalVp) {
186 #ifdef AFS_DARWIN80_ENV
187 afs_PutVCache(afs_globalVp);
188 #else
189 AFS_GUNLOCK();
190 vrele(AFSTOV(afs_globalVp));
191 AFS_GLOCK();
192 #endif
194 afs_globalVp = NULL;
195 AFS_GUNLOCK();
196 vflush(mp, NULLVP, FORCECLOSE/*0*/);
197 AFS_GLOCK();
198 afs_globalVFS = 0;
199 afs_shutdown();
200 } else {
201 AFS_GUNLOCK();
202 return EBUSY;
205 vfs_clearflags(mp, MNT_LOCAL);
208 AFS_GUNLOCK();
210 return 0;
213 #ifdef AFS_DARWIN80_ENV
215 afs_root(struct mount *mp, struct vnode **vpp, vfs_context_t ctx)
216 #else
218 afs_root(struct mount *mp, struct vnode **vpp)
219 #endif
221 void *mdata = vfs_fsprivate(mp);
222 int error;
223 struct vrequest treq;
224 struct vcache *tvp = 0;
225 struct vcache *gvp;
226 int needref=0;
227 #ifdef AFS_DARWIN80_ENV
228 struct ucred *cr = vfs_context_ucred(ctx);
229 #else
230 struct proc *p = current_proc();
231 struct ucred _cr;
232 struct ucred *cr = &_cr;
234 pcred_readlock(p);
235 _cr = *p->p_cred->pc_ucred;
236 pcred_unlock(p);
237 #endif
238 AFS_GLOCK();
239 AFS_STATCNT(afs_root);
241 again:
242 if (mdata == NULL && afs_globalVp
243 && (afs_globalVp->f.states & CStatd)) {
244 tvp = afs_globalVp;
245 error = 0;
246 needref=1;
247 } else if (mdata == (qaddr_t) - 1) {
248 error = ENOENT;
249 } else {
250 struct VenusFid *rootFid = (mdata == NULL)
251 ? &afs_rootFid : (struct VenusFid *)mdata;
253 if (!(error = afs_InitReq(&treq, cr)) && !(error = afs_CheckInit())) {
254 tvp = afs_GetVCache(rootFid, &treq, NULL, NULL);
255 #ifdef AFS_DARWIN80_ENV
256 if (tvp) {
257 AFS_GUNLOCK();
258 error = afs_darwin_finalizevnode(tvp, NULL, NULL, 1, 0);
259 AFS_GLOCK();
260 if (error)
261 tvp = NULL;
262 else
263 /* re-acquire the usecount that finalizevnode disposed of */
264 vnode_ref(AFSTOV(tvp));
266 #endif
267 /* we really want this to stay around */
268 if (tvp) {
269 if (mdata == NULL) {
270 gvp = afs_globalVp;
271 afs_globalVp = tvp;
272 if (gvp) {
273 afs_PutVCache(gvp);
274 if (tvp != afs_globalVp) {
275 /* someone else got there before us! */
276 afs_PutVCache(tvp);
277 tvp = 0;
278 goto again;
281 needref=1;
283 } else
284 error = EIO;
287 if (tvp) {
288 #ifndef AFS_DARWIN80_ENV /* KPI callers don't need a usecount reference */
289 osi_vnhold(tvp, 0);
290 AFS_GUNLOCK();
291 vn_lock(AFSTOV(tvp), LK_EXCLUSIVE | LK_RETRY, p);
292 AFS_GLOCK();
293 #endif
295 if (needref)
296 #ifdef AFS_DARWIN80_ENV
297 /* This iocount is for the caller. the initial iocount
298 * is for the eventual afs_PutVCache. for mdata != null,
299 * there will not be a PutVCache, so the caller gets the
300 * initial (from GetVCache or finalizevnode) iocount
302 vnode_get(AFSTOV(tvp));
303 #else
305 #endif
307 if (mdata == NULL)
308 afs_globalVFS = mp;
310 *vpp = AFSTOV(tvp);
311 #ifndef AFS_DARWIN80_ENV
312 AFSTOV(tvp)->v_flag |= VROOT;
313 AFSTOV(tvp)->v_vfsp = mp;
314 #endif
317 afs_Trace2(afs_iclSetp, CM_TRACE_VFSROOT, ICL_TYPE_POINTER, *vpp,
318 ICL_TYPE_INT32, error);
319 AFS_GUNLOCK();
320 return error;
323 #ifndef AFS_DARWIN80_ENV /* vget vfsop never had this prototype AFAIK */
325 afs_vget(struct mount *mp, int lfl, struct vnode *vp)
327 int error;
328 //printf("vget called. help!\n");
329 if (vp->v_usecount < 0) {
330 vprint("bad usecount", vp);
331 panic("afs_vget");
333 error = vget(vp, lfl, current_proc());
334 if (!error)
335 insmntque(vp, mp); /* take off free list */
336 return error;
339 int afs_vfs_vget(struct mount *mp, void *ino, struct vnode **vpp)
341 return ENOENT; /* cannot implement */
344 #endif
347 afs_statfs(struct mount *mp, STATFS_TYPE *abp, CTX_TYPE ctx)
349 STATFS_TYPE *sysstat = vfs_statfs(mp);
350 AFS_GLOCK();
351 AFS_STATCNT(afs_statfs);
353 #ifdef AFS_DARWIN80_ENV
354 abp->f_iosize = (256 * 1024);
355 abp->f_bsize = vfs_devblocksize(mp);
356 #else
357 abp->f_bsize = mp->vfs_bsize;
358 abp->f_iosize = mp->vfs_bsize;
359 #endif
360 #if 0
361 abp->f_type = MOUNT_AFS;
362 #endif
364 abp->f_blocks = abp->f_bfree = abp->f_bavail = abp->f_files =
365 abp->f_ffree = AFS_VFS_FAKEFREE;
367 if (abp != sysstat) {
368 abp->f_fsid.val[0] = sysstat->f_fsid.val[0];
369 abp->f_fsid.val[1] = sysstat->f_fsid.val[1];
370 #ifndef AFS_DARWIN80_ENV
371 abp->f_type = vfs_typenum(mp);
372 #endif
373 memcpy((caddr_t) & abp->f_mntonname[0],
374 (caddr_t) sysstat->f_mntonname, MNAMELEN);
375 memcpy((caddr_t) & abp->f_mntfromname[0],
376 (caddr_t) sysstat->f_mntfromname, MNAMELEN);
379 AFS_GUNLOCK();
380 return 0;
383 #ifdef AFS_DARWIN80_ENV
385 afs_vfs_getattr(struct mount *mp, struct vfs_attr *outattrs,
386 vfs_context_t context)
388 VFSATTR_RETURN(outattrs, f_bsize, vfs_devblocksize(mp));
389 VFSATTR_RETURN(outattrs, f_iosize, vfs_devblocksize(mp));
390 VFSATTR_RETURN(outattrs, f_blocks, 2000000);
391 VFSATTR_RETURN(outattrs, f_bfree, 2000000);
392 VFSATTR_RETURN(outattrs, f_bavail, 2000000);
393 VFSATTR_RETURN(outattrs, f_files, 2000000);
394 VFSATTR_RETURN(outattrs, f_ffree, 2000000);
395 if ( VFSATTR_IS_ACTIVE(outattrs, f_capabilities) )
397 vol_capabilities_attr_t *vcapattrptr;
398 vcapattrptr = &outattrs->f_capabilities;
399 vcapattrptr->capabilities[VOL_CAPABILITIES_FORMAT] =
400 VOL_CAP_FMT_SYMBOLICLINKS |
401 VOL_CAP_FMT_HARDLINKS |
402 VOL_CAP_FMT_ZERO_RUNS |
403 VOL_CAP_FMT_CASE_SENSITIVE |
404 VOL_CAP_FMT_CASE_PRESERVING |
405 VOL_CAP_FMT_PERSISTENTOBJECTIDS |
406 VOL_CAP_FMT_2TB_FILESIZE |
407 VOL_CAP_FMT_FAST_STATFS;
408 vcapattrptr->capabilities[VOL_CAPABILITIES_INTERFACES] =
409 VOL_CAP_INT_ADVLOCK |
410 VOL_CAP_INT_FLOCK;
411 vcapattrptr->capabilities[VOL_CAPABILITIES_RESERVED1] = 0;
412 vcapattrptr->capabilities[VOL_CAPABILITIES_RESERVED2] = 0;
414 /* Capabilities we know about: */
415 vcapattrptr->valid[VOL_CAPABILITIES_FORMAT] =
416 VOL_CAP_FMT_PERSISTENTOBJECTIDS |
417 VOL_CAP_FMT_SYMBOLICLINKS |
418 VOL_CAP_FMT_HARDLINKS |
419 VOL_CAP_FMT_JOURNAL |
420 VOL_CAP_FMT_JOURNAL_ACTIVE |
421 VOL_CAP_FMT_NO_ROOT_TIMES |
422 VOL_CAP_FMT_SPARSE_FILES |
423 VOL_CAP_FMT_ZERO_RUNS |
424 VOL_CAP_FMT_CASE_SENSITIVE |
425 VOL_CAP_FMT_CASE_PRESERVING |
426 VOL_CAP_FMT_PERSISTENTOBJECTIDS |
427 VOL_CAP_FMT_2TB_FILESIZE |
428 VOL_CAP_FMT_FAST_STATFS;
429 vcapattrptr->valid[VOL_CAPABILITIES_INTERFACES] =
430 VOL_CAP_INT_SEARCHFS |
431 VOL_CAP_INT_ATTRLIST |
432 VOL_CAP_INT_NFSEXPORT |
433 VOL_CAP_INT_READDIRATTR |
434 VOL_CAP_INT_EXCHANGEDATA |
435 VOL_CAP_INT_COPYFILE |
436 VOL_CAP_INT_ALLOCATE |
437 VOL_CAP_INT_VOL_RENAME |
438 VOL_CAP_INT_ADVLOCK |
439 VOL_CAP_INT_FLOCK;
440 vcapattrptr->valid[VOL_CAPABILITIES_RESERVED1] = 0;
441 vcapattrptr->valid[VOL_CAPABILITIES_RESERVED2] = 0;
443 VFSATTR_SET_SUPPORTED(outattrs, f_capabilities);
445 return 0;
447 #endif
449 #ifdef AFS_DARWIN80_ENV
451 afs_sync(struct mount *mp, int waitfor, CTX_TYPE ctx)
452 #else
454 afs_sync(struct mount *mp, int waitfor, struct ucred *cred, struct proc *p)
455 #endif
457 return 0;
460 u_int32_t afs_darwin_realmodes = 0;
461 u_int32_t afs_darwin_fsevents = 0;
462 extern int AFSDOBULK;
465 afs_sysctl_int(int *name, u_int namelen, user_addr_t oldp, size_t *oldlenp,
466 user_addr_t newp, size_t newlen, u_int32_t *object)
468 #ifdef AFS_DARWIN80_ENV
469 int error;
471 if (oldp != USER_ADDR_NULL && oldlenp == NULL)
472 return (EFAULT);
473 if (oldp && *oldlenp < sizeof(u_int32_t))
474 return (ENOMEM);
475 if (newp && newlen != sizeof(u_int32_t))
476 return (EINVAL);
477 *oldlenp = sizeof(u_int32_t);
478 if (oldp) {
479 if ((error = copyout(object,
480 oldp, sizeof(u_int32_t)))) {
481 return error;
484 if (newp)
485 return copyin(newp, object, sizeof(u_int32_t));
486 return 0;
487 #else
488 return sysctl_int(oldp, oldlenp, newp, newlen,
489 object);
490 #endif
493 #ifdef AFS_DARWIN80_ENV
495 afs_sysctl(int *name, u_int namelen, user_addr_t oldp, size_t *oldlenp,
496 user_addr_t newp, size_t newlen, vfs_context_t context)
497 #else
499 afs_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp,
500 void *newp, size_t newlen, struct proc *p)
501 #endif
503 switch (name[0]) {
504 case AFS_SC_ALL:
505 /* nothing defined */
506 break;
507 case AFS_SC_DARWIN:
508 if (namelen < 3)
509 return ENOENT;
510 switch (name[1]) {
511 case AFS_SC_DARWIN_ALL:
512 switch (name[2]) {
513 case AFS_SC_DARWIN_ALL_REALMODES:
514 return afs_sysctl_int(name, namelen, oldp, oldlenp,
515 newp, newlen, &afs_darwin_realmodes);
516 case AFS_SC_DARWIN_ALL_FSEVENTS:
517 return afs_sysctl_int(name, namelen, oldp, oldlenp,
518 newp, newlen, &afs_darwin_fsevents);
519 case AFS_SC_DARWIN_ALL_BULKSTAT:
520 return afs_sysctl_int(name, namelen, oldp, oldlenp,
521 newp, newlen, &AFSDOBULK);
523 break;
524 /* darwin version specific sysctl's goes here */
526 break;
528 return ENOTSUP;
531 typedef (*PFI) ();
532 extern int vfs_opv_numops; /* The total number of defined vnode operations */
533 extern struct vnodeopv_desc afs_vnodeop_opv_desc;
535 afs_init(struct vfsconf *vfc)
537 #ifndef AFS_DARWIN80_ENV /* vfs_fsadd does all this junk */
538 int j;
539 int (**opv_desc_vector) ();
540 struct vnodeopv_entry_desc *opve_descp;
544 MALLOC(afs_vnodeop_p, PFI *, vfs_opv_numops * sizeof(PFI), M_TEMP,
545 M_WAITOK);
547 memset(afs_vnodeop_p, 0, vfs_opv_numops * sizeof(PFI));
549 opv_desc_vector = afs_vnodeop_p;
550 for (j = 0; afs_vnodeop_opv_desc.opv_desc_ops[j].opve_op; j++) {
551 opve_descp = &(afs_vnodeop_opv_desc.opv_desc_ops[j]);
554 * Sanity check: is this operation listed
555 * in the list of operations? We check this
556 * by seeing if its offest is zero. Since
557 * the default routine should always be listed
558 * first, it should be the only one with a zero
559 * offset. Any other operation with a zero
560 * offset is probably not listed in
561 * vfs_op_descs, and so is probably an error.
563 * A panic here means the layer programmer
564 * has committed the all-too common bug
565 * of adding a new operation to the layer's
566 * list of vnode operations but
567 * not adding the operation to the system-wide
568 * list of supported operations.
570 if (opve_descp->opve_op->vdesc_offset == 0
571 && opve_descp->opve_op->vdesc_offset != VOFFSET(vop_default)) {
572 printf("afs_init: operation %s not listed in %s.\n",
573 opve_descp->opve_op->vdesc_name, "vfs_op_descs");
574 panic("load_afs: bad operation");
577 * Fill in this entry.
579 opv_desc_vector[opve_descp->opve_op->vdesc_offset] =
580 opve_descp->opve_impl;
584 * Finally, go back and replace unfilled routines
585 * with their default. (Sigh, an O(n^3) algorithm. I
586 * could make it better, but that'd be work, and n is small.)
590 * Force every operations vector to have a default routine.
592 opv_desc_vector = afs_vnodeop_p;
593 if (opv_desc_vector[VOFFSET(vop_default)] == NULL) {
594 panic("afs_init: operation vector without default routine.");
596 for (j = 0; j < vfs_opv_numops; j++)
597 if (opv_desc_vector[j] == NULL)
598 opv_desc_vector[j] = opv_desc_vector[VOFFSET(vop_default)];
599 #endif
600 return 0;
603 struct vfsops afs_vfsops = {
604 afs_mount,
605 afs_start,
606 afs_unmount,
607 afs_root,
608 #ifdef AFS_DARWIN80_ENV
610 afs_vfs_getattr,
611 #else
612 afs_quotactl,
613 afs_statfs,
614 #endif
615 afs_sync,
616 #ifdef AFS_DARWIN80_ENV
617 0,0,0,
618 #else
619 afs_vfs_vget,
620 afs_fhtovp,
621 afs_vptofh,
622 #endif
623 afs_init,
624 afs_sysctl,
625 #ifdef AFS_DARWIN80_ENV
626 0 /*setattr */,
628 #endif