diff --git a/fs/squashfs/sqfs.c b/fs/squashfs/sqfs.c
index e2d91c654c..5c05ddca38 100644
--- a/fs/squashfs/sqfs.c
+++ b/fs/squashfs/sqfs.c
@@ -442,7 +442,7 @@ static char *sqfs_resolve_symlink(struct squashfs_symlink_inode *sym,
   * table.
   */
  static int sqfs_search_dir(struct squashfs_dir_stream *dirs, char **token_list,
-			   int token_count, u32 *m_list, int m_count)
+			   int token_count, u32 *m_list, int m_count, int root_inode)
  {
  	struct squashfs_super_block *sblk = ctxt.sblk;
  	char *path, *target, **sym_tokens, *res, *rem;
@@ -463,7 +463,7 @@ static int sqfs_search_dir(struct squashfs_dir_stream *dirs, char **token_list,
  	dirsp = (struct fs_dir_stream *)dirs;
  
  	/* Start by root inode */
-	table = sqfs_find_inode(dirs->inode_table, le32_to_cpu(sblk->inodes),
+	table = sqfs_find_inode(dirs->inode_table, root_inode,
  				sblk->inodes, sblk->block_size);
  
  	dir = (struct squashfs_dir_inode *)table;
@@ -576,7 +576,7 @@ static int sqfs_search_dir(struct squashfs_dir_stream *dirs, char **token_list,
  			dirs->entry = NULL;
  
  			ret = sqfs_search_dir(dirs, sym_tokens, token_count,
-					      m_list, m_count);
+					      m_list, m_count, root_inode);
  			goto out;
  		} else if (!sqfs_is_dir(get_unaligned_le16(&dir->inode_type))) {
  			printf("** Cannot find directory. **\n");
@@ -684,15 +684,17 @@ static int sqfs_get_metablk_pos(u32 *pos_list, void *table, u32 offset,
  	return ret;
  }
  
-static int sqfs_read_inode_table(unsigned char **inode_table)
+static int sqfs_read_inode_table(unsigned char **inode_table,
+				 const struct squashfs_base_inode **root_inode)
  {
  	struct squashfs_super_block *sblk = ctxt.sblk;
-	u64 start, n_blks, table_offset, table_size;
+	u64 start, n_blks, table_offset, src_table_pos = 0, table_size;
  	int j, ret = 0, metablks_count;
  	unsigned char *src_table, *itb;
  	u32 src_len, dest_offset = 0;
  	unsigned long dest_len = 0;
  	bool compressed;
+	u64 root_inode_block, root_inode_offset;
  
  	table_size = get_unaligned_le64(&sblk->directory_table_start) -
  		get_unaligned_le64(&sblk->inode_table_start);
@@ -701,6 +703,13 @@ static int sqfs_read_inode_table(unsigned char **inode_table)
  	n_blks = sqfs_calc_n_blks(sblk->inode_table_start,
  				  sblk->directory_table_start, &table_offset);
  
+	/*
+	 * Value to indicate 'not found' - set it here so that it's not unset
+	 * in case of an error.
+	 */
+	if (root_inode)
+		*root_inode = NULL;
+
  	/* Allocate a proper sized buffer (itb) to store the inode table */
  	itb = malloc_cache_aligned(n_blks * ctxt.cur_dev->blksz);
  	if (!itb)
@@ -733,8 +742,34 @@ static int sqfs_read_inode_table(unsigned char **inode_table)
  
  	src_table = itb + table_offset + SQFS_HEADER_SIZE;
  
+	/*
+	 * While we're here, find the root inode. It's specified by an on-disk
+	 * block position and offset, which we can't look up anywhere else if
+	 * the metadata is compressed. Thus find it's inode index, which can
+	 * later be used to look it up.
+	 *
+	 * Note that while directory entries also have these offset
+	 * parameters, they also include the inode number which is what this
+	 * implementation uses to look them up.
+	 */
+	root_inode_block = (u64)le64_to_cpu(sblk->root_inode) >> 16;
+	root_inode_offset = (u64)le64_to_cpu(sblk->root_inode) & 0xffff;
+
  	/* Extract compressed Inode table */
  	for (j = 0; j < metablks_count; j++) {
+		/*
+		 * Check if we're at the raw block offset the root inode is
+		 * specified to live at, and if so point the root inode to
+		 * where it's about to end up.
+		 *
+		 * Note we're doing this now, before dest_offset has been
+		 * pointed to the next block.
+		 */
+		if (src_table_pos == root_inode_block && root_inode) {
+			*root_inode = (const struct squashfs_base_inode *)
+			    (*inode_table + dest_offset + root_inode_offset);
+		}
+
  		sqfs_read_metablock(itb, table_offset, &compressed, &src_len);
  		if (compressed) {
  			dest_len = SQFS_METADATA_BLOCK_SIZE;
@@ -749,8 +784,8 @@ static int sqfs_read_inode_table(unsigned char **inode_table)
  
  			dest_offset += dest_len;
  		} else {
-			memcpy(*inode_table + (j * SQFS_METADATA_BLOCK_SIZE),
-			       src_table, src_len);
+			memcpy(*inode_table + dest_offset, src_table, src_len);
+			dest_offset += SQFS_METADATA_BLOCK_SIZE;
  		}
  
  		/*
@@ -760,6 +795,17 @@ static int sqfs_read_inode_table(unsigned char **inode_table)
  
  		table_offset += src_len + SQFS_HEADER_SIZE;
  		src_table += src_len + SQFS_HEADER_SIZE;
+		src_table_pos += src_len + SQFS_HEADER_SIZE;
+	}
+
+	/*
+	 * If we couldn't find the inode, return an error to reduce the chance
+	 * someone will try to index this null pointer.
+	 */
+	if (root_inode && !*root_inode) {
+		printf("Failed to locate root squashfs inode.\n");
+		ret = -ENOENT;
+		goto free_itb;
  	}
  
  free_itb:
@@ -875,6 +921,7 @@ int sqfs_opendir(const char *filename, struct fs_dir_stream **dirsp)
  	struct squashfs_dir_stream *dirs;
  	char **token_list = NULL, *path = NULL;
  	u32 *pos_list = NULL;
+	const struct squashfs_base_inode *root_inode = NULL;
  
  	dirs = calloc(1, sizeof(*dirs));
  	if (!dirs)
@@ -887,7 +934,7 @@ int sqfs_opendir(const char *filename, struct fs_dir_stream **dirsp)
  	dirs->inode_table = NULL;
  	dirs->dir_table = NULL;
  
-	ret = sqfs_read_inode_table(&inode_table);
+	ret = sqfs_read_inode_table(&inode_table, &root_inode);
  	if (ret) {
  		ret = -EINVAL;
  		goto out;
@@ -929,7 +976,7 @@ int sqfs_opendir(const char *filename, struct fs_dir_stream **dirsp)
  	dirs->inode_table = inode_table;
  	dirs->dir_table = dir_table;
  	ret = sqfs_search_dir(dirs, token_list, token_count, pos_list,
-			      metablks_count);
+			      metablks_count, (int)get_unaligned_le32(&root_inode->inode_number));
  	if (ret)
  		goto out;
  
