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>
This commit is contained in:
parent
174d1232eb
commit
83998ccd9b
|
@ -1940,7 +1940,6 @@ int gfs2_dir_mvino(struct gfs2_inode *dip, const struct qstr *filename,
|
|||
{
|
||||
struct buffer_head *bh;
|
||||
struct gfs2_dirent *dent;
|
||||
int error;
|
||||
|
||||
dent = gfs2_dirent_search(&dip->i_inode, filename, gfs2_dirent_find, &bh);
|
||||
if (!dent) {
|
||||
|
@ -1953,18 +1952,10 @@ int gfs2_dir_mvino(struct gfs2_inode *dip, const struct qstr *filename,
|
|||
gfs2_trans_add_meta(dip->i_gl, bh);
|
||||
gfs2_inum_out(nip, dent);
|
||||
dent->de_type = cpu_to_be16(new_type);
|
||||
|
||||
if (dip->i_diskflags & GFS2_DIF_EXHASH) {
|
||||
brelse(bh);
|
||||
error = gfs2_meta_inode_buffer(dip, &bh);
|
||||
if (error)
|
||||
return error;
|
||||
gfs2_trans_add_meta(dip->i_gl, bh);
|
||||
}
|
||||
brelse(bh);
|
||||
|
||||
dip->i_inode.i_mtime = dip->i_inode.i_ctime = current_time(&dip->i_inode);
|
||||
gfs2_dinode_out(dip, bh->b_data);
|
||||
brelse(bh);
|
||||
mark_inode_dirty_sync(&dip->i_inode);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -1326,19 +1326,11 @@ static int gfs2_ok_to_move(struct gfs2_inode *this, struct gfs2_inode *to)
|
|||
static int update_moved_ino(struct gfs2_inode *ip, struct gfs2_inode *ndip,
|
||||
int dir_rename)
|
||||
{
|
||||
int error;
|
||||
struct buffer_head *dibh;
|
||||
|
||||
if (dir_rename)
|
||||
return gfs2_dir_mvino(ip, &gfs2_qdotdot, ndip, DT_DIR);
|
||||
|
||||
error = gfs2_meta_inode_buffer(ip, &dibh);
|
||||
if (error)
|
||||
return error;
|
||||
ip->i_inode.i_ctime = current_time(&ip->i_inode);
|
||||
gfs2_trans_add_meta(ip->i_gl, dibh);
|
||||
gfs2_dinode_out(ip, dibh->b_data);
|
||||
brelse(dibh);
|
||||
mark_inode_dirty_sync(&ip->i_inode);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue