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