include-afsconfig-before-param-h-20010712
[openafs.git] / src / afs / DUX / 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 "../afs/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 *osi_UFSOpen(ainode)
28     afs_int32 ainode;
29 {
30     static struct vnode *tags_vnode = NULL;
31     struct inode *ip;
32     register struct osi_file *afile = NULL;
33     extern int cacheDiskType;
34     afs_int32 code = 0;
35     int dummy;
36     AFS_STATCNT(osi_UFSOpen);
37     if(cacheDiskType != AFS_FCACHE_TYPE_UFS) 
38         osi_Panic("UFSOpen called for non-UFS cache\n");
39
40     afile = (struct osi_file *) osi_AllocSmallSpace(sizeof(struct osi_file));
41     AFS_GUNLOCK();
42
43     switch(afs_cacheVfsp->m_stat.f_type) {
44     case MOUNT_UFS:
45        code = igetinode(afs_cacheVfsp, (dev_t) cacheDev.dev, (ino_t)ainode, &ip, &dummy);
46        if (code) {
47            osi_FreeSmallSpace(afile);
48            osi_Panic("UFSOpen: igetinode failed");
49        }
50        IN_UNLOCK(ip);
51        afile->vnode = ITOV(ip);
52        afile->size = VTOI(afile->vnode)->i_size;
53        afile->offset = 0;
54        afile->proc = NULL;
55        afile->inum = ainode;        /* for hint validity checking */
56        break;
57     case MOUNT_MSFS: {
58        char path[1024];
59        struct nameidata nd, *ndp = &nd;
60        struct utask_nd utnd = { NULL, NULL };
61        struct vattr attr;
62
63        bzero(&nd, sizeof(nd));
64        ndp->ni_utnd = &utnd;
65        ndp->ni_nameiop = LOOKUP;
66        ndp->ni_cred = &afs_osi_cred;
67        ndp->ni_segflg  = UIO_SYSSPACE;
68
69        /* get hold of a vnode for the .tags directory, so we can
70            lookup files relative to it */
71        if(tags_vnode == NULL) {
72            ndp->ni_cdir = afs_cacheVfsp->m_vnodecovered;
73            strcpy(path, afs_cacheVfsp->m_stat.f_mntonname);
74            strcat(path, "/.tags");
75            ndp->ni_dirp = path;
76            if((code = namei(ndp)))
77                osi_Panic("failed to lookup %s (%d)", path, code);
78            tags_vnode = ndp->ni_vp;
79        }
80        sprintf(path, "%d", ainode);
81        ndp->ni_dirp = path;
82        ndp->ni_cdir = tags_vnode;
83        if((code = namei(ndp)))
84            osi_Panic("failed to lookup %s (%d)", path, code);
85
86        /* XXX this sucks, chances are we're going to do this again right
87           away, but apparently we can't just set the size to 0 */
88        VOP_GETATTR(ndp->ni_vp, &attr, &afs_osi_cred, code);
89        if(code) 
90            osi_Panic("failed to stat %s (%d)", path, code);
91
92        afile->vnode = ndp->ni_vp;
93        afile->size = attr.va_size;
94        afile->offset = 0;
95        afile->proc = NULL;
96        afile->inum = ainode;        /* for hint validity checking */
97        break;
98     }
99     default:
100         osi_Panic("UFSOpen called for unknown cache-type (%d)", 
101                   afs_cacheVfsp->m_stat.f_type);
102     }
103
104     AFS_GLOCK();
105     return afile;
106 }
107
108 afs_osi_Stat(afile, astat)
109     register struct osi_file *afile;
110     register struct osi_stat *astat; {
111     register afs_int32 code;
112     struct vattr tvattr;
113     AFS_STATCNT(osi_Stat);
114     MObtainWriteLock(&afs_xosi,320);
115     AFS_GUNLOCK();
116     VOP_GETATTR(afile->vnode, &tvattr, &afs_osi_cred, code);
117     AFS_GLOCK();
118     if (code == 0) {
119         astat->size = tvattr.va_size;
120         astat->blksize = tvattr.va_blocksize;
121         astat->mtime = tvattr.va_mtime.tv_sec;
122         astat->atime = tvattr.va_atime.tv_sec;
123     }
124     MReleaseWriteLock(&afs_xosi);
125     return code;
126 }
127
128 osi_UFSClose(afile)
129      register struct osi_file *afile;
130   {
131       AFS_STATCNT(osi_Close);
132       if(afile->vnode) {
133         AFS_RELE(afile->vnode);
134       }
135       
136       osi_FreeSmallSpace(afile);
137       return 0;
138   }
139
140 osi_UFSTruncate(afile, asize)
141     register struct osi_file *afile;
142     afs_int32 asize; {
143     struct AFS_UCRED *oldCred;
144     struct vattr tvattr;
145     register afs_int32 code;
146     struct osi_stat tstat;
147     AFS_STATCNT(osi_Truncate);
148
149     /* This routine only shrinks files, and most systems
150      * have very slow truncates, even when the file is already
151      * small enough.  Check now and save some time.
152      */
153     code = afs_osi_Stat(afile, &tstat);
154     if (code || tstat.size <= asize) return code;
155     MObtainWriteLock(&afs_xosi,321);    
156     VATTR_NULL(&tvattr);
157     /* note that this credential swapping stuff is only necessary because
158         of ufs's references directly to u.u_cred instead of to
159         credentials parameter.  Probably should fix ufs some day. */
160     oldCred = u.u_cred;     /* remember old credentials pointer  */
161     u.u_cred = &afs_osi_cred;   /* temporarily use superuser credentials */
162     tvattr.va_size = asize;
163     AFS_GUNLOCK();
164     VOP_SETATTR(afile->vnode, &tvattr, &afs_osi_cred, code);
165     AFS_GLOCK();
166     u.u_cred = oldCred;     /* restore */
167     MReleaseWriteLock(&afs_xosi);
168     return code;
169 }
170
171 void osi_DisableAtimes(avp)
172 struct vnode *avp;
173 {
174    struct inode *ip;
175    assert(avp->v_tag == VT_UFS);
176    ip = VTOI(avp);
177    ip->i_flag &= ~IACC;
178 }
179
180
181 /* Generic read interface */
182 afs_osi_Read(afile, offset, aptr, asize)
183     register struct osi_file *afile;
184     int offset;
185     char *aptr;
186     afs_int32 asize; {
187     struct AFS_UCRED *oldCred;
188     unsigned int resid;
189     register afs_int32 code;
190     register afs_int32 cnt1=0;
191     AFS_STATCNT(osi_Read);
192
193     /**
194       * If the osi_file passed in is NULL, panic only if AFS is not shutting
195       * down. No point in crashing when we are already shutting down
196       */
197     if ( !afile ) {
198         if ( !afs_shuttingdown )
199             osi_Panic("osi_Read called with null param");
200         else
201             return EIO;
202     }
203
204     if (offset != -1) afile->offset = offset;
205     AFS_GUNLOCK();
206     code = gop_rdwr(UIO_READ, afile->vnode, (caddr_t) aptr, asize, afile->offset,
207                   AFS_UIOSYS, IO_UNIT, &afs_osi_cred, &resid);
208     AFS_GLOCK();
209     if (code == 0) {
210         code = asize - resid;
211         afile->offset += code;
212         osi_DisableAtimes(afile->vnode);
213     }
214     else {
215         afs_Trace2(afs_iclSetp, CM_TRACE_READFAILED, ICL_TYPE_INT32, resid,
216                  ICL_TYPE_INT32, code);
217         code = -1;
218     }
219     return code;
220 }
221
222 /* Generic write interface */
223 afs_osi_Write(afile, offset, aptr, asize)
224     register struct osi_file *afile;
225     char *aptr;
226     afs_int32 offset;
227     afs_int32 asize; {
228     struct AFS_UCRED *oldCred;
229     unsigned int resid;
230     register afs_int32 code;
231     AFS_STATCNT(osi_Write);
232     if ( !afile )
233         osi_Panic("afs_osi_Write called with null param");
234     if (offset != -1) afile->offset = offset;
235     {
236         struct ucred *tmpcred = u.u_cred;
237         u.u_cred = &afs_osi_cred;
238         AFS_GUNLOCK();
239         code = gop_rdwr(UIO_WRITE, afile->vnode, (caddr_t) aptr, asize, afile->offset,
240                   AFS_UIOSYS, IO_UNIT, &afs_osi_cred, &resid);
241         AFS_GLOCK();
242         u.u_cred = tmpcred;
243     }
244     if (code == 0) {
245         code = asize - resid;
246         afile->offset += code;
247     }
248     else {
249         code = -1;
250     }
251     if (afile->proc) {
252         (*afile->proc)(afile, code);
253     }
254     return code;
255 }
256
257
258 /*  This work should be handled by physstrat in ca/machdep.c.
259     This routine written from the RT NFS port strategy routine.
260     It has been generalized a bit, but should still be pretty clear. */
261 int afs_osi_MapStrategy(aproc, bp)
262         int (*aproc)();
263         register struct buf *bp;
264 {
265     afs_int32 returnCode;
266
267     AFS_STATCNT(osi_MapStrategy);
268     returnCode = (*aproc) (bp);
269
270     return returnCode;
271 }
272
273
274
275 void
276 shutdown_osifile()
277 {
278   extern int afs_cold_shutdown;
279
280   AFS_STATCNT(shutdown_osifile);
281   if (afs_cold_shutdown) {
282     afs_osicred_initialized = 0;
283   }
284 }
285