📄 vfs.c
字号:
bzero((caddr_t) fwip->fwi_buckets, sizeof(fist_bucket_t *) * FIST_HT_SIZE); mutex_init(&fwip->fwi_ht_lock, "wrapfs HT lock", MUTEX_DEFAULT, NULL); /* fwip->fwi_rootvnode: is setup in the "root vnode" section below *//************************************************************************** * VFS FOR THE FIST_WRAPFS FILESYSTEM: */ vfsp->vfs_bsize = vp->v_vfsp->vfs_bsize; /* was 1024, now inherited */ vfsp->vfs_fstype = wrapfs_fstype; /* Assign a unique device id to the mount */ mutex_enter(&wrapfs_minor_lock); do { wrapfs_minor = (wrapfs_minor + 1) & MAXMIN; wrapfs_dev = makedevice(wrapfs_major, wrapfs_minor); } while (vfs_devsearch(wrapfs_dev)); mutex_exit(&wrapfs_minor_lock); /* set the rest of the fields */ vfsp->vfs_dev = wrapfs_dev; vfsp->vfs_fsid.val[0] = wrapfs_dev; vfsp->vfs_fsid.val[1] = wrapfs_fstype; vfsp->vfs_bcount = 0; /* store private fist_wrapfs info in the pre-made vfs */ vfsp->vfs_data = (caddr_t) fwip; /* fill in the vnode we are mounted on, in the vfs */ vfsp->vfs_vnodecovered = vp;/************************************************************************** * FIST_WRAPFSNODE: * The private information stored by interposing vnodes. * The interposing vnode here is the new root vnode of fist_wrapfs. It * interposes upon the uap->spec vnode we are mounting on (the directory, * or partition interposed upon). *//************************************************************************** * ROOT VNODE OF FIST_WRAPFS: */ rootvp = wrapfs_interpose(interposed_vp, vfsp); /* this is a root vnode of this filesystem */ rootvp->v_flag |= VROOT; fwip->fwi_rootvnodep = rootvp;/************************************************************************** * VNODE MOUNTED UPON: */ /* this vnode to mount on is a mount point for fist_wrapfs */ vp->v_vfsmountedhere = vfsp; /* print values after we change them */ if (vfsp) fist_print_vfs("wrapfs_mount2", vfsp); if (vp) fist_print_vnode("wrapfs_mount2", vp); if (rootvp) fist_print_vnode("wrapfs_mount2rvp", rootvp); fist_print_vnode("wrapfs_mount2rvn", fwip->fwi_rootvnodep); print_location(); return (error);out: /* * Cleanup our mess */ module_keepcnt--; print_location(); return (error);}/* * Undo fist_wrapfs mount */static intwrapfs_unmount( vfs_t * vfsp, cred_t * cr){ struct fist_wrapfs_info *fwip; vnode_t *vnp; fist_dprint(4, "wrapfs_unmount vfsp %x\n", vfsp); /* check if permitted */ if (!suser(cr)) { return (EPERM); } /* free memory used by private data of vfs */ if (!vfsp->vfs_data) { goto out; } fwip = vfstofwi(vfsp); if (fwip->fwi_num_vnodes > 1) { /* always at least 1 b/c of rootvp */ return (EBUSY); } fist_print_vnode("wrapfs_unmount rvp", fwip->fwi_rootvnodep); if (fwip->fwi_rootvnodep->v_count != 1) { fist_dprint(4, "wrapfs_unmount root vnode is busy %d\n", fwip->fwi_rootvnodep->v_count); return (EBUSY); } vnp = vfsp->vfs_vnodecovered; fist_dprint(4, "WRAPFS_UMOUNT: vnodecovered 0x%x has count %d\n", vnp, vnp->v_count); /* XXX: need to VN_RELE(vnp); */ vnp->v_vfsmountedhere = NULL; VN_RELE(fwip->fwi_rootvnodep); /* will free last entry in vp HT */ /* check if HT is really empty */ ASSERT(fist_ht_empty_assert(vfsp) == 1); mutex_destroy(&fwip->fwi_ht_lock); /* free private data */ kmem_free(fwip, sizeof(struct fist_wrapfs_info));out: module_keepcnt--; return (0);}/* * find root of fist_wrapfs */static intwrapfs_root( vfs_t * vfsp, vnode_t ** vpp){ struct fist_wrapfs_info *fwip = NULL; fist_dprint(4, "wrapfs_root vfsp %x vnode %x\n", vfsp, *vpp); fwip = vfstofwi(vfsp); ASSERT(fwip != NULL); *vpp = fwip->fwi_rootvnodep; fist_dprint(4, "wrapfs_root rootvnode %x\n", *vpp); /* * Should I apply the same operation to the hidden filesystem? * probably not, since this root vnode can lead me to the root vnode it * was interposed upon in vnodep->v_data->... * ANSWER: no! */ /* error = VFS_ROOT(vfsp, vpp); */ fist_dprint(4, "WRAPFS_ROOT1 root count %d, hidden count %d\n", (*vpp)->v_count, vntofwn(*vpp)->fwn_vnodep->v_count);#if 1 /* XXX: is this right? Should I HOLD a vnode everytime root is called? */ /* probably ok, since we are holding the root vnode for fist_wrapfs... */ VN_HOLD(*vpp);#else if (*vpp) { fist_print_vnode("wrapfs_root", *vpp); } /* mutex_enter(&(*vpp)->v_lock); */ /* (*vpp)->v_count++; */ /* mutex_exit(&(*vpp)->v_lock); */#endif fist_dprint(4, "WRAPFS_ROOT2 root count %d, hidden count %d\n", (*vpp)->v_count, vntofwn(*vpp)->fwn_vnodep->v_count); print_location(); return (0);}/* * Get file system statistics. */static intwrapfs_statvfs( register vfs_t * vfsp, struct statvfs64 * sbp){ int error = EPERM; struct fist_wrapfs_info *fwip = NULL; vfs_t *hidden_vfsp; fist_dprint(4, "wrapfs_statvfs %x\n", vfsp); if (vfsp) { /* find hidden vfs */ fwip = vfstofwi(vfsp); ASSERT(fwip != NULL); hidden_vfsp = fwip->fwi_mountvfs; /* pass operation to hidden filesystem, and return status */ error = VFS_STATVFS(hidden_vfsp, sbp); } else { /* error: vfsp is invalid */ error = EINVAL; } print_location(); return (error);}/* * Flush any pending I/O to file system vfsp. * The wrapfs_update() routine will only flush *all* fist_wrapfs files. * If vfsp is non-NULL, only sync this fist_wrapfs (in preparation * for a umount). */static intwrapfs_sync(vfs_t *vfsp, short flag, struct cred *cr){ /* commented the print of the sync since i got annoyed a message when we * only return 0 */#if 0 fist_dprint(4, "wrapfs_sync %x\n", vfsp);#endif /* do not sync() lower layer f/s. It'll be sync'ed on its own */ return 0;#if 0 /* if vfsp is NULL, then this is a generic "sync()", treat it as ok */ if (vfsp) { /* find hidden vfs */ fwip = vfstofwi(vfsp); ASSERT(fwip != NULL); hidden_vfsp = fwip->fwi_mountvfs; /* pass operation to hidden filesystem, and return status */ error = VFS_SYNC(hidden_vfsp, flag, cr); } print_location(); return (error);#endif}static intwrapfs_vget( vfs_t *vfsp, vnode_t **vpp, struct fid *fidp){ int error = EPERM; struct fist_wrapfs_info *fwip = NULL; vfs_t *hidden_vfsp; fist_dprint(4, "wrapfs_vget %x\n", vfsp); if (vfsp) { /* find hidden vfs */ fwip = vfstofwi(vfsp); ASSERT(fwip != NULL); hidden_vfsp = fwip->fwi_mountvfs; /* pass operation to hidden filesystem, and return status */ error = VFS_VGET(hidden_vfsp, vpp, fidp); } else { /* error: vfsp is invalid */ error = EINVAL; } print_location(); return (error);}/* * Mount root file system. * "why" is ROOT_INIT on initial call, ROOT_REMOUNT if called to * remount the root file system, and ROOT_UNMOUNT if called to * unmount the root (e.g., as part of a system shutdown). * * XXX - this may be partially machine-dependent; it, along with the * VFS_SWAPVP operation, goes along with auto-configuration. A mechanism * should be provided by which machine-INdependent code in the kernel can * say "get me the right root file system" and "get me the right initial * swap area", and have that done in what may well be a machine-dependent * fashion. Unfortunately, it is also file-system-type dependent (NFS gets * it via bootparams calls, FIST_WRAPFS gets it from various and sundry * machine-dependent mechanisms, as SPECFS does for swap). */static intwrapfs_mountroot( vfs_t *vfsp, enum whymountroot why){ /* * XXX: stackable filesystems cannot be used to as root filesystems, for * now. * -Erez Zadok <ezk@cs.columbia.edu> */ fist_dprint(4, "wrapfs_mountroot %x\n", vfsp); print_location(); return (EINVAL);}static intwrapfs_swapvp( vfs_t *vfsp, vnode_t **vpp, char *nm){ int error = EPERM; struct fist_wrapfs_info *fwip = NULL; vfs_t *hidden_vfsp; fist_dprint(4, "wrapfs_swapvp %x\n", vfsp); if (vfsp) { /* find hidden vfs */ fwip = vfstofwi(vfsp); ASSERT(fwip != NULL); hidden_vfsp = fwip->fwi_mountvfs; /* pass operation to hidden filesystem, and return status */ error = VFS_SWAPVP(hidden_vfsp, vpp, nm); } else { /* error: vfsp is invalid */ error = EINVAL; } print_location(); return (error);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -