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 #ifdef AFS_LINUX24_ENV
15 #include "h/module.h" /* early to avoid printf->printk mapping */
17 #include "afs/sysincludes.h" /* Standard vendor system headers */
18 #include "afsincludes.h" /* Afs-based standard headers */
19 #include "afs/afs_stats.h" /* afs statistics */
20 #include "h/smp_lock.h"
22 afs_lock_t afs_xosi; /* lock is for tvattr */
23 extern struct osi_dev cacheDev;
24 #if defined(AFS_LINUX24_ENV)
25 extern struct vfsmount *afs_cacheMnt;
27 extern struct super_block *afs_cacheSBp;
30 osi_UFSOpen(afs_dcache_id_t *ainode)
32 struct osi_file *afile = NULL;
33 extern int cacheDiskType;
35 struct inode *tip = NULL;
36 struct file *filp = NULL;
37 AFS_STATCNT(osi_UFSOpen);
38 if (cacheDiskType != AFS_FCACHE_TYPE_UFS) {
39 osi_Panic("UFSOpen called for non-UFS cache\n");
41 if (!afs_osicred_initialized) {
42 /* valid for alpha_osf, SunOS, Ultrix */
43 memset(&afs_osi_cred, 0, sizeof(afs_ucred_t));
44 crhold(&afs_osi_cred); /* don't let it evaporate, since it is static */
45 afs_osicred_initialized = 1;
47 afile = (struct osi_file *)osi_AllocLargeSpace(sizeof(struct osi_file));
50 osi_Panic("osi_UFSOpen: Failed to allocate %d bytes for osi_file.\n",
51 sizeof(struct osi_file));
53 memset(afile, 0, sizeof(struct osi_file));
55 filp->f_dentry = &afile->dentry;
56 tip = iget(afs_cacheSBp, ainode->ufs);
58 osi_Panic("Can't get inode %d\n", ainode->ufs);
59 FILE_INODE(filp) = tip;
60 tip->i_flags |= MS_NOATIME; /* Disable updating access times. */
61 filp->f_flags = O_RDWR;
62 #if defined(AFS_LINUX24_ENV)
63 filp->f_mode = FMODE_READ|FMODE_WRITE;
64 filp->f_op = fops_get(tip->i_fop);
66 filp->f_op = tip->i_op->default_file_ops;
68 if (filp->f_op && filp->f_op->open)
69 code = filp->f_op->open(tip, filp);
71 osi_Panic("Can't open inode %d\n", ainode->ufs);
72 afile->size = i_size_read(tip);
75 afile->proc = (int (*)())0;
79 void osi_get_fh(struct dentry *dp, afs_ufs_dcache_id_t *ainode) {
80 *ainode = dp->d_inode->i_ino;
84 afs_osi_Stat(struct osi_file *afile, struct osi_stat *astat)
87 AFS_STATCNT(osi_Stat);
88 ObtainWriteLock(&afs_xosi, 320);
89 astat->size = i_size_read(OSIFILE_INODE(afile));
90 astat->mtime = OSIFILE_INODE(afile)->i_mtime;
91 astat->atime = OSIFILE_INODE(afile)->i_atime;
93 ReleaseWriteLock(&afs_xosi);
98 osi_UFSClose(struct osi_file *afile)
100 AFS_STATCNT(osi_Close);
102 if (FILE_INODE(&afile->file)) {
103 struct file *filp = &afile->file;
104 if (filp->f_op && filp->f_op->release)
105 filp->f_op->release(FILE_INODE(filp), filp);
106 iput(FILE_INODE(filp));
110 osi_FreeLargeSpace(afile);
115 osi_UFSTruncate(struct osi_file *afile, afs_int32 asize)
118 struct osi_stat tstat;
119 struct iattr newattrs;
120 struct inode *inode = OSIFILE_INODE(afile);
121 AFS_STATCNT(osi_Truncate);
123 /* This routine only shrinks files, and most systems
124 * have very slow truncates, even when the file is already
125 * small enough. Check now and save some time.
127 code = afs_osi_Stat(afile, &tstat);
128 if (code || tstat.size <= asize)
130 ObtainWriteLock(&afs_xosi, 321);
132 #ifdef STRUCT_INODE_HAS_I_ALLOC_SEM
133 down_write(&inode->i_alloc_sem);
135 #ifdef STRUCT_INODE_HAS_I_MUTEX
136 mutex_lock(&inode->i_mutex);
140 newattrs.ia_size = asize;
141 newattrs.ia_valid = ATTR_SIZE | ATTR_CTIME;
142 #if defined(AFS_LINUX24_ENV)
143 newattrs.ia_ctime = CURRENT_TIME;
145 /* avoid notify_change() since it wants to update dentry->d_parent */
147 code = inode_change_ok(inode, &newattrs);
149 #ifdef INODE_SETATTR_NOT_VOID
150 code = inode_setattr(inode, &newattrs);
152 inode_setattr(inode, &newattrs);
157 truncate_inode_pages(&inode->i_data, asize);
159 i_size_write(inode, asize);
160 if (inode->i_sb->s_op && inode->i_sb->s_op->notify_change) {
161 code = inode->i_sb->s_op->notify_change(&afile->dentry, &newattrs);
164 truncate_inode_pages(inode, asize);
165 if (inode->i_op && inode->i_op->truncate)
166 inode->i_op->truncate(inode);
170 #ifdef STRUCT_INODE_HAS_I_MUTEX
171 mutex_unlock(&inode->i_mutex);
175 #ifdef STRUCT_INODE_HAS_I_ALLOC_SEM
176 up_write(&inode->i_alloc_sem);
179 ReleaseWriteLock(&afs_xosi);
184 /* Generic read interface */
186 afs_osi_Read(struct osi_file *afile, int offset, void *aptr,
193 AFS_STATCNT(osi_Read);
196 * If the osi_file passed in is NULL, panic only if AFS is not shutting
197 * down. No point in crashing when we are already shutting down
200 if (!afs_shuttingdown)
201 osi_Panic("osi_Read called with null param");
207 afile->offset = offset;
208 setup_uio(&auio, &iov, aptr, afile->offset, asize, UIO_READ, AFS_UIOSYS);
210 code = osi_rdwr(afile, &auio, UIO_READ);
213 code = asize - auio.uio_resid;
214 afile->offset += code;
216 afs_Trace2(afs_iclSetp, CM_TRACE_READFAILED, ICL_TYPE_INT32, auio.uio_resid,
217 ICL_TYPE_INT32, code);
225 /* Generic write interface */
227 afs_osi_Write(struct osi_file *afile, afs_int32 offset, void *aptr,
234 AFS_STATCNT(osi_Write);
237 if (!afs_shuttingdown)
238 osi_Panic("afs_osi_Write called with null param");
244 afile->offset = offset;
245 setup_uio(&auio, &iov, aptr, afile->offset, asize, UIO_WRITE, AFS_UIOSYS);
247 code = osi_rdwr(afile, &auio, UIO_WRITE);
250 code = asize - auio.uio_resid;
251 afile->offset += code;
255 ("\n\n\n*** Cache partition is FULL - Decrease cachesize!!! ***\n\n");
262 (*afile->proc)(afile, code);
268 /* This work should be handled by physstrat in ca/machdep.c.
269 This routine written from the RT NFS port strategy routine.
270 It has been generalized a bit, but should still be pretty clear. */
272 afs_osi_MapStrategy(int (*aproc) (struct buf * bp), struct buf *bp)
274 afs_int32 returnCode;
276 AFS_STATCNT(osi_MapStrategy);
277 returnCode = (*aproc) (bp);
283 shutdown_osifile(void)
285 AFS_STATCNT(shutdown_osifile);
286 if (afs_cold_shutdown) {
287 afs_osicred_initialized = 0;
291 /* Intialize cache device info and fragment size for disk cache partition. */
293 osi_InitCacheInfo(char *aname)
296 extern afs_dcache_id_t cacheInode;
298 extern struct osi_dev cacheDev;
299 extern afs_int32 afs_fsfragsize;
300 extern struct super_block *afs_cacheSBp;
301 extern struct vfsmount *afs_cacheMnt;
302 code = osi_lookupname_internal(aname, 1, &afs_cacheMnt, &dp);
306 osi_get_fh(dp, &cacheInode.ufs);
307 cacheDev.dev = dp->d_inode->i_sb->s_dev;
308 afs_fsfragsize = dp->d_inode->i_sb->s_blocksize - 1;
309 afs_cacheSBp = dp->d_inode->i_sb;
317 #define FOP_READ(F, B, C) (F)->f_op->read(F, B, (size_t)(C), &(F)->f_pos)
318 #define FOP_WRITE(F, B, C) (F)->f_op->write(F, B, (size_t)(C), &(F)->f_pos)
321 * seek, then read or write to an open inode. addrp points to data in
325 osi_rdwr(struct osi_file *osifile, struct uio *uiop, int rw)
327 struct file *filp = &osifile->file;
332 unsigned long savelim;
334 savelim = current->TASK_STRUCT_RLIM[RLIMIT_FSIZE].rlim_cur;
335 current->TASK_STRUCT_RLIM[RLIMIT_FSIZE].rlim_cur = RLIM_INFINITY;
337 if (uiop->uio_seg == AFS_UIOSYS)
340 /* seek to the desired position. Return -1 on error. */
341 if (filp->f_op->llseek) {
342 if (filp->f_op->llseek(filp, (loff_t) uiop->uio_offset, 0) != uiop->uio_offset)
345 filp->f_pos = uiop->uio_offset;
347 while (code == 0 && uiop->uio_resid > 0 && uiop->uio_iovcnt > 0) {
349 count = iov->iov_len;
357 code = FOP_READ(filp, iov->iov_base, count);
359 code = FOP_WRITE(filp, iov->iov_base, count);
364 } else if (code == 0) {
366 * This is bad -- we can't read any more data from the
367 * file, but we have no good way of signaling a partial
374 iov->iov_base += code;
375 iov->iov_len -= code;
376 uiop->uio_resid -= code;
377 uiop->uio_offset += code;
381 if (uiop->uio_seg == AFS_UIOSYS)
384 current->TASK_STRUCT_RLIM[RLIMIT_FSIZE].rlim_cur = savelim;
390 * Setup a uio struct.
393 setup_uio(struct uio *uiop, struct iovec *iovecp, const char *buf, afs_offs_t pos,
394 int count, uio_flag_t flag, uio_seg_t seg)
396 iovecp->iov_base = (char *)buf;
397 iovecp->iov_len = count;
398 uiop->uio_iov = iovecp;
399 uiop->uio_iovcnt = 1;
400 uiop->uio_offset = pos;
402 uiop->uio_resid = count;
403 uiop->uio_flag = flag;
408 * UIO_READ : dp -> uio
409 * UIO_WRITE : uio -> dp
412 uiomove(char *dp, int length, uio_flag_t rw, struct uio *uiop)
418 while (length > 0 && uiop->uio_resid > 0 && uiop->uio_iovcnt > 0) {
420 count = iov->iov_len;
431 switch (uiop->uio_seg) {
435 memcpy(iov->iov_base, dp, count);
438 memcpy(dp, iov->iov_base, count);
441 printf("uiomove: Bad rw = %d\n", rw);
448 AFS_COPYOUT(dp, iov->iov_base, count, code);
451 AFS_COPYIN(iov->iov_base, dp, count, code);
454 printf("uiomove: Bad rw = %d\n", rw);
459 printf("uiomove: Bad seg = %d\n", uiop->uio_seg);
465 iov->iov_base += count;
466 iov->iov_len -= count;
467 uiop->uio_offset += count;
468 uiop->uio_resid -= count;