Commit e9bd2b3bafd29bf75522546207f0bba0ec4515c2

Authored by Wendy Cheng
Committed by Steven Whitehouse
1 parent c4f68a130f

[GFS2] fix inode meta data corruption

Fix a nasty inode meta data corruption issue by keeping the buffer head in
icache array. This buffer needs to stay in memory until journal flush occurs
Otherwise, gfs2_meta_inode_buffer could do a disk read before the inode hits
disk. It ends up with meta data corruptions. The buffer will be released as
part of the existing journal flush logic.

Signed-off-by: S. Wendy Cheng <wcheng@redhat.com>
Signed-off-by: Steven Whitehouse <swhiteho@redhat.com>

Showing 1 changed file with 15 additions and 5 deletions Side-by-side Diff

... ... @@ -244,6 +244,11 @@
244 244 return 0;
245 245 }
246 246  
  247 +static void gfs2_inode_bh(struct gfs2_inode *ip, struct buffer_head *bh)
  248 +{
  249 + ip->i_cache[0] = bh;
  250 +}
  251 +
247 252 /**
248 253 * gfs2_inode_refresh - Refresh the incore copy of the dinode
249 254 * @ip: The GFS2 inode
... ... @@ -688,7 +693,7 @@
688 693 static void init_dinode(struct gfs2_inode *dip, struct gfs2_glock *gl,
689 694 const struct gfs2_inum_host *inum, unsigned int mode,
690 695 unsigned int uid, unsigned int gid,
691   - const u64 *generation, dev_t dev)
  696 + const u64 *generation, dev_t dev, struct buffer_head **bhp)
692 697 {
693 698 struct gfs2_sbd *sdp = GFS2_SB(&dip->i_inode);
694 699 struct gfs2_dinode *di;
695 700  
696 701  
... ... @@ -743,13 +748,15 @@
743 748 di->di_mtime_nsec = cpu_to_be32(tv.tv_nsec);
744 749 di->di_ctime_nsec = cpu_to_be32(tv.tv_nsec);
745 750 memset(&di->di_reserved, 0, sizeof(di->di_reserved));
  751 +
  752 + set_buffer_uptodate(dibh);
746 753  
747   - brelse(dibh);
  754 + *bhp = dibh;
748 755 }
749 756  
750 757 static int make_dinode(struct gfs2_inode *dip, struct gfs2_glock *gl,
751 758 unsigned int mode, const struct gfs2_inum_host *inum,
752   - const u64 *generation, dev_t dev)
  759 + const u64 *generation, dev_t dev, struct buffer_head **bhp)
753 760 {
754 761 struct gfs2_sbd *sdp = GFS2_SB(&dip->i_inode);
755 762 unsigned int uid, gid;
... ... @@ -770,7 +777,7 @@
770 777 if (error)
771 778 goto out_quota;
772 779  
773   - init_dinode(dip, gl, inum, mode, uid, gid, generation, dev);
  780 + init_dinode(dip, gl, inum, mode, uid, gid, generation, dev, bhp);
774 781 gfs2_quota_change(dip, +1, uid, gid);
775 782 gfs2_trans_end(sdp);
776 783  
... ... @@ -909,6 +916,7 @@
909 916 struct gfs2_inum_host inum = { .no_addr = 0, .no_formal_ino = 0 };
910 917 int error;
911 918 u64 generation;
  919 + struct buffer_head *bh=NULL;
912 920  
913 921 if (!name->len || name->len > GFS2_FNAMESIZE)
914 922 return ERR_PTR(-ENAMETOOLONG);
... ... @@ -935,7 +943,7 @@
935 943 if (error)
936 944 goto fail_gunlock;
937 945  
938   - error = make_dinode(dip, ghs[1].gh_gl, mode, &inum, &generation, dev);
  946 + error = make_dinode(dip, ghs[1].gh_gl, mode, &inum, &generation, dev, &bh);
939 947 if (error)
940 948 goto fail_gunlock2;
941 949  
... ... @@ -944,6 +952,8 @@
944 952 inum.no_formal_ino);
945 953 if (IS_ERR(inode))
946 954 goto fail_gunlock2;
  955 +
  956 + gfs2_inode_bh(GFS2_I(inode), bh);
947 957  
948 958 error = gfs2_inode_refresh(GFS2_I(inode));
949 959 if (error)