macos-104-not-yet-20050508
[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 RCSID
8     ("$Header$");
9
10 #include <afs/sysincludes.h>    /* Standard vendor system headers */
11 #include <afsincludes.h>        /* Afs-based standard headers */
12 #include <afs/afs_stats.h>      /* statistics */
13 #include <sys/malloc.h>
14 #include <sys/namei.h>
15 #include <sys/conf.h>
16 #include <sys/syscall.h>
17 #include <sys/sysctl.h>
18 #include "../afs/sysctl.h"
19
20 struct vcache *afs_globalVp = 0;
21 struct mount *afs_globalVFS = 0;
22
23 int
24 afs_quotactl()
25 {
26     return EOPNOTSUPP;
27 }
28
29 int
30 afs_fhtovp(mp, fhp, vpp)
31      struct mount *mp;
32      struct fid *fhp;
33      struct vnode **vpp;
34 {
35
36     return (EINVAL);
37 }
38
39 int
40 afs_vptofh(vp, fhp)
41      struct vnode *vp;
42      struct fid *fhp;
43 {
44
45     return (EINVAL);
46 }
47
48 int
49 afs_start(mp, flags, p)
50      struct mount *mp;
51      int flags;
52      struct proc *p;
53 {
54     return (0);                 /* nothing to do. ? */
55 }
56
57 int
58 afs_mount(mp, path, data, ndp, p)
59      register struct mount *mp;
60      char *path;
61      caddr_t data;
62      struct nameidata *ndp;
63      struct proc *p;
64 {
65     /* ndp contains the mounted-from device.  Just ignore it.
66      * we also don't care about our proc struct. */
67     size_t size;
68     int error;
69
70     if (mp->mnt_flag & MNT_UPDATE)
71         return EINVAL;
72
73     AFS_GLOCK();
74     AFS_STATCNT(afs_mount);
75
76     if (data == NULL && afs_globalVFS) {        /* Don't allow remounts. */
77         AFS_GUNLOCK();
78         return (EBUSY);
79     }
80
81     afs_globalVFS = mp;
82     mp->vfs_bsize = 8192;
83     vfs_getnewfsid(mp);
84     mp->mnt_stat.f_iosize = 8192;
85
86     (void)copyinstr(path, mp->mnt_stat.f_mntonname, MNAMELEN - 1, &size);
87     memset(mp->mnt_stat.f_mntonname + size, 0, MNAMELEN - size);
88     memset(mp->mnt_stat.f_mntfromname, 0, MNAMELEN);
89
90     if (data == NULL) {
91         strcpy(mp->mnt_stat.f_mntfromname, "AFS");
92         /* null terminated string "AFS" will fit, just leave it be. */
93         mp->mnt_data = (qaddr_t) NULL;
94     } else {
95         struct VenusFid *rootFid = NULL;
96         struct volume *tvp;
97         char volName[MNAMELEN];
98
99         (void)copyinstr((char *)data, volName, MNAMELEN - 1, &size);
100         memset(volName + size, 0, MNAMELEN - size);
101
102         if (volName[0] == 0) {
103             strcpy(mp->mnt_stat.f_mntfromname, "AFS");
104             mp->mnt_data = (qaddr_t) & afs_rootFid;
105         } else {
106             struct cell *localcell = afs_GetPrimaryCell(READ_LOCK);
107             if (localcell == NULL) {
108                 AFS_GUNLOCK();
109                 return ENODEV;
110             }
111
112             /* Set the volume identifier to "AFS:volume.name" */
113             snprintf(mp->mnt_stat.f_mntfromname, MNAMELEN - 1, "AFS:%s",
114                      volName);
115             tvp =
116                 afs_GetVolumeByName(volName, localcell->cellNum, 1,
117                                     (struct vrequest *)0, READ_LOCK);
118
119             if (tvp) {
120                 int volid = (tvp->roVol ? tvp->roVol : tvp->volume);
121                 MALLOC(rootFid, struct VenusFid *, sizeof(*rootFid), M_UFSMNT,
122                        M_WAITOK);
123                 rootFid->Cell = localcell->cellNum;
124                 rootFid->Fid.Volume = volid;
125                 rootFid->Fid.Vnode = 1;
126                 rootFid->Fid.Unique = 1;
127             } else {
128                 AFS_GUNLOCK();
129                 return ENODEV;
130             }
131
132             mp->mnt_data = (qaddr_t) rootFid;
133         }
134     }
135     strcpy(mp->mnt_stat.f_fstypename, "afs");
136     AFS_GUNLOCK();
137     (void)afs_statfs(mp, &mp->mnt_stat, p);
138     return 0;
139 }
140
141 int
142 afs_unmount(mp, flags, p)
143      struct mount *mp;
144      int flags;
145      struct proc *p;
146 {
147
148     AFS_GLOCK();
149     AFS_STATCNT(afs_unmount);
150
151     if (mp->mnt_data != (qaddr_t) - 1) {
152         if (mp->mnt_data != NULL) {
153             FREE(mp->mnt_data, M_UFSMNT);
154             mp->mnt_data = (qaddr_t) - 1;
155         } else {
156             if (flags & MNT_FORCE) {
157                 if (afs_globalVp) {
158                     AFS_GUNLOCK();
159 #ifdef AFS_DARWIN80_ENV
160                     vnode_rele(AFSTOV(afs_globalVp));
161 #else
162                     vrele(AFSTOV(afs_globalVp));
163 #endif
164                     AFS_GLOCK();
165                 }
166                 afs_globalVp = NULL;
167                 AFS_GUNLOCK();
168                 vflush(mp, NULLVP, FORCECLOSE/*0*/);
169                 AFS_GLOCK();
170                 afs_globalVFS = 0;
171                 afs_shutdown();
172             } else {
173                 AFS_GUNLOCK();
174                 return EBUSY;
175             }
176         }
177         mp->mnt_flag &= ~MNT_LOCAL;
178     }
179
180     AFS_GUNLOCK();
181
182     return 0;
183 }
184
185 int
186 afs_root(struct mount *mp, struct vnode **vpp)
187 {
188     int error;
189     struct vrequest treq;
190     register struct vcache *tvp = 0;
191     struct proc *p = current_proc();
192     struct ucred cr;
193
194     pcred_readlock(p);
195     cr = *p->p_cred->pc_ucred;
196     pcred_unlock(p);
197     AFS_GLOCK();
198     AFS_STATCNT(afs_root);
199     if (mp->mnt_data == NULL && afs_globalVp
200         && (afs_globalVp->states & CStatd)) {
201         tvp = afs_globalVp;
202         error = 0;
203     } else if (mp->mnt_data == (qaddr_t) - 1) {
204         error = ENOENT;
205     } else {
206         struct VenusFid *rootFid = (mp->mnt_data == NULL)
207             ? &afs_rootFid : (struct VenusFid *)mp->mnt_data;
208
209         if (afs_globalVp) {
210             afs_PutVCache(afs_globalVp);
211             afs_globalVp = NULL;
212         }
213
214         if (!(error = afs_InitReq(&treq, &cr)) && !(error = afs_CheckInit())) {
215             tvp = afs_GetVCache(rootFid, &treq, NULL, NULL);
216             /* we really want this to stay around */
217             if (tvp) {
218                 if (mp->mnt_data == NULL)
219                     afs_globalVp = tvp;
220             } else
221                 error = ENOENT;
222         }
223     }
224     if (tvp) {
225         osi_vnhold(tvp, 0);
226         AFS_GUNLOCK();
227         vn_lock(AFSTOV(tvp), LK_EXCLUSIVE | LK_RETRY, p);
228         AFS_GLOCK();
229         if (mp->mnt_data == NULL) {
230             afs_globalVFS = mp;
231         }
232         *vpp = AFSTOV(tvp);
233         AFSTOV(tvp)->v_flag |= VROOT;
234         AFSTOV(tvp)->v_vfsp = mp;
235     }
236
237     afs_Trace2(afs_iclSetp, CM_TRACE_VFSROOT, ICL_TYPE_POINTER, *vpp,
238                ICL_TYPE_INT32, error);
239     AFS_GUNLOCK();
240     return error;
241 }
242
243 int
244 afs_vget(mp, lfl, vp)
245      struct mount *mp;
246      struct vnode *vp;
247      int lfl;
248 {
249     int error;
250     //printf("vget called. help!\n");
251     if (vp->v_usecount < 0) {
252         vprint("bad usecount", vp);
253         panic("afs_vget");
254     }
255 #ifdef AFS_DARWIN80_ENV
256     error = vnode_get(vp);
257 #else
258     error = vget(vp, lfl, current_proc());
259 #endif
260     if (!error)
261         insmntque(vp, mp);      /* take off free list */
262     return error;
263 }
264
265 int
266 afs_statfs(struct mount *mp, struct statfs *abp, struct proc *p)
267 {
268     AFS_GLOCK();
269     AFS_STATCNT(afs_statfs);
270
271 #if 0
272     abp->f_type = MOUNT_AFS;
273 #endif
274     abp->f_bsize = mp->vfs_bsize;
275     abp->f_iosize = mp->vfs_bsize;
276
277     /* Fake a high number below to satisfy programs that use the statfs call
278      * to make sure that there's enough space in the device partition before
279      * storing something there.
280      */
281     abp->f_blocks = abp->f_bfree = abp->f_bavail = abp->f_files =
282         abp->f_ffree = 2000000;
283
284     abp->f_fsid.val[0] = mp->mnt_stat.f_fsid.val[0];
285     abp->f_fsid.val[1] = mp->mnt_stat.f_fsid.val[1];
286     if (abp != &mp->mnt_stat) {
287         abp->f_type = mp->mnt_vfc->vfc_typenum;
288         memcpy((caddr_t) & abp->f_mntonname[0],
289                (caddr_t) mp->mnt_stat.f_mntonname, MNAMELEN);
290         memcpy((caddr_t) & abp->f_mntfromname[0],
291                (caddr_t) mp->mnt_stat.f_mntfromname, MNAMELEN);
292     }
293
294     AFS_GUNLOCK();
295     return 0;
296 }
297
298 int
299 afs_sync(mp, waitfor, cred, p)
300      struct mount *mp;
301      int waitfor;
302      struct ucred *cred;
303      struct prioc *p;
304 {
305     return 0;
306 }
307
308 u_int32_t afs_darwin_realmodes = 0;
309
310 int afs_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, 
311                void *newp, size_t newlen, struct proc *p)
312 {
313     int error;
314
315     switch (name[0]) {
316     case AFS_SC_ALL:
317         /* nothing defined */
318         break;
319     case AFS_SC_DARWIN:
320         if (namelen < 3)
321             return ENOENT;
322         switch (name[1]) {
323         case AFS_SC_DARWIN_ALL:
324             switch (name[2]) {
325             case AFS_SC_DARWIN_ALL_REALMODES:
326                 return sysctl_int(oldp, oldlenp, newp, newlen,
327                                   &afs_darwin_realmodes);
328             }
329             break;
330             /* darwin version specific sysctl's goes here */
331         }
332         break;
333     }
334     return EOPNOTSUPP;
335 }
336
337 typedef (*PFI) ();
338 extern int vfs_opv_numops;      /* The total number of defined vnode operations */
339 extern struct vnodeopv_desc afs_vnodeop_opv_desc;
340 int
341 afs_init(struct vfsconf *vfc)
342 {
343     int j;
344     int (**opv_desc_vector) ();
345     struct vnodeopv_entry_desc *opve_descp;
346
347
348
349     MALLOC(afs_vnodeop_p, PFI *, vfs_opv_numops * sizeof(PFI), M_TEMP,
350            M_WAITOK);
351
352     memset(afs_vnodeop_p, 0, vfs_opv_numops * sizeof(PFI));
353
354     opv_desc_vector = afs_vnodeop_p;
355     for (j = 0; afs_vnodeop_opv_desc.opv_desc_ops[j].opve_op; j++) {
356         opve_descp = &(afs_vnodeop_opv_desc.opv_desc_ops[j]);
357
358         /*
359          * Sanity check:  is this operation listed
360          * in the list of operations?  We check this
361          * by seeing if its offest is zero.  Since
362          * the default routine should always be listed
363          * first, it should be the only one with a zero
364          * offset.  Any other operation with a zero
365          * offset is probably not listed in
366          * vfs_op_descs, and so is probably an error.
367          *
368          * A panic here means the layer programmer
369          * has committed the all-too common bug
370          * of adding a new operation to the layer's
371          * list of vnode operations but
372          * not adding the operation to the system-wide
373          * list of supported operations.
374          */
375         if (opve_descp->opve_op->vdesc_offset == 0
376             && opve_descp->opve_op->vdesc_offset != VOFFSET(vop_default)) {
377             printf("afs_init: operation %s not listed in %s.\n",
378                    opve_descp->opve_op->vdesc_name, "vfs_op_descs");
379             panic("load_afs: bad operation");
380         }
381         /*
382          * Fill in this entry.
383          */
384         opv_desc_vector[opve_descp->opve_op->vdesc_offset] =
385             opve_descp->opve_impl;
386     }
387
388     /*
389      * Finally, go back and replace unfilled routines
390      * with their default.  (Sigh, an O(n^3) algorithm.  I
391      * could make it better, but that'd be work, and n is small.)
392      */
393
394     /*
395      * Force every operations vector to have a default routine.
396      */
397     opv_desc_vector = afs_vnodeop_p;
398     if (opv_desc_vector[VOFFSET(vop_default)] == NULL) {
399         panic("afs_init: operation vector without default routine.");
400     }
401     for (j = 0; j < vfs_opv_numops; j++)
402         if (opv_desc_vector[j] == NULL)
403             opv_desc_vector[j] = opv_desc_vector[VOFFSET(vop_default)];
404 }
405
406 struct vfsops afs_vfsops = {
407     afs_mount,
408     afs_start,
409     afs_unmount,
410     afs_root,
411     afs_quotactl,
412     afs_statfs,
413     afs_sync,
414     afs_vget,
415     afs_fhtovp,
416     afs_vptofh,
417     afs_init,
418     afs_sysctl
419 };