diff options
author | Andreas Gruenbacher <agruenba@redhat.com> | 2018-02-28 14:48:53 -0500 |
---|---|---|
committer | Bob Peterson <rpeterso@redhat.com> | 2018-03-08 11:26:20 -0500 |
commit | 83998ccd9bfff881f04ce03f6964f8a83e6c5b54 (patch) | |
tree | 0d7ce75cf2531a013e58d0681daa596c5b36fe32 /fs/gfs2/dir.c | |
parent | 174d1232ebc84fcde8f5889d1171c9c7e74a10a7 (diff) |
gfs2: Dirty source inode during rename
Mark the source inode dirty during a rename instead of just updating the
underlying buffer head. Otherwise, fsync may find the inode clean and
will then skip flushing the journal. A subsequent power failure will
cause the rename to be lost. This happens in command sequences like:
xfs_io -f -c 'pwrite 0 4096' -c 'fsync' foo
mv foo bar
xfs_io -c 'fsync' bar
# power failure
Fixes xfstests generic/322, generic/376.
Signed-off-by: Andreas Gruenbacher <agruenba@redhat.com>
Signed-off-by: Bob Peterson <rpeterso@redhat.com>
Diffstat (limited to 'fs/gfs2/dir.c')
-rw-r--r-- | fs/gfs2/dir.c | 13 |
1 files changed, 2 insertions, 11 deletions
diff --git a/fs/gfs2/dir.c b/fs/gfs2/dir.c index 7c21aea0266b..d9fb0ad6cc30 100644 --- a/fs/gfs2/dir.c +++ b/fs/gfs2/dir.c | |||
@@ -1940,7 +1940,6 @@ int gfs2_dir_mvino(struct gfs2_inode *dip, const struct qstr *filename, | |||
1940 | { | 1940 | { |
1941 | struct buffer_head *bh; | 1941 | struct buffer_head *bh; |
1942 | struct gfs2_dirent *dent; | 1942 | struct gfs2_dirent *dent; |
1943 | int error; | ||
1944 | 1943 | ||
1945 | dent = gfs2_dirent_search(&dip->i_inode, filename, gfs2_dirent_find, &bh); | 1944 | dent = gfs2_dirent_search(&dip->i_inode, filename, gfs2_dirent_find, &bh); |
1946 | if (!dent) { | 1945 | if (!dent) { |
@@ -1953,18 +1952,10 @@ int gfs2_dir_mvino(struct gfs2_inode *dip, const struct qstr *filename, | |||
1953 | gfs2_trans_add_meta(dip->i_gl, bh); | 1952 | gfs2_trans_add_meta(dip->i_gl, bh); |
1954 | gfs2_inum_out(nip, dent); | 1953 | gfs2_inum_out(nip, dent); |
1955 | dent->de_type = cpu_to_be16(new_type); | 1954 | dent->de_type = cpu_to_be16(new_type); |
1956 | 1955 | brelse(bh); | |
1957 | if (dip->i_diskflags & GFS2_DIF_EXHASH) { | ||
1958 | brelse(bh); | ||
1959 | error = gfs2_meta_inode_buffer(dip, &bh); | ||
1960 | if (error) | ||
1961 | return error; | ||
1962 | gfs2_trans_add_meta(dip->i_gl, bh); | ||
1963 | } | ||
1964 | 1956 | ||
1965 | dip->i_inode.i_mtime = dip->i_inode.i_ctime = current_time(&dip->i_inode); | 1957 | dip->i_inode.i_mtime = dip->i_inode.i_ctime = current_time(&dip->i_inode); |
1966 | gfs2_dinode_out(dip, bh->b_data); | 1958 | mark_inode_dirty_sync(&dip->i_inode); |
1967 | brelse(bh); | ||
1968 | return 0; | 1959 | return 0; |
1969 | } | 1960 | } |
1970 | 1961 | ||