IRIX: Remove pre-65 code
[openafs.git] / src / afs / IRIX / osi_vfsops.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 /*
11  * osi_vfsops.c for IRIX
12  */
13 #include <afsconfig.h>
14 #include "afs/param.h"
15
16
17 #include "afs/sysincludes.h"    /* Standard vendor system headers */
18 #include "afsincludes.h"        /* Afs-based standard headers */
19 #include "afs/afs_stats.h"      /* statistics stuff */
20 #include "sys/syssgi.h"
21
22
23 struct vfs *afs_globalVFS = 0;
24 struct vcache *afs_globalVp = 0;
25
26 #ifdef AFS_SGI_VNODE_GLUE
27 #include <sys/invent.h>
28 int afs_is_numa_arch;
29 mutex_t afs_init_kern_lock;
30 #endif
31
32
33 #define SYS_setgroups SGI_SETGROUPS
34
35 int afs_fstype;
36 lock_t afs_rxlock;
37
38 #include "sys/mload.h"
39 char *Afs_mversion = M_VERSION;
40
41 extern int (*setgroupsp) (int, gid_t *);
42 extern struct afs_lock afs_xvcache;
43 extern int idbg_afsuser();
44 extern void afs_mpservice(void *);
45
46 /*
47  * AFS fs initialization - we also plug system calls here
48  */
49 #define NewSystemCall(n,f,a) \
50         syscallsw[ABI_IRIX5].sc_sysent[(n)-1000].sy_narg = a; \
51         syscallsw[ABI_IRIX5].sc_sysent[(n)-1000].sy_call = f; \
52         syscallsw[ABI_IRIX5].sc_sysent[(n)-1000].sy_flags = 0;
53 extern struct vfsops Afs_vfsops, *afs_vfsopsp;
54 extern struct vnodeops Afs_vnodeops, *afs_vnodeopsp;
55 extern void (*afsidestroyp) (struct inode *);
56 extern void afsidestroy(struct inode *);
57 extern int (*idbg_prafsnodep) (vnode_t *);
58 extern int (*idbg_afsvfslistp) (void);
59 extern int idbg_prafsnode(vnode_t *);
60 extern int idbg_afsvfslist(void);
61
62
63 int
64 Afs_init(struct vfssw *vswp, int fstype)
65 {
66     extern int Afs_syscall(), Afs_xsetgroups(), afs_pioctl(), afs_setpag();
67     extern int icreate(), iopen(), iinc(), idec();
68 #ifdef AFS_SGI_XFS_IOPS_ENV
69     extern int iopen64();
70 #else
71     extern int iread(), iwrite();
72 #endif
73
74     AFS_STATCNT(afsinit);
75     osi_Init();
76     afs_fstype = fstype;
77
78 #ifdef AFS_SGI_VNODE_GLUE
79     /* Synchronize doing NUMA test. */
80     mutex_init(&afs_init_kern_lock, MUTEX_DEFAULT, "init_kern_lock");
81 #endif
82     /*
83      * set up pointers from main kernel into us
84      */
85     afs_vnodeopsp = &Afs_vnodeops;
86     afs_vfsopsp = &Afs_vfsops;
87     afsidestroyp = afsidestroy;
88     idbg_prafsnodep = idbg_prafsnode;
89     idbg_afsvfslistp = idbg_afsvfslist;
90     NewSystemCall(AFS_SYSCALL, Afs_syscall, 6);
91     NewSystemCall(AFS_PIOCTL, afs_pioctl, 4);
92     NewSystemCall(AFS_SETPAG, afs_setpag, 0);
93     NewSystemCall(AFS_IOPEN, iopen, 3);
94     NewSystemCall(AFS_ICREATE, icreate, 6);
95     NewSystemCall(AFS_IINC, iinc, 3);
96     NewSystemCall(AFS_IDEC, idec, 3);
97 #ifdef AFS_SGI_XFS_IOPS_ENV
98     NewSystemCall(AFS_IOPEN64, iopen64, 4);
99 #else
100     NewSystemCall(AFS_IREAD, iread, 6);
101     NewSystemCall(AFS_IWRITE, iwrite, 6);
102 #endif
103
104     /* last replace these */
105     setgroupsp = Afs_xsetgroups;
106
107     idbg_addfunc("afsuser", idbg_afsuser);
108     return (0);
109 }
110
111
112 extern int afs_mount(), afs_unmount(), afs_root(), afs_statfs();
113 extern int afs_sync(OSI_VFS_DECL(afsp), int flags, struct cred *cr);
114 extern int afs_vget(OSI_VFS_DECL(afsp), vnode_t ** vpp, struct fid *afidp);
115 #ifdef MP
116 struct vfsops afs_lockedvfsops =
117 #else
118 struct vfsops Afs_vfsops =
119 #endif
120 {
121     BHV_IDENTITY_INIT_POSITION(VFS_POSITION_BASE),
122     afs_mount,
123     fs_nosys,                   /* rootinit */
124     fs_nosys,                   /* mntupdate */
125     fs_dounmount,
126     afs_unmount,
127     afs_root,
128     afs_statfs,
129     afs_sync,
130     afs_vget,
131     fs_nosys,                   /* mountroot */
132     fs_nosys,                   /* realvfsops */
133     fs_import,                  /* import */
134     fs_nosys,                   /* quotactl */
135 };
136 extern struct afs_q VLRU;       /*vcache LRU */
137
138 static bhv_desc_t afs_vfs_bhv;
139 afs_mount(struct vfs *afsp, vnode_t * mvp, struct mounta *uap,
140           char *attrs,
141           cred_t * cr)
142 {
143     AFS_STATCNT(afs_mount);
144
145     if (!suser())
146         return EPERM;
147
148     if (mvp->v_type != VDIR)
149         return ENOTDIR;
150
151     if (afs_globalVFS) {        /* Don't allow remounts. */
152         return EBUSY;
153     }
154
155     afs_globalVFS = afsp;
156     afsp->vfs_bsize = 8192;
157     afsp->vfs_fsid.val[0] = AFS_VFSMAGIC;       /* magic */
158     afsp->vfs_fsid.val[1] = afs_fstype;
159     vfs_insertbhv(afsp, &afs_vfs_bhv, &Afs_vfsops, &afs_vfs_bhv);
160     afsp->vfs_fstype = afs_fstype;
161     afsp->vfs_dev = 0xbabebabe; /* XXX this should be unique */
162
163     return 0;
164 }
165
166 afs_unmount(OSI_VFS_ARG(afsp), flags, cr)
167     OSI_VFS_DECL(afsp);
168      int flags;
169      cred_t *cr;
170 {
171     struct vcache *tvc;
172     vnode_t *vp, *rootvp = NULL;
173     struct afs_q *tq;
174     struct afs_q *uq;
175     int error, fv_slept;
176     OSI_VFS_CONVERT(afsp);
177
178     AFS_STATCNT(afs_unmount);
179
180     if (!suser())
181         return EPERM;
182
183     /*
184      * flush all pages from inactive vnodes - return
185      * EBUSY if any still in use
186      */
187     ObtainWriteLock(&afs_xvcache, 172);
188  retry:
189     for (tq = VLRU.prev; tq != &VLRU; tq = uq) {
190         tvc = QTOV(tq);
191         uq = QPrev(tq);
192         vp = (vnode_t *) tvc;
193         if (error = afs_FlushVCache(tvc, &fv_slept)) {
194             if (vp->v_flag & VROOT) {
195                 rootvp = vp;
196                 continue;
197             } else {
198                 ReleaseWriteLock(&afs_xvcache);
199                 return error;
200             }
201         }
202         if (fv_slept) {
203             goto retry;
204         }
205     }
206
207     /*
208      * rootvp gets lots of ref counts
209      */
210     if (rootvp) {
211         tvc = VTOAFS(rootvp);
212         if (tvc->opens || CheckLock(&tvc->lock) || LockWaiters(&tvc->lock)) {
213             ReleaseWriteLock(&afs_xvcache);
214             return EBUSY;
215         }
216         ReleaseWriteLock(&afs_xvcache);
217         rootvp->v_count = 1;
218         AFS_RELE(rootvp);
219         ObtainWriteLock(&afs_xvcache, 173);
220         afs_FlushVCache(tvc, &fv_slept);
221     }
222     ReleaseWriteLock(&afs_xvcache);
223     afs_globalVFS = 0;
224     afs_shutdown(AFS_WARM);
225     VFS_REMOVEBHV(afsp, &afs_vfs_bhv);
226     return 0;
227 }
228
229
230
231 afs_root(OSI_VFS_ARG(afsp), avpp)
232     OSI_VFS_DECL(afsp);
233      struct vnode **avpp;
234 {
235     afs_int32 code = 0;
236     struct vrequest treq;
237     struct vcache *tvp = 0;
238     OSI_VFS_CONVERT(afsp);
239
240     AFS_STATCNT(afs_root);
241     if (afs_globalVp && (afs_globalVp->f.states & CStatd)) {
242         tvp = afs_globalVp;
243     } else {
244         if (afs_globalVp) {
245             afs_PutVCache(afs_globalVp);
246             afs_globalVp = NULL;
247         }
248
249         if (!(code = afs_InitReq(&treq, OSI_GET_CURRENT_CRED()))
250             && !(code = afs_CheckInit())) {
251             tvp = afs_GetVCache(&afs_rootFid, &treq);
252             /* we really want this to stay around */
253             if (tvp) {
254                 afs_globalVp = tvp;
255             } else
256                 code = EIO;
257         }
258     }
259     if (tvp) {
260         int s;
261         VN_HOLD(AFSTOV(tvp));
262         s = VN_LOCK(AFSTOV(tvp));
263         AFSTOV(tvp)->v_flag |= VROOT;
264         VN_UNLOCK(AFSTOV(tvp), s);
265
266         afs_globalVFS = afsp;
267         *avpp = AFSTOV(tvp);
268     }
269
270     afs_Trace2(afs_iclSetp, CM_TRACE_VFSROOT, ICL_TYPE_POINTER, *avpp,
271                ICL_TYPE_INT32, code);
272     return code;
273 }
274
275 afs_statfs(OSI_VFS_ARG(afsp), abp, avp)
276     OSI_VFS_DECL(afsp);
277      struct statvfs *abp;
278      struct vnode *avp;         /* unused */
279 {
280     OSI_VFS_CONVERT(afsp);
281
282     AFS_STATCNT(afs_statfs);
283     abp->f_bsize = afsp->vfs_bsize;
284     abp->f_frsize = afsp->vfs_bsize;
285     /* Fake a high number below to satisfy programs that use the statfs
286      * call to make sure that there's enough space in the device partition
287      * before storing something there.
288      */
289     abp->f_blocks = abp->f_bfree = abp->f_bavail = abp->f_files =
290         abp->f_ffree = abp->f_favail = AFS_VFS_FAKEFREE;
291
292     abp->f_fsid = AFS_VFSMAGIC; /* magic */
293     strcpy(abp->f_basetype, AFS_MOUNT_STR);
294     abp->f_flag = 0;
295     abp->f_namemax = 256;
296     return 0;
297 }
298
299
300
301 /*
302  * sync's responsibilities include pushing back DELWRI pages
303  * Things to watch out for:
304  *      1) don't want to hold off new vnodes in the file system
305  *              while pushing back pages
306  *      2) since we can deal with un-referenced vndoes need to watch
307  *              races with folks who recycle vnodes
308  * Flags:
309  *      SYNC_BDFLUSH - do NOT sleep waiting for an inode - also, when
310  *                      when pushing DELWRI - only push old ones.
311  *      SYNC_PDFLUSH - push v_dpages.
312  *      SYNC_ATTR    - sync attributes - note that ordering considerations
313  *                      dictate that we also flush dirty pages
314  *      SYNC_WAIT    - do synchronouse writes - inode & delwri
315  *      SYNC_NOWAIT  - start delayed writes.
316  *      SYNC_DELWRI  - look at inodes w/ delwri pages. Other flags
317  *                      decide how to deal with them.
318  *      SYNC_CLOSE   - flush delwri and invalidate others.
319  *      SYNC_FSDATA  - push fs data (e.g. superblocks)
320  */
321
322 extern afs_int32 vcachegen;
323 #define PREEMPT_MASK    0x7f
324 #define PREEMPT()
325
326 int
327 afs_sync(OSI_VFS_DECL(afsp),
328          int flags,
329          struct cred *cr)
330 {
331     /* Why enable the vfs sync operation?? */
332     int error, lasterr, preempt;
333     struct vcache *tvc;
334     struct vnode *vp;
335     afs_uint32 lvcachegen;
336     struct afs_q *tq;
337     struct afs_q *uq;
338     int s;
339     OSI_VFS_CONVERT(afsp);
340
341     error = lasterr = 0;
342     /*
343      * if not interested in vnodes, skip all this
344      */
345     if ((flags & (SYNC_CLOSE | SYNC_DELWRI | SYNC_PDFLUSH)) == 0)
346         goto end;
347   loop:
348     ObtainReadLock(&afs_xvcache);
349     for (tq = VLRU.prev; tq != &VLRU; tq = uq) {
350         tvc = QTOV(tq);
351         uq = QPrev(tq);
352         vp = (vnode_t *) tvc;
353         /*
354          * Since we push all dirty pages on last close/VOP_INACTIVE
355          * we are only concerned with vnodes with
356          * active reference counts.
357          */
358         s = VN_LOCK(vp);
359         if (vp->v_count == 0) {
360             VN_UNLOCK(vp, s);
361             continue;
362         }
363         if ((flags & SYNC_CLOSE) == 0 && !AFS_VN_DIRTY(vp)) {
364             VN_UNLOCK(vp, s);
365             continue;
366         }
367
368         /*
369          * ignore vnodes which need no flushing
370          */
371         if (flags & SYNC_DELWRI) {
372             if (!AFS_VN_DIRTY(vp)) {
373                 VN_UNLOCK(vp, s);
374                 continue;
375             }
376         }
377         else if (flags & SYNC_PDFLUSH) {
378             if (!VN_GET_DPAGES(vp)) {
379                 VN_UNLOCK(vp, s);
380                 continue;
381             }
382         }
383
384         vp->v_count++;
385         VN_UNLOCK(vp, s);
386         lvcachegen = vcachegen;
387         ReleaseReadLock(&afs_xvcache);
388
389         /*
390          * Try to lock rwlock without sleeping.  If we can't, we must
391          * sleep for rwlock.
392          */
393         if (afs_rwlock_nowait(vp, 1) == 0) {
394             if (flags & (SYNC_BDFLUSH | SYNC_PDFLUSH))
395             {
396                 AFS_RELE(vp);
397                 ObtainReadLock(&afs_xvcache);
398                 if (vcachegen != lvcachegen) {
399                     ReleaseReadLock(&afs_xvcache);
400                     goto loop;
401                 }
402                 continue;
403             }
404             AFS_RWLOCK(vp, VRWLOCK_WRITE);
405         }
406
407         AFS_GUNLOCK();
408         if (flags & SYNC_CLOSE) {
409             PFLUSHINVALVP(vp, (off_t) 0, (off_t) tvc->f.m.Length);
410         }
411         else if (flags & SYNC_PDFLUSH) {
412             if (VN_GET_DPAGES(vp)) {
413                 pdflush(vp, B_ASYNC);
414             }
415         }
416
417
418         if ((flags & SYNC_DELWRI) && AFS_VN_DIRTY(vp)) {
419             PFLUSHVP(vp, (off_t) tvc->f.m.Length,
420                      (flags & SYNC_WAIT) ? 0 : B_ASYNC, error);
421         }
422
423         /*
424          * Release vp, check error and whether to preempt, and if
425          * we let go of xvcache lock and someone has changed the
426          * VLRU, restart the loop
427          */
428         AFS_GLOCK();
429         AFS_RWUNLOCK(vp, VRWLOCK_WRITE);
430         AFS_RELE(vp);
431         if (error)
432             lasterr = error;
433         if ((++preempt & PREEMPT_MASK) == 0) {
434             AFS_GUNLOCK();
435             PREEMPT();
436             AFS_GLOCK();
437         }
438         ObtainReadLock(&afs_xvcache);
439         if (vcachegen != lvcachegen) {
440             ReleaseReadLock(&afs_xvcache);
441             goto loop;
442         }
443     }
444     ReleaseReadLock(&afs_xvcache);
445   end:
446     return lasterr;
447 }
448
449
450 afs_vget(OSI_VFS_DECL(afsp), vnode_t ** avcp, struct fid * fidp)
451 {
452     struct VenusFid vfid;
453     struct vrequest treq;
454     struct cell *tcell;
455     afs_int32 code = 0;
456     afs_int32 ret;
457
458 #if defined(CKPT) && !defined(_R5000_CVT_WAR)
459     afs_fid2_t *afid2;
460 #endif
461
462     OSI_VFS_CONVERT(afsp);
463
464     AFS_STATCNT(afs_vget);
465
466     *avcp = NULL;
467
468 #if defined(CKPT) && !defined(_R5000_CVT_WAR)
469     afid2 = (afs_fid2_t *) fidp;
470     if (afid2->af_len == sizeof(afs_fid2_t) - sizeof(afid2->af_len)) {
471         /* It's a checkpoint restart fid. */
472         tcell = afs_GetCellByIndex(afid2->af_cell, READ_LOCK);
473         if (!tcell) {
474             code = EIO;
475             goto out;
476         }
477         vfid.Cell = tcell->cellNum;
478         afs_PutCell(tcell, READ_LOCK);
479         vfid.Fid.Volume = afid2->af_volid;
480         vfid.Fid.Vnode = afid2->af_vno;
481         vfid.Fid.Unique = afid2->af_uniq;
482
483         if (code = afs_InitReq(&treq, OSI_GET_CURRENT_CRED()))
484             goto out;
485         *avcp =
486             (vnode_t *) afs_GetVCache(&vfid, &treq);
487         if (!*avcp) {
488             code = EIO;
489         }
490         goto out;
491     }
492 #endif
493
494     if (code = afs_InitReq(&treq, OSI_GET_CURRENT_CRED()))
495         goto out;
496     code = afs_osi_vget((struct vcache **)avcp, fidp, &treq);
497
498   out:
499     afs_Trace3(afs_iclSetp, CM_TRACE_VGET, ICL_TYPE_POINTER, *avcp,
500                ICL_TYPE_INT32, treq.uid, ICL_TYPE_FID, &vfid);
501     code = afs_CheckCode(code, &treq, 42);
502     return code;
503 }
504
505
506 #ifdef MP                       /* locked versions of vfs operations. */
507
508 /* wrappers for vfs calls */
509 #define AFS_MP_VFS_ARG(A) bhv_desc_t A
510
511 int
512 mp_afs_mount(struct vfs *a, struct vnode *b, struct mounta *c,
513              char *d,
514              struct cred *e)
515 {
516     int rv;
517     AFS_GLOCK();
518     rv = afs_lockedvfsops.vfs_mount(a, b, c, d
519                                     , e
520         );
521     AFS_GUNLOCK();
522     return rv;
523 }
524
525 int
526 mp_afs_unmount(AFS_MP_VFS_ARG(*a), int b, struct cred *c)
527 {
528     int rv;
529     AFS_GLOCK();
530     rv = afs_lockedvfsops.vfs_unmount(a, b, c);
531     AFS_GUNLOCK();
532     return rv;
533 }
534
535 int
536 mp_afs_root(AFS_MP_VFS_ARG(*a), struct vnode **b)
537 {
538     int rv;
539     AFS_GLOCK();
540     rv = afs_lockedvfsops.vfs_root(a, b);
541     AFS_GUNLOCK();
542     return rv;
543 }
544
545 int
546 mp_afs_statvfs(AFS_MP_VFS_ARG(*a), struct statvfs *b, struct vnode *c)
547 {
548     int rv;
549     AFS_GLOCK();
550     rv = afs_lockedvfsops.vfs_statvfs(a, b, c);
551     AFS_GUNLOCK();
552     return rv;
553 }
554
555 int
556 mp_afs_sync(AFS_MP_VFS_ARG(*a),
557             int b,
558             struct cred *c)
559 {
560     int rv;
561     AFS_GLOCK();
562     rv = afs_lockedvfsops.vfs_sync(a, b, c);
563     AFS_GUNLOCK();
564     return rv;
565 }
566
567 int
568 mp_afs_vget(AFS_MP_VFS_ARG(*a), struct vnode **b, struct fid *c)
569 {
570     int rv;
571     AFS_GLOCK();
572     rv = afs_lockedvfsops.vfs_vget(a, b, c);
573     AFS_GUNLOCK();
574     return rv;
575 }
576
577 struct vfsops Afs_vfsops = {
578     BHV_IDENTITY_INIT_POSITION(VFS_POSITION_BASE),
579     mp_afs_mount,
580     fs_nosys,                   /* rootinit */
581     fs_nosys,                   /* mntupdate */
582     fs_dounmount,
583     mp_afs_unmount,
584     mp_afs_root,
585     mp_afs_statvfs,
586     mp_afs_sync,
587     mp_afs_vget,
588     fs_nosys,                   /* mountroot */
589     fs_nosys,                   /* realvfsops */
590     fs_import,                  /* import */
591     fs_nosys,                   /* quotactl */
592 };
593
594 #endif /* MP */