aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVivek Goyal <vgoyal@redhat.com>2018-05-11 11:49:28 -0400
committerMiklos Szeredi <mszeredi@redhat.com>2018-07-20 03:56:08 -0400
commit2002df85367ca69961d39020f56d3d727897be01 (patch)
treedac68a1f359f9da75b69af772c217e323685fa26
parent44d5bf109a73f4162d97ab714770fdf76a8dc685 (diff)
ovl: Add helper ovl_already_copied_up()
There are couple of places where we need to know if file is already copied up (in lockless manner). Right now its open coded and there are only two conditions to check. Soon this patch series will introduce another condition to check and Amir wants to introduce one more. So introduce a helper instead to check this so that code is easier to read. Signed-off-by: Vivek Goyal <vgoyal@redhat.com> Reviewed-by: Amir Goldstein <amir73il@gmail.com> Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
-rw-r--r--fs/overlayfs/copy_up.c20
-rw-r--r--fs/overlayfs/overlayfs.h1
-rw-r--r--fs/overlayfs/util.c26
3 files changed, 28 insertions, 19 deletions
diff --git a/fs/overlayfs/copy_up.c b/fs/overlayfs/copy_up.c
index d23467976725..aa3c62a4e462 100644
--- a/fs/overlayfs/copy_up.c
+++ b/fs/overlayfs/copy_up.c
@@ -761,21 +761,7 @@ int ovl_copy_up_flags(struct dentry *dentry, int flags)
761 struct dentry *next; 761 struct dentry *next;
762 struct dentry *parent = NULL; 762 struct dentry *parent = NULL;
763 763
764 /* 764 if (ovl_already_copied_up(dentry))
765 * Check if copy-up has happened as well as for upper alias (in
766 * case of hard links) is there.
767 *
768 * Both checks are lockless:
769 * - false negatives: will recheck under oi->lock
770 * - false positives:
771 * + ovl_dentry_upper() uses memory barriers to ensure the
772 * upper dentry is up-to-date
773 * + ovl_dentry_has_upper_alias() relies on locking of
774 * upper parent i_rwsem to prevent reordering copy-up
775 * with rename.
776 */
777 if (ovl_dentry_upper(dentry) &&
778 (ovl_dentry_has_upper_alias(dentry) || disconnected))
779 break; 765 break;
780 766
781 next = dget(dentry); 767 next = dget(dentry);
@@ -803,9 +789,7 @@ int ovl_copy_up_flags(struct dentry *dentry, int flags)
803static bool ovl_open_need_copy_up(struct dentry *dentry, int flags) 789static bool ovl_open_need_copy_up(struct dentry *dentry, int flags)
804{ 790{
805 /* Copy up of disconnected dentry does not set upper alias */ 791 /* Copy up of disconnected dentry does not set upper alias */
806 if (ovl_dentry_upper(dentry) && 792 if (ovl_already_copied_up(dentry))
807 (ovl_dentry_has_upper_alias(dentry) ||
808 (dentry->d_flags & DCACHE_DISCONNECTED)))
809 return false; 793 return false;
810 794
811 if (special_file(d_inode(dentry)->i_mode)) 795 if (special_file(d_inode(dentry)->i_mode))
diff --git a/fs/overlayfs/overlayfs.h b/fs/overlayfs/overlayfs.h
index c0318b5a50f0..206e588df095 100644
--- a/fs/overlayfs/overlayfs.h
+++ b/fs/overlayfs/overlayfs.h
@@ -238,6 +238,7 @@ bool ovl_is_whiteout(struct dentry *dentry);
238struct file *ovl_path_open(struct path *path, int flags); 238struct file *ovl_path_open(struct path *path, int flags);
239int ovl_copy_up_start(struct dentry *dentry); 239int ovl_copy_up_start(struct dentry *dentry);
240void ovl_copy_up_end(struct dentry *dentry); 240void ovl_copy_up_end(struct dentry *dentry);
241bool ovl_already_copied_up(struct dentry *dentry);
241bool ovl_check_origin_xattr(struct dentry *dentry); 242bool ovl_check_origin_xattr(struct dentry *dentry);
242bool ovl_check_dir_xattr(struct dentry *dentry, const char *name); 243bool ovl_check_dir_xattr(struct dentry *dentry, const char *name);
243int ovl_check_setxattr(struct dentry *dentry, struct dentry *upperdentry, 244int ovl_check_setxattr(struct dentry *dentry, struct dentry *upperdentry,
diff --git a/fs/overlayfs/util.c b/fs/overlayfs/util.c
index 25d202b47326..43235294e77b 100644
--- a/fs/overlayfs/util.c
+++ b/fs/overlayfs/util.c
@@ -377,13 +377,37 @@ struct file *ovl_path_open(struct path *path, int flags)
377 return dentry_open(path, flags | O_NOATIME, current_cred()); 377 return dentry_open(path, flags | O_NOATIME, current_cred());
378} 378}
379 379
380bool ovl_already_copied_up(struct dentry *dentry)
381{
382 bool disconnected = dentry->d_flags & DCACHE_DISCONNECTED;
383
384 /*
385 * Check if copy-up has happened as well as for upper alias (in
386 * case of hard links) is there.
387 *
388 * Both checks are lockless:
389 * - false negatives: will recheck under oi->lock
390 * - false positives:
391 * + ovl_dentry_upper() uses memory barriers to ensure the
392 * upper dentry is up-to-date
393 * + ovl_dentry_has_upper_alias() relies on locking of
394 * upper parent i_rwsem to prevent reordering copy-up
395 * with rename.
396 */
397 if (ovl_dentry_upper(dentry) &&
398 (ovl_dentry_has_upper_alias(dentry) || disconnected))
399 return true;
400
401 return false;
402}
403
380int ovl_copy_up_start(struct dentry *dentry) 404int ovl_copy_up_start(struct dentry *dentry)
381{ 405{
382 struct ovl_inode *oi = OVL_I(d_inode(dentry)); 406 struct ovl_inode *oi = OVL_I(d_inode(dentry));
383 int err; 407 int err;
384 408
385 err = mutex_lock_interruptible(&oi->lock); 409 err = mutex_lock_interruptible(&oi->lock);
386 if (!err && ovl_dentry_has_upper_alias(dentry)) { 410 if (!err && ovl_already_copied_up(dentry)) {
387 err = 1; /* Already copied up */ 411 err = 1; /* Already copied up */
388 mutex_unlock(&oi->lock); 412 mutex_unlock(&oi->lock);
389 } 413 }