diff options
-rw-r--r-- | fs/exportfs/expfs.c | 9 | ||||
-rw-r--r-- | fs/overlayfs/export.c | 4 | ||||
-rw-r--r-- | fs/overlayfs/namei.c | 16 | ||||
-rw-r--r-- | fs/overlayfs/overlayfs.h | 5 |
4 files changed, 23 insertions, 11 deletions
diff --git a/fs/exportfs/expfs.c b/fs/exportfs/expfs.c index 329a5d103846..645158dc33f1 100644 --- a/fs/exportfs/expfs.c +++ b/fs/exportfs/expfs.c | |||
@@ -435,6 +435,15 @@ struct dentry *exportfs_decode_fh(struct vfsmount *mnt, struct fid *fid, | |||
435 | if (IS_ERR_OR_NULL(result)) | 435 | if (IS_ERR_OR_NULL(result)) |
436 | return ERR_PTR(-ESTALE); | 436 | return ERR_PTR(-ESTALE); |
437 | 437 | ||
438 | /* | ||
439 | * If no acceptance criteria was specified by caller, a disconnected | ||
440 | * dentry is also accepatable. Callers may use this mode to query if | ||
441 | * file handle is stale or to get a reference to an inode without | ||
442 | * risking the high overhead caused by directory reconnect. | ||
443 | */ | ||
444 | if (!acceptable) | ||
445 | return result; | ||
446 | |||
438 | if (d_is_dir(result)) { | 447 | if (d_is_dir(result)) { |
439 | /* | 448 | /* |
440 | * This request is for a directory. | 449 | * This request is for a directory. |
diff --git a/fs/overlayfs/export.c b/fs/overlayfs/export.c index e688cf019460..15411350a7a1 100644 --- a/fs/overlayfs/export.c +++ b/fs/overlayfs/export.c | |||
@@ -685,7 +685,7 @@ static struct dentry *ovl_upper_fh_to_d(struct super_block *sb, | |||
685 | if (!ofs->upper_mnt) | 685 | if (!ofs->upper_mnt) |
686 | return ERR_PTR(-EACCES); | 686 | return ERR_PTR(-EACCES); |
687 | 687 | ||
688 | upper = ovl_decode_real_fh(fh, ofs->upper_mnt); | 688 | upper = ovl_decode_real_fh(fh, ofs->upper_mnt, true); |
689 | if (IS_ERR_OR_NULL(upper)) | 689 | if (IS_ERR_OR_NULL(upper)) |
690 | return upper; | 690 | return upper; |
691 | 691 | ||
@@ -735,7 +735,7 @@ static struct dentry *ovl_lower_fh_to_d(struct super_block *sb, | |||
735 | } | 735 | } |
736 | 736 | ||
737 | /* Then lookup origin by fh */ | 737 | /* Then lookup origin by fh */ |
738 | err = ovl_check_origin_fh(ofs, fh, NULL, &stack); | 738 | err = ovl_check_origin_fh(ofs, fh, true, NULL, &stack); |
739 | if (err) { | 739 | if (err) { |
740 | goto out_err; | 740 | goto out_err; |
741 | } else if (index) { | 741 | } else if (index) { |
diff --git a/fs/overlayfs/namei.c b/fs/overlayfs/namei.c index 24bd387321d1..810a333d2221 100644 --- a/fs/overlayfs/namei.c +++ b/fs/overlayfs/namei.c | |||
@@ -180,7 +180,8 @@ invalid: | |||
180 | goto out; | 180 | goto out; |
181 | } | 181 | } |
182 | 182 | ||
183 | struct dentry *ovl_decode_real_fh(struct ovl_fh *fh, struct vfsmount *mnt) | 183 | struct dentry *ovl_decode_real_fh(struct ovl_fh *fh, struct vfsmount *mnt, |
184 | bool connected) | ||
184 | { | 185 | { |
185 | struct dentry *real; | 186 | struct dentry *real; |
186 | int bytes; | 187 | int bytes; |
@@ -195,7 +196,7 @@ struct dentry *ovl_decode_real_fh(struct ovl_fh *fh, struct vfsmount *mnt) | |||
195 | bytes = (fh->len - offsetof(struct ovl_fh, fid)); | 196 | bytes = (fh->len - offsetof(struct ovl_fh, fid)); |
196 | real = exportfs_decode_fh(mnt, (struct fid *)fh->fid, | 197 | real = exportfs_decode_fh(mnt, (struct fid *)fh->fid, |
197 | bytes >> 2, (int)fh->type, | 198 | bytes >> 2, (int)fh->type, |
198 | ovl_acceptable, mnt); | 199 | connected ? ovl_acceptable : NULL, mnt); |
199 | if (IS_ERR(real)) { | 200 | if (IS_ERR(real)) { |
200 | /* | 201 | /* |
201 | * Treat stale file handle to lower file as "origin unknown". | 202 | * Treat stale file handle to lower file as "origin unknown". |
@@ -319,14 +320,15 @@ static int ovl_lookup_layer(struct dentry *base, struct ovl_lookup_data *d, | |||
319 | } | 320 | } |
320 | 321 | ||
321 | 322 | ||
322 | int ovl_check_origin_fh(struct ovl_fs *ofs, struct ovl_fh *fh, | 323 | int ovl_check_origin_fh(struct ovl_fs *ofs, struct ovl_fh *fh, bool connected, |
323 | struct dentry *upperdentry, struct ovl_path **stackp) | 324 | struct dentry *upperdentry, struct ovl_path **stackp) |
324 | { | 325 | { |
325 | struct dentry *origin = NULL; | 326 | struct dentry *origin = NULL; |
326 | int i; | 327 | int i; |
327 | 328 | ||
328 | for (i = 0; i < ofs->numlower; i++) { | 329 | for (i = 0; i < ofs->numlower; i++) { |
329 | origin = ovl_decode_real_fh(fh, ofs->lower_layers[i].mnt); | 330 | origin = ovl_decode_real_fh(fh, ofs->lower_layers[i].mnt, |
331 | connected); | ||
330 | if (origin) | 332 | if (origin) |
331 | break; | 333 | break; |
332 | } | 334 | } |
@@ -370,7 +372,7 @@ static int ovl_check_origin(struct ovl_fs *ofs, struct dentry *upperdentry, | |||
370 | if (IS_ERR_OR_NULL(fh)) | 372 | if (IS_ERR_OR_NULL(fh)) |
371 | return PTR_ERR(fh); | 373 | return PTR_ERR(fh); |
372 | 374 | ||
373 | err = ovl_check_origin_fh(ofs, fh, upperdentry, stackp); | 375 | err = ovl_check_origin_fh(ofs, fh, false, upperdentry, stackp); |
374 | kfree(fh); | 376 | kfree(fh); |
375 | 377 | ||
376 | if (err) { | 378 | if (err) { |
@@ -460,7 +462,7 @@ struct dentry *ovl_index_upper(struct ovl_fs *ofs, struct dentry *index) | |||
460 | if (IS_ERR_OR_NULL(fh)) | 462 | if (IS_ERR_OR_NULL(fh)) |
461 | return ERR_CAST(fh); | 463 | return ERR_CAST(fh); |
462 | 464 | ||
463 | upper = ovl_decode_real_fh(fh, ofs->upper_mnt); | 465 | upper = ovl_decode_real_fh(fh, ofs->upper_mnt, true); |
464 | kfree(fh); | 466 | kfree(fh); |
465 | 467 | ||
466 | if (IS_ERR_OR_NULL(upper)) | 468 | if (IS_ERR_OR_NULL(upper)) |
@@ -567,7 +569,7 @@ int ovl_verify_index(struct ovl_fs *ofs, struct dentry *index) | |||
567 | 569 | ||
568 | /* Check if non-dir index is orphan and don't warn before cleaning it */ | 570 | /* Check if non-dir index is orphan and don't warn before cleaning it */ |
569 | if (!d_is_dir(index) && d_inode(index)->i_nlink == 1) { | 571 | if (!d_is_dir(index) && d_inode(index)->i_nlink == 1) { |
570 | err = ovl_check_origin_fh(ofs, fh, index, &stack); | 572 | err = ovl_check_origin_fh(ofs, fh, false, index, &stack); |
571 | if (err) | 573 | if (err) |
572 | goto fail; | 574 | goto fail; |
573 | 575 | ||
diff --git a/fs/overlayfs/overlayfs.h b/fs/overlayfs/overlayfs.h index dd6c10e5a7db..b51613b355c5 100644 --- a/fs/overlayfs/overlayfs.h +++ b/fs/overlayfs/overlayfs.h | |||
@@ -266,8 +266,9 @@ static inline bool ovl_is_impuredir(struct dentry *dentry) | |||
266 | 266 | ||
267 | /* namei.c */ | 267 | /* namei.c */ |
268 | int ovl_check_fh_len(struct ovl_fh *fh, int fh_len); | 268 | int ovl_check_fh_len(struct ovl_fh *fh, int fh_len); |
269 | struct dentry *ovl_decode_real_fh(struct ovl_fh *fh, struct vfsmount *mnt); | 269 | struct dentry *ovl_decode_real_fh(struct ovl_fh *fh, struct vfsmount *mnt, |
270 | int ovl_check_origin_fh(struct ovl_fs *ofs, struct ovl_fh *fh, | 270 | bool connected); |
271 | int ovl_check_origin_fh(struct ovl_fs *ofs, struct ovl_fh *fh, bool connected, | ||
271 | struct dentry *upperdentry, struct ovl_path **stackp); | 272 | struct dentry *upperdentry, struct ovl_path **stackp); |
272 | int ovl_verify_set_fh(struct dentry *dentry, const char *name, | 273 | int ovl_verify_set_fh(struct dentry *dentry, const char *name, |
273 | struct dentry *real, bool is_upper, bool set); | 274 | struct dentry *real, bool is_upper, bool set); |