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