2 * Copyright 2000, International Business Machines Corporation and others.
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
10 #include <afsconfig.h>
11 #include "afs/param.h"
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"
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
;
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.
32 /* Initialized in osi_InitCacheFSType(). Used to determine inode type. */
33 int afs_CacheFSType
= -1;
35 /* pointer to VXFS routine to access vnodes by inode number */
36 int (*vxfs_vx_vp_byino
) ();
38 /* Initialize the cache operations. Called while initializing cache files. */
40 afs_InitDualFSCacheOps(struct vnode
*vp
)
43 static int inited
= 0;
45 struct statvfs64 vfst
;
56 osi_Panic("afs_InitDualFSCacheOps: vp->v_vfsp is NULL");
57 code
= VFS_STATVFS(vfsp
, &vfst
);
59 osi_Panic("afs_InitDualFSCacheOps: statvfs failed");
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
)
65 ("afs_InitDualFSCacheOps: modlookup(vx_vp_byino) failed");
67 afs_CacheFSType
= AFS_SUN_VXFS_CACHE
;
71 afs_CacheFSType
= AFS_SUN_UFS_CACHE
;
76 VnodeToIno(vnode_t
* vp
)
81 vattr
.va_mask
= AT_FSID
| AT_NODEID
; /* quick return using this mask. */
83 code
= VOP_GETATTR(vp
, &vattr
, 0, afs_osi_credp
, NULL
);
85 code
= VOP_GETATTR(vp
, &vattr
, 0, afs_osi_credp
);
88 osi_Panic("VnodeToIno");
90 return vattr
.va_nodeid
;
94 VnodeToDev(vnode_t
* vp
)
99 vattr
.va_mask
= AT_FSID
| AT_NODEID
; /* quick return using this mask. */
101 #ifdef AFS_SUN511_ENV
102 code
= VOP_GETATTR(vp
, &vattr
, 0, afs_osi_credp
, NULL
);
104 code
= VOP_GETATTR(vp
, &vattr
, 0, afs_osi_credp
);
108 osi_Panic("VnodeToDev");
110 return (dev_t
) vattr
.va_fsid
;
114 VnodeToSize(vnode_t
* vp
)
120 * We lock xosi in osi_Stat, so we probably should
121 * lock it here too - RWH.
123 ObtainWriteLock(&afs_xosi
, 578);
124 vattr
.va_mask
= AT_SIZE
;
126 #ifdef AFS_SUN511_ENV
127 code
= VOP_GETATTR(vp
, &vattr
, 0, afs_osi_credp
, NULL
);
129 code
= VOP_GETATTR(vp
, &vattr
, 0, afs_osi_credp
);
133 osi_Panic("VnodeToSize");
135 ReleaseWriteLock(&afs_xosi
);
136 return (afs_int32
) (vattr
.va_size
);
140 osi_VxfsOpen(afs_dcache_id_t
*ainode
)
143 struct osi_file
*afile
= NULL
;
146 afile
= osi_AllocSmallSpace(sizeof(struct osi_file
));
148 code
= (*vxfs_vx_vp_byino
) (afs_cacheVfsp
, &vp
, (unsigned int)ainode
->ufs
);
151 osi_FreeSmallSpace(afile
);
152 osi_Panic("VxfsOpen: vx_vp_byino failed");
155 afile
->size
= VnodeToSize(afile
->vnode
);
157 afile
->proc
= (int (*)())0;
158 return (void *)afile
;
160 #endif /* AFS_HAVE_VXFS */
163 osi_UfsOpen(afs_dcache_id_t
*ainode
)
165 #ifdef AFS_CACHE_VNODE_PATH
170 struct osi_file
*afile
= NULL
;
173 #ifdef AFS_CACHE_VNODE_PATH
175 struct pathname lookpn
;
177 struct osi_stat tstat
;
178 afile
= osi_AllocSmallSpace(sizeof(struct osi_file
));
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.
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 /
191 code
= pn_get_buf(ainode
->ufs
, AFS_UIOSYS
, &lookpn
, namebuf
, sizeof(namebuf
));
193 osi_Panic("UfsOpen: pn_get_buf failed %ld %s", code
, ainode
->ufs
);
195 VN_HOLD(rootdir
); /* released in loopuppnvp */
196 code
= lookuppnvp(&lookpn
, NULL
, FOLLOW
, NULL
, &vp
,
197 rootdir
, rootdir
, afs_osi_credp
);
199 osi_Panic("UfsOpen: lookuppnvp failed %ld %s", code
, ainode
->ufs
);
201 #ifdef AFS_SUN511_ENV
202 code
= VOP_OPEN(&vp
, FREAD
|FWRITE
, afs_osi_credp
, NULL
);
204 code
= VOP_OPEN(&vp
, FREAD
|FWRITE
, afs_osi_credp
);
208 osi_Panic("UfsOpen: VOP_OPEN failed %ld %s", code
, ainode
->ufs
);
212 igetinode(afs_cacheVfsp
, (dev_t
) cacheDev
.dev
, ainode
->ufs
, &ip
,
217 osi_FreeSmallSpace(afile
);
218 osi_Panic("UfsOpen: igetinode failed %ld %s", code
, ainode
->ufs
);
220 #ifdef AFS_CACHE_VNODE_PATH
222 code
= afs_osi_Stat(afile
, &tstat
);
223 afile
->size
= tstat
.size
;
225 afile
->vnode
= ITOV(ip
);
226 afile
->size
= VTOI(afile
->vnode
)->i_size
;
229 afile
->proc
= (int (*)())0;
230 return (void *)afile
;
234 * In Solaris 7 we use 64 bit inode numbers
237 osi_UFSOpen(afs_dcache_id_t
*ainode
)
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");
244 if (!afs_osicred_initialized
) {
245 afs_osi_credp
= kcred
;
246 afs_osicred_initialized
= 1;
249 if (afs_CacheFSType
== AFS_SUN_VXFS_CACHE
)
250 return osi_VxfsOpen(ainode
);
252 return osi_UfsOpen(ainode
);
256 afs_osi_Stat(struct osi_file
*afile
, struct osi_stat
*astat
)
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
;
265 #ifdef AFS_SUN511_ENV
266 code
= VOP_GETATTR(afile
->vnode
, &tvattr
, 0, afs_osi_credp
, NULL
);
268 code
= VOP_GETATTR(afile
->vnode
, &tvattr
, 0, afs_osi_credp
);
272 astat
->size
= tvattr
.va_size
;
273 astat
->mtime
= tvattr
.va_mtime
.tv_sec
;
274 astat
->atime
= tvattr
.va_atime
.tv_sec
;
276 ReleaseWriteLock(&afs_xosi
);
281 osi_UFSClose(struct osi_file
*afile
)
283 AFS_STATCNT(osi_Close
);
285 AFS_RELE(afile
->vnode
);
288 osi_FreeSmallSpace(afile
);
293 osi_UFSTruncate(struct osi_file
*afile
, afs_int32 asize
)
295 afs_ucred_t
*oldCred
;
298 struct osi_stat tstat
;
299 AFS_STATCNT(osi_Truncate
);
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.
305 code
= afs_osi_Stat(afile
, &tstat
);
306 if (code
|| tstat
.size
<= asize
)
308 ObtainWriteLock(&afs_xosi
, 321);
309 tvattr
.va_mask
= AT_SIZE
;
310 tvattr
.va_size
= asize
;
312 * The only time a flag is used (ATTR_UTIME) is when we're changing the time
315 #ifdef AFS_SUN510_ENV
316 code
= VOP_SETATTR(afile
->vnode
, &tvattr
, 0, afs_osi_credp
, NULL
);
318 code
= VOP_SETATTR(afile
->vnode
, &tvattr
, 0, afs_osi_credp
);
321 ReleaseWriteLock(&afs_xosi
);
326 osi_DisableAtimes(struct vnode
*avp
)
328 if (afs_CacheFSType
== AFS_SUN_UFS_CACHE
) {
329 #ifndef AFS_CACHE_VNODE_PATH
330 struct inode
*ip
= VTOI(avp
);
331 rw_enter(&ip
->i_contents
, RW_READER
);
332 mutex_enter(&ip
->i_tlock
);
334 mutex_exit(&ip
->i_tlock
);
335 rw_exit(&ip
->i_contents
);
341 /* Generic read interface */
343 afs_osi_Read(struct osi_file
*afile
, int offset
, void *aptr
,
346 afs_ucred_t
*oldCred
;
350 AFS_STATCNT(osi_Read
);
353 * If the osi_file passed in is NULL, panic only if AFS is not shutting
354 * down. No point in crashing when we are already shutting down
357 if (afs_shuttingdown
== AFS_RUNNING
)
358 osi_Panic("osi_Read called with null param");
364 afile
->offset
= offset
;
367 gop_rdwr(UIO_READ
, afile
->vnode
, (caddr_t
) aptr
, asize
, afile
->offset
,
368 AFS_UIOSYS
, 0, 0, afs_osi_credp
, &resid
);
371 code
= asize
- resid
;
372 afile
->offset
+= code
;
373 osi_DisableAtimes(afile
->vnode
);
375 afs_Trace2(afs_iclSetp
, CM_TRACE_READFAILED
, ICL_TYPE_INT32
, resid
,
376 ICL_TYPE_INT32
, code
);
384 /* Generic write interface */
386 afs_osi_Write(struct osi_file
*afile
, afs_int32 offset
, void *aptr
,
389 afs_ucred_t
*oldCred
;
392 AFS_STATCNT(osi_Write
);
394 osi_Panic("afs_osi_Write called with null param");
396 afile
->offset
= offset
;
399 gop_rdwr(UIO_WRITE
, afile
->vnode
, (caddr_t
) aptr
, asize
,
400 afile
->offset
, AFS_UIOSYS
, 0, RLIM64_INFINITY
, afs_osi_credp
,
404 code
= asize
- resid
;
405 afile
->offset
+= code
;
412 (*afile
->proc
) (afile
, code
);
418 /* This work should be handled by physstrat in ca/machdep.c.
419 This routine written from the RT NFS port strategy routine.
420 It has been generalized a bit, but should still be pretty clear. */
422 afs_osi_MapStrategy(int (*aproc
) (), struct buf
*bp
)
424 afs_int32 returnCode
;
426 AFS_STATCNT(osi_MapStrategy
);
427 returnCode
= (*aproc
) (bp
);
435 shutdown_osifile(void)
437 AFS_STATCNT(shutdown_osifile
);
438 if (afs_cold_shutdown
) {
439 afs_osicred_initialized
= 0;