514dcf9f80b199638f46ecf407c61ffc9d52c981
[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     register 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     for (tq = VLRU.prev; tq != &VLRU; tq = uq) {
220         tvc = QTOV(tq);
221         uq = QPrev(tq);
222         vp = (vnode_t *) tvc;
223         if (error = afs_FlushVCache(tvc, &fv_slept))
224             if (vp->v_flag & VROOT) {
225                 rootvp = vp;
226                 continue;
227             } else {
228                 ReleaseWriteLock(&afs_xvcache);
229                 return error;
230             }
231     }
232
233     /*
234      * rootvp gets lots of ref counts
235      */
236     if (rootvp) {
237         tvc = VTOAFS(rootvp);
238         if (tvc->opens || CheckLock(&tvc->lock) || LockWaiters(&tvc->lock)) {
239             ReleaseWriteLock(&afs_xvcache);
240             return EBUSY;
241         }
242         ReleaseWriteLock(&afs_xvcache);
243         rootvp->v_count = 1;
244         AFS_RELE(rootvp);
245         ObtainWriteLock(&afs_xvcache, 173);
246         afs_FlushVCache(tvc, &fv_slept);
247     }
248     ReleaseWriteLock(&afs_xvcache);
249     afs_globalVFS = 0;
250     afs_shutdown();
251 #ifdef AFS_SGI65_ENV
252     VFS_REMOVEBHV(afsp, &afs_vfs_bhv);
253 #endif
254     return 0;
255 }
256
257
258
259 afs_root(OSI_VFS_ARG(afsp), avpp)
260     OSI_VFS_DECL(afsp);
261      struct vnode **avpp;
262 {
263     register afs_int32 code = 0;
264     struct vrequest treq;
265     register struct vcache *tvp = 0;
266     OSI_VFS_CONVERT(afsp);
267
268     AFS_STATCNT(afs_root);
269     if (afs_globalVp && (afs_globalVp->f.states & CStatd)) {
270         tvp = afs_globalVp;
271     } else {
272         if (afs_globalVp) {
273             afs_PutVCache(afs_globalVp);
274             afs_globalVp = NULL;
275         }
276
277         if (!(code = afs_InitReq(&treq, OSI_GET_CURRENT_CRED()))
278             && !(code = afs_CheckInit())) {
279             tvp = afs_GetVCache(&afs_rootFid, &treq, NULL, NULL);
280             /* we really want this to stay around */
281             if (tvp) {
282                 afs_globalVp = tvp;
283             } else
284                 code = ENOENT;
285         }
286     }
287     if (tvp) {
288         int s;
289         VN_HOLD(AFSTOV(tvp));
290         s = VN_LOCK(AFSTOV(tvp));
291         AFSTOV(tvp)->v_flag |= VROOT;
292         VN_UNLOCK(AFSTOV(tvp), s);
293
294         afs_globalVFS = afsp;
295         *avpp = AFSTOV(tvp);
296     }
297
298     afs_Trace2(afs_iclSetp, CM_TRACE_VFSROOT, ICL_TYPE_POINTER, *avpp,
299                ICL_TYPE_INT32, code);
300     return code;
301 }
302
303 afs_statfs(OSI_VFS_ARG(afsp), abp, avp)
304     OSI_VFS_DECL(afsp);
305      struct statvfs *abp;
306      struct vnode *avp;         /* unused */
307 {
308     OSI_VFS_CONVERT(afsp);
309
310     AFS_STATCNT(afs_statfs);
311     abp->f_bsize = afsp->vfs_bsize;
312     abp->f_frsize = afsp->vfs_bsize;
313     /* Fake a high number below to satisfy programs that use the statfs
314      * call to make sure that there's enough space in the device partition
315      * before storing something there.
316      */
317     abp->f_blocks = abp->f_bfree = abp->f_bavail = abp->f_files =
318         abp->f_ffree = abp->f_favail = 900000;
319
320     abp->f_fsid = AFS_VFSMAGIC; /* magic */
321     strcpy(abp->f_basetype, AFS_MOUNT_AFS);
322     abp->f_flag = 0;
323     abp->f_namemax = 256;
324     return 0;
325 }
326
327
328
329 /*
330  * sync's responsibilities include pushing back DELWRI pages
331  * Things to watch out for:
332  *      1) don't want to hold off new vnodes in the file system
333  *              while pushing back pages
334  *      2) since we can deal with un-referenced vndoes need to watch
335  *              races with folks who recycle vnodes
336  * Flags:
337  *      SYNC_BDFLUSH - do NOT sleep waiting for an inode - also, when
338  *                      when pushing DELWRI - only push old ones.
339  *      SYNC_PDFLUSH - push v_dpages.
340  *      SYNC_ATTR    - sync attributes - note that ordering considerations
341  *                      dictate that we also flush dirty pages
342  *      SYNC_WAIT    - do synchronouse writes - inode & delwri
343  *      SYNC_NOWAIT  - start delayed writes.
344  *      SYNC_DELWRI  - look at inodes w/ delwri pages. Other flags
345  *                      decide how to deal with them.
346  *      SYNC_CLOSE   - flush delwri and invalidate others.
347  *      SYNC_FSDATA  - push fs data (e.g. superblocks)
348  */
349
350 extern afs_int32 vcachegen;
351 #define PREEMPT_MASK    0x7f
352 #ifdef AFS_SGI64_ENV
353 #define PREEMPT()
354 #endif
355
356 int
357 afs_sync(OSI_VFS_DECL(afsp),
358 #ifdef AFS_SGI65_ENV
359          int flags,
360 #else
361          short flags,
362 #endif
363          struct cred *cr)
364 {
365     /* Why enable the vfs sync operation?? */
366     int error, lasterr, preempt;
367     struct vcache *tvc;
368     struct vnode *vp;
369     afs_uint32 lvcachegen;
370     register struct afs_q *tq;
371     struct afs_q *uq;
372     int s;
373     OSI_VFS_CONVERT(afsp);
374
375     error = lasterr = 0;
376     /*
377      * if not interested in vnodes, skip all this
378      */
379 #ifdef AFS_SGI61_ENV
380     if ((flags & (SYNC_CLOSE | SYNC_DELWRI | SYNC_PDFLUSH)) == 0)
381         goto end;
382 #else /* AFS_SGI61_ENV */
383     if ((flags & (SYNC_CLOSE | SYNC_DELWRI | SYNC_ATTR)) == 0)
384         goto end;
385 #endif /* AFS_SGI61_ENV */
386   loop:
387     ObtainReadLock(&afs_xvcache);
388     for (tq = VLRU.prev; tq != &VLRU; tq = uq) {
389         tvc = QTOV(tq);
390         uq = QPrev(tq);
391         vp = (vnode_t *) tvc;
392         /*
393          * Since we push all dirty pages on last close/VOP_INACTIVE
394          * we are only concerned with vnodes with
395          * active reference counts.
396          */
397         s = VN_LOCK(vp);
398         if (vp->v_count == 0) {
399             VN_UNLOCK(vp, s);
400             continue;
401         }
402         if ((flags & SYNC_CLOSE) == 0 && !AFS_VN_DIRTY(vp)) {
403             VN_UNLOCK(vp, s);
404             continue;
405         }
406
407         /*
408          * ignore vnodes which need no flushing
409          */
410         if (flags & SYNC_DELWRI) {
411             if (!AFS_VN_DIRTY(vp)) {
412                 VN_UNLOCK(vp, s);
413                 continue;
414             }
415         }
416 #ifdef AFS_SGI61_ENV
417         else if (flags & SYNC_PDFLUSH) {
418             if (!VN_GET_DPAGES(vp)) {
419                 VN_UNLOCK(vp, s);
420                 continue;
421             }
422         }
423 #endif /* AFS_SGI61_ENV */
424
425         vp->v_count++;
426         VN_UNLOCK(vp, s);
427         lvcachegen = vcachegen;
428         ReleaseReadLock(&afs_xvcache);
429
430         /*
431          * Try to lock rwlock without sleeping.  If we can't, we must
432          * sleep for rwlock.
433          */
434         if (afs_rwlock_nowait(vp, 1) == 0) {
435 #ifdef AFS_SGI61_ENV
436             if (flags & (SYNC_BDFLUSH | SYNC_PDFLUSH))
437 #else /* AFS_SGI61_ENV */
438             if (flags & SYNC_BDFLUSH)
439 #endif /* AFS_SGI61_ENV */
440             {
441                 AFS_RELE(vp);
442                 ObtainReadLock(&afs_xvcache);
443                 if (vcachegen != lvcachegen) {
444                     ReleaseReadLock(&afs_xvcache);
445                     goto loop;
446                 }
447                 continue;
448             }
449             AFS_RWLOCK(vp, VRWLOCK_WRITE);
450         }
451
452         AFS_GUNLOCK();
453         if (flags & SYNC_CLOSE) {
454             PFLUSHINVALVP(vp, (off_t) 0, (off_t) tvc->f.m.Length);
455         }
456 #ifdef AFS_SGI61_ENV
457         else if (flags & SYNC_PDFLUSH) {
458             if (VN_GET_DPAGES(vp)) {
459                 pdflush(vp, B_ASYNC);
460             }
461         }
462 #endif /* AFS_SGI61_ENV */
463
464
465         if ((flags & SYNC_DELWRI) && AFS_VN_DIRTY(vp)) {
466 #ifdef AFS_SGI61_ENV
467             PFLUSHVP(vp, (off_t) tvc->f.m.Length,
468                      (flags & SYNC_WAIT) ? 0 : B_ASYNC, error);
469 #else /* AFS_SGI61_ENV */
470             if (flags & SYNC_WAIT)
471                 /* push all and wait */
472                 PFLUSHVP(vp, (off_t) tvc->f.m.Length, (off_t) 0, error);
473             else if (flags & SYNC_BDFLUSH) {
474                 /* push oldest */
475                 error = pdflush(vp, B_ASYNC);
476             } else {
477                 /* push all but don't wait */
478                 PFLUSHVP(vp, (off_t) tvc->f.m.Length, (off_t) B_ASYNC, error);
479             }
480 #endif /* AFS_SGI61_ENV */
481         }
482
483         /*
484          * Release vp, check error and whether to preempt, and if
485          * we let go of xvcache lock and someone has changed the
486          * VLRU, restart the loop
487          */
488         AFS_GLOCK();
489         AFS_RWUNLOCK(vp, VRWLOCK_WRITE);
490         AFS_RELE(vp);
491         if (error)
492             lasterr = error;
493         if ((++preempt & PREEMPT_MASK) == 0) {
494             AFS_GUNLOCK();
495             PREEMPT();
496             AFS_GLOCK();
497         }
498         ObtainReadLock(&afs_xvcache);
499         if (vcachegen != lvcachegen) {
500             ReleaseReadLock(&afs_xvcache);
501             goto loop;
502         }
503     }
504     ReleaseReadLock(&afs_xvcache);
505   end:
506     return lasterr;
507 }
508
509
510 afs_vget(OSI_VFS_DECL(afsp), vnode_t ** avcp, struct fid * fidp)
511 {
512     struct VenusFid vfid;
513     struct vrequest treq;
514     register struct cell *tcell;
515     register afs_int32 code = 0;
516     afs_int32 ret;
517
518 #if defined(AFS_SGI64_ENV) && defined(CKPT) && !defined(_R5000_CVT_WAR)
519     afs_fid2_t *afid2;
520 #endif
521
522     OSI_VFS_CONVERT(afsp);
523
524     AFS_STATCNT(afs_vget);
525
526     *avcp = NULL;
527
528 #if defined(AFS_SGI64_ENV) && defined(CKPT) && !defined(_R5000_CVT_WAR)
529     afid2 = (afs_fid2_t *) fidp;
530     if (afid2->af_len == sizeof(afs_fid2_t) - sizeof(afid2->af_len)) {
531         /* It's a checkpoint restart fid. */
532         tcell = afs_GetCellByIndex(afid2->af_cell, READ_LOCK);
533         if (!tcell) {
534             code = ENOENT;
535             goto out;
536         }
537         vfid.Cell = tcell->cellNum;
538         afs_PutCell(tcell, READ_LOCK);
539         vfid.Fid.Volume = afid2->af_volid;
540         vfid.Fid.Vnode = afid2->af_vno;
541         vfid.Fid.Unique = afid2->af_uniq;
542
543         if (code = afs_InitReq(&treq, OSI_GET_CURRENT_CRED()))
544             goto out;
545         *avcp =
546             (vnode_t *) afs_GetVCache(&vfid, &treq, NULL, (struct vcache *)0);
547         if (!*avcp) {
548             code = ENOENT;
549         }
550         goto out;
551     }
552 #endif
553
554     if (code = afs_InitReq(&treq, OSI_GET_CURRENT_CRED()))
555         goto out;
556     code = afs_osi_vget((struct vcache **)avcp, fidp, &treq);
557
558   out:
559     afs_Trace3(afs_iclSetp, CM_TRACE_VGET, ICL_TYPE_POINTER, *avcp,
560                ICL_TYPE_INT32, treq.uid, ICL_TYPE_FID, &vfid);
561     code = afs_CheckCode(code, &treq, 42);
562     return code;
563 }
564
565
566 #ifdef MP                       /* locked versions of vfs operations. */
567
568 /* wrappers for vfs calls */
569 #ifdef AFS_SGI64_ENV
570 #define AFS_MP_VFS_ARG(A) bhv_desc_t A
571 #else
572 #define AFS_MP_VFS_ARG(A) struct vfs A
573 #endif
574
575 int
576 mp_afs_mount(struct vfs *a, struct vnode *b, struct mounta *c,
577 #ifdef AFS_SGI65_ENV
578              char *d,
579 #endif
580              struct cred *e)
581 {
582     int rv;
583     AFS_GLOCK();
584     rv = afs_lockedvfsops.vfs_mount(a, b, c, d
585 #ifdef AFS_SGI65_ENV
586                                     , e
587 #endif
588         );
589     AFS_GUNLOCK();
590     return rv;
591 }
592
593 int
594 mp_afs_unmount(AFS_MP_VFS_ARG(*a), int b, struct cred *c)
595 {
596     int rv;
597     AFS_GLOCK();
598     rv = afs_lockedvfsops.vfs_unmount(a, b, c);
599     AFS_GUNLOCK();
600     return rv;
601 }
602
603 int
604 mp_afs_root(AFS_MP_VFS_ARG(*a), struct vnode **b)
605 {
606     int rv;
607     AFS_GLOCK();
608     rv = afs_lockedvfsops.vfs_root(a, b);
609     AFS_GUNLOCK();
610     return rv;
611 }
612
613 int
614 mp_afs_statvfs(AFS_MP_VFS_ARG(*a), struct statvfs *b, struct vnode *c)
615 {
616     int rv;
617     AFS_GLOCK();
618     rv = afs_lockedvfsops.vfs_statvfs(a, b, c);
619     AFS_GUNLOCK();
620     return rv;
621 }
622
623 int
624 mp_afs_sync(AFS_MP_VFS_ARG(*a),
625 #ifdef AFS_SGI65_ENV
626             int b,
627 #else
628             short b,
629 #endif
630             struct cred *c)
631 {
632     int rv;
633     AFS_GLOCK();
634     rv = afs_lockedvfsops.vfs_sync(a, b, c);
635     AFS_GUNLOCK();
636     return rv;
637 }
638
639 int
640 mp_afs_vget(AFS_MP_VFS_ARG(*a), struct vnode **b, struct fid *c)
641 {
642     int rv;
643     AFS_GLOCK();
644     rv = afs_lockedvfsops.vfs_vget(a, b, c);
645     AFS_GUNLOCK();
646     return rv;
647 }
648
649 struct vfsops Afs_vfsops = {
650 #ifdef AFS_SGI64_ENV
651 #ifdef AFS_SGI65_ENV
652     BHV_IDENTITY_INIT_POSITION(VFS_POSITION_BASE),
653 #else
654     VFS_POSITION_BASE,
655 #endif
656 #endif
657     mp_afs_mount,
658 #ifdef AFS_SGI64_ENV
659     fs_nosys,                   /* rootinit */
660     fs_nosys,                   /* mntupdate */
661     fs_dounmount,
662 #endif
663     mp_afs_unmount,
664     mp_afs_root,
665     mp_afs_statvfs,
666     mp_afs_sync,
667     mp_afs_vget,
668     fs_nosys,                   /* mountroot */
669 #ifdef AFS_SGI65_ENV
670     fs_nosys,                   /* realvfsops */
671     fs_import,                  /* import */
672     fs_nosys,                   /* quotactl */
673 #else
674     fs_nosys,                   /* swapvp */
675 #endif
676 };
677
678 #endif /* MP */