Import Upstream version 1.8.5
[hcoop/debian/openafs.git] / src / afs / HPUX / 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
14 #include "afs/sysincludes.h" /* Standard vendor system headers */
15 #include "afsincludes.h" /* Afs-based standard headers */
16 #include "afs/afs_stats.h" /* afs statistics */
17 #include "afs/osi_inode.h" /* igetinode() */
18
19
20 int afs_osicred_initialized = 0;
21 afs_ucred_t afs_osi_cred;
22 extern struct osi_dev cacheDev;
23 extern struct vfs *afs_cacheVfsp;
24
25
26 void *
27 osi_UFSOpen(afs_dcache_id_t *ainode)
28 {
29 struct inode *ip;
30 struct osi_file *afile = NULL;
31 extern int cacheDiskType;
32 afs_int32 code = 0;
33 int dummy;
34 AFS_STATCNT(osi_UFSOpen);
35 if (cacheDiskType != AFS_FCACHE_TYPE_UFS) {
36 osi_Panic("UFSOpen called for non-UFS cache\n");
37 }
38 if (!afs_osicred_initialized) {
39 /* valid for alpha_osf, SunOS, Ultrix */
40 memset(&afs_osi_cred, 0, sizeof(afs_ucred_t));
41 crhold(&afs_osi_cred); /* don't let it evaporate, since it is static */
42 afs_osicred_initialized = 1;
43 }
44 afile = osi_AllocSmallSpace(sizeof(struct osi_file));
45 setuerror(0);
46 AFS_GUNLOCK();
47 ip = (struct inode *)igetinode(afs_cacheVfsp, (dev_t) cacheDev.dev,
48 (ino_t) ainode->ufs, &dummy);
49 AFS_GLOCK();
50 if (getuerror()) {
51 osi_FreeSmallSpace(afile);
52 osi_Panic("UFSOpen: igetinode failed");
53 }
54 iunlock(ip);
55 afile->vnode = ITOV(ip);
56 afile->size = VTOI(afile->vnode)->i_size;
57 afile->offset = 0;
58 afile->proc = (int (*)())0;
59 return (void *)afile;
60 }
61
62 int
63 afs_osi_Stat(struct osi_file *afile, struct osi_stat *astat)
64 {
65 afs_int32 code;
66 struct vattr tvattr;
67 AFS_STATCNT(osi_Stat);
68 AFS_GUNLOCK();
69 code = VOP_GETATTR(afile->vnode, &tvattr, &afs_osi_cred, VSYNC);
70 AFS_GLOCK();
71 if (code == 0) {
72 astat->size = tvattr.va_size;
73 astat->mtime = tvattr.va_mtime.tv_sec;
74 astat->atime = tvattr.va_atime.tv_sec;
75 }
76 return code;
77 }
78
79 int
80 osi_UFSClose(struct osi_file *afile)
81 {
82 AFS_STATCNT(osi_Close);
83 if (afile->vnode) {
84 AFS_RELE(afile->vnode);
85 }
86
87 osi_FreeSmallSpace(afile);
88 return 0;
89 }
90
91 int
92 osi_UFSTruncate(struct osi_file *afile, afs_int32 asize)
93 {
94 afs_ucred_t *oldCred;
95 struct vattr tvattr;
96 afs_int32 code;
97 struct osi_stat tstat;
98 AFS_STATCNT(osi_Truncate);
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 VATTR_NULL(&tvattr);
108 /* note that this credential swapping stuff is only necessary because
109 * of ufs's references directly to u.u_cred instead of to
110 * credentials parameter. Probably should fix ufs some day. */
111 oldCred = p_cred(u.u_procp);
112 set_p_cred(u.u_procp, &afs_osi_cred);
113 tvattr.va_size = asize;
114 AFS_GUNLOCK();
115 code = VOP_SETATTR(afile->vnode, &tvattr, &afs_osi_cred, 0);
116 AFS_GLOCK();
117 set_p_cred(u.u_procp, oldCred); /* restore */
118 return code;
119 }
120
121 void
122 osi_DisableAtimes(struct vnode *avp)
123 {
124 struct inode *ip = VTOI(avp);
125 ip->i_flag &= ~IACC;
126 }
127
128
129 /* Generic read interface */
130 int
131 afs_osi_Read(struct osi_file *afile, int offset, void *aptr,
132 afs_int32 asize)
133 {
134 afs_ucred_t *oldCred;
135 long resid;
136 afs_int32 code;
137 afs_int32 cnt1 = 0;
138 AFS_STATCNT(osi_Read);
139
140 /**
141 * If the osi_file passed in is NULL, panic only if AFS is not shutting
142 * down. No point in crashing when we are already shutting down
143 */
144 if (!afile) {
145 if (afs_shuttingdown == AFS_RUNNING)
146 osi_Panic("osi_Read called with null param");
147 else
148 return -EIO;
149 }
150
151 if (offset != -1)
152 afile->offset = offset;
153 retry_IO:
154 AFS_GUNLOCK();
155 code =
156 gop_rdwr(UIO_READ, afile->vnode, (caddr_t) aptr, asize, afile->offset,
157 AFS_UIOSYS, IO_UNIT, &resid);
158 AFS_GLOCK();
159 if (code == 0) {
160 code = asize - resid;
161 afile->offset += code;
162 osi_DisableAtimes(afile->vnode);
163 } else {
164 afs_Trace2(afs_iclSetp, CM_TRACE_READFAILED, ICL_TYPE_INT32,
165 (afs_int32) resid, ICL_TYPE_INT32, code);
166 /*
167 * To handle periodic low-level EFAULT failures that we've seen with the
168 * Weitek chip; in all observed failed cases a second read succeeded.
169 */
170 if ((code == EFAULT) && (cnt1++ < 5)) {
171 afs_stats_cmperf.osiread_efaults++;
172 goto retry_IO;
173 }
174 setuerror(code);
175 if (code > 0) {
176 code = -code;
177 }
178 }
179 return code;
180 }
181
182 /* Generic write interface */
183 int
184 afs_osi_Write(struct osi_file *afile, afs_int32 offset, void *aptr,
185 afs_int32 asize)
186 {
187 afs_ucred_t *oldCred;
188 long resid;
189 afs_int32 code;
190 AFS_STATCNT(osi_Write);
191 if (!afile)
192 osi_Panic("afs_osi_Write called with null param");
193 if (offset != -1)
194 afile->offset = offset;
195 AFS_GUNLOCK();
196 code =
197 gop_rdwr(UIO_WRITE, afile->vnode, (caddr_t) aptr, asize,
198 afile->offset, AFS_UIOSYS, IO_UNIT, &resid);
199 AFS_GLOCK();
200 if (code == 0) {
201 code = asize - resid;
202 afile->offset += code;
203 } else {
204 if (code == ENOSPC)
205 afs_WarnENOSPC();
206 setuerror(code);
207 if (code > 0) {
208 code = -code;
209 }
210 }
211 if (afile->proc) {
212 (*afile->proc) (afile, code);
213 }
214 return code;
215 }
216
217
218 void
219 shutdown_osifile(void)
220 {
221 AFS_STATCNT(shutdown_osifile);
222 if (afs_cold_shutdown) {
223 afs_osicred_initialized = 0;
224 }
225 }