diff options
Diffstat (limited to 'fs/overlayfs/export.c')
| -rw-r--r-- | fs/overlayfs/export.c | 36 | 
1 files changed, 25 insertions, 11 deletions
diff --git a/fs/overlayfs/export.c b/fs/overlayfs/export.c index 35680b6e175b..c8c8588bd98c 100644 --- a/fs/overlayfs/export.c +++ b/fs/overlayfs/export.c @@ -174,28 +174,37 @@ static int ovl_connect_layer(struct dentry *dentry)   * U = upper file handle   * L = lower file handle   * - * (*) Connecting an overlay dir from real lower dentry is not always + * (*) Decoding a connected overlay dir from real lower dentry is not always   * possible when there are redirects in lower layers and non-indexed merge dirs.   * To mitigate those case, we may copy up the lower dir ancestor before encode - * a lower dir file handle. + * of a decodable file handle for non-upper dir.   *   * Return 0 for upper file handle, > 0 for lower file handle or < 0 on error.   */  static int ovl_check_encode_origin(struct dentry *dentry)  { -	struct ovl_fs *ofs = dentry->d_sb->s_fs_info; +	struct ovl_fs *ofs = OVL_FS(dentry->d_sb); +	bool decodable = ofs->config.nfs_export; + +	/* Lower file handle for non-upper non-decodable */ +	if (!ovl_dentry_upper(dentry) && !decodable) +		return 0;  	/* Upper file handle for pure upper */  	if (!ovl_dentry_lower(dentry))  		return 0;  	/* -	 * Upper file handle for non-indexed upper. -	 *  	 * Root is never indexed, so if there's an upper layer, encode upper for  	 * root.  	 */ -	if (ovl_dentry_upper(dentry) && +	if (dentry == dentry->d_sb->s_root) +		return 0; + +	/* +	 * Upper decodable file handle for non-indexed upper. +	 */ +	if (ovl_dentry_upper(dentry) && decodable &&  	    !ovl_test_flag(OVL_INDEX, d_inode(dentry)))  		return 0; @@ -205,7 +214,7 @@ static int ovl_check_encode_origin(struct dentry *dentry)  	 * ovl_connect_layer() will try to make origin's layer "connected" by  	 * copying up a "connectable" ancestor.  	 */ -	if (d_is_dir(dentry) && ovl_upper_mnt(ofs)) +	if (d_is_dir(dentry) && ovl_upper_mnt(ofs) && decodable)  		return ovl_connect_layer(dentry);  	/* Lower file handle for indexed and non-upper dir/non-dir */ @@ -435,7 +444,7 @@ static struct dentry *ovl_lookup_real_inode(struct super_block *sb,  					    struct dentry *real,  					    const struct ovl_layer *layer)  { -	struct ovl_fs *ofs = sb->s_fs_info; +	struct ovl_fs *ofs = OVL_FS(sb);  	struct dentry *index = NULL;  	struct dentry *this = NULL;  	struct inode *inode; @@ -656,7 +665,7 @@ static struct dentry *ovl_get_dentry(struct super_block *sb,  				     struct ovl_path *lowerpath,  				     struct dentry *index)  { -	struct ovl_fs *ofs = sb->s_fs_info; +	struct ovl_fs *ofs = OVL_FS(sb);  	const struct ovl_layer *layer = upper ? &ofs->layers[0] : lowerpath->layer;  	struct dentry *real = upper ?: (index ?: lowerpath->dentry); @@ -681,7 +690,7 @@ static struct dentry *ovl_get_dentry(struct super_block *sb,  static struct dentry *ovl_upper_fh_to_d(struct super_block *sb,  					struct ovl_fh *fh)  { -	struct ovl_fs *ofs = sb->s_fs_info; +	struct ovl_fs *ofs = OVL_FS(sb);  	struct dentry *dentry;  	struct dentry *upper; @@ -701,7 +710,7 @@ static struct dentry *ovl_upper_fh_to_d(struct super_block *sb,  static struct dentry *ovl_lower_fh_to_d(struct super_block *sb,  					struct ovl_fh *fh)  { -	struct ovl_fs *ofs = sb->s_fs_info; +	struct ovl_fs *ofs = OVL_FS(sb);  	struct ovl_path origin = { };  	struct ovl_path *stack = &origin;  	struct dentry *dentry = NULL; @@ -876,3 +885,8 @@ const struct export_operations ovl_export_operations = {  	.get_name	= ovl_get_name,  	.get_parent	= ovl_get_parent,  }; + +/* encode_fh() encodes non-decodable file handles with nfs_export=off */ +const struct export_operations ovl_export_fid_operations = { +	.encode_fh	= ovl_encode_fh, +};  |