macos103-20031024
[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                 afs_globalVFS = 0;
158                 afs_shutdown();
159             } else {
160                 AFS_GUNLOCK();
161                 return EBUSY;
162             }
163         }
164         mp->mnt_flag &= ~MNT_LOCAL;
165     }
166
167     AFS_GUNLOCK();
168
169     return 0;
170 }
171
172 int
173 afs_root(struct mount *mp, struct vnode **vpp)
174 {
175     int error;
176     struct vrequest treq;
177     register struct vcache *tvp = 0;
178     struct proc *p = current_proc();
179     struct ucred cr;
180
181     pcred_readlock(p);
182     cr = *p->p_cred->pc_ucred;
183     pcred_unlock(p);
184     AFS_GLOCK();
185     AFS_STATCNT(afs_root);
186     if (mp->mnt_data == NULL && afs_globalVp
187         && (afs_globalVp->states & CStatd)) {
188         tvp = afs_globalVp;
189         error = 0;
190     } else if (mp->mnt_data == (qaddr_t) - 1) {
191         error = ENOENT;
192     } else {
193         struct VenusFid *rootFid = (mp->mnt_data == NULL)
194             ? &afs_rootFid : (struct VenusFid *)mp->mnt_data;
195
196         if (afs_globalVp) {
197             afs_PutVCache(afs_globalVp);
198             afs_globalVp = NULL;
199         }
200
201         if (!(error = afs_InitReq(&treq, &cr)) && !(error = afs_CheckInit())) {
202             tvp = afs_GetVCache(rootFid, &treq, NULL, NULL);
203             /* we really want this to stay around */
204             if (tvp) {
205                 if (mp->mnt_data == NULL)
206                     afs_globalVp = tvp;
207             } else
208                 error = ENOENT;
209         }
210     }
211     if (tvp) {
212         osi_vnhold(tvp, 0);
213         AFS_GUNLOCK();
214         vn_lock(AFSTOV(tvp), LK_EXCLUSIVE | LK_RETRY, p);
215         AFS_GLOCK();
216         if (mp->mnt_data == NULL) {
217             afs_globalVFS = mp;
218         }
219         *vpp = AFSTOV(tvp);
220         AFSTOV(tvp)->v_flag |= VROOT;
221         AFSTOV(tvp)->v_vfsp = mp;
222     }
223
224     afs_Trace2(afs_iclSetp, CM_TRACE_VFSROOT, ICL_TYPE_POINTER, *vpp,
225                ICL_TYPE_INT32, error);
226     AFS_GUNLOCK();
227     return error;
228 }
229
230 int
231 afs_vget(mp, lfl, vp)
232      struct mount *mp;
233      struct vnode *vp;
234      int lfl;
235 {
236     int error;
237     printf("vget called. help!\n");
238     if (vp->v_usecount < 0) {
239         vprint("bad usecount", vp);
240         panic("afs_vget");
241     }
242     error = vget(vp, lfl, current_proc());
243     if (!error)
244         insmntque(vp, mp);      /* take off free list */
245     return error;
246 }
247
248 int
249 afs_statfs(struct mount *mp, struct statfs *abp, struct proc *p)
250 {
251     AFS_GLOCK();
252     AFS_STATCNT(afs_statfs);
253
254 #if 0
255     abp->f_type = MOUNT_AFS;
256 #endif
257     abp->f_bsize = mp->vfs_bsize;
258     abp->f_iosize = mp->vfs_bsize;
259
260     /* Fake a high number below to satisfy programs that use the statfs call
261      * to make sure that there's enough space in the device partition before
262      * storing something there.
263      */
264     abp->f_blocks = abp->f_bfree = abp->f_bavail = abp->f_files =
265         abp->f_ffree = 2000000;
266
267     abp->f_fsid.val[0] = mp->mnt_stat.f_fsid.val[0];
268     abp->f_fsid.val[1] = mp->mnt_stat.f_fsid.val[1];
269     if (abp != &mp->mnt_stat) {
270         abp->f_type = mp->mnt_vfc->vfc_typenum;
271         memcpy((caddr_t) & abp->f_mntonname[0],
272                (caddr_t) mp->mnt_stat.f_mntonname, MNAMELEN);
273         memcpy((caddr_t) & abp->f_mntfromname[0],
274                (caddr_t) mp->mnt_stat.f_mntfromname, MNAMELEN);
275     }
276
277     AFS_GUNLOCK();
278     return 0;
279 }
280
281 int
282 afs_sync(mp, waitfor, cred, p)
283      struct mount *mp;
284      int waitfor;
285      struct ucred *cred;
286      struct prioc *p;
287 {
288     return 0;
289 }
290
291 u_int32_t afs_darwin_realmodes = 0;
292
293 int afs_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, 
294                void *newp, size_t newlen, struct proc *p)
295 {
296     int error;
297
298     switch (name[0]) {
299     case AFS_SC_ALL:
300         /* nothing defined */
301         break;
302     case AFS_SC_DARWIN:
303         if (namelen < 3)
304             return ENOENT;
305         switch (name[1]) {
306         case AFS_SC_DARWIN_ALL:
307             switch (name[2]) {
308             case AFS_SC_DARWIN_ALL_REALMODES:
309                 return sysctl_int(oldp, oldlenp, newp, newlen,
310                                   &afs_darwin_realmodes);
311             }
312             break;
313             /* darwin version specific sysctl's goes here */
314         }
315         break;
316     }
317     return EOPNOTSUPP;
318 }
319
320 typedef (*PFI) ();
321 extern int vfs_opv_numops;      /* The total number of defined vnode operations */
322 extern struct vnodeopv_desc afs_vnodeop_opv_desc;
323 int
324 afs_init(struct vfsconf *vfc)
325 {
326     int j;
327     int (**opv_desc_vector) ();
328     struct vnodeopv_entry_desc *opve_descp;
329
330
331
332     MALLOC(afs_vnodeop_p, PFI *, vfs_opv_numops * sizeof(PFI), M_TEMP,
333            M_WAITOK);
334
335     memset(afs_vnodeop_p, 0, vfs_opv_numops * sizeof(PFI));
336
337     opv_desc_vector = afs_vnodeop_p;
338     for (j = 0; afs_vnodeop_opv_desc.opv_desc_ops[j].opve_op; j++) {
339         opve_descp = &(afs_vnodeop_opv_desc.opv_desc_ops[j]);
340
341         /*
342          * Sanity check:  is this operation listed
343          * in the list of operations?  We check this
344          * by seeing if its offest is zero.  Since
345          * the default routine should always be listed
346          * first, it should be the only one with a zero
347          * offset.  Any other operation with a zero
348          * offset is probably not listed in
349          * vfs_op_descs, and so is probably an error.
350          *
351          * A panic here means the layer programmer
352          * has committed the all-too common bug
353          * of adding a new operation to the layer's
354          * list of vnode operations but
355          * not adding the operation to the system-wide
356          * list of supported operations.
357          */
358         if (opve_descp->opve_op->vdesc_offset == 0
359             && opve_descp->opve_op->vdesc_offset != VOFFSET(vop_default)) {
360             printf("afs_init: operation %s not listed in %s.\n",
361                    opve_descp->opve_op->vdesc_name, "vfs_op_descs");
362             panic("load_afs: bad operation");
363         }
364         /*
365          * Fill in this entry.
366          */
367         opv_desc_vector[opve_descp->opve_op->vdesc_offset] =
368             opve_descp->opve_impl;
369     }
370
371     /*
372      * Finally, go back and replace unfilled routines
373      * with their default.  (Sigh, an O(n^3) algorithm.  I
374      * could make it better, but that'd be work, and n is small.)
375      */
376
377     /*
378      * Force every operations vector to have a default routine.
379      */
380     opv_desc_vector = afs_vnodeop_p;
381     if (opv_desc_vector[VOFFSET(vop_default)] == NULL) {
382         panic("afs_init: operation vector without default routine.");
383     }
384     for (j = 0; j < vfs_opv_numops; j++)
385         if (opv_desc_vector[j] == NULL)
386             opv_desc_vector[j] = opv_desc_vector[VOFFSET(vop_default)];
387 }
388
389 struct vfsops afs_vfsops = {
390     afs_mount,
391     afs_start,
392     afs_unmount,
393     afs_root,
394     afs_quotactl,
395     afs_statfs,
396     afs_sync,
397     afs_vget,
398     afs_fhtovp,
399     afs_vptofh,
400     afs_init,
401     afs_sysctl
402 };