summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/overlayfs/copy_up.c56
-rw-r--r--fs/overlayfs/overlayfs.h18
-rw-r--r--fs/overlayfs/super.c1
-rw-r--r--fs/overlayfs/util.c78
4 files changed, 142 insertions, 11 deletions
diff --git a/fs/overlayfs/copy_up.c b/fs/overlayfs/copy_up.c
index aa3c62a4e462..7e6664d6643d 100644
--- a/fs/overlayfs/copy_up.c
+++ b/fs/overlayfs/copy_up.c
@@ -180,6 +180,16 @@ out_fput:
180 return error; 180 return error;
181} 181}
182 182
183static int ovl_set_size(struct dentry *upperdentry, struct kstat *stat)
184{
185 struct iattr attr = {
186 .ia_valid = ATTR_SIZE,
187 .ia_size = stat->size,
188 };
189
190 return notify_change(upperdentry, &attr, NULL);
191}
192
183static int ovl_set_timestamps(struct dentry *upperdentry, struct kstat *stat) 193static int ovl_set_timestamps(struct dentry *upperdentry, struct kstat *stat)
184{ 194{
185 struct iattr attr = { 195 struct iattr attr = {
@@ -520,8 +530,18 @@ static int ovl_copy_up_inode(struct ovl_copy_up_ctx *c, struct dentry *temp)
520 return err; 530 return err;
521 } 531 }
522 532
533 if (c->metacopy) {
534 err = ovl_check_setxattr(c->dentry, temp, OVL_XATTR_METACOPY,
535 NULL, 0, -EOPNOTSUPP);
536 if (err)
537 return err;
538 }
539
523 inode_lock(temp->d_inode); 540 inode_lock(temp->d_inode);
524 err = ovl_set_attr(temp, &c->stat); 541 if (c->metacopy)
542 err = ovl_set_size(temp, &c->stat);
543 if (!err)
544 err = ovl_set_attr(temp, &c->stat);
525 inode_unlock(temp->d_inode); 545 inode_unlock(temp->d_inode);
526 546
527 return err; 547 return err;
@@ -559,6 +579,8 @@ static int ovl_copy_up_locked(struct ovl_copy_up_ctx *c)
559 if (err) 579 if (err)
560 goto out; 580 goto out;
561 581
582 if (!c->metacopy)
583 ovl_set_upperdata(d_inode(c->dentry));
562 inode = d_inode(c->dentry); 584 inode = d_inode(c->dentry);
563 ovl_inode_update(inode, newdentry); 585 ovl_inode_update(inode, newdentry);
564 if (S_ISDIR(inode->i_mode)) 586 if (S_ISDIR(inode->i_mode))
@@ -681,6 +703,28 @@ static bool ovl_need_meta_copy_up(struct dentry *dentry, umode_t mode,
681 return true; 703 return true;
682} 704}
683 705
706/* Copy up data of an inode which was copied up metadata only in the past. */
707static int ovl_copy_up_meta_inode_data(struct ovl_copy_up_ctx *c)
708{
709 struct path upperpath;
710 int err;
711
712 ovl_path_upper(c->dentry, &upperpath);
713 if (WARN_ON(upperpath.dentry == NULL))
714 return -EIO;
715
716 err = ovl_copy_up_data(&c->lowerpath, &upperpath, c->stat.size);
717 if (err)
718 return err;
719
720 err = vfs_removexattr(upperpath.dentry, OVL_XATTR_METACOPY);
721 if (err)
722 return err;
723
724 ovl_set_upperdata(d_inode(c->dentry));
725 return err;
726}
727
684static int ovl_copy_up_one(struct dentry *parent, struct dentry *dentry, 728static int ovl_copy_up_one(struct dentry *parent, struct dentry *dentry,
685 int flags) 729 int flags)
686{ 730{
@@ -726,7 +770,7 @@ static int ovl_copy_up_one(struct dentry *parent, struct dentry *dentry,
726 return PTR_ERR(ctx.link); 770 return PTR_ERR(ctx.link);
727 } 771 }
728 772
729 err = ovl_copy_up_start(dentry); 773 err = ovl_copy_up_start(dentry, flags);
730 /* err < 0: interrupted, err > 0: raced with another copy-up */ 774 /* err < 0: interrupted, err > 0: raced with another copy-up */
731 if (unlikely(err)) { 775 if (unlikely(err)) {
732 if (err > 0) 776 if (err > 0)
@@ -736,6 +780,8 @@ static int ovl_copy_up_one(struct dentry *parent, struct dentry *dentry,
736 err = ovl_do_copy_up(&ctx); 780 err = ovl_do_copy_up(&ctx);
737 if (!err && parent && !ovl_dentry_has_upper_alias(dentry)) 781 if (!err && parent && !ovl_dentry_has_upper_alias(dentry))
738 err = ovl_link_up(&ctx); 782 err = ovl_link_up(&ctx);
783 if (!err && ovl_dentry_needs_data_copy_up_locked(dentry, flags))
784 err = ovl_copy_up_meta_inode_data(&ctx);
739 ovl_copy_up_end(dentry); 785 ovl_copy_up_end(dentry);
740 } 786 }
741 do_delayed_call(&done); 787 do_delayed_call(&done);
@@ -761,7 +807,7 @@ int ovl_copy_up_flags(struct dentry *dentry, int flags)
761 struct dentry *next; 807 struct dentry *next;
762 struct dentry *parent = NULL; 808 struct dentry *parent = NULL;
763 809
764 if (ovl_already_copied_up(dentry)) 810 if (ovl_already_copied_up(dentry, flags))
765 break; 811 break;
766 812
767 next = dget(dentry); 813 next = dget(dentry);
@@ -789,13 +835,13 @@ int ovl_copy_up_flags(struct dentry *dentry, int flags)
789static bool ovl_open_need_copy_up(struct dentry *dentry, int flags) 835static bool ovl_open_need_copy_up(struct dentry *dentry, int flags)
790{ 836{
791 /* Copy up of disconnected dentry does not set upper alias */ 837 /* Copy up of disconnected dentry does not set upper alias */
792 if (ovl_already_copied_up(dentry)) 838 if (ovl_already_copied_up(dentry, flags))
793 return false; 839 return false;
794 840
795 if (special_file(d_inode(dentry)->i_mode)) 841 if (special_file(d_inode(dentry)->i_mode))
796 return false; 842 return false;
797 843
798 if (!(OPEN_FMODE(flags) & FMODE_WRITE) && !(flags & O_TRUNC)) 844 if (!ovl_open_flags_need_copy_up(flags))
799 return false; 845 return false;
800 846
801 return true; 847 return true;
diff --git a/fs/overlayfs/overlayfs.h b/fs/overlayfs/overlayfs.h
index 206e588df095..16a000694c4e 100644
--- a/fs/overlayfs/overlayfs.h
+++ b/fs/overlayfs/overlayfs.h
@@ -29,6 +29,7 @@ enum ovl_path_type {
29#define OVL_XATTR_IMPURE OVL_XATTR_PREFIX "impure" 29#define OVL_XATTR_IMPURE OVL_XATTR_PREFIX "impure"
30#define OVL_XATTR_NLINK OVL_XATTR_PREFIX "nlink" 30#define OVL_XATTR_NLINK OVL_XATTR_PREFIX "nlink"
31#define OVL_XATTR_UPPER OVL_XATTR_PREFIX "upper" 31#define OVL_XATTR_UPPER OVL_XATTR_PREFIX "upper"
32#define OVL_XATTR_METACOPY OVL_XATTR_PREFIX "metacopy"
32 33
33enum ovl_inode_flag { 34enum ovl_inode_flag {
34 /* Pure upper dir that may contain non pure upper entries */ 35 /* Pure upper dir that may contain non pure upper entries */
@@ -36,6 +37,7 @@ enum ovl_inode_flag {
36 /* Non-merge dir that may contain whiteout entries */ 37 /* Non-merge dir that may contain whiteout entries */
37 OVL_WHITEOUTS, 38 OVL_WHITEOUTS,
38 OVL_INDEX, 39 OVL_INDEX,
40 OVL_UPPERDATA,
39}; 41};
40 42
41enum ovl_entry_flag { 43enum ovl_entry_flag {
@@ -191,6 +193,14 @@ static inline struct dentry *ovl_do_tmpfile(struct dentry *dentry, umode_t mode)
191 return ret; 193 return ret;
192} 194}
193 195
196static inline bool ovl_open_flags_need_copy_up(int flags)
197{
198 if (!flags)
199 return false;
200
201 return ((OPEN_FMODE(flags) & FMODE_WRITE) || (flags & O_TRUNC));
202}
203
194/* util.c */ 204/* util.c */
195int ovl_want_write(struct dentry *dentry); 205int ovl_want_write(struct dentry *dentry);
196void ovl_drop_write(struct dentry *dentry); 206void ovl_drop_write(struct dentry *dentry);
@@ -226,6 +236,10 @@ bool ovl_dentry_is_whiteout(struct dentry *dentry);
226void ovl_dentry_set_opaque(struct dentry *dentry); 236void ovl_dentry_set_opaque(struct dentry *dentry);
227bool ovl_dentry_has_upper_alias(struct dentry *dentry); 237bool ovl_dentry_has_upper_alias(struct dentry *dentry);
228void ovl_dentry_set_upper_alias(struct dentry *dentry); 238void ovl_dentry_set_upper_alias(struct dentry *dentry);
239bool ovl_dentry_needs_data_copy_up(struct dentry *dentry, int flags);
240bool ovl_dentry_needs_data_copy_up_locked(struct dentry *dentry, int flags);
241bool ovl_has_upperdata(struct inode *inode);
242void ovl_set_upperdata(struct inode *inode);
229bool ovl_redirect_dir(struct super_block *sb); 243bool ovl_redirect_dir(struct super_block *sb);
230const char *ovl_dentry_get_redirect(struct dentry *dentry); 244const char *ovl_dentry_get_redirect(struct dentry *dentry);
231void ovl_dentry_set_redirect(struct dentry *dentry, const char *redirect); 245void ovl_dentry_set_redirect(struct dentry *dentry, const char *redirect);
@@ -236,9 +250,9 @@ void ovl_dir_modified(struct dentry *dentry, bool impurity);
236u64 ovl_dentry_version_get(struct dentry *dentry); 250u64 ovl_dentry_version_get(struct dentry *dentry);
237bool ovl_is_whiteout(struct dentry *dentry); 251bool ovl_is_whiteout(struct dentry *dentry);
238struct file *ovl_path_open(struct path *path, int flags); 252struct file *ovl_path_open(struct path *path, int flags);
239int ovl_copy_up_start(struct dentry *dentry); 253int ovl_copy_up_start(struct dentry *dentry, int flags);
240void ovl_copy_up_end(struct dentry *dentry); 254void ovl_copy_up_end(struct dentry *dentry);
241bool ovl_already_copied_up(struct dentry *dentry); 255bool ovl_already_copied_up(struct dentry *dentry, int flags);
242bool ovl_check_origin_xattr(struct dentry *dentry); 256bool ovl_check_origin_xattr(struct dentry *dentry);
243bool ovl_check_dir_xattr(struct dentry *dentry, const char *name); 257bool ovl_check_dir_xattr(struct dentry *dentry, const char *name);
244int ovl_check_setxattr(struct dentry *dentry, struct dentry *upperdentry, 258int ovl_check_setxattr(struct dentry *dentry, struct dentry *upperdentry,
diff --git a/fs/overlayfs/super.c b/fs/overlayfs/super.c
index d4caeee051ee..ab0039161f85 100644
--- a/fs/overlayfs/super.c
+++ b/fs/overlayfs/super.c
@@ -1485,6 +1485,7 @@ static int ovl_fill_super(struct super_block *sb, void *data, int silent)
1485 /* Root is always merge -> can have whiteouts */ 1485 /* Root is always merge -> can have whiteouts */
1486 ovl_set_flag(OVL_WHITEOUTS, d_inode(root_dentry)); 1486 ovl_set_flag(OVL_WHITEOUTS, d_inode(root_dentry));
1487 ovl_dentry_set_flag(OVL_E_CONNECTED, root_dentry); 1487 ovl_dentry_set_flag(OVL_E_CONNECTED, root_dentry);
1488 ovl_set_upperdata(d_inode(root_dentry));
1488 ovl_inode_init(d_inode(root_dentry), upperpath.dentry, 1489 ovl_inode_init(d_inode(root_dentry), upperpath.dentry,
1489 ovl_dentry_lower(root_dentry)); 1490 ovl_dentry_lower(root_dentry));
1490 1491
diff --git a/fs/overlayfs/util.c b/fs/overlayfs/util.c
index 43235294e77b..f8e3c95711b8 100644
--- a/fs/overlayfs/util.c
+++ b/fs/overlayfs/util.c
@@ -279,6 +279,62 @@ void ovl_dentry_set_upper_alias(struct dentry *dentry)
279 ovl_dentry_set_flag(OVL_E_UPPER_ALIAS, dentry); 279 ovl_dentry_set_flag(OVL_E_UPPER_ALIAS, dentry);
280} 280}
281 281
282static bool ovl_should_check_upperdata(struct inode *inode)
283{
284 if (!S_ISREG(inode->i_mode))
285 return false;
286
287 if (!ovl_inode_lower(inode))
288 return false;
289
290 return true;
291}
292
293bool ovl_has_upperdata(struct inode *inode)
294{
295 if (!ovl_should_check_upperdata(inode))
296 return true;
297
298 if (!ovl_test_flag(OVL_UPPERDATA, inode))
299 return false;
300 /*
301 * Pairs with smp_wmb() in ovl_set_upperdata(). Main user of
302 * ovl_has_upperdata() is ovl_copy_up_meta_inode_data(). Make sure
303 * if setting of OVL_UPPERDATA is visible, then effects of writes
304 * before that are visible too.
305 */
306 smp_rmb();
307 return true;
308}
309
310void ovl_set_upperdata(struct inode *inode)
311{
312 /*
313 * Pairs with smp_rmb() in ovl_has_upperdata(). Make sure
314 * if OVL_UPPERDATA flag is visible, then effects of write operations
315 * before it are visible as well.
316 */
317 smp_wmb();
318 ovl_set_flag(OVL_UPPERDATA, inode);
319}
320
321/* Caller should hold ovl_inode->lock */
322bool ovl_dentry_needs_data_copy_up_locked(struct dentry *dentry, int flags)
323{
324 if (!ovl_open_flags_need_copy_up(flags))
325 return false;
326
327 return !ovl_test_flag(OVL_UPPERDATA, d_inode(dentry));
328}
329
330bool ovl_dentry_needs_data_copy_up(struct dentry *dentry, int flags)
331{
332 if (!ovl_open_flags_need_copy_up(flags))
333 return false;
334
335 return !ovl_has_upperdata(d_inode(dentry));
336}
337
282bool ovl_redirect_dir(struct super_block *sb) 338bool ovl_redirect_dir(struct super_block *sb)
283{ 339{
284 struct ovl_fs *ofs = sb->s_fs_info; 340 struct ovl_fs *ofs = sb->s_fs_info;
@@ -377,7 +433,20 @@ struct file *ovl_path_open(struct path *path, int flags)
377 return dentry_open(path, flags | O_NOATIME, current_cred()); 433 return dentry_open(path, flags | O_NOATIME, current_cred());
378} 434}
379 435
380bool ovl_already_copied_up(struct dentry *dentry) 436/* Caller should hold ovl_inode->lock */
437static bool ovl_already_copied_up_locked(struct dentry *dentry, int flags)
438{
439 bool disconnected = dentry->d_flags & DCACHE_DISCONNECTED;
440
441 if (ovl_dentry_upper(dentry) &&
442 (ovl_dentry_has_upper_alias(dentry) || disconnected) &&
443 !ovl_dentry_needs_data_copy_up_locked(dentry, flags))
444 return true;
445
446 return false;
447}
448
449bool ovl_already_copied_up(struct dentry *dentry, int flags)
381{ 450{
382 bool disconnected = dentry->d_flags & DCACHE_DISCONNECTED; 451 bool disconnected = dentry->d_flags & DCACHE_DISCONNECTED;
383 452
@@ -395,19 +464,20 @@ bool ovl_already_copied_up(struct dentry *dentry)
395 * with rename. 464 * with rename.
396 */ 465 */
397 if (ovl_dentry_upper(dentry) && 466 if (ovl_dentry_upper(dentry) &&
398 (ovl_dentry_has_upper_alias(dentry) || disconnected)) 467 (ovl_dentry_has_upper_alias(dentry) || disconnected) &&
468 !ovl_dentry_needs_data_copy_up(dentry, flags))
399 return true; 469 return true;
400 470
401 return false; 471 return false;
402} 472}
403 473
404int ovl_copy_up_start(struct dentry *dentry) 474int ovl_copy_up_start(struct dentry *dentry, int flags)
405{ 475{
406 struct ovl_inode *oi = OVL_I(d_inode(dentry)); 476 struct ovl_inode *oi = OVL_I(d_inode(dentry));
407 int err; 477 int err;
408 478
409 err = mutex_lock_interruptible(&oi->lock); 479 err = mutex_lock_interruptible(&oi->lock);
410 if (!err && ovl_already_copied_up(dentry)) { 480 if (!err && ovl_already_copied_up_locked(dentry, flags)) {
411 err = 1; /* Already copied up */ 481 err = 1; /* Already copied up */
412 mutex_unlock(&oi->lock); 482 mutex_unlock(&oi->lock);
413 } 483 }