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