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