static inline unsigned long HgfsComputeBlockBits(unsigned long blockSize);
static compat_kmem_cache_ctor HgfsInodeCacheCtor;
static HgfsSuperInfo *HgfsInitSuperInfo(HgfsMountInfo *mountInfo);
+static struct dentry *HgfsGetRootDentry(struct super_block *sb);
static int HgfsReadSuper(struct super_block *sb,
void *rawData,
int flags);
}
+/*
+ *----------------------------------------------------------------------------
+ *
+ * HgfsGetRootDentry --
+ *
+ * Gets the root dentry for a given super block.
+ *
+ * Results:
+ * A valid root dentry on success, NULL otherwise.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------------
+ */
+
+static struct dentry *
+HgfsGetRootDentry(struct super_block *sb) // IN: Super block object
+{
+ struct dentry *rootDentry = NULL;
+ struct inode *rootInode;
+
+ ASSERT(sb);
+
+ LOG(6, (KERN_DEBUG "VMware hgfs: %s: entered\n", __func__));
+
+ rootInode = HgfsGetInode(sb, HGFS_ROOT_INO);
+ if (rootInode) {
+ HgfsInodeInfo *iinfo;
+ static const HgfsAttrInfo attr = {
+ .type = HGFS_FILE_TYPE_DIRECTORY,
+ .size = 4192,
+ .specialPerms = 0,
+ .ownerPerms = HGFS_PERM_READ | HGFS_PERM_EXEC,
+ .groupPerms = HGFS_PERM_READ | HGFS_PERM_EXEC,
+ .otherPerms = HGFS_PERM_READ | HGFS_PERM_EXEC,
+ .mask = HGFS_ATTR_VALID_TYPE |
+ HGFS_ATTR_VALID_SIZE |
+ HGFS_ATTR_VALID_SPECIAL_PERMS |
+ HGFS_ATTR_VALID_OWNER_PERMS |
+ HGFS_ATTR_VALID_GROUP_PERMS |
+ HGFS_ATTR_VALID_OTHER_PERMS,
+ };
+
+ /*
+ * On an allocation failure in read_super, the inode will have been
+ * marked "bad". If it was, we certainly don't want to start playing with
+ * the HgfsInodeInfo. So quietly put the inode back and fail.
+ */
+ if (is_bad_inode(rootInode)) {
+ LOG(6, (KERN_DEBUG "VMware hgfs: %s: encountered bad inode\n",
+ __func__));
+ iput(rootInode);
+ goto exit;
+ }
+
+ HgfsChangeFileAttributes(rootInode, &attr);
+
+ iinfo = INODE_GET_II_P(rootInode);
+ iinfo->isFakeInodeNumber = FALSE;
+ iinfo->isReferencedInode = TRUE;
+ }
+
+ rootDentry = d_alloc_root(rootInode);
+ if (rootDentry == NULL) {
+ LOG(4, (KERN_WARNING "VMware hgfs: %s: Could not get "
+ "root dentry\n", __func__));
+ goto exit;
+ }
+
+ LOG(6, (KERN_DEBUG "VMware hgfs: %s: finished\n", __func__));
+exit:
+ return rootDentry;
+}
+
+
/*
*-----------------------------------------------------------------------------
*
void *rawData, // IN: Fs-specific mount data
int flags) // IN: Mount flags
{
- int result;
+ int result = 0;
HgfsSuperInfo *si;
HgfsMountInfo *mountInfo;
- struct dentry *rootDentry;
+ struct dentry *rootDentry = NULL;
ASSERT(sb);
sb->s_blocksize_bits = HgfsComputeBlockBits(HGFS_BLOCKSIZE);
sb->s_blocksize = 1 << sb->s_blocksize_bits;
- /*
- * We can't use d_alloc_root() here directly because it requires a valid
- * inode, which only HgfsInstantiate will create. So instead, we'll do the
- * work in pieces. First we'll allocate the dentry and setup its parent
- * and superblock. Then HgfsInstantiate will do the rest, issuing a getattr,
- * getting the inode, and instantiating the dentry with it.
- */
- rootDentry = compat_d_alloc_name(NULL, "/");
+ rootDentry = HgfsGetRootDentry(sb);
if (rootDentry == NULL) {
- LOG(4, (KERN_WARNING "VMware hgfs: HgfsReadSuper: Could not allocate "
- "root dentry\n"));
- result = -ENOMEM;
- goto exit;
- }
- rootDentry->d_parent = rootDentry;
- rootDentry->d_sb = sb;
- result = HgfsInstantiate(rootDentry, HGFS_ROOT_INO, NULL);
- if (result) {
LOG(4, (KERN_WARNING "VMware hgfs: HgfsReadSuper: Could not instantiate "
"root dentry\n"));
+ result = -ENOMEM;
goto exit;
}
sb->s_root = rootDentry;