freebsd60-20050422
[openafs.git] / src / afs / FBSD / 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 = NULL;
16 struct mount *afs_globalVFS = NULL;
17 int afs_pbuf_freecnt = -1;
18
19 #ifdef AFS_FBSD50_ENV
20 #define THREAD_OR_PROC struct thread *p
21 #else
22 #define THREAD_OR_PROC struct proc *p
23 #endif
24
25 int
26 afs_start(struct mount *mp, int flags, THREAD_OR_PROC)
27 {
28     afs_pbuf_freecnt = nswbuf / 2 + 1;
29     return (0);                 /* nothing to do. ? */
30 }
31
32 #ifdef AFS_FBSD53_ENV
33 int
34 afs_mount(struct mount *mp, struct thread *td)
35 {
36     int afs_omount(struct mount *mp, char *path, caddr_t data, struct thread *p);
37
38     return afs_omount(mp, NULL, NULL, td);
39 }
40 #endif
41
42 int
43 #ifdef AFS_FBSD53_ENV
44 afs_omount(struct mount *mp, char *path, caddr_t data, struct thread *p)
45 #else
46 afs_omount(struct mount *mp, char *path, caddr_t data, struct nameidata *ndp,
47         THREAD_OR_PROC)
48 #endif
49 {
50     /* ndp contains the mounted-from device.  Just ignore it.
51      * we also don't care about our proc struct. */
52     size_t size;
53
54     if (mp->mnt_flag & MNT_UPDATE)
55         return EINVAL;
56
57     AFS_GLOCK();
58     AFS_STATCNT(afs_mount);
59
60     if (afs_globalVFS) {        /* Don't allow remounts. */
61         AFS_GUNLOCK();
62         return EBUSY;
63     }
64
65     afs_globalVFS = mp;
66     mp->vfs_bsize = 8192;
67     vfs_getnewfsid(mp);
68     mp->mnt_stat.f_iosize = 8192;
69
70     if (path)
71         (void) copyinstr(path, mp->mnt_stat.f_mntonname, MNAMELEN - 1, &size);
72     memset(mp->mnt_stat.f_mntonname + size, 0, MNAMELEN - size);
73     memset(mp->mnt_stat.f_mntfromname, 0, MNAMELEN);
74     strcpy(mp->mnt_stat.f_mntfromname, "AFS");
75     /* null terminated string "AFS" will fit, just leave it be. */
76     strcpy(mp->mnt_stat.f_fstypename, "afs");
77     AFS_GUNLOCK();
78     (void)afs_statfs(mp, &mp->mnt_stat, p);
79     return 0;
80 }
81
82 #ifdef AFS_FBSD60_ENV
83 static int
84 afs_cmount(struct mntarg *ma, void *data, int flags, struct thread *td)
85 {
86     return kernel_mount(ma, flags);
87 }
88 #endif
89
90 int
91 afs_unmount(struct mount *mp, int flags, THREAD_OR_PROC)
92 {
93
94     /*
95      * Release any remaining vnodes on this mount point.
96      * The `1' means that we hold one extra reference on
97      * the root vnode (this is just a guess right now).
98      * This has to be done outside the global lock.
99      */
100 #ifdef AFS_FBSD53_ENV
101     vflush(mp, 1, (flags & MNT_FORCE) ? FORCECLOSE : 0, p);
102 #else
103     vflush(mp, 1, (flags & MNT_FORCE) ? FORCECLOSE : 0);
104 #endif
105     AFS_GLOCK();
106     AFS_STATCNT(afs_unmount);
107     afs_globalVFS = 0;
108     afs_shutdown();
109     AFS_GUNLOCK();
110
111     return 0;
112 }
113
114 int
115 #ifdef AFS_FBSD53_ENV
116 afs_root(struct mount *mp, struct vnode **vpp, struct thread *td)
117 #else
118 afs_root(struct mount *mp, struct vnode **vpp)
119 #endif
120 {
121     int error;
122     struct vrequest treq;
123     register struct vcache *tvp = 0;
124 #ifdef AFS_FBSD50_ENV
125 #ifndef AFS_FBSD53_ENV
126     struct thread *td = curthread;
127 #endif
128     struct ucred *cr = td->td_ucred;
129 #else
130     struct proc *p = curproc;
131     struct ucred *cr = p->p_cred->pc_ucred;
132 #endif
133
134     AFS_GLOCK();
135     AFS_STATCNT(afs_root);
136     crhold(cr);
137     if (afs_globalVp && (afs_globalVp->states & CStatd)) {
138         tvp = afs_globalVp;
139         error = 0;
140     } else {
141 tryagain:
142         if (afs_globalVp) {
143             afs_PutVCache(afs_globalVp);
144             /* vrele() needed here or not? */
145             afs_globalVp = NULL;
146         }
147
148         if (!(error = afs_InitReq(&treq, cr)) && !(error = afs_CheckInit())) {
149             tvp = afs_GetVCache(&afs_rootFid, &treq, NULL, NULL);
150             /* we really want this to stay around */
151             if (tvp)
152                 afs_globalVp = tvp;
153             else
154                 error = ENOENT;
155         }
156     }
157     if (tvp) {
158         struct vnode *vp = AFSTOV(tvp);
159
160 #ifdef AFS_FBSD50_ENV
161         ASSERT_VI_UNLOCKED(vp, "afs_root");
162 #endif
163         AFS_GUNLOCK();
164         /*
165          * I'm uncomfortable about this.  Shouldn't this happen at a
166          * higher level, and shouldn't we busy the top-level directory
167          * to prevent recycling?
168          */
169 #ifdef AFS_FBSD50_ENV
170         error = vget(vp, LK_EXCLUSIVE | LK_RETRY, td);
171         vp->v_vflag |= VV_ROOT;
172 #else
173         error = vget(vp, LK_EXCLUSIVE | LK_RETRY, p);
174         vp->v_flag |= VROOT;
175 #endif
176         AFS_GLOCK();
177         if (error != 0)
178                 goto tryagain;
179
180         afs_globalVFS = mp;
181         *vpp = vp;
182     }
183
184     afs_Trace2(afs_iclSetp, CM_TRACE_VFSROOT, ICL_TYPE_POINTER, *vpp,
185                ICL_TYPE_INT32, error);
186     AFS_GUNLOCK();
187     crfree(cr);
188     return error;
189 }
190
191 int
192 afs_statfs(struct mount *mp, struct statfs *abp, THREAD_OR_PROC)
193 {
194     AFS_GLOCK();
195     AFS_STATCNT(afs_statfs);
196
197     abp->f_bsize = mp->vfs_bsize;
198     abp->f_iosize = mp->vfs_bsize;
199
200     /* Fake a high number below to satisfy programs that use the statfs call
201      * to make sure that there's enough space in the device partition before
202      * storing something there.
203      */
204     abp->f_blocks = abp->f_bfree = abp->f_bavail = abp->f_files =
205         abp->f_ffree = 2000000;
206
207     abp->f_fsid.val[0] = mp->mnt_stat.f_fsid.val[0];
208     abp->f_fsid.val[1] = mp->mnt_stat.f_fsid.val[1];
209     if (abp != &mp->mnt_stat) {
210         abp->f_type = mp->mnt_vfc->vfc_typenum;
211         memcpy((caddr_t) & abp->f_mntonname[0],
212                (caddr_t) mp->mnt_stat.f_mntonname, MNAMELEN);
213         memcpy((caddr_t) & abp->f_mntfromname[0],
214                (caddr_t) mp->mnt_stat.f_mntfromname, MNAMELEN);
215     }
216
217     AFS_GUNLOCK();
218     return 0;
219 }
220
221 int
222 #ifdef AFS_FBSD60_ENV
223 afs_sync(struct mount *mp, int waitfor, struct thread *td)
224 #else
225 afs_sync(struct mount *mp, int waitfor, struct ucred *cred, THREAD_OR_PROC)
226 #endif
227 {
228     return 0;
229 }
230
231 int
232 afs_init(struct vfsconf *vfc)
233 {
234     return 0;
235 }
236
237 #ifdef AFS_FBSD60_ENV
238 struct vfsops afs_vfsops = {
239         .vfs_init =             afs_init,
240         .vfs_mount =            afs_mount,
241         .vfs_cmount =           afs_cmount,
242         .vfs_root =             afs_root,
243         .vfs_statfs =           afs_statfs,
244         .vfs_sync =             afs_sync,
245         .vfs_uninit =           vfs_stduninit,
246         .vfs_unmount =          afs_unmount,
247         .vfs_sysctl =           vfs_stdsysctl,
248 };
249 #else
250 struct vfsops afs_vfsops = {
251 #ifdef AFS_FBSD53_ENV
252     afs_mount,
253 #endif
254     afs_omount,
255     afs_start,
256     afs_unmount,
257     afs_root,
258     vfs_stdquotactl,
259     afs_statfs,
260     afs_sync,
261     vfs_stdvget,
262     vfs_stdfhtovp,
263     vfs_stdcheckexp,
264     vfs_stdvptofh,
265     afs_init,
266     vfs_stduninit,
267     vfs_stdextattrctl,
268 #ifdef AFS_FBSD50_ENV
269     vfs_stdsysctl,
270 #endif
271 };
272 #endif