Import Upstream version 1.8.5
[hcoop/debian/openafs.git] / src / afs / DARWIN / osi_vfsops.c
1 /*
2 * Portions Copyright (c) 2003 Apple Computer, Inc. All rights reserved.
3 */
4 #include <afsconfig.h>
5 #include <afs/param.h>
6
7
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"
19
20 #ifndef M_UFSMNT
21 #define M_UFSMNT M_TEMP /* DARWIN80 MALLOC doesn't look at the type anyway */
22 #endif
23
24 struct vcache *afs_globalVp = 0;
25 struct mount *afs_globalVFS = 0;
26 int afs_vfs_typenum;
27
28 int
29 afs_quotactl()
30 {
31 return ENOTSUP;
32 }
33
34 int
35 afs_fhtovp(struct mount *mp, struct fid *fhp, struct vnode **vpp)
36 {
37 return (EINVAL);
38 }
39
40 int
41 afs_vptofh(struct vnode *vp, struct fid *fhp)
42 {
43 return (EINVAL);
44 }
45
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)
57
58 int
59 afs_start(struct mount *mp, int flags, CTX_TYPE p)
60 {
61 return (0); /* nothing to do. ? */
62 }
63
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
73 {
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);
85
86 if (vfs_isupdate(mp))
87 return EINVAL;
88
89 AFS_GLOCK();
90 AFS_STATCNT(afs_mount);
91
92 if (data == 0 && afs_globalVFS) { /* Don't allow remounts. */
93 AFS_GUNLOCK();
94 return (EBUSY);
95 }
96
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);
108
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);
114
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];
123
124 (void)copyinstr(data, volName, MNAMELEN - 1, &size);
125 memset(volName + size, 0, MNAMELEN - size);
126
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;
135 }
136
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);
143
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;
155 }
156
157 vfs_setfsprivate(mp, &rootFid);
158 }
159 }
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;
170 }
171
172 int
173 afs_unmount(struct mount *mp, int flags, CTX_TYPE ctx)
174 {
175 void *mdata = vfs_fsprivate(mp);
176 AFS_GLOCK();
177 AFS_STATCNT(afs_unmount);
178
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
193 }
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;
203 }
204 }
205 vfs_clearflags(mp, MNT_LOCAL);
206 }
207
208 AFS_GUNLOCK();
209
210 return 0;
211 }
212
213 #ifdef AFS_DARWIN80_ENV
214 int
215 afs_root(struct mount *mp, struct vnode **vpp, vfs_context_t ctx)
216 #else
217 int
218 afs_root(struct mount *mp, struct vnode **vpp)
219 #endif
220 {
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;
233
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);
240
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;
252
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));
265 }
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;
279 }
280 }
281 needref=1;
282 }
283 } else
284 error = EIO;
285 }
286 }
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
294
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
301 */
302 vnode_get(AFSTOV(tvp));
303 #else
304 ;
305 #endif
306
307 if (mdata == NULL)
308 afs_globalVFS = mp;
309
310 *vpp = AFSTOV(tvp);
311 #ifndef AFS_DARWIN80_ENV
312 AFSTOV(tvp)->v_flag |= VROOT;
313 AFSTOV(tvp)->v_vfsp = mp;
314 #endif
315 }
316
317 afs_Trace2(afs_iclSetp, CM_TRACE_VFSROOT, ICL_TYPE_POINTER, *vpp,
318 ICL_TYPE_INT32, error);
319 AFS_GUNLOCK();
320 return error;
321 }
322
323 #ifndef AFS_DARWIN80_ENV /* vget vfsop never had this prototype AFAIK */
324 int
325 afs_vget(struct mount *mp, int lfl, struct vnode *vp)
326 {
327 int error;
328 //printf("vget called. help!\n");
329 if (vp->v_usecount < 0) {
330 vprint("bad usecount", vp);
331 panic("afs_vget");
332 }
333 error = vget(vp, lfl, current_proc());
334 if (!error)
335 insmntque(vp, mp); /* take off free list */
336 return error;
337 }
338
339 int afs_vfs_vget(struct mount *mp, void *ino, struct vnode **vpp)
340 {
341 return ENOENT; /* cannot implement */
342 }
343
344 #endif
345
346 int
347 afs_statfs(struct mount *mp, STATFS_TYPE *abp, CTX_TYPE ctx)
348 {
349 STATFS_TYPE *sysstat = vfs_statfs(mp);
350 AFS_GLOCK();
351 AFS_STATCNT(afs_statfs);
352
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
363
364 abp->f_blocks = abp->f_bfree = abp->f_bavail = abp->f_files =
365 abp->f_ffree = AFS_VFS_FAKEFREE;
366
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);
377 }
378
379 AFS_GUNLOCK();
380 return 0;
381 }
382
383 #ifdef AFS_DARWIN80_ENV
384 int
385 afs_vfs_getattr(struct mount *mp, struct vfs_attr *outattrs,
386 vfs_context_t context)
387 {
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) )
396 {
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;
413
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;
442
443 VFSATTR_SET_SUPPORTED(outattrs, f_capabilities);
444 }
445 return 0;
446 }
447 #endif
448
449 #ifdef AFS_DARWIN80_ENV
450 int
451 afs_sync(struct mount *mp, int waitfor, CTX_TYPE ctx)
452 #else
453 int
454 afs_sync(struct mount *mp, int waitfor, struct ucred *cred, struct proc *p)
455 #endif
456 {
457 return 0;
458 }
459
460 u_int32_t afs_darwin_realmodes = 0;
461 u_int32_t afs_darwin_fsevents = 0;
462 extern int AFSDOBULK;
463
464 int
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)
467 {
468 #ifdef AFS_DARWIN80_ENV
469 int error;
470
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;
482 }
483 }
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
491 }
492
493 #ifdef AFS_DARWIN80_ENV
494 int
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
498 int
499 afs_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp,
500 void *newp, size_t newlen, struct proc *p)
501 #endif
502 {
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);
522 }
523 break;
524 /* darwin version specific sysctl's goes here */
525 }
526 break;
527 }
528 return ENOTSUP;
529 }
530
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;
534 int
535 afs_init(struct vfsconf *vfc)
536 {
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;
541
542
543
544 MALLOC(afs_vnodeop_p, PFI *, vfs_opv_numops * sizeof(PFI), M_TEMP,
545 M_WAITOK);
546
547 memset(afs_vnodeop_p, 0, vfs_opv_numops * sizeof(PFI));
548
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]);
552
553 /*
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.
562 *
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.
569 */
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");
575 }
576 /*
577 * Fill in this entry.
578 */
579 opv_desc_vector[opve_descp->opve_op->vdesc_offset] =
580 opve_descp->opve_impl;
581 }
582
583 /*
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.)
587 */
588
589 /*
590 * Force every operations vector to have a default routine.
591 */
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.");
595 }
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;
601 }
602
603 struct vfsops afs_vfsops = {
604 afs_mount,
605 afs_start,
606 afs_unmount,
607 afs_root,
608 #ifdef AFS_DARWIN80_ENV
609 0,
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 */,
627 {0}
628 #endif
629 };