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"
18 #include "../afs/sysincludes.h" /* Standard vendor system headers */
19 #include "../afs/afsincludes.h" /* Afs-based standard headers */
20 #include "../afs/afs_stats.h" /* statistics stuff */
21 #include "sys/syssgi.h"
24 struct vfs *afs_globalVFS = 0;
25 struct vcache *afs_globalVp = 0;
27 #ifdef AFS_SGI_VNODE_GLUE
28 #include <sys/invent.h>
30 mutex_t afs_init_kern_lock;
34 #define SYS_setgroups SGI_SETGROUPS
36 int (*nfs_rfsdisptab_v2)() = NULL;
41 #include "sys/mload.h"
42 char *Afs_mversion = M_VERSION;
44 extern int (*setgroupsp)(int, gid_t *);
45 extern struct afs_lock afs_xvcache;
46 extern int idbg_afsuser();
47 extern void afs_mpservice(void *);
50 * AFS fs initialization - we also plug system calls here
52 #define NewSystemCall(n,f,a) \
53 syscallsw[ABI_IRIX5].sc_sysent[(n)-1000].sy_narg = a; \
54 syscallsw[ABI_IRIX5].sc_sysent[(n)-1000].sy_call = f; \
55 syscallsw[ABI_IRIX5].sc_sysent[(n)-1000].sy_flags = 0;
56 extern struct vfsops Afs_vfsops, *afs_vfsopsp;
57 extern struct vnodeops Afs_vnodeops, *afs_vnodeopsp;
58 extern void (*afsidestroyp)(struct inode *);
59 extern void (*afsdptoipp)(struct efs_dinode *, struct inode *);
60 extern void (*afsiptodpp)(struct inode *, struct efs_dinode *);
61 extern void afsidestroy(struct inode *);
62 extern void afsdptoip(struct efs_dinode *, struct inode *);
63 extern void afsiptodp(struct inode *, struct efs_dinode *);
64 extern int (*idbg_prafsnodep)(vnode_t *);
65 extern int (*idbg_afsvfslistp)(void);
66 extern int idbg_prafsnode(vnode_t *);
67 extern int idbg_afsvfslist(void);
71 Afs_init(struct vfssw *vswp, int fstype)
73 extern int Afs_syscall(), Afs_xsetgroups(), afs_pioctl(), afs_setpag();
74 extern int icreate(), iopen(), iinc(), idec();
75 #ifdef AFS_SGI_XFS_IOPS_ENV
78 extern int iread(), iwrite();
85 #ifdef AFS_SGI_VNODE_GLUE
86 /* Synchronize doing NUMA test. */
87 mutex_init(&afs_init_kern_lock, MUTEX_DEFAULT, "init_kern_lock");
90 * set up pointers from main kernel into us
92 afs_vnodeopsp = &Afs_vnodeops;
93 afs_vfsopsp = &Afs_vfsops;
94 afsidestroyp = afsidestroy;
95 afsiptodpp = afsiptodp;
96 afsdptoipp = afsdptoip;
97 idbg_prafsnodep = idbg_prafsnode;
98 idbg_afsvfslistp = idbg_afsvfslist;
99 NewSystemCall (AFS_SYSCALL, Afs_syscall, 6);
100 NewSystemCall (AFS_PIOCTL, afs_pioctl, 4);
101 NewSystemCall (AFS_SETPAG, afs_setpag, 0);
102 NewSystemCall (AFS_IOPEN, iopen, 3);
103 NewSystemCall (AFS_ICREATE, icreate, 6);
104 NewSystemCall (AFS_IINC, iinc, 3);
105 NewSystemCall (AFS_IDEC, idec, 3);
106 #ifdef AFS_SGI_XFS_IOPS_ENV
107 NewSystemCall (AFS_IOPEN64, iopen64, 4);
109 NewSystemCall (AFS_IREAD, iread, 6);
110 NewSystemCall (AFS_IWRITE, iwrite, 6);
113 /* last replace these */
114 setgroupsp = Afs_xsetgroups;
116 idbg_addfunc("afsuser", idbg_afsuser);
121 extern int afs_mount(), afs_unmount(), afs_root(), afs_statfs();
123 extern int afs_sync(OSI_VFS_DECL(afsp), int flags, struct cred *cr);
125 extern int afs_sync(OSI_VFS_DECL(afsp), short flags, struct cred *cr);
127 extern int afs_vget(OSI_VFS_DECL(afsp), vnode_t **vpp, struct fid *afidp);
129 struct vfsops afs_lockedvfsops =
131 struct vfsops Afs_vfsops =
136 BHV_IDENTITY_INIT_POSITION(VFS_POSITION_BASE),
143 fs_nosys, /* rootinit */
144 fs_nosys, /* mntupdate */
152 fs_nosys, /* mountroot */
154 fs_nosys, /* realvfsops */
155 fs_import, /* import */
156 fs_nosys, /* quotactl */
158 fs_nosys, /* swapvp */
161 extern struct afs_q VLRU; /*vcache LRU*/
164 static bhv_desc_t afs_vfs_bhv;
166 afs_mount(struct vfs *afsp, vnode_t *mvp, struct mounta *uap,
172 AFS_STATCNT(afs_mount);
177 if (mvp->v_type != VDIR)
180 if (afs_globalVFS) { /* Don't allow remounts. */
184 afs_globalVFS = afsp;
185 afsp->vfs_bsize = 8192;
186 afsp->vfs_fsid.val[0] = AFS_VFSMAGIC; /* magic */
187 afsp->vfs_fsid.val[1] = afs_fstype;
189 vfs_insertbhv(afsp, &afs_vfs_bhv, &Afs_vfsops, &afs_vfs_bhv);
191 afsp->vfs_data = NULL;
193 afsp->vfs_fstype = afs_fstype;
194 afsp->vfs_dev = 0xbabebabe; /* XXX this should be unique */
196 #ifndef AFS_NONFSTRANS
197 if (nfs_rfsdisptab_v2)
198 afs_xlatorinit_v2(nfs_rfsdisptab_v2);
204 afs_unmount(OSI_VFS_ARG(afsp), flags, cr)
209 extern int afs_afs_cold_shutdown;
211 vnode_t *vp, *rootvp = NULL;
212 register struct afs_q *tq;
215 OSI_VFS_CONVERT(afsp)
217 AFS_STATCNT(afs_unmount);
223 * flush all pages from inactive vnodes - return
224 * EBUSY if any still in use
226 ObtainWriteLock(&afs_xvcache,172);
227 for (tq = VLRU.prev; tq != &VLRU; tq = uq) {
231 if (error = afs_FlushVCache(tvc, &fv_slept))
232 if (vp->v_flag & VROOT) {
236 ReleaseWriteLock(&afs_xvcache);
242 * rootvp gets lots of ref counts
245 tvc = VTOAFS(rootvp);
246 if (tvc->opens || CheckLock(&tvc->lock) || LockWaiters(&tvc->lock)) {
247 ReleaseWriteLock(&afs_xvcache);
250 ReleaseWriteLock(&afs_xvcache);
253 ObtainWriteLock(&afs_xvcache,173);
254 afs_FlushVCache(tvc, &fv_slept);
256 ReleaseWriteLock(&afs_xvcache);
260 VFS_REMOVEBHV(afsp, &afs_vfs_bhv);
267 afs_root (OSI_VFS_ARG(afsp), avpp)
271 register afs_int32 code = 0;
272 struct vrequest treq;
273 register struct vcache *tvp=0;
274 OSI_VFS_CONVERT(afsp)
276 AFS_STATCNT(afs_root);
277 if (afs_globalVp && (afs_globalVp->states & CStatd)) {
281 afs_PutVCache(afs_globalVp);
285 if (!(code = afs_InitReq(&treq, OSI_GET_CURRENT_CRED())) &&
286 !(code = afs_CheckInit())) {
287 tvp = afs_GetVCache(&afs_rootFid, &treq, NULL, NULL);
288 /* we really want this to stay around */
297 VN_HOLD(AFSTOV(tvp));
298 s = VN_LOCK(AFSTOV(tvp));
299 AFSTOV(tvp)->v_flag |= VROOT;
300 VN_UNLOCK(AFSTOV(tvp), s);
302 afs_globalVFS = afsp;
306 afs_Trace2(afs_iclSetp, CM_TRACE_VFSROOT, ICL_TYPE_POINTER, *avpp,
307 ICL_TYPE_INT32, code);
311 afs_statfs(OSI_VFS_ARG(afsp), abp, avp)
314 struct vnode *avp; /* unused */
316 OSI_VFS_CONVERT(afsp)
318 AFS_STATCNT(afs_statfs);
319 abp->f_bsize = afsp->vfs_bsize;
320 abp->f_frsize = afsp->vfs_bsize;
321 /* Fake a high number below to satisfy programs that use the statfs
322 * call to make sure that there's enough space in the device partition
323 * before storing something there.
325 abp->f_blocks = abp->f_bfree = abp->f_bavail = abp->f_files =
326 abp->f_ffree = abp->f_favail = 900000;
328 abp->f_fsid = AFS_VFSMAGIC; /* magic */
329 strcpy(abp->f_basetype, AFS_MOUNT_AFS);
331 abp->f_namemax = 256;
338 * sync's responsibilities include pushing back DELWRI pages
339 * Things to watch out for:
340 * 1) don't want to hold off new vnodes in the file system
341 * while pushing back pages
342 * 2) since we can deal with un-referenced vndoes need to watch
343 * races with folks who recycle vnodes
345 * SYNC_BDFLUSH - do NOT sleep waiting for an inode - also, when
346 * when pushing DELWRI - only push old ones.
347 * SYNC_PDFLUSH - push v_dpages.
348 * SYNC_ATTR - sync attributes - note that ordering considerations
349 * dictate that we also flush dirty pages
350 * SYNC_WAIT - do synchronouse writes - inode & delwri
351 * SYNC_NOWAIT - start delayed writes.
352 * SYNC_DELWRI - look at inodes w/ delwri pages. Other flags
353 * decide how to deal with them.
354 * SYNC_CLOSE - flush delwri and invalidate others.
355 * SYNC_FSDATA - push fs data (e.g. superblocks)
358 extern afs_int32 vcachegen;
359 #define PREEMPT_MASK 0x7f
365 afs_sync(OSI_VFS_DECL(afsp),
373 /* Why enable the vfs sync operation?? */
374 int error, lasterr, preempt;
377 afs_uint32 lvcachegen;
378 register struct afs_q *tq;
381 OSI_VFS_CONVERT(afsp)
385 * if not interested in vnodes, skip all this
388 if ((flags & (SYNC_CLOSE|SYNC_DELWRI|SYNC_PDFLUSH)) == 0)
390 #else /* AFS_SGI61_ENV */
391 if ((flags & (SYNC_CLOSE|SYNC_DELWRI|SYNC_ATTR)) == 0)
393 #endif /* AFS_SGI61_ENV */
395 ObtainReadLock(&afs_xvcache);
396 for (tq = VLRU.prev; tq != &VLRU; tq = uq) {
401 * Since we push all dirty pages on last close/VOP_INACTIVE
402 * we are only concerned with vnodes with
403 * active reference counts.
406 if (vp->v_count == 0) {
410 if ((flags & SYNC_CLOSE) == 0 && !AFS_VN_DIRTY(vp)) {
416 * ignore vnodes which need no flushing
418 if (flags & SYNC_DELWRI) {
419 if (!AFS_VN_DIRTY(vp)) {
425 else if (flags & SYNC_PDFLUSH) {
426 if (!VN_GET_DPAGES(vp)) {
431 #endif /* AFS_SGI61_ENV */
435 lvcachegen = vcachegen;
436 ReleaseReadLock(&afs_xvcache);
439 * Try to lock rwlock without sleeping. If we can't, we must
442 if (afs_rwlock_nowait(vp, 1) == 0) {
444 if (flags & (SYNC_BDFLUSH | SYNC_PDFLUSH))
445 #else /* AFS_SGI61_ENV */
446 if (flags & SYNC_BDFLUSH)
447 #endif /* AFS_SGI61_ENV */
450 ObtainReadLock(&afs_xvcache);
451 if (vcachegen != lvcachegen) {
452 ReleaseReadLock(&afs_xvcache);
457 AFS_RWLOCK(vp, VRWLOCK_WRITE);
461 if (flags & SYNC_CLOSE) {
462 PFLUSHINVALVP(vp, (off_t)0, (off_t)tvc->m.Length);
465 else if (flags & SYNC_PDFLUSH) {
466 if (VN_GET_DPAGES(vp)) {
467 pdflush(vp, B_ASYNC);
470 #endif /* AFS_SGI61_ENV */
473 if ((flags & SYNC_DELWRI) && AFS_VN_DIRTY(vp)) {
475 PFLUSHVP(vp, (off_t)tvc->m.Length,
476 (flags & SYNC_WAIT) ? 0 : B_ASYNC, error);
477 #else /* AFS_SGI61_ENV */
478 if (flags & SYNC_WAIT)
479 /* push all and wait */
480 PFLUSHVP(vp, (off_t)tvc->m.Length,
482 else if (flags & SYNC_BDFLUSH) {
484 error = pdflush(vp, B_ASYNC);
487 /* push all but don't wait */
488 PFLUSHVP(vp, (off_t)tvc->m.Length,
489 (off_t)B_ASYNC, error);
491 #endif /* AFS_SGI61_ENV */
495 * Release vp, check error and whether to preempt, and if
496 * we let go of xvcache lock and someone has changed the
497 * VLRU, restart the loop
500 AFS_RWUNLOCK(vp, VRWLOCK_WRITE);
504 if ((++preempt & PREEMPT_MASK) == 0) {
509 ObtainReadLock(&afs_xvcache);
510 if (vcachegen != lvcachegen) {
511 ReleaseReadLock(&afs_xvcache);
515 ReleaseReadLock(&afs_xvcache);
521 afs_vget(OSI_VFS_DECL(afsp), vnode_t **avcp, struct fid *fidp)
523 struct VenusFid vfid;
524 struct vrequest treq;
525 extern struct cell *afs_GetCellByIndex();
526 register struct cell *tcell;
527 register afs_int32 code = 0;
530 #if defined(AFS_SGI64_ENV) && defined(CKPT) && !defined(_R5000_CVT_WAR)
534 OSI_VFS_CONVERT(afsp)
536 AFS_STATCNT(afs_vget);
540 #if defined(AFS_SGI64_ENV) && defined(CKPT) && !defined(_R5000_CVT_WAR)
541 afid2 = (afs_fid2_t*)fidp;
542 if (afid2->af_len == sizeof(afs_fid2_t) - sizeof(afid2->af_len)) {
543 /* It's a checkpoint restart fid. */
544 tcell = afs_GetCellByIndex(afid2->af_cell, READ_LOCK, 0 /* !refresh */);
549 vfid.Cell = tcell->cell;
550 afs_PutCell(tcell, WRITE_LOCK);
551 vfid.Fid.Volume = afid2->af_volid;
552 vfid.Fid.Vnode = afid2->af_vno;
553 vfid.Fid.Unique = afid2->af_uniq;
555 if (code = afs_InitReq(&treq, OSI_GET_CURRENT_CRED()))
557 *avcp = (vnode_t*) afs_GetVCache(&vfid, &treq, NULL, (struct vcache*)0);
565 if (code = afs_InitReq(&treq, OSI_GET_CURRENT_CRED())) goto out;
566 code = afs_osi_vget((struct vcache**)avcp, fidp, &treq);
569 afs_Trace3(afs_iclSetp, CM_TRACE_VGET, ICL_TYPE_POINTER, *avcp,
570 ICL_TYPE_INT32, treq.uid, ICL_TYPE_FID, &vfid);
571 code = afs_CheckCode(code, &treq, 42);
576 #ifdef MP /* locked versions of vfs operations. */
578 /* wrappers for vfs calls */
580 #define AFS_MP_VFS_ARG(A) bhv_desc_t A
582 #define AFS_MP_VFS_ARG(A) struct vfs A
585 int mp_afs_mount(struct vfs *a, struct vnode *b, struct mounta *c,
593 rv = afs_lockedvfsops.vfs_mount(a, b, c, d
602 int mp_afs_unmount(AFS_MP_VFS_ARG(*a), int b, struct cred *c)
606 rv = afs_lockedvfsops.vfs_unmount(a, b, c);
611 int mp_afs_root(AFS_MP_VFS_ARG(*a), struct vnode **b)
615 rv = afs_lockedvfsops.vfs_root(a, b);
620 int mp_afs_statvfs(AFS_MP_VFS_ARG(*a), struct statvfs *b, struct vnode *c)
624 rv = afs_lockedvfsops.vfs_statvfs(a, b, c);
628 int mp_afs_sync(AFS_MP_VFS_ARG(*a),
638 rv = afs_lockedvfsops.vfs_sync(a, b, c);
642 int mp_afs_vget(AFS_MP_VFS_ARG(*a), struct vnode **b, struct fid *c)
646 rv = afs_lockedvfsops.vfs_vget(a, b, c);
651 struct vfsops Afs_vfsops = {
654 BHV_IDENTITY_INIT_POSITION(VFS_POSITION_BASE),
661 fs_nosys, /* rootinit */
662 fs_nosys, /* mntupdate */
670 fs_nosys, /* mountroot */
672 fs_nosys, /* realvfsops */
673 fs_import, /* import */
674 fs_nosys, /* quotactl */
676 fs_nosys, /* swapvp */