macos: fix race in afs_root
[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 = ENOENT;
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     /* Fake a high number below to satisfy programs that use the statfs call
365      * to make sure that there's enough space in the device partition before
366      * storing something there.
367      */
368     abp->f_blocks = abp->f_bfree = abp->f_bavail = abp->f_files =
369       abp->f_ffree = 0x7fffffff;
370
371     if (abp != sysstat) {
372         abp->f_fsid.val[0] = sysstat->f_fsid.val[0];
373         abp->f_fsid.val[1] = sysstat->f_fsid.val[1];
374 #ifndef AFS_DARWIN80_ENV
375         abp->f_type = vfs_typenum(mp);
376 #endif
377         memcpy((caddr_t) & abp->f_mntonname[0],
378                (caddr_t) sysstat->f_mntonname, MNAMELEN);
379         memcpy((caddr_t) & abp->f_mntfromname[0],
380                (caddr_t) sysstat->f_mntfromname, MNAMELEN);
381     }
382
383     AFS_GUNLOCK();
384     return 0;
385 }
386
387 #ifdef AFS_DARWIN80_ENV
388 int
389 afs_vfs_getattr(struct mount *mp, struct vfs_attr *outattrs,
390                 vfs_context_t context)
391 {
392     VFSATTR_RETURN(outattrs, f_bsize, vfs_devblocksize(mp));
393     VFSATTR_RETURN(outattrs, f_iosize, vfs_devblocksize(mp));
394     VFSATTR_RETURN(outattrs, f_blocks, 2000000);
395     VFSATTR_RETURN(outattrs, f_bfree, 2000000);
396     VFSATTR_RETURN(outattrs, f_bavail, 2000000);
397     VFSATTR_RETURN(outattrs, f_files, 2000000);
398     VFSATTR_RETURN(outattrs, f_ffree, 2000000);
399     if ( VFSATTR_IS_ACTIVE(outattrs, f_capabilities) )
400     {
401          vol_capabilities_attr_t *vcapattrptr;
402          vcapattrptr = &outattrs->f_capabilities;
403          vcapattrptr->capabilities[VOL_CAPABILITIES_FORMAT] =
404                    VOL_CAP_FMT_SYMBOLICLINKS |
405                    VOL_CAP_FMT_HARDLINKS |
406                    VOL_CAP_FMT_ZERO_RUNS |
407                    VOL_CAP_FMT_CASE_SENSITIVE |
408                    VOL_CAP_FMT_CASE_PRESERVING |
409                    VOL_CAP_FMT_PERSISTENTOBJECTIDS |
410                    VOL_CAP_FMT_2TB_FILESIZE |
411                    VOL_CAP_FMT_FAST_STATFS;
412          vcapattrptr->capabilities[VOL_CAPABILITIES_INTERFACES] = 
413                    VOL_CAP_INT_ADVLOCK | 
414                    VOL_CAP_INT_FLOCK;
415          vcapattrptr->capabilities[VOL_CAPABILITIES_RESERVED1] = 0;
416          vcapattrptr->capabilities[VOL_CAPABILITIES_RESERVED2] = 0;
417
418          /* Capabilities we know about: */
419          vcapattrptr->valid[VOL_CAPABILITIES_FORMAT] =
420                  VOL_CAP_FMT_PERSISTENTOBJECTIDS |
421                  VOL_CAP_FMT_SYMBOLICLINKS |
422                  VOL_CAP_FMT_HARDLINKS |
423                  VOL_CAP_FMT_JOURNAL |
424                  VOL_CAP_FMT_JOURNAL_ACTIVE |
425                  VOL_CAP_FMT_NO_ROOT_TIMES |
426                  VOL_CAP_FMT_SPARSE_FILES |
427                  VOL_CAP_FMT_ZERO_RUNS |
428                  VOL_CAP_FMT_CASE_SENSITIVE |
429                  VOL_CAP_FMT_CASE_PRESERVING |
430                  VOL_CAP_FMT_PERSISTENTOBJECTIDS |
431                  VOL_CAP_FMT_2TB_FILESIZE |
432                  VOL_CAP_FMT_FAST_STATFS;
433          vcapattrptr->valid[VOL_CAPABILITIES_INTERFACES] =
434                  VOL_CAP_INT_SEARCHFS |
435                  VOL_CAP_INT_ATTRLIST |
436                  VOL_CAP_INT_NFSEXPORT |
437                  VOL_CAP_INT_READDIRATTR |
438                  VOL_CAP_INT_EXCHANGEDATA |
439                  VOL_CAP_INT_COPYFILE |
440                  VOL_CAP_INT_ALLOCATE |
441                  VOL_CAP_INT_VOL_RENAME |
442                  VOL_CAP_INT_ADVLOCK |
443                  VOL_CAP_INT_FLOCK;
444          vcapattrptr->valid[VOL_CAPABILITIES_RESERVED1] = 0;
445          vcapattrptr->valid[VOL_CAPABILITIES_RESERVED2] = 0;
446              
447          VFSATTR_SET_SUPPORTED(outattrs, f_capabilities);
448     }
449     return 0;
450 }
451 #endif
452
453 #ifdef AFS_DARWIN80_ENV
454 int
455 afs_sync(struct mount *mp, int waitfor, CTX_TYPE ctx)
456 #else
457 int
458 afs_sync(struct mount *mp, int waitfor, struct ucred *cred, struct proc *p)
459 #endif
460 {
461     return 0;
462 }
463
464 u_int32_t afs_darwin_realmodes = 0;
465 u_int32_t afs_darwin_fsevents = 0;
466 extern int AFSDOBULK;
467
468 int
469 afs_sysctl_int(int *name, u_int namelen, user_addr_t oldp, size_t *oldlenp,
470                user_addr_t newp, size_t newlen, u_int32_t *object)
471 {
472 #ifdef AFS_DARWIN80_ENV
473     int error;
474
475     if (oldp != USER_ADDR_NULL && oldlenp == NULL)
476         return (EFAULT);
477     if (oldp && *oldlenp < sizeof(u_int32_t))
478         return (ENOMEM);
479     if (newp && newlen != sizeof(u_int32_t))
480         return (EINVAL);
481     *oldlenp = sizeof(u_int32_t);
482     if (oldp) {
483         if ((error = copyout(object,
484                              oldp, sizeof(u_int32_t)))) {
485             return error;
486         }
487     }
488     if (newp)
489         return copyin(newp, object, sizeof(u_int32_t));
490     return 0;
491 #else
492     return sysctl_int(oldp, oldlenp, newp, newlen,
493                       object);
494 #endif
495 }
496
497 #ifdef AFS_DARWIN80_ENV
498 int
499 afs_sysctl(int *name, u_int namelen, user_addr_t oldp, size_t *oldlenp,
500                user_addr_t newp, size_t newlen, vfs_context_t context)
501 #else
502 int
503 afs_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp,
504                void *newp, size_t newlen, struct proc *p)
505 #endif
506 {
507     switch (name[0]) {
508     case AFS_SC_ALL:
509         /* nothing defined */
510         break;
511     case AFS_SC_DARWIN:
512         if (namelen < 3)
513             return ENOENT;
514         switch (name[1]) {
515         case AFS_SC_DARWIN_ALL:
516             switch (name[2]) {
517             case AFS_SC_DARWIN_ALL_REALMODES:
518                 return afs_sysctl_int(name, namelen, oldp, oldlenp,
519                                       newp, newlen, &afs_darwin_realmodes);
520             case AFS_SC_DARWIN_ALL_FSEVENTS:
521                 return afs_sysctl_int(name, namelen, oldp, oldlenp,
522                                       newp, newlen, &afs_darwin_fsevents);
523             case AFS_SC_DARWIN_ALL_BULKSTAT:
524                 return afs_sysctl_int(name, namelen, oldp, oldlenp,
525                                       newp, newlen, &AFSDOBULK);
526             }
527             break;
528             /* darwin version specific sysctl's goes here */
529         }
530         break;
531     }
532     return ENOTSUP;
533 }
534
535 typedef (*PFI) ();
536 extern int vfs_opv_numops;      /* The total number of defined vnode operations */
537 extern struct vnodeopv_desc afs_vnodeop_opv_desc;
538 int
539 afs_init(struct vfsconf *vfc)
540 {
541 #ifndef AFS_DARWIN80_ENV /* vfs_fsadd does all this junk */
542     int j;
543     int (**opv_desc_vector) ();
544     struct vnodeopv_entry_desc *opve_descp;
545
546
547
548     MALLOC(afs_vnodeop_p, PFI *, vfs_opv_numops * sizeof(PFI), M_TEMP,
549            M_WAITOK);
550
551     memset(afs_vnodeop_p, 0, vfs_opv_numops * sizeof(PFI));
552
553     opv_desc_vector = afs_vnodeop_p;
554     for (j = 0; afs_vnodeop_opv_desc.opv_desc_ops[j].opve_op; j++) {
555         opve_descp = &(afs_vnodeop_opv_desc.opv_desc_ops[j]);
556
557         /*
558          * Sanity check:  is this operation listed
559          * in the list of operations?  We check this
560          * by seeing if its offest is zero.  Since
561          * the default routine should always be listed
562          * first, it should be the only one with a zero
563          * offset.  Any other operation with a zero
564          * offset is probably not listed in
565          * vfs_op_descs, and so is probably an error.
566          *
567          * A panic here means the layer programmer
568          * has committed the all-too common bug
569          * of adding a new operation to the layer's
570          * list of vnode operations but
571          * not adding the operation to the system-wide
572          * list of supported operations.
573          */
574         if (opve_descp->opve_op->vdesc_offset == 0
575             && opve_descp->opve_op->vdesc_offset != VOFFSET(vop_default)) {
576             printf("afs_init: operation %s not listed in %s.\n",
577                    opve_descp->opve_op->vdesc_name, "vfs_op_descs");
578             panic("load_afs: bad operation");
579         }
580         /*
581          * Fill in this entry.
582          */
583         opv_desc_vector[opve_descp->opve_op->vdesc_offset] =
584             opve_descp->opve_impl;
585     }
586
587     /*
588      * Finally, go back and replace unfilled routines
589      * with their default.  (Sigh, an O(n^3) algorithm.  I
590      * could make it better, but that'd be work, and n is small.)
591      */
592
593     /*
594      * Force every operations vector to have a default routine.
595      */
596     opv_desc_vector = afs_vnodeop_p;
597     if (opv_desc_vector[VOFFSET(vop_default)] == NULL) {
598         panic("afs_init: operation vector without default routine.");
599     }
600     for (j = 0; j < vfs_opv_numops; j++)
601         if (opv_desc_vector[j] == NULL)
602             opv_desc_vector[j] = opv_desc_vector[VOFFSET(vop_default)];
603 #endif
604     return 0;
605 }
606
607 struct vfsops afs_vfsops = {
608    afs_mount,
609    afs_start,
610    afs_unmount,
611    afs_root,
612 #ifdef AFS_DARWIN80_ENV
613    0,
614    afs_vfs_getattr,
615 #else
616    afs_quotactl,
617    afs_statfs,
618 #endif
619    afs_sync,
620 #ifdef AFS_DARWIN80_ENV
621    0,0,0,
622 #else
623    afs_vfs_vget,
624    afs_fhtovp,
625    afs_vptofh,
626 #endif
627    afs_init,
628    afs_sysctl, 
629 #ifdef AFS_DARWIN80_ENV
630    0 /*setattr */,
631    {0}
632 #endif
633 };