From: Andreas Gruenbacher <agrue...@redhat.com>

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 <agrue...@redhat.com>
Signed-off-by: Bob Peterson <rpete...@redhat.com>
---
 fs/gfs2/dir.c   | 13 ++-----------
 fs/gfs2/inode.c | 10 +---------
 2 files changed, 3 insertions(+), 20 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,
 {
        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;
 }
 
diff --git a/fs/gfs2/inode.c b/fs/gfs2/inode.c
index 59e0560180ec..8700eb815638 100644
--- a/fs/gfs2/inode.c
+++ b/fs/gfs2/inode.c
@@ -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;
 }
 
-- 
2.14.3

Reply via email to