Import Upstream version 1.8.5
[hcoop/debian/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 extern struct osi_dev cacheDev;
20 extern struct mount *afs_cacheVfsp;
21
22 void *
23 osi_UFSOpen(afs_dcache_id_t *ainode)
24 {
25 struct osi_file *afile;
26 struct vnode *vp;
27 extern int cacheDiskType;
28 afs_int32 code;
29
30 AFS_STATCNT(osi_UFSOpen);
31 if (cacheDiskType != AFS_FCACHE_TYPE_UFS)
32 osi_Panic("UFSOpen called for non-UFS cache\n");
33 afile = osi_AllocSmallSpace(sizeof(struct osi_file));
34 AFS_GUNLOCK();
35 code = VFS_VGET(cacheDev.mp, (ino_t) ainode->ufs, &vp);
36 AFS_GLOCK();
37 if (code == 0 && vp->v_type == VNON)
38 code = ENOENT;
39 if (code) {
40 osi_FreeSmallSpace(afile);
41 osi_Panic("UFSOpen: igetinode failed");
42 }
43 #if defined(AFS_NBSD60_ENV)
44 VOP_UNLOCK(vp);
45 #else
46 VOP_UNLOCK(vp, 0);
47 #endif
48 afile->vnode = vp;
49 afile->size = VTOI(vp)->i_ffs1_size;
50 afile->offset = 0;
51 afile->proc = NULL;
52 return (void *)afile;
53 }
54
55 int
56 afs_osi_Stat(struct osi_file *afile, struct osi_stat *astat)
57 {
58 afs_int32 code;
59 struct vattr tvattr;
60
61 AFS_STATCNT(osi_Stat);
62 AFS_GUNLOCK();
63 #ifdef AFS_NBSD50_ENV
64 code = VOP_GETATTR(afile->vnode, &tvattr, afs_osi_credp);
65 #else
66 code = VOP_GETATTR(afile->vnode, &tvattr, afs_osi_credp,
67 osi_curproc());
68 #endif
69 AFS_GLOCK();
70 if (code == 0) {
71 astat->size = afile->size = tvattr.va_size;
72 astat->mtime = tvattr.va_mtime.tv_sec;
73 astat->atime = tvattr.va_atime.tv_sec;
74 }
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 VATTR_NULL(&tvattr);
109 tvattr.va_size = asize;
110 AFS_GUNLOCK();
111 VOP_LOCK(afile->vnode, LK_EXCLUSIVE | LK_RETRY);
112 #ifdef AFS_NBSD50_ENV
113 code = VOP_SETATTR(afile->vnode, &tvattr, afs_osi_credp);
114 #else
115 code = VOP_SETATTR(afile->vnode, &tvattr, afs_osi_credp,
116 osi_curproc());
117 #endif
118 #ifdef AFS_NBSD60_ENV
119 VOP_UNLOCK(afile->vnode);
120 #else
121 VOP_UNLOCK(afile->vnode, 0);
122 #endif
123 AFS_GLOCK();
124 if (code == 0)
125 afile->size = asize;
126 return code;
127 }
128
129 void
130 osi_DisableAtimes(struct vnode *avp)
131 {
132 #if 0
133 VTOI(avp)->i_flag &= ~IN_ACCESS;
134 #endif
135 }
136
137
138 /* Generic read interface */
139 int
140 afs_osi_Read(struct osi_file *afile, int offset, void *aptr, afs_int32 asize)
141 {
142 size_t resid;
143 afs_int32 code;
144
145 AFS_STATCNT(osi_Read);
146
147 /*
148 * If the osi_file passed in is NULL, panic only if AFS is not shutting
149 * down. No point in crashing when we are already shutting down
150 */
151 if (!afile) {
152 if (afs_shuttingdown == AFS_RUNNING)
153 osi_Panic("osi_Read called with null param");
154 else
155 return -EIO;
156 }
157
158 if (offset != -1)
159 afile->offset = offset;
160 AFS_GUNLOCK();
161 code =
162 vn_rdwr(UIO_READ, afile->vnode, aptr, asize, afile->offset,
163 AFS_UIOSYS, IO_UNIT, afs_osi_credp, &resid,
164 osi_curproc());
165 AFS_GLOCK();
166 if (code == 0) {
167 code = asize - resid;
168 afile->offset += code;
169 osi_DisableAtimes(afile->vnode);
170 } else {
171 afs_Trace2(afs_iclSetp, CM_TRACE_READFAILED, ICL_TYPE_INT32, resid,
172 ICL_TYPE_INT32, code);
173 if (code > 0) {
174 code = -code;
175 }
176 }
177 return code;
178 }
179
180 /* Generic write interface */
181 int
182 afs_osi_Write(struct osi_file *afile, afs_int32 offset, void *aptr,
183 afs_int32 asize)
184 {
185 size_t resid;
186 afs_int32 code;
187
188 AFS_STATCNT(osi_Write);
189 if (!afile)
190 osi_Panic("afs_osi_Write called with null afile");
191 if (offset != -1)
192 afile->offset = offset;
193
194 AFS_GUNLOCK();
195 code =
196 vn_rdwr(UIO_WRITE, afile->vnode, aptr, asize, afile->offset,
197 AFS_UIOSYS, IO_UNIT, afs_osi_credp, &resid, osi_curproc());
198 AFS_GLOCK();
199
200 if (code == 0) {
201 code = asize - resid;
202 afile->offset += code;
203 if (afile->offset > afile->size)
204 afile->size = afile->offset;
205 } else {
206 if (code > 0) {
207 code = -code;
208 }
209 }
210
211 if (afile->proc)
212 (*afile->proc) (afile, code);
213
214 return code;
215 }
216
217 /*
218 * This work should be handled by physstrat in ca/machdep.c. This routine
219 * written from the RT NFS port strategy routine. It has been generalized a
220 * bit, but should still be pretty clear.
221 */
222 int
223 afs_osi_MapStrategy(int (*aproc)(struct buf *), struct buf *bp)
224 {
225 afs_int32 returnCode;
226
227 AFS_STATCNT(osi_MapStrategy);
228 returnCode = (*aproc) (bp);
229
230 return returnCode;
231 }
232
233 void
234 shutdown_osifile(void)
235 {
236 AFS_STATCNT(shutdown_osifile);
237 if (afs_cold_shutdown)
238 afs_osicred_initialized = 0;
239 }