2 * Copyright 2000, International Business Machines Corporation and others.
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
11 * osi_vfsops.c for IRIX
13 #include <afsconfig.h>
14 #include "afs/param.h"
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"
23 struct vfs *afs_globalVFS = 0;
24 struct vcache *afs_globalVp = 0;
26 #ifdef AFS_SGI_VNODE_GLUE
27 #include <sys/invent.h>
29 mutex_t afs_init_kern_lock;
33 #define SYS_setgroups SGI_SETGROUPS
35 int (*nfs_rfsdisptab_v2) () = NULL;
40 #include "sys/mload.h"
41 char *Afs_mversion = M_VERSION;
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 *);
49 * AFS fs initialization - we also plug system calls here
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 (*afsdptoipp) (struct efs_dinode *, struct inode *);
59 extern void (*afsiptodpp) (struct inode *, struct efs_dinode *);
60 extern void afsidestroy(struct inode *);
61 extern void afsdptoip(struct efs_dinode *, struct inode *);
62 extern void afsiptodp(struct inode *, struct efs_dinode *);
63 extern int (*idbg_prafsnodep) (vnode_t *);
64 extern int (*idbg_afsvfslistp) (void);
65 extern int idbg_prafsnode(vnode_t *);
66 extern int idbg_afsvfslist(void);
70 Afs_init(struct vfssw *vswp, int fstype)
72 extern int Afs_syscall(), Afs_xsetgroups(), afs_pioctl(), afs_setpag();
73 extern int icreate(), iopen(), iinc(), idec();
74 #ifdef AFS_SGI_XFS_IOPS_ENV
77 extern int iread(), iwrite();
84 #ifdef AFS_SGI_VNODE_GLUE
85 /* Synchronize doing NUMA test. */
86 mutex_init(&afs_init_kern_lock, MUTEX_DEFAULT, "init_kern_lock");
89 * set up pointers from main kernel into us
91 afs_vnodeopsp = &Afs_vnodeops;
92 afs_vfsopsp = &Afs_vfsops;
93 afsidestroyp = afsidestroy;
94 afsiptodpp = afsiptodp;
95 afsdptoipp = afsdptoip;
96 idbg_prafsnodep = idbg_prafsnode;
97 idbg_afsvfslistp = idbg_afsvfslist;
98 NewSystemCall(AFS_SYSCALL, Afs_syscall, 6);
99 NewSystemCall(AFS_PIOCTL, afs_pioctl, 4);
100 NewSystemCall(AFS_SETPAG, afs_setpag, 0);
101 NewSystemCall(AFS_IOPEN, iopen, 3);
102 NewSystemCall(AFS_ICREATE, icreate, 6);
103 NewSystemCall(AFS_IINC, iinc, 3);
104 NewSystemCall(AFS_IDEC, idec, 3);
105 #ifdef AFS_SGI_XFS_IOPS_ENV
106 NewSystemCall(AFS_IOPEN64, iopen64, 4);
108 NewSystemCall(AFS_IREAD, iread, 6);
109 NewSystemCall(AFS_IWRITE, iwrite, 6);
112 /* last replace these */
113 setgroupsp = Afs_xsetgroups;
115 idbg_addfunc("afsuser", idbg_afsuser);
120 extern int afs_mount(), afs_unmount(), afs_root(), afs_statfs();
122 extern int afs_sync(OSI_VFS_DECL(afsp), int flags, struct cred *cr);
124 extern int afs_sync(OSI_VFS_DECL(afsp), short flags, struct cred *cr);
126 extern int afs_vget(OSI_VFS_DECL(afsp), vnode_t ** vpp, struct fid *afidp);
128 struct vfsops afs_lockedvfsops =
130 struct vfsops Afs_vfsops =
135 BHV_IDENTITY_INIT_POSITION(VFS_POSITION_BASE),
142 fs_nosys, /* rootinit */
143 fs_nosys, /* mntupdate */
151 fs_nosys, /* mountroot */
153 fs_nosys, /* realvfsops */
154 fs_import, /* import */
155 fs_nosys, /* quotactl */
157 fs_nosys, /* swapvp */
160 extern struct afs_q VLRU; /*vcache LRU */
163 static bhv_desc_t afs_vfs_bhv;
165 afs_mount(struct vfs *afsp, vnode_t * mvp, struct mounta *uap,
171 AFS_STATCNT(afs_mount);
176 if (mvp->v_type != VDIR)
179 if (afs_globalVFS) { /* Don't allow remounts. */
183 afs_globalVFS = afsp;
184 afsp->vfs_bsize = 8192;
185 afsp->vfs_fsid.val[0] = AFS_VFSMAGIC; /* magic */
186 afsp->vfs_fsid.val[1] = afs_fstype;
188 vfs_insertbhv(afsp, &afs_vfs_bhv, &Afs_vfsops, &afs_vfs_bhv);
190 afsp->vfs_data = NULL;
192 afsp->vfs_fstype = afs_fstype;
193 afsp->vfs_dev = 0xbabebabe; /* XXX this should be unique */
195 #ifndef AFS_NONFSTRANS
196 if (nfs_rfsdisptab_v2)
197 afs_xlatorinit_v2(nfs_rfsdisptab_v2);
203 afs_unmount(OSI_VFS_ARG(afsp), flags, cr)
209 vnode_t *vp, *rootvp = NULL;
210 register struct afs_q *tq;
213 OSI_VFS_CONVERT(afsp);
215 AFS_STATCNT(afs_unmount);
221 * flush all pages from inactive vnodes - return
222 * EBUSY if any still in use
224 ObtainWriteLock(&afs_xvcache, 172);
225 for (tq = VLRU.prev; tq != &VLRU; tq = uq) {
228 vp = (vnode_t *) tvc;
229 if (error = afs_FlushVCache(tvc, &fv_slept))
230 if (vp->v_flag & VROOT) {
234 ReleaseWriteLock(&afs_xvcache);
240 * rootvp gets lots of ref counts
243 tvc = VTOAFS(rootvp);
244 if (tvc->opens || CheckLock(&tvc->lock) || LockWaiters(&tvc->lock)) {
245 ReleaseWriteLock(&afs_xvcache);
248 ReleaseWriteLock(&afs_xvcache);
251 ObtainWriteLock(&afs_xvcache, 173);
252 afs_FlushVCache(tvc, &fv_slept);
254 ReleaseWriteLock(&afs_xvcache);
258 VFS_REMOVEBHV(afsp, &afs_vfs_bhv);
265 afs_root(OSI_VFS_ARG(afsp), avpp)
269 register afs_int32 code = 0;
270 struct vrequest treq;
271 register struct vcache *tvp = 0;
272 OSI_VFS_CONVERT(afsp);
274 AFS_STATCNT(afs_root);
275 if (afs_globalVp && (afs_globalVp->f.states & CStatd)) {
279 afs_PutVCache(afs_globalVp);
283 if (!(code = afs_InitReq(&treq, OSI_GET_CURRENT_CRED()))
284 && !(code = afs_CheckInit())) {
285 tvp = afs_GetVCache(&afs_rootFid, &treq, NULL, NULL);
286 /* we really want this to stay around */
295 VN_HOLD(AFSTOV(tvp));
296 s = VN_LOCK(AFSTOV(tvp));
297 AFSTOV(tvp)->v_flag |= VROOT;
298 VN_UNLOCK(AFSTOV(tvp), s);
300 afs_globalVFS = afsp;
304 afs_Trace2(afs_iclSetp, CM_TRACE_VFSROOT, ICL_TYPE_POINTER, *avpp,
305 ICL_TYPE_INT32, code);
309 afs_statfs(OSI_VFS_ARG(afsp), abp, avp)
312 struct vnode *avp; /* unused */
314 OSI_VFS_CONVERT(afsp);
316 AFS_STATCNT(afs_statfs);
317 abp->f_bsize = afsp->vfs_bsize;
318 abp->f_frsize = afsp->vfs_bsize;
319 /* Fake a high number below to satisfy programs that use the statfs
320 * call to make sure that there's enough space in the device partition
321 * before storing something there.
323 abp->f_blocks = abp->f_bfree = abp->f_bavail = abp->f_files =
324 abp->f_ffree = abp->f_favail = 900000;
326 abp->f_fsid = AFS_VFSMAGIC; /* magic */
327 strcpy(abp->f_basetype, AFS_MOUNT_AFS);
329 abp->f_namemax = 256;
336 * sync's responsibilities include pushing back DELWRI pages
337 * Things to watch out for:
338 * 1) don't want to hold off new vnodes in the file system
339 * while pushing back pages
340 * 2) since we can deal with un-referenced vndoes need to watch
341 * races with folks who recycle vnodes
343 * SYNC_BDFLUSH - do NOT sleep waiting for an inode - also, when
344 * when pushing DELWRI - only push old ones.
345 * SYNC_PDFLUSH - push v_dpages.
346 * SYNC_ATTR - sync attributes - note that ordering considerations
347 * dictate that we also flush dirty pages
348 * SYNC_WAIT - do synchronouse writes - inode & delwri
349 * SYNC_NOWAIT - start delayed writes.
350 * SYNC_DELWRI - look at inodes w/ delwri pages. Other flags
351 * decide how to deal with them.
352 * SYNC_CLOSE - flush delwri and invalidate others.
353 * SYNC_FSDATA - push fs data (e.g. superblocks)
356 extern afs_int32 vcachegen;
357 #define PREEMPT_MASK 0x7f
363 afs_sync(OSI_VFS_DECL(afsp),
371 /* Why enable the vfs sync operation?? */
372 int error, lasterr, preempt;
375 afs_uint32 lvcachegen;
376 register struct afs_q *tq;
379 OSI_VFS_CONVERT(afsp);
383 * if not interested in vnodes, skip all this
386 if ((flags & (SYNC_CLOSE | SYNC_DELWRI | SYNC_PDFLUSH)) == 0)
388 #else /* AFS_SGI61_ENV */
389 if ((flags & (SYNC_CLOSE | SYNC_DELWRI | SYNC_ATTR)) == 0)
391 #endif /* AFS_SGI61_ENV */
393 ObtainReadLock(&afs_xvcache);
394 for (tq = VLRU.prev; tq != &VLRU; tq = uq) {
397 vp = (vnode_t *) tvc;
399 * Since we push all dirty pages on last close/VOP_INACTIVE
400 * we are only concerned with vnodes with
401 * active reference counts.
404 if (vp->v_count == 0) {
408 if ((flags & SYNC_CLOSE) == 0 && !AFS_VN_DIRTY(vp)) {
414 * ignore vnodes which need no flushing
416 if (flags & SYNC_DELWRI) {
417 if (!AFS_VN_DIRTY(vp)) {
423 else if (flags & SYNC_PDFLUSH) {
424 if (!VN_GET_DPAGES(vp)) {
429 #endif /* AFS_SGI61_ENV */
433 lvcachegen = vcachegen;
434 ReleaseReadLock(&afs_xvcache);
437 * Try to lock rwlock without sleeping. If we can't, we must
440 if (afs_rwlock_nowait(vp, 1) == 0) {
442 if (flags & (SYNC_BDFLUSH | SYNC_PDFLUSH))
443 #else /* AFS_SGI61_ENV */
444 if (flags & SYNC_BDFLUSH)
445 #endif /* AFS_SGI61_ENV */
448 ObtainReadLock(&afs_xvcache);
449 if (vcachegen != lvcachegen) {
450 ReleaseReadLock(&afs_xvcache);
455 AFS_RWLOCK(vp, VRWLOCK_WRITE);
459 if (flags & SYNC_CLOSE) {
460 PFLUSHINVALVP(vp, (off_t) 0, (off_t) tvc->f.m.Length);
463 else if (flags & SYNC_PDFLUSH) {
464 if (VN_GET_DPAGES(vp)) {
465 pdflush(vp, B_ASYNC);
468 #endif /* AFS_SGI61_ENV */
471 if ((flags & SYNC_DELWRI) && AFS_VN_DIRTY(vp)) {
473 PFLUSHVP(vp, (off_t) tvc->f.m.Length,
474 (flags & SYNC_WAIT) ? 0 : B_ASYNC, error);
475 #else /* AFS_SGI61_ENV */
476 if (flags & SYNC_WAIT)
477 /* push all and wait */
478 PFLUSHVP(vp, (off_t) tvc->f.m.Length, (off_t) 0, error);
479 else if (flags & SYNC_BDFLUSH) {
481 error = pdflush(vp, B_ASYNC);
483 /* push all but don't wait */
484 PFLUSHVP(vp, (off_t) tvc->f.m.Length, (off_t) B_ASYNC, error);
486 #endif /* AFS_SGI61_ENV */
490 * Release vp, check error and whether to preempt, and if
491 * we let go of xvcache lock and someone has changed the
492 * VLRU, restart the loop
495 AFS_RWUNLOCK(vp, VRWLOCK_WRITE);
499 if ((++preempt & PREEMPT_MASK) == 0) {
504 ObtainReadLock(&afs_xvcache);
505 if (vcachegen != lvcachegen) {
506 ReleaseReadLock(&afs_xvcache);
510 ReleaseReadLock(&afs_xvcache);
516 afs_vget(OSI_VFS_DECL(afsp), vnode_t ** avcp, struct fid * fidp)
518 struct VenusFid vfid;
519 struct vrequest treq;
520 register struct cell *tcell;
521 register afs_int32 code = 0;
524 #if defined(AFS_SGI64_ENV) && defined(CKPT) && !defined(_R5000_CVT_WAR)
528 OSI_VFS_CONVERT(afsp);
530 AFS_STATCNT(afs_vget);
534 #if defined(AFS_SGI64_ENV) && defined(CKPT) && !defined(_R5000_CVT_WAR)
535 afid2 = (afs_fid2_t *) fidp;
536 if (afid2->af_len == sizeof(afs_fid2_t) - sizeof(afid2->af_len)) {
537 /* It's a checkpoint restart fid. */
538 tcell = afs_GetCellByIndex(afid2->af_cell, READ_LOCK);
543 vfid.Cell = tcell->cellNum;
544 afs_PutCell(tcell, READ_LOCK);
545 vfid.Fid.Volume = afid2->af_volid;
546 vfid.Fid.Vnode = afid2->af_vno;
547 vfid.Fid.Unique = afid2->af_uniq;
549 if (code = afs_InitReq(&treq, OSI_GET_CURRENT_CRED()))
552 (vnode_t *) afs_GetVCache(&vfid, &treq, NULL, (struct vcache *)0);
560 if (code = afs_InitReq(&treq, OSI_GET_CURRENT_CRED()))
562 code = afs_osi_vget((struct vcache **)avcp, fidp, &treq);
565 afs_Trace3(afs_iclSetp, CM_TRACE_VGET, ICL_TYPE_POINTER, *avcp,
566 ICL_TYPE_INT32, treq.uid, ICL_TYPE_FID, &vfid);
567 code = afs_CheckCode(code, &treq, 42);
572 #ifdef MP /* locked versions of vfs operations. */
574 /* wrappers for vfs calls */
576 #define AFS_MP_VFS_ARG(A) bhv_desc_t A
578 #define AFS_MP_VFS_ARG(A) struct vfs A
582 mp_afs_mount(struct vfs *a, struct vnode *b, struct mounta *c,
590 rv = afs_lockedvfsops.vfs_mount(a, b, c, d
600 mp_afs_unmount(AFS_MP_VFS_ARG(*a), int b, struct cred *c)
604 rv = afs_lockedvfsops.vfs_unmount(a, b, c);
610 mp_afs_root(AFS_MP_VFS_ARG(*a), struct vnode **b)
614 rv = afs_lockedvfsops.vfs_root(a, b);
620 mp_afs_statvfs(AFS_MP_VFS_ARG(*a), struct statvfs *b, struct vnode *c)
624 rv = afs_lockedvfsops.vfs_statvfs(a, b, c);
630 mp_afs_sync(AFS_MP_VFS_ARG(*a),
640 rv = afs_lockedvfsops.vfs_sync(a, b, c);
646 mp_afs_vget(AFS_MP_VFS_ARG(*a), struct vnode **b, struct fid *c)
650 rv = afs_lockedvfsops.vfs_vget(a, b, c);
655 struct vfsops Afs_vfsops = {
658 BHV_IDENTITY_INIT_POSITION(VFS_POSITION_BASE),
665 fs_nosys, /* rootinit */
666 fs_nosys, /* mntupdate */
674 fs_nosys, /* mountroot */
676 fs_nosys, /* realvfsops */
677 fs_import, /* import */
678 fs_nosys, /* quotactl */
680 fs_nosys, /* swapvp */