b2cd97e3d88f49f625cf6a23dd7319c49231e1dc
[openafs.git] / src / afs / AIX / osi_vfsops.c
1 /*
2  * Copyright 2000, International Business Machines Corporation and others.
3  * All Rights Reserved.
4  * 
5  * This software has been released under the terms of the IBM Public
6  * License.  For details, see the LICENSE file in the top-level source
7  * directory or online at http://www.openafs.org/dl/license10.html
8  */
9
10 /*
11  * osi_vfsops.c for AIX
12  */
13 #include <afsconfig.h>
14 #include "afs/param.h"
15
16
17 #include "afs/sysincludes.h"    /* Standard vendor system headers */
18 #include "afsincludes.h"        /* Afs-based standard headers */
19 #include "afs/afs_stats.h"      /* statistics stuff */
20
21
22 #ifdef AFS_AIX_IAUTH_ENV
23 #include "afs/nfsclient.h"
24 #include "afs/exporter.h"
25 extern struct afs_exporter *afs_nfsexporter;
26 #endif
27
28 #define AFS_VFSLOCK_DECL register int glockOwner = ISAFS_GLOCK()
29 #define AFS_VFSLOCK()   if (!glockOwner) AFS_GLOCK()
30 #define AFS_VFSUNLOCK() if (!glockOwner) AFS_GUNLOCK()
31
32 struct vfs *afs_globalVFS = 0;
33 struct vcache *afs_globalVp = 0;
34
35 static int afs_root_nolock(struct vfs *afsp, struct vnode **avpp);
36
37 static int
38 afs_mount(afsp, path, data)
39      char *path;
40      caddr_t data;
41      struct vfs *afsp;
42 {
43     struct vnode *afsrootvp = NULL;
44     int error;
45     AFS_VFSLOCK_DECL;
46     AFS_VFSLOCK();
47     AFS_STATCNT(afs_mount);
48
49     if (afs_globalVFS) {
50         /* Don't allow remounts since some system (like AIX) don't handle
51          * it well.
52          */
53         AFS_VFSUNLOCK();
54         return (setuerror(EBUSY));
55     }
56
57
58     afs_globalVFS = afsp;
59     afsp->vfs_bsize = 8192;
60     afsp->vfs_count = 0;
61 #ifdef AFS_64BIT_CLIENT
62     afsp->vfs_flag |= VFS_DEVMOUNT;
63 #endif /* AFS_64BIT_CLIENT */
64
65     afsp->vfs_fsid.val[0] = AFS_VFSMAGIC;       /* magic */
66     afsp->vfs_fsid.val[1] = AFS_VFSFSID;
67
68     /* For AFS, we don't allow file over file mounts. */
69     if (afsp->vfs_mntdover->v_type != VDIR)
70         return (ENOTDIR);
71     /* try to get the root vnode, but don't worry if you don't.  The actual
72      * setting of the root vnode (vfs_mntd) is done in afs_root, so that it
73      * get re-eval'd at the right time if things aren't working when we
74      * first try the mount.
75      */
76     afs_root_nolock(afsp, &afsrootvp);
77
78     afsp->vfs_mntdover->v_mvfsp = afsp;
79     afsp->vfs_mdata->vmt_flags |= MNT_REMOTE;
80
81 #ifdef AFS_AIX51_ENV
82     afsp->vfs_count = 1;
83     afsp->vfs_mntd->v_count = 1;
84 #endif
85 #ifdef AFS_AIX_IAUTH_ENV
86     if (afs_iauth_register() < 0)
87         afs_warn("Can't register AFS iauth interface.\n");
88 #endif
89     AFS_VFSUNLOCK();
90     return 0;
91 }
92
93 static int
94 afs_unmount(struct vfs *afsp, int flag)
95 {
96     AFS_VFSLOCK_DECL;
97     AFS_VFSLOCK();
98     AFS_STATCNT(afs_unmount);
99
100     afs_globalVFS = 0;
101     afs_cold_shutdown = 1;
102     afs_shutdown();
103
104     AFS_VFSUNLOCK();
105     return 0;
106 }
107
108 static int
109 afs_root_nolock(struct vfs *afsp, struct vnode **avpp)
110 {
111     register afs_int32 code = 0;
112     struct vrequest treq;
113     register struct vcache *tvp = 0;
114
115     AFS_STATCNT(afs_root);
116     if (afs_globalVp && (afs_globalVp->f.states & CStatd)) {
117         tvp = afs_globalVp;
118     } else {
119         struct ucred *credp;
120         if (afs_globalVp) {
121             afs_PutVCache(afs_globalVp);
122             afs_globalVp = NULL;
123         }
124         credp = crref();
125         if (!(code = afs_InitReq(&treq, credp)) && !(code = afs_CheckInit())) {
126             tvp = afs_GetVCache(&afs_rootFid, &treq, NULL, NULL);
127             /* we really want this to stay around */
128             if (tvp) {
129                 afs_globalVp = tvp;
130             } else
131                 code = ENOENT;
132         }
133         crfree(credp);
134     }
135     if (tvp) {
136         VN_HOLD(AFSTOV(tvp));
137
138         VN_LOCK(AFSTOV(tvp));
139         AFSTOV(tvp)->v_flag |= VROOT;   /* No-op on Ultrix 2.2 */
140         VN_UNLOCK(AFSTOV(tvp));
141
142         afs_globalVFS = afsp;
143         *avpp = AFSTOV(tvp);
144         afsp->vfs_mntd = *avpp;
145     }
146
147     afs_Trace2(afs_iclSetp, CM_TRACE_VFSROOT, ICL_TYPE_POINTER, *avpp,
148                ICL_TYPE_INT32, code);
149     return code;
150 }
151
152
153 static int
154 afs_root(struct vfs *afsp, struct vnode **avpp)
155 {
156     int code;
157     AFS_VFSLOCK_DECL;
158     AFS_VFSLOCK();
159     code = afs_root_nolock(afsp, avpp);
160     AFS_VFSUNLOCK();
161     return code;
162 }
163
164 static int
165 afs_statfs(struct vfs *afsp, struct statfs *abp, struct ucred *credp)
166 {
167     AFS_VFSLOCK_DECL;
168     AFS_VFSLOCK();
169     AFS_STATCNT(afs_statfs);
170
171     abp->f_version = 0;
172     abp->f_type = 0;
173     abp->f_bsize = afsp->vfs_bsize;
174     abp->f_blocks = abp->f_bfree = abp->f_bavail = abp->f_files =
175         abp->f_ffree = 9000000;
176     abp->f_vfstype = AFS_VFSFSID;
177     abp->f_vfsnumber = afsp->vfs_number;
178     abp->f_vfsoff = abp->f_vfslen = abp->f_vfsvers = -1;
179     abp->f_fsize = 4096;        /* fundamental filesystem block size */
180     abp->f_fsid = afsp->vfs_fsid;
181     (void)strcpy(abp->f_fname, "/afs");
182     (void)strcpy(abp->f_fpack, "AFS");
183     abp->f_name_max = 256;
184
185     AFS_VFSUNLOCK();
186     return 0;
187 }
188
189 static int
190 afs_sync()
191 {
192     AFS_VFSLOCK_DECL;
193     AFS_VFSLOCK();
194     AFS_STATCNT(afs_sync);
195
196     AFS_VFSUNLOCK();
197     return 0;
198 }
199
200
201 /* Note that the cred is only for AIX 4.1.5+ and AIX 4.2+ */
202 static int
203 afs_vget(struct vfs *vfsp, struct vnode **avcp, struct fileid *fidp,
204          struct ucred *credp)
205 {
206     int code;
207     struct vrequest treq;
208     AFS_VFSLOCK_DECL;
209     AFS_VFSLOCK();
210     AFS_STATCNT(afs_vget);
211     *avcp = NULL;
212
213 #ifdef AFS_AIX_IAUTH_ENV
214     /* If the exporter is off and this is an nfsd, fail immediately. */
215     if (AFS_NFSXLATORREQ(credp)
216         && !(afs_nfsexporter->exp_states & EXP_EXPORTED)) {
217         return EACCES;
218     }
219 #endif
220
221     if ((code = afs_InitReq(&treq, credp)) == 0) {
222         code = afs_osi_vget((struct vcache **)avcp, fidp, &treq);
223     }
224
225     afs_Trace3(afs_iclSetp, CM_TRACE_VGET, ICL_TYPE_POINTER, *avcp,
226                ICL_TYPE_INT32, treq.uid, ICL_TYPE_FID, fidp);
227     code = afs_CheckCode(code, &treq, 42);
228
229     AFS_VFSUNLOCK();
230     return code;
231 }
232
233 static int
234 afs_badop()
235 {
236     return EOPNOTSUPP;
237 }
238
239
240 struct vfsops Afs_vfsops = {
241     afs_mount,
242     afs_unmount,
243     afs_root,
244     afs_statfs,
245     afs_sync,
246     afs_vget,
247     afs_badop,                  /* vfs_cntl */
248     afs_badop                   /* vfs_quotactl */
249 #ifdef AFS_AIX51_ENV
250         , afs_badop             /* vfs_syncvfs */
251 #endif
252 };
253
254 /*
255  * VFS is initialized in osi_config.c
256  */