Skip to content

Commit 934600d

Browse files
committed
Merge tag 'vfs-6.17-rc1.ovl' of git://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs
Pull overlayfs updates from Christian Brauner: "This contains overlayfs updates for this cycle. The changes for overlayfs in here are primarily focussed on preparing for some proposed changes to directory locking. Overlayfs currently will sometimes lock a directory on the upper filesystem and do a few different things while holding the lock. This is incompatible with the new potential scheme. This series narrows the region of code protected by the directory lock, taking it multiple times when necessary. This theoretically opens up the possibilty of other changes happening on the upper filesytem between the unlock and the lock. To some extent the patches guard against that by checking the dentries still have the expect parent after retaking the lock. In general, concurrent changes to the upper and lower filesystems aren't supported properly anyway" * tag 'vfs-6.17-rc1.ovl' of git://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs: (25 commits) ovl: properly print correct variable ovl: rename ovl_cleanup_unlocked() to ovl_cleanup() ovl: change ovl_create_real() to receive dentry parent ovl: narrow locking in ovl_check_rename_whiteout() ovl: narrow locking in ovl_whiteout() ovl: change ovl_cleanup_and_whiteout() to take rename lock as needed ovl: narrow locking on ovl_remove_and_whiteout() ovl: change ovl_workdir_cleanup() to take dir lock as needed. ovl: narrow locking in ovl_workdir_cleanup_recurse() ovl: narrow locking in ovl_indexdir_cleanup() ovl: narrow locking in ovl_workdir_create() ovl: narrow locking in ovl_cleanup_index() ovl: narrow locking in ovl_cleanup_whiteouts() ovl: narrow locking in ovl_rename() ovl: simplify gotos in ovl_rename() ovl: narrow locking in ovl_create_over_whiteout() ovl: narrow locking in ovl_clear_empty() ovl: narrow locking in ovl_create_upper() ovl: narrow the locked region in ovl_copy_up_workdir() ovl: Call ovl_create_temp() without lock held. ...
2 parents 117eab5 + 672820a commit 934600d

File tree

14 files changed

+302
-225
lines changed

14 files changed

+302
-225
lines changed

fs/backing-file.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ struct file *backing_file_open(const struct path *user_path, int flags,
4141
return f;
4242

4343
path_get(user_path);
44-
*backing_file_user_path(f) = *user_path;
44+
backing_file_set_user_path(f, user_path);
4545
error = vfs_open(real_path, f);
4646
if (error) {
4747
fput(f);
@@ -65,7 +65,7 @@ struct file *backing_tmpfile_open(const struct path *user_path, int flags,
6565
return f;
6666

6767
path_get(user_path);
68-
*backing_file_user_path(f) = *user_path;
68+
backing_file_set_user_path(f, user_path);
6969
error = vfs_tmpfile(real_idmap, real_parentpath, f, mode);
7070
if (error) {
7171
fput(f);

fs/file_table.c

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -52,17 +52,20 @@ struct backing_file {
5252
};
5353
};
5454

55-
static inline struct backing_file *backing_file(struct file *f)
56-
{
57-
return container_of(f, struct backing_file, file);
58-
}
55+
#define backing_file(f) container_of(f, struct backing_file, file)
5956

60-
struct path *backing_file_user_path(struct file *f)
57+
struct path *backing_file_user_path(const struct file *f)
6158
{
6259
return &backing_file(f)->user_path;
6360
}
6461
EXPORT_SYMBOL_GPL(backing_file_user_path);
6562

63+
void backing_file_set_user_path(struct file *f, const struct path *path)
64+
{
65+
backing_file(f)->user_path = *path;
66+
}
67+
EXPORT_SYMBOL_GPL(backing_file_set_user_path);
68+
6669
static inline void file_free(struct file *f)
6770
{
6871
security_file_free(f);

fs/internal.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,7 @@ extern void chroot_fs_refs(const struct path *, const struct path *);
101101
struct file *alloc_empty_file(int flags, const struct cred *cred);
102102
struct file *alloc_empty_file_noaccount(int flags, const struct cred *cred);
103103
struct file *alloc_empty_backing_file(int flags, const struct cred *cred);
104+
void backing_file_set_user_path(struct file *f, const struct path *path);
104105

105106
static inline void file_put_write_access(struct file *file)
106107
{

fs/overlayfs/copy_up.c

Lines changed: 24 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -517,15 +517,12 @@ static int ovl_set_upper_fh(struct ovl_fs *ofs, struct dentry *upper,
517517

518518
/*
519519
* Create and install index entry.
520-
*
521-
* Caller must hold i_mutex on indexdir.
522520
*/
523521
static int ovl_create_index(struct dentry *dentry, const struct ovl_fh *fh,
524522
struct dentry *upper)
525523
{
526524
struct ovl_fs *ofs = OVL_FS(dentry->d_sb);
527525
struct dentry *indexdir = ovl_indexdir(dentry->d_sb);
528-
struct inode *dir = d_inode(indexdir);
529526
struct dentry *index = NULL;
530527
struct dentry *temp = NULL;
531528
struct qstr name = { };
@@ -559,16 +556,20 @@ static int ovl_create_index(struct dentry *dentry, const struct ovl_fh *fh,
559556
if (err)
560557
goto out;
561558

559+
err = ovl_parent_lock(indexdir, temp);
560+
if (err)
561+
goto out;
562562
index = ovl_lookup_upper(ofs, name.name, indexdir, name.len);
563563
if (IS_ERR(index)) {
564564
err = PTR_ERR(index);
565565
} else {
566566
err = ovl_do_rename(ofs, indexdir, temp, indexdir, index, 0);
567567
dput(index);
568568
}
569+
ovl_parent_unlock(indexdir);
569570
out:
570571
if (err)
571-
ovl_cleanup(ofs, dir, temp);
572+
ovl_cleanup(ofs, indexdir, temp);
572573
dput(temp);
573574
free_name:
574575
kfree(name.name);
@@ -762,7 +763,6 @@ static int ovl_copy_up_workdir(struct ovl_copy_up_ctx *c)
762763
{
763764
struct ovl_fs *ofs = OVL_FS(c->dentry->d_sb);
764765
struct inode *inode;
765-
struct inode *wdir = d_inode(c->workdir);
766766
struct path path = { .mnt = ovl_upper_mnt(ofs) };
767767
struct dentry *temp, *upper, *trap;
768768
struct ovl_cu_creds cc;
@@ -779,9 +779,7 @@ static int ovl_copy_up_workdir(struct ovl_copy_up_ctx *c)
779779
return err;
780780

781781
ovl_start_write(c->dentry);
782-
inode_lock(wdir);
783782
temp = ovl_create_temp(ofs, c->workdir, &cattr);
784-
inode_unlock(wdir);
785783
ovl_end_write(c->dentry);
786784
ovl_revert_cu_creds(&cc);
787785

@@ -794,45 +792,47 @@ static int ovl_copy_up_workdir(struct ovl_copy_up_ctx *c)
794792
*/
795793
path.dentry = temp;
796794
err = ovl_copy_up_data(c, &path);
795+
ovl_start_write(c->dentry);
796+
if (err)
797+
goto cleanup_unlocked;
798+
799+
if (S_ISDIR(c->stat.mode) && c->indexed) {
800+
err = ovl_create_index(c->dentry, c->origin_fh, temp);
801+
if (err)
802+
goto cleanup_unlocked;
803+
}
804+
797805
/*
798806
* We cannot hold lock_rename() throughout this helper, because of
799807
* lock ordering with sb_writers, which shouldn't be held when calling
800808
* ovl_copy_up_data(), so lock workdir and destdir and make sure that
801809
* temp wasn't moved before copy up completion or cleanup.
802810
*/
803-
ovl_start_write(c->dentry);
804811
trap = lock_rename(c->workdir, c->destdir);
805812
if (trap || temp->d_parent != c->workdir) {
806813
/* temp or workdir moved underneath us? abort without cleanup */
807814
dput(temp);
808815
err = -EIO;
809-
if (IS_ERR(trap))
810-
goto out;
811-
goto unlock;
812-
} else if (err) {
813-
goto cleanup;
816+
if (!IS_ERR(trap))
817+
unlock_rename(c->workdir, c->destdir);
818+
goto out;
814819
}
815820

816821
err = ovl_copy_up_metadata(c, temp);
817822
if (err)
818823
goto cleanup;
819824

820-
if (S_ISDIR(c->stat.mode) && c->indexed) {
821-
err = ovl_create_index(c->dentry, c->origin_fh, temp);
822-
if (err)
823-
goto cleanup;
824-
}
825-
826825
upper = ovl_lookup_upper(ofs, c->destname.name, c->destdir,
827826
c->destname.len);
828827
err = PTR_ERR(upper);
829828
if (IS_ERR(upper))
830829
goto cleanup;
831830

832831
err = ovl_do_rename(ofs, c->workdir, temp, c->destdir, upper, 0);
832+
unlock_rename(c->workdir, c->destdir);
833833
dput(upper);
834834
if (err)
835-
goto cleanup;
835+
goto cleanup_unlocked;
836836

837837
inode = d_inode(c->dentry);
838838
if (c->metacopy_digest)
@@ -846,17 +846,17 @@ static int ovl_copy_up_workdir(struct ovl_copy_up_ctx *c)
846846
ovl_inode_update(inode, temp);
847847
if (S_ISDIR(inode->i_mode))
848848
ovl_set_flag(OVL_WHITEOUTS, inode);
849-
unlock:
850-
unlock_rename(c->workdir, c->destdir);
851849
out:
852850
ovl_end_write(c->dentry);
853851

854852
return err;
855853

856854
cleanup:
857-
ovl_cleanup(ofs, wdir, temp);
855+
unlock_rename(c->workdir, c->destdir);
856+
cleanup_unlocked:
857+
ovl_cleanup(ofs, c->workdir, temp);
858858
dput(temp);
859-
goto unlock;
859+
goto out;
860860
}
861861

862862
/* Copyup using O_TMPFILE which does not require cross dir locking */

0 commit comments

Comments
 (0)