1 /* Copyright (C) 1995, 1998 Transarc Corporation - All rights reserved. */
3 * (C) COPYRIGHT IBM CORPORATION 1987, 1988
4 * LICENSED MATERIALS - PROPERTY OF IBM
7 * osi_vfsops.c for IRIX
9 #include "../afs/param.h" /* Should be always first */
10 #include "../afs/sysincludes.h" /* Standard vendor system headers */
11 #include "../afs/afsincludes.h" /* Afs-based standard headers */
12 #include "../afs/afs_stats.h" /* statistics stuff */
13 #include "sys/syssgi.h"
16 struct vfs *afs_globalVFS = 0;
17 struct vcache *afs_globalVp = 0;
19 #ifdef AFS_SGI_VNODE_GLUE
20 #include <sys/invent.h>
22 mutex_t afs_init_kern_lock;
26 #define SYS_setgroups SGI_SETGROUPS
28 int (*nfs_rfsdisptab_v2)() = NULL;
33 #include "sys/mload.h"
34 char *Afs_mversion = M_VERSION;
36 extern int (*setgroupsp)(int, gid_t *);
37 extern struct afs_lock afs_xvcache;
38 extern int idbg_afsuser();
39 extern void afs_mpservice(void *);
42 * AFS fs initialization - we also plug system calls here
44 #define NewSystemCall(n,f,a) \
45 syscallsw[ABI_IRIX5].sc_sysent[(n)-1000].sy_narg = a; \
46 syscallsw[ABI_IRIX5].sc_sysent[(n)-1000].sy_call = f; \
47 syscallsw[ABI_IRIX5].sc_sysent[(n)-1000].sy_flags = 0;
48 extern struct vfsops Afs_vfsops, *afs_vfsopsp;
49 extern struct vnodeops Afs_vnodeops, *afs_vnodeopsp;
50 extern void (*afsidestroyp)(struct inode *);
51 extern void (*afsdptoipp)(struct efs_dinode *, struct inode *);
52 extern void (*afsiptodpp)(struct inode *, struct efs_dinode *);
53 extern void afsidestroy(struct inode *);
54 extern void afsdptoip(struct efs_dinode *, struct inode *);
55 extern void afsiptodp(struct inode *, struct efs_dinode *);
56 extern int (*idbg_prafsnodep)(vnode_t *);
57 extern int (*idbg_afsvfslistp)(void);
58 extern int idbg_prafsnode(vnode_t *);
59 extern int idbg_afsvfslist(void);
63 Afs_init(struct vfssw *vswp, int fstype)
65 extern int Afs_syscall(), Afs_xsetgroups(), afs_pioctl(), afs_setpag();
66 extern int icreate(), iopen(), iinc(), idec();
67 #ifdef AFS_SGI_XFS_IOPS_ENV
70 extern int iread(), iwrite();
77 #ifdef AFS_SGI_VNODE_GLUE
78 /* Synchronize doing NUMA test. */
79 mutex_init(&afs_init_kern_lock, MUTEX_DEFAULT, "init_kern_lock");
82 * set up pointers from main kernel into us
84 afs_vnodeopsp = &Afs_vnodeops;
85 afs_vfsopsp = &Afs_vfsops;
86 afsidestroyp = afsidestroy;
87 afsiptodpp = afsiptodp;
88 afsdptoipp = afsdptoip;
89 idbg_prafsnodep = idbg_prafsnode;
90 idbg_afsvfslistp = idbg_afsvfslist;
91 NewSystemCall (AFS_SYSCALL, Afs_syscall, 6);
92 NewSystemCall (AFS_PIOCTL, afs_pioctl, 4);
93 NewSystemCall (AFS_SETPAG, afs_setpag, 0);
94 NewSystemCall (AFS_IOPEN, iopen, 3);
95 NewSystemCall (AFS_ICREATE, icreate, 6);
96 NewSystemCall (AFS_IINC, iinc, 3);
97 NewSystemCall (AFS_IDEC, idec, 3);
98 #ifdef AFS_SGI_XFS_IOPS_ENV
99 NewSystemCall (AFS_IOPEN64, iopen64, 4);
101 NewSystemCall (AFS_IREAD, iread, 6);
102 NewSystemCall (AFS_IWRITE, iwrite, 6);
105 /* last replace these */
106 setgroupsp = Afs_xsetgroups;
108 idbg_addfunc("afsuser", idbg_afsuser);
113 extern int afs_mount(), afs_unmount(), afs_root(), afs_statfs();
115 extern int afs_sync(OSI_VFS_DECL(afsp), int flags, struct cred *cr);
117 extern int afs_sync(OSI_VFS_DECL(afsp), short flags, struct cred *cr);
119 extern int afs_vget(OSI_VFS_DECL(afsp), vnode_t **vpp, struct fid *afidp);
121 struct vfsops afs_lockedvfsops =
123 struct vfsops Afs_vfsops =
128 BHV_IDENTITY_INIT_POSITION(VFS_POSITION_BASE),
135 fs_nosys, /* rootinit */
136 fs_nosys, /* mntupdate */
144 fs_nosys, /* mountroot */
146 fs_nosys, /* realvfsops */
147 fs_import, /* import */
148 fs_nosys, /* quotactl */
150 fs_nosys, /* swapvp */
153 extern struct afs_q VLRU; /*vcache LRU*/
156 static bhv_desc_t afs_vfs_bhv;
158 afs_mount(struct vfs *afsp, vnode_t *mvp, struct mounta *uap,
164 AFS_STATCNT(afs_mount);
169 if (mvp->v_type != VDIR)
172 if (afs_globalVFS) { /* Don't allow remounts. */
176 afs_globalVFS = afsp;
177 afsp->vfs_bsize = 8192;
178 afsp->vfs_fsid.val[0] = AFS_VFSMAGIC; /* magic */
179 afsp->vfs_fsid.val[1] = afs_fstype;
181 vfs_insertbhv(afsp, &afs_vfs_bhv, &Afs_vfsops, &afs_vfs_bhv);
183 afsp->vfs_data = NULL;
185 afsp->vfs_fstype = afs_fstype;
186 afsp->vfs_dev = 0xbabebabe; /* XXX this should be unique */
188 #ifndef AFS_NONFSTRANS
189 if (nfs_rfsdisptab_v2)
190 afs_xlatorinit_v2(nfs_rfsdisptab_v2);
196 afs_unmount(OSI_VFS_ARG(afsp), flags, cr)
201 extern int afs_afs_cold_shutdown;
203 vnode_t *vp, *rootvp = NULL;
204 register struct afs_q *tq;
207 OSI_VFS_CONVERT(afsp)
209 AFS_STATCNT(afs_unmount);
215 * flush all pages from inactive vnodes - return
216 * EBUSY if any still in use
218 ObtainWriteLock(&afs_xvcache,172);
219 for (tq = VLRU.prev; tq != &VLRU; tq = uq) {
223 if (error = afs_FlushVCache(tvc, &fv_slept))
224 if (vp->v_flag & VROOT) {
228 ReleaseWriteLock(&afs_xvcache);
234 * rootvp gets lots of ref counts
237 tvc = (struct vcache *)rootvp;
238 if (tvc->opens || CheckLock(&tvc->lock) || LockWaiters(&tvc->lock)) {
239 ReleaseWriteLock(&afs_xvcache);
242 ReleaseWriteLock(&afs_xvcache);
245 ObtainWriteLock(&afs_xvcache,173);
246 afs_FlushVCache(tvc, &fv_slept);
248 ReleaseWriteLock(&afs_xvcache);
252 VFS_REMOVEBHV(afsp, &afs_vfs_bhv);
259 afs_root (OSI_VFS_ARG(afsp), avpp)
263 register afs_int32 code = 0;
264 struct vrequest treq;
265 register struct vcache *tvp=0;
266 OSI_VFS_CONVERT(afsp)
268 AFS_STATCNT(afs_root);
269 if (afs_globalVp && (afs_globalVp->states & CStatd)) {
272 if (!(code = afs_InitReq(&treq, OSI_GET_CURRENT_CRED())) &&
273 !(code = afs_CheckInit())) {
274 tvp = afs_GetVCache(&afs_rootFid, &treq, (afs_int32 *)0,
275 (struct vcache*)0, WRITE_LOCK);
276 /* we really want this to stay around */
285 VN_HOLD((struct vnode *)tvp);
286 s = VN_LOCK((struct vnode *)tvp);
287 tvp->v.v_flag |= VROOT;
288 VN_UNLOCK((struct vnode *)tvp, s);
290 afs_globalVFS = afsp;
291 *avpp = (struct vnode *) tvp;
294 afs_Trace2(afs_iclSetp, CM_TRACE_VFSROOT, ICL_TYPE_POINTER, *avpp,
295 ICL_TYPE_INT32, code);
299 afs_statfs(OSI_VFS_ARG(afsp), abp, avp)
302 struct vnode *avp; /* unused */
304 OSI_VFS_CONVERT(afsp)
306 AFS_STATCNT(afs_statfs);
307 abp->f_bsize = afsp->vfs_bsize;
308 abp->f_frsize = afsp->vfs_bsize;
309 /* Fake a high number below to satisfy programs that use the statfs
310 * call to make sure that there's enough space in the device partition
311 * before storing something there.
313 abp->f_blocks = abp->f_bfree = abp->f_bavail = abp->f_files =
314 abp->f_ffree = abp->f_favail = 900000;
316 abp->f_fsid = AFS_VFSMAGIC; /* magic */
317 strcpy(abp->f_basetype, AFS_MOUNT_AFS);
319 abp->f_namemax = 256;
326 * sync's responsibilities include pushing back DELWRI pages
327 * Things to watch out for:
328 * 1) don't want to hold off new vnodes in the file system
329 * while pushing back pages
330 * 2) since we can deal with un-referenced vndoes need to watch
331 * races with folks who recycle vnodes
333 * SYNC_BDFLUSH - do NOT sleep waiting for an inode - also, when
334 * when pushing DELWRI - only push old ones.
335 * SYNC_PDFLUSH - push v_dpages.
336 * SYNC_ATTR - sync attributes - note that ordering considerations
337 * dictate that we also flush dirty pages
338 * SYNC_WAIT - do synchronouse writes - inode & delwri
339 * SYNC_NOWAIT - start delayed writes.
340 * SYNC_DELWRI - look at inodes w/ delwri pages. Other flags
341 * decide how to deal with them.
342 * SYNC_CLOSE - flush delwri and invalidate others.
343 * SYNC_FSDATA - push fs data (e.g. superblocks)
346 extern afs_int32 vcachegen;
347 #define PREEMPT_MASK 0x7f
353 afs_sync(OSI_VFS_DECL(afsp),
361 /* Why enable the vfs sync operation?? */
362 int error, lasterr, preempt;
365 afs_uint32 lvcachegen;
366 register struct afs_q *tq;
369 OSI_VFS_CONVERT(afsp)
373 * if not interested in vnodes, skip all this
376 if ((flags & (SYNC_CLOSE|SYNC_DELWRI|SYNC_PDFLUSH)) == 0)
378 #else /* AFS_SGI61_ENV */
379 if ((flags & (SYNC_CLOSE|SYNC_DELWRI|SYNC_ATTR)) == 0)
381 #endif /* AFS_SGI61_ENV */
383 ObtainReadLock(&afs_xvcache);
384 for (tq = VLRU.prev; tq != &VLRU; tq = uq) {
389 * Since we push all dirty pages on last close/VOP_INACTIVE
390 * we are only concerned with vnodes with
391 * active reference counts.
394 if (vp->v_count == 0) {
398 if ((flags & SYNC_CLOSE) == 0 && !AFS_VN_DIRTY(vp)) {
404 * ignore vnodes which need no flushing
406 if (flags & SYNC_DELWRI) {
407 if (!AFS_VN_DIRTY(vp)) {
413 else if (flags & SYNC_PDFLUSH) {
414 if (!VN_GET_DPAGES(vp)) {
419 #endif /* AFS_SGI61_ENV */
423 lvcachegen = vcachegen;
424 ReleaseReadLock(&afs_xvcache);
427 * Try to lock rwlock without sleeping. If we can't, we must
430 if (afs_rwlock_nowait(vp, 1) == 0) {
432 if (flags & (SYNC_BDFLUSH | SYNC_PDFLUSH))
433 #else /* AFS_SGI61_ENV */
434 if (flags & SYNC_BDFLUSH)
435 #endif /* AFS_SGI61_ENV */
438 ObtainReadLock(&afs_xvcache);
439 if (vcachegen != lvcachegen) {
440 ReleaseReadLock(&afs_xvcache);
445 AFS_RWLOCK(vp, VRWLOCK_WRITE);
449 if (flags & SYNC_CLOSE) {
450 PFLUSHINVALVP(vp, (off_t)0, (off_t)tvc->m.Length);
453 else if (flags & SYNC_PDFLUSH) {
454 if (VN_GET_DPAGES(vp)) {
455 pdflush(vp, B_ASYNC);
458 #endif /* AFS_SGI61_ENV */
461 if ((flags & SYNC_DELWRI) && AFS_VN_DIRTY(vp)) {
463 PFLUSHVP(vp, (off_t)tvc->m.Length,
464 (flags & SYNC_WAIT) ? 0 : B_ASYNC, error);
465 #else /* AFS_SGI61_ENV */
466 if (flags & SYNC_WAIT)
467 /* push all and wait */
468 PFLUSHVP(vp, (off_t)tvc->m.Length,
470 else if (flags & SYNC_BDFLUSH) {
472 error = pdflush(vp, B_ASYNC);
475 /* push all but don't wait */
476 PFLUSHVP(vp, (off_t)tvc->m.Length,
477 (off_t)B_ASYNC, error);
479 #endif /* AFS_SGI61_ENV */
483 * Release vp, check error and whether to preempt, and if
484 * we let go of xvcache lock and someone has changed the
485 * VLRU, restart the loop
488 AFS_RWUNLOCK(vp, VRWLOCK_WRITE);
492 if ((++preempt & PREEMPT_MASK) == 0) {
497 ObtainReadLock(&afs_xvcache);
498 if (vcachegen != lvcachegen) {
499 ReleaseReadLock(&afs_xvcache);
503 ReleaseReadLock(&afs_xvcache);
509 afs_vget(OSI_VFS_DECL(afsp), vnode_t **avcp, struct fid *fidp)
511 struct VenusFid vfid;
512 struct vrequest treq;
513 extern struct cell *afs_GetCellByIndex();
514 register struct cell *tcell;
515 register afs_int32 code = 0;
518 #if defined(AFS_SGI64_ENV) && defined(CKPT)
522 OSI_VFS_CONVERT(afsp)
524 AFS_STATCNT(afs_vget);
528 #if defined(AFS_SGI64_ENV) && defined(CKPT)
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);
537 vfid.Cell = tcell->cell;
538 afs_PutCell(tcell, WRITE_LOCK);
539 vfid.Fid.Volume = afid2->af_volid;
540 vfid.Fid.Vnode = afid2->af_vno;
541 vfid.Fid.Unique = afid2->af_uniq;
543 if (code = afs_InitReq(&treq, OSI_GET_CURRENT_CRED()))
545 *avcp = (vnode_t*) afs_GetVCache(&vfid, &treq, (afs_int32 *)0,
546 (struct vcache*)0, 0);
554 if (code = afs_InitReq(&treq, OSI_GET_CURRENT_CRED())) goto out;
555 code = afs_osi_vget((struct vcache**)avcp, fidp, &treq);
558 afs_Trace3(afs_iclSetp, CM_TRACE_VGET, ICL_TYPE_POINTER, *avcp,
559 ICL_TYPE_INT32, treq.uid, ICL_TYPE_FID, &vfid);
560 code = afs_CheckCode(code, &treq, 42);
565 #ifdef MP /* locked versions of vfs operations. */
567 /* wrappers for vfs calls */
569 #define AFS_MP_VFS_ARG(A) bhv_desc_t A
571 #define AFS_MP_VFS_ARG(A) struct vfs A
574 int mp_afs_mount(struct vfs *a, struct vnode *b, struct mounta *c,
582 rv = afs_lockedvfsops.vfs_mount(a, b, c, d
591 int mp_afs_unmount(AFS_MP_VFS_ARG(*a), int b, struct cred *c)
595 rv = afs_lockedvfsops.vfs_unmount(a, b, c);
600 int mp_afs_root(AFS_MP_VFS_ARG(*a), struct vnode **b)
604 rv = afs_lockedvfsops.vfs_root(a, b);
609 int mp_afs_statvfs(AFS_MP_VFS_ARG(*a), struct statvfs *b, struct vnode *c)
613 rv = afs_lockedvfsops.vfs_statvfs(a, b, c);
617 int mp_afs_sync(AFS_MP_VFS_ARG(*a),
627 rv = afs_lockedvfsops.vfs_sync(a, b, c);
631 int mp_afs_vget(AFS_MP_VFS_ARG(*a), struct vnode **b, struct fid *c)
635 rv = afs_lockedvfsops.vfs_vget(a, b, c);
640 struct vfsops Afs_vfsops = {
643 BHV_IDENTITY_INIT_POSITION(VFS_POSITION_BASE),
650 fs_nosys, /* rootinit */
651 fs_nosys, /* mntupdate */
659 fs_nosys, /* mountroot */
661 fs_nosys, /* realvfsops */
662 fs_import, /* import */
663 fs_nosys, /* quotactl */
665 fs_nosys, /* swapvp */