Skip to content

Commit 162d064

Browse files
committed
ovl: reorder ovl_want_write() after ovl_inode_lock()
Make the locking order of ovl_inode_lock() strictly between the two vfs stacked layers, i.e.: - ovl vfs locks: sb_writers, inode_lock, ... - ovl_inode_lock - upper vfs locks: sb_writers, inode_lock, ... To that effect, move ovl_want_write() into the helpers ovl_nlink_start() and ovl_copy_up_start which currently take the ovl_inode_lock() after ovl_want_write(). Signed-off-by: Amir Goldstein <[email protected]>
1 parent d08d3b3 commit 162d064

File tree

5 files changed

+84
-87
lines changed

5 files changed

+84
-87
lines changed

fs/overlayfs/copy_up.c

Lines changed: 3 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1170,17 +1170,10 @@ static bool ovl_open_need_copy_up(struct dentry *dentry, int flags)
11701170

11711171
int ovl_maybe_copy_up(struct dentry *dentry, int flags)
11721172
{
1173-
int err = 0;
1174-
1175-
if (ovl_open_need_copy_up(dentry, flags)) {
1176-
err = ovl_want_write(dentry);
1177-
if (!err) {
1178-
err = ovl_copy_up_flags(dentry, flags);
1179-
ovl_drop_write(dentry);
1180-
}
1181-
}
1173+
if (!ovl_open_need_copy_up(dentry, flags))
1174+
return 0;
11821175

1183-
return err;
1176+
return ovl_copy_up_flags(dentry, flags);
11841177
}
11851178

11861179
int ovl_copy_up_with_data(struct dentry *dentry)

fs/overlayfs/dir.c

Lines changed: 26 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -559,10 +559,6 @@ static int ovl_create_or_link(struct dentry *dentry, struct inode *inode,
559559
struct cred *override_cred;
560560
struct dentry *parent = dentry->d_parent;
561561

562-
err = ovl_copy_up(parent);
563-
if (err)
564-
return err;
565-
566562
old_cred = ovl_override_creds(dentry->d_sb);
567563

568564
/*
@@ -626,6 +622,10 @@ static int ovl_create_object(struct dentry *dentry, int mode, dev_t rdev,
626622
.link = link,
627623
};
628624

625+
err = ovl_copy_up(dentry->d_parent);
626+
if (err)
627+
return err;
628+
629629
err = ovl_want_write(dentry);
630630
if (err)
631631
goto out;
@@ -700,28 +700,24 @@ static int ovl_link(struct dentry *old, struct inode *newdir,
700700
int err;
701701
struct inode *inode;
702702

703-
err = ovl_want_write(old);
703+
err = ovl_copy_up(old);
704704
if (err)
705705
goto out;
706706

707-
err = ovl_copy_up(old);
707+
err = ovl_copy_up(new->d_parent);
708708
if (err)
709-
goto out_drop_write;
709+
goto out;
710710

711-
err = ovl_copy_up(new->d_parent);
711+
err = ovl_nlink_start(old);
712712
if (err)
713-
goto out_drop_write;
713+
goto out;
714714

715715
if (ovl_is_metacopy_dentry(old)) {
716716
err = ovl_set_link_redirect(old);
717717
if (err)
718-
goto out_drop_write;
718+
goto out_nlink_end;
719719
}
720720

721-
err = ovl_nlink_start(old);
722-
if (err)
723-
goto out_drop_write;
724-
725721
inode = d_inode(old);
726722
ihold(inode);
727723

@@ -731,9 +727,8 @@ static int ovl_link(struct dentry *old, struct inode *newdir,
731727
if (err)
732728
iput(inode);
733729

730+
out_nlink_end:
734731
ovl_nlink_end(old);
735-
out_drop_write:
736-
ovl_drop_write(old);
737732
out:
738733
return err;
739734
}
@@ -891,17 +886,13 @@ static int ovl_do_remove(struct dentry *dentry, bool is_dir)
891886
goto out;
892887
}
893888

894-
err = ovl_want_write(dentry);
895-
if (err)
896-
goto out;
897-
898889
err = ovl_copy_up(dentry->d_parent);
899890
if (err)
900-
goto out_drop_write;
891+
goto out;
901892

902893
err = ovl_nlink_start(dentry);
903894
if (err)
904-
goto out_drop_write;
895+
goto out;
905896

906897
old_cred = ovl_override_creds(dentry->d_sb);
907898
if (!lower_positive)
@@ -926,8 +917,6 @@ static int ovl_do_remove(struct dentry *dentry, bool is_dir)
926917
if (ovl_dentry_upper(dentry))
927918
ovl_copyattr(d_inode(dentry));
928919

929-
out_drop_write:
930-
ovl_drop_write(dentry);
931920
out:
932921
ovl_cache_free(&list);
933922
return err;
@@ -1131,29 +1120,32 @@ static int ovl_rename(struct mnt_idmap *idmap, struct inode *olddir,
11311120
}
11321121
}
11331122

1134-
err = ovl_want_write(old);
1135-
if (err)
1136-
goto out;
1137-
11381123
err = ovl_copy_up(old);
11391124
if (err)
1140-
goto out_drop_write;
1125+
goto out;
11411126

11421127
err = ovl_copy_up(new->d_parent);
11431128
if (err)
1144-
goto out_drop_write;
1129+
goto out;
11451130
if (!overwrite) {
11461131
err = ovl_copy_up(new);
11471132
if (err)
1148-
goto out_drop_write;
1133+
goto out;
11491134
} else if (d_inode(new)) {
11501135
err = ovl_nlink_start(new);
11511136
if (err)
1152-
goto out_drop_write;
1137+
goto out;
11531138

11541139
update_nlink = true;
11551140
}
11561141

1142+
if (!update_nlink) {
1143+
/* ovl_nlink_start() took ovl_want_write() */
1144+
err = ovl_want_write(old);
1145+
if (err)
1146+
goto out;
1147+
}
1148+
11571149
old_cred = ovl_override_creds(old->d_sb);
11581150

11591151
if (!list_empty(&list)) {
@@ -1286,8 +1278,8 @@ static int ovl_rename(struct mnt_idmap *idmap, struct inode *olddir,
12861278
revert_creds(old_cred);
12871279
if (update_nlink)
12881280
ovl_nlink_end(new);
1289-
out_drop_write:
1290-
ovl_drop_write(old);
1281+
else
1282+
ovl_drop_write(old);
12911283
out:
12921284
dput(opaquedir);
12931285
ovl_cache_free(&list);

fs/overlayfs/export.c

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -23,12 +23,7 @@ static int ovl_encode_maybe_copy_up(struct dentry *dentry)
2323
if (ovl_dentry_upper(dentry))
2424
return 0;
2525

26-
err = ovl_want_write(dentry);
27-
if (!err) {
28-
err = ovl_copy_up(dentry);
29-
ovl_drop_write(dentry);
30-
}
31-
26+
err = ovl_copy_up(dentry);
3227
if (err) {
3328
pr_warn_ratelimited("failed to copy up on encode (%pd2, err=%i)\n",
3429
dentry, err);

fs/overlayfs/inode.c

Lines changed: 27 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -32,10 +32,6 @@ int ovl_setattr(struct mnt_idmap *idmap, struct dentry *dentry,
3232
if (err)
3333
return err;
3434

35-
err = ovl_want_write(dentry);
36-
if (err)
37-
goto out;
38-
3935
if (attr->ia_valid & ATTR_SIZE) {
4036
/* Truncate should trigger data copy up as well */
4137
full_copy_up = true;
@@ -54,7 +50,7 @@ int ovl_setattr(struct mnt_idmap *idmap, struct dentry *dentry,
5450
winode = d_inode(upperdentry);
5551
err = get_write_access(winode);
5652
if (err)
57-
goto out_drop_write;
53+
goto out;
5854
}
5955

6056
if (attr->ia_valid & (ATTR_KILL_SUID|ATTR_KILL_SGID))
@@ -78,19 +74,23 @@ int ovl_setattr(struct mnt_idmap *idmap, struct dentry *dentry,
7874
*/
7975
attr->ia_valid &= ~ATTR_OPEN;
8076

77+
err = ovl_want_write(dentry);
78+
if (err)
79+
goto out_put_write;
80+
8181
inode_lock(upperdentry->d_inode);
8282
old_cred = ovl_override_creds(dentry->d_sb);
8383
err = ovl_do_notify_change(ofs, upperdentry, attr);
8484
revert_creds(old_cred);
8585
if (!err)
8686
ovl_copyattr(dentry->d_inode);
8787
inode_unlock(upperdentry->d_inode);
88+
ovl_drop_write(dentry);
8889

90+
out_put_write:
8991
if (winode)
9092
put_write_access(winode);
9193
}
92-
out_drop_write:
93-
ovl_drop_write(dentry);
9494
out:
9595
return err;
9696
}
@@ -361,27 +361,27 @@ int ovl_xattr_set(struct dentry *dentry, struct inode *inode, const char *name,
361361
struct path realpath;
362362
const struct cred *old_cred;
363363

364-
err = ovl_want_write(dentry);
365-
if (err)
366-
goto out;
367-
368364
if (!value && !upperdentry) {
369365
ovl_path_lower(dentry, &realpath);
370366
old_cred = ovl_override_creds(dentry->d_sb);
371367
err = vfs_getxattr(mnt_idmap(realpath.mnt), realdentry, name, NULL, 0);
372368
revert_creds(old_cred);
373369
if (err < 0)
374-
goto out_drop_write;
370+
goto out;
375371
}
376372

377373
if (!upperdentry) {
378374
err = ovl_copy_up(dentry);
379375
if (err)
380-
goto out_drop_write;
376+
goto out;
381377

382378
realdentry = ovl_dentry_upper(dentry);
383379
}
384380

381+
err = ovl_want_write(dentry);
382+
if (err)
383+
goto out;
384+
385385
old_cred = ovl_override_creds(dentry->d_sb);
386386
if (value) {
387387
err = ovl_do_setxattr(ofs, realdentry, name, value, size,
@@ -391,12 +391,10 @@ int ovl_xattr_set(struct dentry *dentry, struct inode *inode, const char *name,
391391
err = ovl_do_removexattr(ofs, realdentry, name);
392392
}
393393
revert_creds(old_cred);
394+
ovl_drop_write(dentry);
394395

395396
/* copy c/mtime */
396397
ovl_copyattr(inode);
397-
398-
out_drop_write:
399-
ovl_drop_write(dentry);
400398
out:
401399
return err;
402400
}
@@ -611,10 +609,6 @@ static int ovl_set_or_remove_acl(struct dentry *dentry, struct inode *inode,
611609
struct dentry *upperdentry = ovl_dentry_upper(dentry);
612610
struct dentry *realdentry = upperdentry ?: ovl_dentry_lower(dentry);
613611

614-
err = ovl_want_write(dentry);
615-
if (err)
616-
return err;
617-
618612
/*
619613
* If ACL is to be removed from a lower file, check if it exists in
620614
* the first place before copying it up.
@@ -630,31 +624,34 @@ static int ovl_set_or_remove_acl(struct dentry *dentry, struct inode *inode,
630624
revert_creds(old_cred);
631625
if (IS_ERR(real_acl)) {
632626
err = PTR_ERR(real_acl);
633-
goto out_drop_write;
627+
goto out;
634628
}
635629
posix_acl_release(real_acl);
636630
}
637631

638632
if (!upperdentry) {
639633
err = ovl_copy_up(dentry);
640634
if (err)
641-
goto out_drop_write;
635+
goto out;
642636

643637
realdentry = ovl_dentry_upper(dentry);
644638
}
645639

640+
err = ovl_want_write(dentry);
641+
if (err)
642+
goto out;
643+
646644
old_cred = ovl_override_creds(dentry->d_sb);
647645
if (acl)
648646
err = ovl_do_set_acl(ofs, realdentry, acl_name, acl);
649647
else
650648
err = ovl_do_remove_acl(ofs, realdentry, acl_name);
651649
revert_creds(old_cred);
650+
ovl_drop_write(dentry);
652651

653652
/* copy c/mtime */
654653
ovl_copyattr(inode);
655-
656-
out_drop_write:
657-
ovl_drop_write(dentry);
654+
out:
658655
return err;
659656
}
660657

@@ -778,14 +775,14 @@ int ovl_fileattr_set(struct mnt_idmap *idmap,
778775
unsigned int flags;
779776
int err;
780777

781-
err = ovl_want_write(dentry);
782-
if (err)
783-
goto out;
784-
785778
err = ovl_copy_up(dentry);
786779
if (!err) {
787780
ovl_path_real(dentry, &upperpath);
788781

782+
err = ovl_want_write(dentry);
783+
if (err)
784+
goto out;
785+
789786
old_cred = ovl_override_creds(inode->i_sb);
790787
/*
791788
* Store immutable/append-only flags in xattr and clear them
@@ -798,6 +795,7 @@ int ovl_fileattr_set(struct mnt_idmap *idmap,
798795
if (!err)
799796
err = ovl_real_fileattr_set(&upperpath, fa);
800797
revert_creds(old_cred);
798+
ovl_drop_write(dentry);
801799

802800
/*
803801
* Merge real inode flags with inode flags read from
@@ -812,7 +810,6 @@ int ovl_fileattr_set(struct mnt_idmap *idmap,
812810
/* Update ctime */
813811
ovl_copyattr(inode);
814812
}
815-
ovl_drop_write(dentry);
816813
out:
817814
return err;
818815
}

0 commit comments

Comments
 (0)