afs: Remove afs_xosi
[openafs.git] / src / afs / SOLARIS / osi_file.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 #include <afsconfig.h>
11 #include "afs/param.h"
12
13
14 #include "afs/sysincludes.h"    /* Standard vendor system headers */
15 #include "afsincludes.h"        /* Afs-based standard headers */
16 #include "afs/afs_stats.h"      /* afs statistics */
17 #include "afs/osi_inode.h"
18
19
20 int afs_osicred_initialized = 0;
21 extern struct osi_dev cacheDev;
22 extern struct vfs *afs_cacheVfsp;
23
24
25 #ifdef AFS_HAVE_VXFS
26
27 /* Support for UFS and VXFS caches. The assumption here is that the size of
28  * a cache file also does not exceed 32 bits. 
29  */
30
31 /* Initialized in osi_InitCacheFSType(). Used to determine inode type. */
32 int afs_CacheFSType = -1;
33
34 /* pointer to VXFS routine to access vnodes by inode number */
35 int (*vxfs_vx_vp_byino) ();
36
37 /* Initialize the cache operations. Called while initializing cache files. */
38 void
39 afs_InitDualFSCacheOps(struct vnode *vp)
40 {
41     int code;
42     static int inited = 0;
43     struct vfs *vfsp;
44     struct statvfs64 vfst;
45
46     if (inited)
47         return;
48     inited = 1;
49
50     if (vp == NULL)
51         return;
52
53     vfsp = vp->v_vfsp;
54     if (vfsp == NULL)
55         osi_Panic("afs_InitDualFSCacheOps: vp->v_vfsp is NULL");
56     code = VFS_STATVFS(vfsp, &vfst);
57     if (code)
58         osi_Panic("afs_InitDualFSCacheOps: statvfs failed");
59
60     if (strcmp(vfst.f_basetype, "vxfs") == 0) {
61         vxfs_vx_vp_byino = (int (*)())modlookup("vxfs", "vx_vp_byino");
62         if (vxfs_vx_vp_byino == NULL)
63             osi_Panic
64                 ("afs_InitDualFSCacheOps: modlookup(vx_vp_byino) failed");
65
66         afs_CacheFSType = AFS_SUN_VXFS_CACHE;
67         return;
68     }
69
70     afs_CacheFSType = AFS_SUN_UFS_CACHE;
71     return;
72 }
73
74 ino_t
75 VnodeToIno(vnode_t * vp)
76 {
77     int code;
78     struct vattr vattr;
79
80     vattr.va_mask = AT_FSID | AT_NODEID;        /* quick return using this mask. */
81 #ifdef AFS_SUN511_ENV
82     code = VOP_GETATTR(vp, &vattr, 0, afs_osi_credp, NULL);
83 #else
84     code = VOP_GETATTR(vp, &vattr, 0, afs_osi_credp);
85 #endif
86     if (code) {
87         osi_Panic("VnodeToIno");
88     }
89     return vattr.va_nodeid;
90 }
91
92 dev_t
93 VnodeToDev(vnode_t * vp)
94 {
95     int code;
96     struct vattr vattr;
97
98     vattr.va_mask = AT_FSID | AT_NODEID;        /* quick return using this mask. */
99     AFS_GUNLOCK();
100 #ifdef AFS_SUN511_ENV
101     code = VOP_GETATTR(vp, &vattr, 0, afs_osi_credp, NULL);
102 #else
103     code = VOP_GETATTR(vp, &vattr, 0, afs_osi_credp);
104 #endif
105     AFS_GLOCK();
106     if (code) {
107         osi_Panic("VnodeToDev");
108     }
109     return (dev_t) vattr.va_fsid;
110 }
111
112 afs_int32
113 VnodeToSize(vnode_t * vp)
114 {
115     int code;
116     struct vattr vattr;
117
118     vattr.va_mask = AT_SIZE;
119     AFS_GUNLOCK();
120 #ifdef AFS_SUN511_ENV
121     code = VOP_GETATTR(vp, &vattr, 0, afs_osi_credp, NULL);
122 #else
123     code = VOP_GETATTR(vp, &vattr, 0, afs_osi_credp);
124 #endif
125     AFS_GLOCK();
126     if (code) {
127         osi_Panic("VnodeToSize");
128     }
129     return (afs_int32) (vattr.va_size);
130 }
131
132 void *
133 osi_VxfsOpen(afs_dcache_id_t *ainode)
134 {
135     struct vnode *vp;
136     struct osi_file *afile = NULL;
137     afs_int32 code = 0;
138     int dummy;
139     afile = osi_AllocSmallSpace(sizeof(struct osi_file));
140     AFS_GUNLOCK();
141     code = (*vxfs_vx_vp_byino) (afs_cacheVfsp, &vp, (unsigned int)ainode->ufs);
142     AFS_GLOCK();
143     if (code) {
144         osi_FreeSmallSpace(afile);
145         osi_Panic("VxfsOpen: vx_vp_byino failed");
146     }
147     afile->vnode = vp;
148     afile->size = VnodeToSize(afile->vnode);
149     afile->offset = 0;
150     afile->proc = (int (*)())0;
151     return (void *)afile;
152 }
153 #endif /* AFS_HAVE_VXFS */
154
155 void *
156 osi_UfsOpen(afs_dcache_id_t *ainode)
157 {
158 #ifdef AFS_CACHE_VNODE_PATH
159     struct vnode *vp;
160 #else
161     struct inode *ip;
162 #endif
163     struct osi_file *afile = NULL;
164     afs_int32 code = 0;
165     int dummy;
166 #ifdef AFS_CACHE_VNODE_PATH
167     char namebuf[1024];
168     struct pathname lookpn;
169 #endif
170     struct osi_stat tstat;
171     afile = osi_AllocSmallSpace(sizeof(struct osi_file));
172     AFS_GUNLOCK();
173
174     /*
175      * AFS_CACHE_VNODE_PATH can be used with any file system, including ZFS or tmpfs.
176      * The ainode is not an inode number but a path.
177      */
178 #ifdef AFS_CACHE_VNODE_PATH
179     /* Can not use vn_open or lookupname, they use user's CRED()
180      * We need to run as root So must use low level lookuppnvp
181      * assume fname starts with /
182      */
183
184     code = pn_get_buf(ainode->ufs, AFS_UIOSYS, &lookpn, namebuf, sizeof(namebuf));
185     if (code != 0) 
186         osi_Panic("UfsOpen: pn_get_buf failed %ld %s", code, ainode->ufs);
187  
188         VN_HOLD(rootdir); /* released in loopuppnvp */
189         code = lookuppnvp(&lookpn, NULL, FOLLOW, NULL, &vp, 
190            rootdir, rootdir, afs_osi_credp);
191     if (code != 0)  
192         osi_Panic("UfsOpen: lookuppnvp failed %ld %s", code, ainode->ufs);
193         
194 #ifdef AFS_SUN511_ENV
195     code = VOP_OPEN(&vp, FREAD|FWRITE, afs_osi_credp, NULL);
196 #else
197     code = VOP_OPEN(&vp, FREAD|FWRITE, afs_osi_credp);
198 #endif
199
200     if (code != 0)
201         osi_Panic("UfsOpen: VOP_OPEN failed %ld %s", code, ainode->ufs);
202
203 #else
204     code =
205         igetinode(afs_cacheVfsp, (dev_t) cacheDev.dev, ainode->ufs, &ip,
206                   CRED(), &dummy);
207 #endif
208     AFS_GLOCK();
209     if (code) {
210         osi_FreeSmallSpace(afile);
211         osi_Panic("UfsOpen: igetinode failed %ld %s", code, ainode->ufs);
212     }
213 #ifdef AFS_CACHE_VNODE_PATH
214     afile->vnode = vp;
215     code = afs_osi_Stat(afile, &tstat);
216     afile->size = tstat.size;
217 #else
218     afile->vnode = ITOV(ip);
219     afile->size = VTOI(afile->vnode)->i_size;
220 #endif
221     afile->offset = 0;
222     afile->proc = (int (*)())0;
223     return (void *)afile;
224 }
225
226 /**
227   * In Solaris 7 we use 64 bit inode numbers
228   */
229 void *
230 osi_UFSOpen(afs_dcache_id_t *ainode)
231 {
232     extern int cacheDiskType;
233     AFS_STATCNT(osi_UFSOpen);
234     if (cacheDiskType != AFS_FCACHE_TYPE_UFS) {
235         osi_Panic("UFSOpen called for non-UFS cache\n");
236     }
237     if (!afs_osicred_initialized) {
238         afs_osi_credp = kcred;
239         afs_osicred_initialized = 1;
240     }
241 #ifdef AFS_HAVE_VXFS
242     if (afs_CacheFSType == AFS_SUN_VXFS_CACHE)
243         return osi_VxfsOpen(ainode);
244 #endif
245     return osi_UfsOpen(ainode);
246 }
247
248 int
249 afs_osi_Stat(struct osi_file *afile, struct osi_stat *astat)
250 {
251     afs_int32 code;
252     struct vattr tvattr;
253     AFS_STATCNT(osi_Stat);
254     /* Ufs doesn't seem to care about the flags so we pass 0 for now */
255     tvattr.va_mask = AT_ALL;
256     AFS_GUNLOCK();
257 #ifdef AFS_SUN511_ENV 
258     code = VOP_GETATTR(afile->vnode, &tvattr, 0, afs_osi_credp, NULL);
259 #else
260     code = VOP_GETATTR(afile->vnode, &tvattr, 0, afs_osi_credp);
261 #endif
262     AFS_GLOCK();
263     if (code == 0) {
264         astat->size = tvattr.va_size;
265         astat->mtime = tvattr.va_mtime.tv_sec;
266         astat->atime = tvattr.va_atime.tv_sec;
267     }
268     return code;
269 }
270
271 int
272 osi_UFSClose(struct osi_file *afile)
273 {
274     AFS_STATCNT(osi_Close);
275     if (afile->vnode) {
276         AFS_RELE(afile->vnode);
277     }
278
279     osi_FreeSmallSpace(afile);
280     return 0;
281 }
282
283 int
284 osi_UFSTruncate(struct osi_file *afile, afs_int32 asize)
285 {
286     afs_ucred_t *oldCred;
287     struct vattr tvattr;
288     afs_int32 code;
289     struct osi_stat tstat;
290     AFS_STATCNT(osi_Truncate);
291
292     /* This routine only shrinks files, and most systems
293      * have very slow truncates, even when the file is already
294      * small enough.  Check now and save some time.
295      */
296     code = afs_osi_Stat(afile, &tstat);
297     if (code || tstat.size <= asize)
298         return code;
299     tvattr.va_mask = AT_SIZE;
300     tvattr.va_size = asize;
301     /*
302      * The only time a flag is used (ATTR_UTIME) is when we're changing the time 
303      */
304     AFS_GUNLOCK();
305 #ifdef AFS_SUN510_ENV
306     code = VOP_SETATTR(afile->vnode, &tvattr, 0, afs_osi_credp, NULL);
307 #else
308     code = VOP_SETATTR(afile->vnode, &tvattr, 0, afs_osi_credp);
309 #endif
310     AFS_GLOCK();
311     return code;
312 }
313
314 void
315 osi_DisableAtimes(struct vnode *avp)
316 {
317     if (afs_CacheFSType == AFS_SUN_UFS_CACHE) {
318 #ifndef AFS_CACHE_VNODE_PATH 
319         struct inode *ip = VTOI(avp);
320         rw_enter(&ip->i_contents, RW_READER);
321         mutex_enter(&ip->i_tlock);
322         ip->i_flag &= ~IACC;
323         mutex_exit(&ip->i_tlock);
324         rw_exit(&ip->i_contents);
325 #endif
326     }
327 }
328
329
330 /* Generic read interface */
331 int
332 afs_osi_Read(struct osi_file *afile, int offset, void *aptr,
333              afs_int32 asize)
334 {
335     afs_ucred_t *oldCred;
336     ssize_t resid;
337     afs_int32 code;
338     afs_int32 cnt1 = 0;
339     AFS_STATCNT(osi_Read);
340
341     /**
342       * If the osi_file passed in is NULL, panic only if AFS is not shutting
343       * down. No point in crashing when we are already shutting down
344       */
345     if (!afile) {
346         if (afs_shuttingdown == AFS_RUNNING)
347             osi_Panic("osi_Read called with null param");
348         else
349             return -EIO;
350     }
351
352     if (offset != -1)
353         afile->offset = offset;
354     AFS_GUNLOCK();
355     code =
356         gop_rdwr(UIO_READ, afile->vnode, (caddr_t) aptr, asize, afile->offset,
357                  AFS_UIOSYS, 0, 0, afs_osi_credp, &resid);
358     AFS_GLOCK();
359     if (code == 0) {
360         code = asize - resid;
361         afile->offset += code;
362         osi_DisableAtimes(afile->vnode);
363     } else {
364         afs_Trace2(afs_iclSetp, CM_TRACE_READFAILED, ICL_TYPE_INT32, resid,
365                    ICL_TYPE_INT32, code);
366         if (code > 0) {
367             code = -code;
368         }
369     }
370     return code;
371 }
372
373 /* Generic write interface */
374 int
375 afs_osi_Write(struct osi_file *afile, afs_int32 offset, void *aptr,
376               afs_int32 asize)
377 {
378     afs_ucred_t *oldCred;
379     ssize_t resid;
380     afs_int32 code;
381     AFS_STATCNT(osi_Write);
382     if (!afile)
383         osi_Panic("afs_osi_Write called with null param");
384     if (offset != -1)
385         afile->offset = offset;
386     AFS_GUNLOCK();
387     code =
388         gop_rdwr(UIO_WRITE, afile->vnode, (caddr_t) aptr, asize,
389                  afile->offset, AFS_UIOSYS, 0, RLIM64_INFINITY, afs_osi_credp,
390                  &resid);
391     AFS_GLOCK();
392     if (code == 0) {
393         code = asize - resid;
394         afile->offset += code;
395     } else {
396         if (code > 0) {
397             code = -code;
398         }
399     }
400     if (afile->proc) {
401         (*afile->proc) (afile, code);
402     }
403     return code;
404 }
405
406
407 /*  This work should be handled by physstrat in ca/machdep.c.
408     This routine written from the RT NFS port strategy routine.
409     It has been generalized a bit, but should still be pretty clear. */
410 int
411 afs_osi_MapStrategy(int (*aproc) (), struct buf *bp)
412 {
413     afs_int32 returnCode;
414
415     AFS_STATCNT(osi_MapStrategy);
416     returnCode = (*aproc) (bp);
417
418     return returnCode;
419 }
420
421
422
423 void
424 shutdown_osifile(void)
425 {
426     AFS_STATCNT(shutdown_osifile);
427     if (afs_cold_shutdown) {
428         afs_osicred_initialized = 0;
429     }
430 }