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