freebsd-20030701
[openafs.git] / src / afs / FBSD / 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 RCSID("$Header$");
14
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
19
20 int afs_osicred_initialized = 0;
21 struct AFS_UCRED afs_osi_cred;
22 afs_lock_t afs_xosi;            /* lock is for tvattr */
23 extern struct osi_dev cacheDev;
24 extern struct mount *afs_cacheVfsp;
25
26
27 void *
28 osi_UFSOpen(afs_int32 ainode)
29 {
30     struct inode *ip;
31     register struct osi_file *afile = NULL;
32     extern int cacheDiskType;
33     afs_int32 code = 0;
34     int dummy;
35     AFS_STATCNT(osi_UFSOpen);
36     if (cacheDiskType != AFS_FCACHE_TYPE_UFS) {
37         osi_Panic("UFSOpen called for non-UFS cache\n");
38     }
39     if (!afs_osicred_initialized) {
40         /* valid for alpha_osf, SunOS, Ultrix */
41         memset((char *)&afs_osi_cred, 0, sizeof(struct AFS_UCRED));
42         afs_osi_cred.cr_ref++;
43         afs_osicred_initialized = 1;
44     }
45     afile = (struct osi_file *)osi_AllocSmallSpace(sizeof(struct osi_file));
46     AFS_GUNLOCK();
47     code =
48         igetinode(afs_cacheVfsp, (dev_t) cacheDev.dev, (ino_t) ainode, &ip,
49                   &dummy);
50     AFS_GLOCK();
51     if (code) {
52         osi_FreeSmallSpace(afile);
53         osi_Panic("UFSOpen: igetinode failed");
54     }
55     afile->vnode = ITOV(ip);
56 #if defined(AFS_FBSD50_ENV)
57     VOP_UNLOCK(afile->vnode, 0, curthread);
58 #else
59     VOP_UNLOCK(afile->vnode, 0, curproc);
60 #endif
61     afile->size = VTOI(afile->vnode)->i_size;
62     afile->offset = 0;
63     afile->proc = (int (*)())0;
64     afile->inum = ainode;       /* for hint validity checking */
65     return (void *)afile;
66 }
67
68 int
69 afs_osi_Stat(register struct osi_file *afile, register struct osi_stat *astat)
70 {
71     register afs_int32 code;
72     struct vattr tvattr;
73     AFS_STATCNT(osi_Stat);
74     MObtainWriteLock(&afs_xosi, 320);
75     AFS_GUNLOCK();
76 #if defined(AFS_FBSD50_ENV)
77     code = VOP_GETATTR(afile->vnode, &tvattr, &afs_osi_cred, curthread);
78 #else
79     code = VOP_GETATTR(afile->vnode, &tvattr, &afs_osi_cred, curproc);
80 #endif
81     AFS_GLOCK();
82     if (code == 0) {
83         astat->size = tvattr.va_size;
84         astat->blksize = tvattr.va_blocksize;
85         astat->mtime = tvattr.va_mtime.tv_sec;
86         astat->atime = tvattr.va_atime.tv_sec;
87     }
88     MReleaseWriteLock(&afs_xosi);
89     return code;
90 }
91
92 int
93 osi_UFSClose(register struct osi_file *afile)
94 {
95     AFS_STATCNT(osi_Close);
96     if (afile->vnode) {
97         AFS_RELE(afile->vnode);
98     }
99
100     osi_FreeSmallSpace(afile);
101     return 0;
102 }
103
104 int
105 osi_UFSTruncate(register struct osi_file *afile, afs_int32 asize)
106 {
107     struct vattr tvattr;
108     register afs_int32 code;
109     struct osi_stat tstat;
110     AFS_STATCNT(osi_Truncate);
111
112     /* This routine only shrinks files, and most systems
113      * have very slow truncates, even when the file is already
114      * small enough.  Check now and save some time.
115      */
116     code = afs_osi_Stat(afile, &tstat);
117     if (code || tstat.size <= asize)
118         return code;
119     MObtainWriteLock(&afs_xosi, 321);
120     VATTR_NULL(&tvattr);
121     tvattr.va_size = asize;
122     AFS_GUNLOCK();
123 #if defined(AFS_FBSD50_ENV)
124     code = VOP_SETATTR(afile->vnode, &tvattr, &afs_osi_cred, curthread);
125 #else
126     code = VOP_SETATTR(afile->vnode, &tvattr, &afs_osi_cred, curproc);
127 #endif
128     AFS_GLOCK();
129     MReleaseWriteLock(&afs_xosi);
130     return code;
131 }
132
133 void
134 osi_DisableAtimes(struct vnode *avp)
135 {
136     struct inode *ip = VTOI(avp);
137     ip->i_flag &= ~IN_ACCESS;
138 }
139
140
141 /* Generic read interface */
142 int
143 afs_osi_Read(register struct osi_file *afile, int offset, void *aptr,
144              afs_int32 asize)
145 {
146     unsigned int resid;
147     register afs_int32 code;
148     AFS_STATCNT(osi_Read);
149
150     /**
151       * If the osi_file passed in is NULL, panic only if AFS is not shutting
152       * down. No point in crashing when we are already shutting down
153       */
154     if (!afile) {
155         if (!afs_shuttingdown)
156             osi_Panic("osi_Read called with null param");
157         else
158             return EIO;
159     }
160
161     if (offset != -1)
162         afile->offset = offset;
163     AFS_GUNLOCK();
164     code =
165         gop_rdwr(UIO_READ, afile->vnode, (caddr_t) aptr, asize, afile->offset,
166                  AFS_UIOSYS, IO_UNIT, &afs_osi_cred, &resid);
167     AFS_GLOCK();
168     if (code == 0) {
169         code = asize - resid;
170         afile->offset += code;
171         osi_DisableAtimes(afile->vnode);
172     } else {
173         afs_Trace2(afs_iclSetp, CM_TRACE_READFAILED, ICL_TYPE_INT32, resid,
174                    ICL_TYPE_INT32, code);
175         code = -1;
176     }
177     return code;
178 }
179
180 /* Generic write interface */
181 int
182 afs_osi_Write(register struct osi_file *afile, afs_int32 offset, void *aptr,
183               afs_int32 asize)
184 {
185     unsigned int resid;
186     register afs_int32 code;
187     AFS_STATCNT(osi_Write);
188     if (!afile)
189         osi_Panic("afs_osi_Write called with null param");
190     if (offset != -1)
191         afile->offset = offset;
192     {
193         AFS_GUNLOCK();
194         code =
195             gop_rdwr(UIO_WRITE, afile->vnode, (caddr_t) aptr, asize,
196                      afile->offset, AFS_UIOSYS, IO_UNIT, &afs_osi_cred,
197                      &resid);
198         AFS_GLOCK();
199     }
200     if (code == 0) {
201         code = asize - resid;
202         afile->offset += code;
203     } else {
204         code = -1;
205     }
206     if (afile->proc) {
207         (*afile->proc) (afile, code);
208     }
209     return code;
210 }
211
212
213 /*  This work should be handled by physstrat in ca/machdep.c.
214     This routine written from the RT NFS port strategy routine.
215     It has been generalized a bit, but should still be pretty clear. */
216 int
217 afs_osi_MapStrategy(int (*aproc) (), register struct buf *bp)
218 {
219     afs_int32 returnCode;
220
221     AFS_STATCNT(osi_MapStrategy);
222     returnCode = (*aproc) (bp);
223
224     return returnCode;
225 }
226
227
228
229 void
230 shutdown_osifile(void)
231 {
232     extern int afs_cold_shutdown;
233
234     AFS_STATCNT(shutdown_osifile);
235     if (afs_cold_shutdown) {
236         afs_osicred_initialized = 0;
237     }
238 }