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