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 <linux/module.h> /* early to avoid printf->printk mapping */
15 #include "afs/sysincludes.h" /* Standard vendor system headers */
16 #include "afsincludes.h" /* Afs-based standard headers */
17 #include "afs/afs_stats.h" /* afs statistics */
18 #include <linux/namei.h>
20 #if defined(HAVE_LINUX_EXPORTFS_H)
21 #include <linux/exportfs.h>
23 #include "osi_compat.h"
26 # if defined(HAVE_LINUX_KTIME_GET_COARSE_REAL_TS64)
27 # define AFS_CURRENT_TIME(x) (ktime_get_coarse_real_ts64((x)))
29 # ifdef IATTR_TAKES_64BIT_TIME
30 # define AFS_CURRENT_TIME(x) do {*(x) = current_kernel_time64();} while (0)
32 # define AFS_CURRENT_TIME(x) do {*(x) = current_kernel_time();} while (0)
36 # define AFS_CURRENT_TIME(x) do {*(x) = CURRENT_TIME;} while(0)
39 int cache_fh_type
= -1;
40 int cache_fh_len
= -1;
42 extern struct osi_dev cacheDev
;
43 extern struct vfsmount
*afs_cacheMnt
;
44 extern struct super_block
*afs_cacheSBp
;
45 #if defined(STRUCT_TASK_STRUCT_HAS_CRED)
46 extern struct cred
*cache_creds
;
49 /* Old export ops: decode_fh will call back here. Accept any dentry it suggests */
51 afs_fh_acceptable(void *context
, struct dentry
*dp
)
57 afs_linux_raw_open(afs_dcache_id_t
*ainode
)
59 struct inode
*tip
= NULL
;
60 struct dentry
*dp
= NULL
;
63 dp
= afs_get_dentry_from_fh(afs_cacheSBp
, ainode
, cache_fh_len
, cache_fh_type
,
65 if ((!dp
) || IS_ERR(dp
))
66 osi_Panic("Can't get dentry\n");
68 tip
->i_flags
|= S_NOATIME
; /* Disable updating access times. */
70 #if defined(STRUCT_TASK_STRUCT_HAS_CRED)
71 /* Use stashed credentials - prevent selinux/apparmor problems */
72 filp
= afs_dentry_open(dp
, afs_cacheMnt
, O_RDWR
, cache_creds
);
74 filp
= afs_dentry_open(dp
, afs_cacheMnt
, O_RDWR
, current_cred());
76 filp
= dentry_open(dget(dp
), mntget(afs_cacheMnt
), O_RDWR
);
79 afs_warn("afs: Cannot open cache file (code %d). Trying to continue, "
80 "but AFS accesses may return errors or panic the system\n",
91 osi_UFSOpen(afs_dcache_id_t
*ainode
)
93 struct osi_file
*afile
= NULL
;
94 extern int cacheDiskType
;
96 AFS_STATCNT(osi_UFSOpen
);
97 if (cacheDiskType
!= AFS_FCACHE_TYPE_UFS
) {
98 osi_Panic("UFSOpen called for non-UFS cache\n");
100 if (!afs_osicred_initialized
) {
101 /* valid for alpha_osf, SunOS, Ultrix */
102 memset(&afs_osi_cred
, 0, sizeof(afs_ucred_t
));
103 crhold(&afs_osi_cred
); /* don't let it evaporate, since it is static */
104 afs_osicred_initialized
= 1;
107 afile
= kmalloc(sizeof(struct osi_file
), GFP_NOFS
);
109 osi_Panic("osi_UFSOpen: Failed to allocate %d bytes for osi_file.\n",
110 (int)sizeof(struct osi_file
));
112 memset(afile
, 0, sizeof(struct osi_file
));
114 afile
->filp
= afs_linux_raw_open(ainode
);
116 afile
->size
= i_size_read(FILE_INODE(afile
->filp
));
121 osi_FreeLargeSpace(afile
);
126 afile
->proc
= (int (*)())0;
127 return (void *)afile
;
131 * Given a dentry, return the file handle as encoded by the filesystem.
132 * We can't assume anything about the length (words, not bytes).
133 * The cache has to live on a single filesystem with uniform file
134 * handles, otherwise we panic.
136 void osi_get_fh(struct dentry
*dp
, afs_ufs_dcache_id_t
*ainode
) {
140 if (cache_fh_len
> 0)
141 max_len
= cache_fh_len
;
143 max_len
= MAX_FH_LEN
;
144 type
= afs_get_fh_from_dentry(dp
, ainode
, &max_len
);
146 osi_Panic("File handle encoding failed\n");
148 if (cache_fh_type
< 0)
149 cache_fh_type
= type
;
150 if (cache_fh_len
< 0) {
151 cache_fh_len
= max_len
;
153 if (type
!= cache_fh_type
|| max_len
!= cache_fh_len
) {
154 osi_Panic("Inconsistent file handles within cache\n");
159 afs_osi_Stat(struct osi_file
*afile
, struct osi_stat
*astat
)
161 AFS_STATCNT(osi_Stat
);
162 astat
->size
= i_size_read(OSIFILE_INODE(afile
));
163 astat
->mtime
= OSIFILE_INODE(afile
)->i_mtime
.tv_sec
;
164 astat
->atime
= OSIFILE_INODE(afile
)->i_atime
.tv_sec
;
170 osi_UFSClose(struct osi_file
*afile
)
172 AFS_STATCNT(osi_Close
);
174 if (OSIFILE_INODE(afile
)) {
175 filp_close(afile
->filp
, NULL
);
183 osi_UFSTruncate(struct osi_file
*afile
, afs_int32 asize
)
186 struct osi_stat tstat
;
187 struct iattr newattrs
;
188 struct inode
*inode
= OSIFILE_INODE(afile
);
189 AFS_STATCNT(osi_Truncate
);
191 /* This routine only shrinks files, and most systems
192 * have very slow truncates, even when the file is already
193 * small enough. Check now and save some time.
195 code
= afs_osi_Stat(afile
, &tstat
);
196 if (code
|| tstat
.size
<= asize
)
199 afs_linux_lock_inode(inode
);
200 #ifdef STRUCT_INODE_HAS_I_ALLOC_SEM
201 down_write(&inode
->i_alloc_sem
);
203 newattrs
.ia_size
= asize
;
204 newattrs
.ia_valid
= ATTR_SIZE
| ATTR_CTIME
;
205 AFS_CURRENT_TIME(&newattrs
.ia_ctime
);
207 /* avoid notify_change() since it wants to update dentry->d_parent */
208 #ifdef HAVE_LINUX_SETATTR_PREPARE
209 code
= setattr_prepare(file_dentry(afile
->filp
), &newattrs
);
211 code
= inode_change_ok(inode
, &newattrs
);
214 code
= afs_inode_setattr(afile
, &newattrs
);
216 truncate_inode_pages(&inode
->i_data
, asize
);
218 #ifdef STRUCT_INODE_HAS_I_ALLOC_SEM
219 up_write(&inode
->i_alloc_sem
);
221 afs_linux_unlock_inode(inode
);
227 /* Generic read interface */
229 afs_osi_Read(struct osi_file
*afile
, int offset
, void *aptr
,
236 memset(&auio
, 0, sizeof(auio
));
237 memset(&iov
, 0, sizeof(iov
));
239 AFS_STATCNT(osi_Read
);
242 * If the osi_file passed in is NULL, panic only if AFS is not shutting
243 * down. No point in crashing when we are already shutting down
246 if (afs_shuttingdown
== AFS_RUNNING
)
247 osi_Panic("osi_Read called with null param");
253 afile
->offset
= offset
;
254 setup_uio(&auio
, &iov
, aptr
, afile
->offset
, asize
, UIO_READ
, AFS_UIOSYS
);
256 code
= osi_rdwr(afile
, &auio
, UIO_READ
);
259 code
= asize
- auio
.uio_resid
;
260 afile
->offset
+= code
;
262 afs_Trace2(afs_iclSetp
, CM_TRACE_READFAILED
, ICL_TYPE_INT32
, auio
.uio_resid
,
263 ICL_TYPE_INT32
, code
);
271 /* Generic write interface */
273 afs_osi_Write(struct osi_file
*afile
, afs_int32 offset
, void *aptr
,
280 memset(&auio
, 0, sizeof(auio
));
281 memset(&iov
, 0, sizeof(iov
));
283 AFS_STATCNT(osi_Write
);
286 if (afs_shuttingdown
== AFS_RUNNING
)
287 osi_Panic("afs_osi_Write called with null param");
293 afile
->offset
= offset
;
294 setup_uio(&auio
, &iov
, aptr
, afile
->offset
, asize
, UIO_WRITE
, AFS_UIOSYS
);
296 code
= osi_rdwr(afile
, &auio
, UIO_WRITE
);
299 code
= asize
- auio
.uio_resid
;
300 afile
->offset
+= code
;
310 (*afile
->proc
)(afile
, code
);
316 /* This work should be handled by physstrat in ca/machdep.c.
317 This routine written from the RT NFS port strategy routine.
318 It has been generalized a bit, but should still be pretty clear. */
320 afs_osi_MapStrategy(int (*aproc
) (struct buf
* bp
), struct buf
*bp
)
322 afs_int32 returnCode
;
324 AFS_STATCNT(osi_MapStrategy
);
325 returnCode
= (*aproc
) (bp
);
331 shutdown_osifile(void)
333 AFS_STATCNT(shutdown_osifile
);
334 if (afs_cold_shutdown
) {
335 afs_osicred_initialized
= 0;
339 /* Intialize cache device info and fragment size for disk cache partition. */
341 osi_InitCacheInfo(char *aname
)
344 extern afs_dcache_id_t cacheInode
;
346 extern struct osi_dev cacheDev
;
347 extern afs_int32 afs_fsfragsize
;
348 extern struct super_block
*afs_cacheSBp
;
349 extern struct vfsmount
*afs_cacheMnt
;
350 code
= osi_lookupname_internal(aname
, 1, &afs_cacheMnt
, &dp
);
354 osi_get_fh(dp
, &cacheInode
.ufs
);
355 cacheDev
.dev
= dp
->d_inode
->i_sb
->s_dev
;
356 afs_fsfragsize
= dp
->d_inode
->i_sb
->s_blocksize
- 1;
357 afs_cacheSBp
= dp
->d_inode
->i_sb
;
361 afs_init_sb_export_ops(afs_cacheSBp
);
368 * seek, then read or write to an open inode. addrp points to data in
372 osi_rdwr(struct osi_file
*osifile
, struct uio
*uiop
, int rw
)
374 struct file
*filp
= osifile
->filp
;
375 #ifdef AFS_FILE_NEEDS_SET_FS
376 mm_segment_t old_fs
= {0};
377 #endif /* AFS_FILE_NEEDS_SET_FS */
381 unsigned long savelim
;
384 savelim
= current
->TASK_STRUCT_RLIM
[RLIMIT_FSIZE
].rlim_cur
;
385 current
->TASK_STRUCT_RLIM
[RLIMIT_FSIZE
].rlim_cur
= RLIM_INFINITY
;
387 #ifdef AFS_FILE_NEEDS_SET_FS
388 if (uiop
->uio_seg
== AFS_UIOSYS
) {
389 /* Switch into user space */
393 #endif /* AFS_FILE_NEEDS_SET_FS */
395 while (code
== 0 && uiop
->uio_resid
> 0 && uiop
->uio_iovcnt
> 0) {
397 count
= iov
->iov_len
;
404 pos
= uiop
->uio_offset
;
406 code
= afs_file_read(filp
, iov
->iov_base
, count
, &pos
);
408 code
= afs_file_write(filp
, iov
->iov_base
, count
, &pos
);
413 } else if (code
== 0) {
415 * This is bad -- we can't read any more data from the
416 * file, but we have no good way of signaling a partial
423 iov
->iov_base
+= code
;
424 iov
->iov_len
-= code
;
425 uiop
->uio_resid
-= code
;
426 uiop
->uio_offset
+= code
;
430 #ifdef AFS_FILE_NEEDS_SET_FS
431 if (uiop
->uio_seg
== AFS_UIOSYS
) {
432 /* Switch back into kernel space */
435 #endif /* AFS_FILE_NEEDS_SET_FS */
437 current
->TASK_STRUCT_RLIM
[RLIMIT_FSIZE
].rlim_cur
= savelim
;
443 * Setup a uio struct.
446 setup_uio(struct uio
*uiop
, struct iovec
*iovecp
, const char *buf
, afs_offs_t pos
,
447 int count
, uio_flag_t flag
, uio_seg_t seg
)
449 iovecp
->iov_base
= (char *)buf
;
450 iovecp
->iov_len
= count
;
451 uiop
->uio_iov
= iovecp
;
452 uiop
->uio_iovcnt
= 1;
453 uiop
->uio_offset
= pos
;
455 uiop
->uio_resid
= count
;
456 uiop
->uio_flag
= flag
;
461 * UIO_READ : dp -> uio
462 * UIO_WRITE : uio -> dp
465 uiomove(char *dp
, int length
, uio_flag_t rw
, struct uio
*uiop
)
471 while (length
> 0 && uiop
->uio_resid
> 0 && uiop
->uio_iovcnt
> 0) {
473 count
= iov
->iov_len
;
484 switch (uiop
->uio_seg
) {
488 memcpy(iov
->iov_base
, dp
, count
);
491 memcpy(dp
, iov
->iov_base
, count
);
494 printf("uiomove: Bad rw = %d\n", rw
);
501 AFS_COPYOUT(dp
, iov
->iov_base
, count
, code
);
504 AFS_COPYIN(iov
->iov_base
, dp
, count
, code
);
507 printf("uiomove: Bad rw = %d\n", rw
);
512 printf("uiomove: Bad seg = %d\n", uiop
->uio_seg
);
518 iov
->iov_base
+= count
;
519 iov
->iov_len
-= count
;
520 uiop
->uio_offset
+= count
;
521 uiop
->uio_resid
-= count
;