ovl: lookup indexed ancestor of lower dir
ovl_lookup_real() in lower layer walks back lower parents to find the topmost indexed parent. If an indexed ancestor is found before reaching lower layer root, ovl_lookup_real() is called recursively with upper layer to walk back from indexed upper to the topmost connected/hashed upper parent (or up to root). ovl_lookup_real() in upper layer then walks forward to connect the topmost upper overlay dir dentry and ovl_lookup_real() in lower layer continues to walk forward to connect the decoded lower overlay dir dentry. Signed-off-by: Amir Goldstein <amir73il@gmail.com> Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
This commit is contained in:
		
							parent
							
								
									4b91c30a5a
								
							
						
					
					
						commit
						0617015403
					
				| @ -294,6 +294,10 @@ fail: | |||||||
| 	goto out; | 	goto out; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | static struct dentry *ovl_lookup_real(struct super_block *sb, | ||||||
|  | 				      struct dentry *real, | ||||||
|  | 				      struct ovl_layer *layer); | ||||||
|  | 
 | ||||||
| /*
 | /*
 | ||||||
|  * Lookup an indexed or hashed overlay dentry by real inode. |  * Lookup an indexed or hashed overlay dentry by real inode. | ||||||
|  */ |  */ | ||||||
| @ -301,9 +305,16 @@ static struct dentry *ovl_lookup_real_inode(struct super_block *sb, | |||||||
| 					    struct dentry *real, | 					    struct dentry *real, | ||||||
| 					    struct ovl_layer *layer) | 					    struct ovl_layer *layer) | ||||||
| { | { | ||||||
|  | 	struct ovl_fs *ofs = sb->s_fs_info; | ||||||
|  | 	struct ovl_layer upper_layer = { .mnt = ofs->upper_mnt }; | ||||||
|  | 	struct dentry *index = NULL; | ||||||
| 	struct dentry *this = NULL; | 	struct dentry *this = NULL; | ||||||
| 	struct inode *inode; | 	struct inode *inode; | ||||||
| 
 | 
 | ||||||
|  | 	/*
 | ||||||
|  | 	 * Decoding upper dir from index is expensive, so first try to lookup | ||||||
|  | 	 * overlay dentry in inode/dcache. | ||||||
|  | 	 */ | ||||||
| 	inode = ovl_lookup_inode(sb, real, !layer->idx); | 	inode = ovl_lookup_inode(sb, real, !layer->idx); | ||||||
| 	if (IS_ERR(inode)) | 	if (IS_ERR(inode)) | ||||||
| 		return ERR_CAST(inode); | 		return ERR_CAST(inode); | ||||||
| @ -312,7 +323,35 @@ static struct dentry *ovl_lookup_real_inode(struct super_block *sb, | |||||||
| 		iput(inode); | 		iput(inode); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	/* TODO: use index when looking up by origin inode */ | 	/*
 | ||||||
|  | 	 * For decoded lower dir file handle, lookup index by origin to check | ||||||
|  | 	 * if lower dir was copied up and and/or removed. | ||||||
|  | 	 */ | ||||||
|  | 	if (!this && layer->idx && ofs->indexdir && !WARN_ON(!d_is_dir(real))) { | ||||||
|  | 		index = ovl_lookup_index(ofs, NULL, real, false); | ||||||
|  | 		if (IS_ERR(index)) | ||||||
|  | 			return index; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	/* Get connected upper overlay dir from index */ | ||||||
|  | 	if (index) { | ||||||
|  | 		struct dentry *upper = ovl_index_upper(ofs, index); | ||||||
|  | 
 | ||||||
|  | 		dput(index); | ||||||
|  | 		if (IS_ERR_OR_NULL(upper)) | ||||||
|  | 			return upper; | ||||||
|  | 
 | ||||||
|  | 		/*
 | ||||||
|  | 		 * ovl_lookup_real() in lower layer may call recursively once to | ||||||
|  | 		 * ovl_lookup_real() in upper layer. The first level call walks | ||||||
|  | 		 * back lower parents to the topmost indexed parent. The second | ||||||
|  | 		 * recursive call walks back from indexed upper to the topmost | ||||||
|  | 		 * connected/hashed upper parent (or up to root). | ||||||
|  | 		 */ | ||||||
|  | 		this = ovl_lookup_real(sb, upper, &upper_layer); | ||||||
|  | 		dput(upper); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
| 	if (!this) | 	if (!this) | ||||||
| 		return NULL; | 		return NULL; | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -661,11 +661,9 @@ struct dentry *ovl_get_index_fh(struct ovl_fs *ofs, struct ovl_fh *fh) | |||||||
| 	return ERR_PTR(err); | 	return ERR_PTR(err); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static struct dentry *ovl_lookup_index(struct dentry *dentry, | struct dentry *ovl_lookup_index(struct ovl_fs *ofs, struct dentry *upper, | ||||||
| 				       struct dentry *upper, | 				struct dentry *origin, bool verify) | ||||||
| 				       struct dentry *origin) |  | ||||||
| { | { | ||||||
| 	struct ovl_fs *ofs = dentry->d_sb->s_fs_info; |  | ||||||
| 	struct dentry *index; | 	struct dentry *index; | ||||||
| 	struct inode *inode; | 	struct inode *inode; | ||||||
| 	struct qstr name; | 	struct qstr name; | ||||||
| @ -693,6 +691,16 @@ static struct dentry *ovl_lookup_index(struct dentry *dentry, | |||||||
| 	inode = d_inode(index); | 	inode = d_inode(index); | ||||||
| 	if (d_is_negative(index)) { | 	if (d_is_negative(index)) { | ||||||
| 		goto out_dput; | 		goto out_dput; | ||||||
|  | 	} else if (ovl_is_whiteout(index) && !verify) { | ||||||
|  | 		/*
 | ||||||
|  | 		 * When index lookup is called with !verify for decoding an | ||||||
|  | 		 * overlay file handle, a whiteout index implies that decode | ||||||
|  | 		 * should treat file handle as stale and no need to print a | ||||||
|  | 		 * warning about it. | ||||||
|  | 		 */ | ||||||
|  | 		dput(index); | ||||||
|  | 		index = ERR_PTR(-ESTALE); | ||||||
|  | 		goto out; | ||||||
| 	} else if (ovl_dentry_weird(index) || ovl_is_whiteout(index) || | 	} else if (ovl_dentry_weird(index) || ovl_is_whiteout(index) || | ||||||
| 		   ((inode->i_mode ^ d_inode(origin)->i_mode) & S_IFMT)) { | 		   ((inode->i_mode ^ d_inode(origin)->i_mode) & S_IFMT)) { | ||||||
| 		/*
 | 		/*
 | ||||||
| @ -706,7 +714,7 @@ static struct dentry *ovl_lookup_index(struct dentry *dentry, | |||||||
| 				    index, d_inode(index)->i_mode & S_IFMT, | 				    index, d_inode(index)->i_mode & S_IFMT, | ||||||
| 				    d_inode(origin)->i_mode & S_IFMT); | 				    d_inode(origin)->i_mode & S_IFMT); | ||||||
| 		goto fail; | 		goto fail; | ||||||
| 	} else if (is_dir) { | 	} else if (is_dir && verify) { | ||||||
| 		if (!upper) { | 		if (!upper) { | ||||||
| 			pr_warn_ratelimited("overlayfs: suspected uncovered redirected dir found (origin=%pd2, index=%pd2).\n", | 			pr_warn_ratelimited("overlayfs: suspected uncovered redirected dir found (origin=%pd2, index=%pd2).\n", | ||||||
| 					    origin, index); | 					    origin, index); | ||||||
| @ -943,7 +951,7 @@ struct dentry *ovl_lookup(struct inode *dir, struct dentry *dentry, | |||||||
| 
 | 
 | ||||||
| 	if (origin && ovl_indexdir(dentry->d_sb) && | 	if (origin && ovl_indexdir(dentry->d_sb) && | ||||||
| 	    (!d.is_dir || ovl_index_all(dentry->d_sb))) { | 	    (!d.is_dir || ovl_index_all(dentry->d_sb))) { | ||||||
| 		index = ovl_lookup_index(dentry, upperdentry, origin); | 		index = ovl_lookup_index(ofs, upperdentry, origin, true); | ||||||
| 		if (IS_ERR(index)) { | 		if (IS_ERR(index)) { | ||||||
| 			err = PTR_ERR(index); | 			err = PTR_ERR(index); | ||||||
| 			index = NULL; | 			index = NULL; | ||||||
|  | |||||||
| @ -274,6 +274,8 @@ struct dentry *ovl_index_upper(struct ovl_fs *ofs, struct dentry *index); | |||||||
| int ovl_verify_index(struct ovl_fs *ofs, struct dentry *index); | int ovl_verify_index(struct ovl_fs *ofs, struct dentry *index); | ||||||
| int ovl_get_index_name(struct dentry *origin, struct qstr *name); | int ovl_get_index_name(struct dentry *origin, struct qstr *name); | ||||||
| struct dentry *ovl_get_index_fh(struct ovl_fs *ofs, struct ovl_fh *fh); | struct dentry *ovl_get_index_fh(struct ovl_fs *ofs, struct ovl_fh *fh); | ||||||
|  | struct dentry *ovl_lookup_index(struct ovl_fs *ofs, struct dentry *upper, | ||||||
|  | 				struct dentry *origin, bool verify); | ||||||
| int ovl_path_next(int idx, struct dentry *dentry, struct path *path); | int ovl_path_next(int idx, struct dentry *dentry, struct path *path); | ||||||
| struct dentry *ovl_lookup(struct inode *dir, struct dentry *dentry, | struct dentry *ovl_lookup(struct inode *dir, struct dentry *dentry, | ||||||
| 			  unsigned int flags); | 			  unsigned int flags); | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user