Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 83998ccd authored by Andreas Gruenbacher's avatar Andreas Gruenbacher Committed by Bob Peterson
Browse files

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: default avatarAndreas Gruenbacher <agruenba@redhat.com>
Signed-off-by: default avatarBob Peterson <rpeterso@redhat.com>
parent 174d1232
Loading
Loading
Loading
Loading
+2 −11
Original line number Original line Diff line number Diff line
@@ -1940,7 +1940,6 @@ int gfs2_dir_mvino(struct gfs2_inode *dip, const struct qstr *filename,
{
{
	struct buffer_head *bh;
	struct buffer_head *bh;
	struct gfs2_dirent *dent;
	struct gfs2_dirent *dent;
	int error;


	dent = gfs2_dirent_search(&dip->i_inode, filename, gfs2_dirent_find, &bh);
	dent = gfs2_dirent_search(&dip->i_inode, filename, gfs2_dirent_find, &bh);
	if (!dent) {
	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_trans_add_meta(dip->i_gl, bh);
	gfs2_inum_out(nip, dent);
	gfs2_inum_out(nip, dent);
	dent->de_type = cpu_to_be16(new_type);
	dent->de_type = cpu_to_be16(new_type);

	if (dip->i_diskflags & GFS2_DIF_EXHASH) {
	brelse(bh);
	brelse(bh);
		error = gfs2_meta_inode_buffer(dip, &bh);
		if (error)
			return error;
		gfs2_trans_add_meta(dip->i_gl, bh);
	}


	dip->i_inode.i_mtime = dip->i_inode.i_ctime = current_time(&dip->i_inode);
	dip->i_inode.i_mtime = dip->i_inode.i_ctime = current_time(&dip->i_inode);
	gfs2_dinode_out(dip, bh->b_data);
	mark_inode_dirty_sync(&dip->i_inode);
	brelse(bh);
	return 0;
	return 0;
}
}


+1 −9
Original line number Original line Diff line number Diff line
@@ -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,
static int update_moved_ino(struct gfs2_inode *ip, struct gfs2_inode *ndip,
			    int dir_rename)
			    int dir_rename)
{
{
	int error;
	struct buffer_head *dibh;

	if (dir_rename)
	if (dir_rename)
		return gfs2_dir_mvino(ip, &gfs2_qdotdot, ndip, DT_DIR);
		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);
	ip->i_inode.i_ctime = current_time(&ip->i_inode);
	gfs2_trans_add_meta(ip->i_gl, dibh);
	mark_inode_dirty_sync(&ip->i_inode);
	gfs2_dinode_out(ip, dibh->b_data);
	brelse(dibh);
	return 0;
	return 0;
}
}