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