struct dentry * vnlayer_get_dentry( SUPER_T *sb, void *fhbits ) { int error; VFS_T *vfsp = SBTOVFS(sb); VNODE_T *vp; MDKI_FID_T *lfidp = fhbits; DENT_T *dp; CALL_DATA_T cd; mdki_linux_init_call_data(&cd); error = VFS_VGET(vfsp, &vp, lfidp, &cd); if (error == 0) { /* rebind if needed */ if (mfs_rebind_vpp(1, &vp, &cd)) { MDKI_VFS_LOG(VFS_LOG_ESTALE, "%s: vp %p rebound\n", __FUNCTION__, vp); } dp = vnlayer_find_dentry(vp); /* always drop vnode's refcount */ VN_RELE(vp); } else { dp = ERR_PTR(mdki_errno_unix_to_linux(error)); } mdki_linux_destroy_call_data(&cd); return dp; }
int vnlayer_linux_statfs( DENT_T *dent_p, LINUX_STATFS_T *stat_p ) #endif { int error; #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18) && !defined(SLES10SP2) error = VFS_STATVFS(SBTOVFS(super_p), stat_p); #else error = VFS_STATVFS(SBTOVFS(dent_p->d_sb), stat_p); #endif return (-error); }
void vnlayer_put_super(struct super_block *super_p) { int err; CALL_DATA_T cd; ASSERT_KERNEL_LOCKED(); ASSERT_SB_LOCKED(super_p); mdki_linux_init_call_data(&cd); err = VFS_UNMOUNT(SBTOVFS(super_p), &cd); mdki_linux_destroy_call_data(&cd); if (err != 0) { VFS_LOG(SBTOVFS(super_p), VFS_LOG_ERR, "Linux file system interface doesn't let vnode/vfs reject unmounts: error %d\n", err); } return /* mdki_errno_unix_to_linux(err)*/; }
void vnlayer_put_super(struct super_block *super_p) { int err; CRED_T *cred; ASSERT_KERNEL_LOCKED(); ASSERT_SB_LOCKED(super_p); cred = MDKI_GET_UCRED(); err = VFS_UNMOUNT(SBTOVFS(super_p), cred); MDKI_CRFREE(cred); if (err != 0) { VFS_LOG(SBTOVFS(super_p), VFS_LOG_ERR, "Linux file system interface doesn't let vnode/vfs reject unmounts: error %d\n", err); } return /* mdki_errno_unix_to_linux(err)*/; }
void vnlayer_write_super(struct super_block *super_p) { CALL_DATA_T cd; int err; ASSERT_SB_LOCKED(super_p); mdki_linux_init_call_data(&cd); err = VFS_SYNC(SBTOVFS(super_p), SBTOVFS(super_p), 0, &cd); mdki_linux_destroy_call_data(&cd); /* They rewrote sync_supers so that it won't proceed through their loop * until the dirty bit is cleared. */ super_p->s_dirt = 0; if (err != 0) VFS_LOG(SBTOVFS(super_p), VFS_LOG_ERR, "%s: error %d syncing\n", __func__, err); return /* mdki_errno_unix_to_linux(err) */; }
void vnlayer_write_super(struct super_block *super_p) { CRED_T *cred; int err; ASSERT_SB_LOCKED(super_p); cred = MDKI_GET_UCRED(); err = VFS_SYNC(SBTOVFS(super_p), SBTOVFS(super_p), 0, cred); MDKI_CRFREE(cred); /* They rewrote sync_supers so that it won't proceed through their loop * until the dirty bit is cleared. */ super_p->s_dirt = 0; if (err != 0) VFS_LOG(SBTOVFS(super_p), VFS_LOG_ERR, "%s: error %d syncing\n", __func__, err); return /* mdki_errno_unix_to_linux(err) */; }
int vnlayer_remount_fs( struct super_block *super_p, int *flags, char *data ) { VFS_T *vfsp = SBTOVFS(super_p); VFS_LOG(vfsp, VFS_LOG_ERR, "Vnode/VFS does not support remounting of file systems (sb=%p)\n", super_p); return -EINVAL; }
/* They rewrote sync_supers so that it won't proceed through their loop * until the dirty bit is cleared. */ super_p->s_dirt = 0; if (err != 0) VFS_LOG(SBTOVFS(super_p), VFS_LOG_ERR, "%s: error %d syncing\n", __func__, err); return /* mdki_errno_unix_to_linux(err) */; } #else /* LINUX_VERSION_CODE < KERNEL_VERSION(3,6,0) */ int vnlayer_sync_super( struct super_block *super_p, int wait ) { CALL_DATA_T cd; int err; /* if wait is not allowed, do nothing */ if (wait == 0) { return 0; } ASSERT_SB_LOCKED(super_p); mdki_linux_init_call_data(&cd); err = VFS_SYNC(SBTOVFS(super_p), SBTOVFS(super_p), 0, &cd); mdki_linux_destroy_call_data(&cd); if (err != 0) { VFS_LOG(SBTOVFS(super_p), VFS_LOG_ERR, "%s: error %d syncing\n", __func__, err); } return mdki_errno_unix_to_linux(err); }
int vnlayer_fill_super( SUPER_T *super_p, void *data_p, int silent ) { INODE_T *ino_p; VNODE_T *rootvp; VATTR_T va; VFS_T *vfsp; int err = 0; CALL_DATA_T cd; ASSERT_KERNEL_LOCKED(); /* sys_mount() */ ASSERT_SB_MOUNT_LOCKED_W(super_p); /* can't assert on mount_sem, we don't have access to it. */ if (vnlayer_vfs_opvec == NULL) { MDKI_VFS_LOG(VFS_LOG_ERR, "%s: VFS operation not set yet " "(no file system module loaded?)\n", __func__); err = -ENODATA; goto return_NULL; } if (MDKI_INOISOURS(vnlayer_get_urdir_inode())) { /* can't handle this case */ MDKI_VFS_LOG(VFS_LOG_ERR, "%s: can't handle mounts inside setview.\n", __func__); err = -EINVAL; goto return_NULL; } /* * The only fields we have coming in are s_type and s_flags. */ /* Verify this */ super_p->s_blocksize = MVFS_DEF_BLKSIZE; super_p->s_blocksize_bits = MVFS_DEF_BLKSIZE_BITS; super_p->s_maxbytes = MVFS_DEF_MAX_FILESIZE; super_p->s_op = &mvfs_super_ops; super_p->s_export_op = &vnlayer_export_ops; super_p->dq_op = NULL; super_p->s_magic = MVFS_SUPER_MAGIC; /* * XXX This module is currently restricted to one client file system * type at a time, as registered via the vnlayer_vfs_opvec. */ vfsp = KMEM_ALLOC(sizeof(*vfsp), KM_SLEEP); if (vfsp == NULL) { MDKI_VFS_LOG(VFS_LOG_ERR, "%s failed: no memory\n", __func__); SET_SBTOVFS(super_p, NULL); err = -ENOMEM; goto return_NULL; } BZERO(vfsp, sizeof(*vfsp)); SET_VFSTOSB(vfsp, super_p); SET_SBTOVFS(super_p, vfsp); vfsp->vfs_op = vnlayer_vfs_opvec; /* XXX fill in more of vfsp (flag?) */ if (super_p->s_flags & MS_RDONLY) vfsp->vfs_flag |= VFS_RDONLY; if (super_p->s_flags & MS_NOSUID) vfsp->vfs_flag |= VFS_NOSUID; err = vnlayer_linux_mount(vfsp, data_p); if (err) { goto bailout; } /* * Now create our dentry and set that up in the superblock. Get * the inode from the vnode at the root of the file system, and * attach it to a new dentry. */ mdki_linux_init_call_data(&cd); err = VFS_ROOT(SBTOVFS(super_p), &rootvp); if (err) { err = mdki_errno_unix_to_linux(err); (void) VFS_UNMOUNT(vfsp,&cd); mdki_linux_destroy_call_data(&cd); goto bailout; } ino_p = VTOI(rootvp); #ifdef CONFIG_FS_POSIX_ACL /* If the system supports ACLs, we set the flag in the superblock * depending on the ability of the underlying filesystem */ if (vfsp->vfs_flag & VFS_POSIXACL) { super_p->s_flags |= MS_POSIXACL; } #endif /* * Call getattr() to prime this inode with real attributes via the * callback to mdki_linux_vattr_pullup() */ VATTR_NULL(&va); /* ignore error code, we're committed */ (void) VOP_GETATTR(rootvp, &va, 0, &cd); /* This will allocate a dentry with a name of /, which is * what Linux uses in all filesystem roots. The dentry is * also not put on the hash chains because Linux does not * hash file system roots. It finds them through the super * blocks. */ super_p->s_root = VNODE_D_ALLOC_ROOT(ino_p); if (super_p->s_root) { if (VFSTOSB(vnlayer_looproot_vp->v_vfsp) == super_p) { /* loopback names are done with regular dentry ops */ MDKI_SET_DOPS(super_p->s_root, &vnode_dentry_ops); } else { /* * setview names come in via VOB mounts, they're marked * with setview dentry ops */ MDKI_SET_DOPS(super_p->s_root, &vnode_setview_dentry_ops); } super_p->s_root->d_fsdata = NULL; #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,38) atomic_set(&super_p->s_root->d_count, 1); #endif /* d_alloc_root assumes that the caller will take care of * bumping the inode count for the dentry. So we will oblige */ igrab(ino_p); } else { VN_RELE(rootvp); (void) VFS_UNMOUNT(vfsp,&cd); mdki_linux_destroy_call_data(&cd); err = -ENOMEM; goto bailout; } mdki_linux_destroy_call_data(&cd); #if LINUX_VERSION_CODE < KERNEL_VERSION(3,6,0) super_p->s_dirt = 1; /* we want to be called on write_super/sync() */ #endif /* LINUX_VERSION_CODE < KERNEL_VERSION(3,6,0) */ #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,38) /* write back is delegated to the undelying fs */ super_p->s_bdi = &noop_backing_dev_info; #endif /* * release reference on rootvp--super block holds appropriate * references now */ VN_RELE(rootvp); return(0); bailout: MDKI_VFS_LOG(VFS_LOG_ERR, "%s failed: error %d\n", __func__, vnlayer_errno_linux_to_unix(err)); SET_SBTOVFS(super_p, NULL); KMEM_FREE(vfsp, sizeof(*vfsp)); return_NULL: return(err); }