diff options
author | Andreas Gruenbacher <agruenba@redhat.com> | 2017-10-04 10:21:19 -0400 |
---|---|---|
committer | Andreas Gruenbacher <agruenba@redhat.com> | 2017-10-31 09:26:56 -0400 |
commit | 6862c44ec5ad0261968c3bc47d23cffb088b6836 (patch) | |
tree | ee4f19ea910c9880dae8018d4c54c5006378df2b | |
parent | cc555b09d8c3817aeebda43a14ab67049a5653f7 (diff) |
gfs2: Fix xattr fsync
Make sure that changing xattrs marks the corresponding inode dirty so
that a subsequent fsync will sync those changes to disk. We set
I_DIRTY_SYNC as well as I_DIRTY_DATASYNC so that both fsync and
fdatasync will sync xattr changes: xattrs can contain information
critical to how the data can be accessed, so we don't want fdatasync
to skip them.
Fixes xfstest generic/066.
Signed-off-by: Andreas Gruenbacher <agruenba@redhat.com>
Reviewed-by: Andrew Price <anprice@redhat.com>
Signed-off-by: Bob Peterson <rpeterso@redhat.com>
-rw-r--r-- | fs/gfs2/xattr.c | 40 |
1 files changed, 8 insertions, 32 deletions
diff --git a/fs/gfs2/xattr.c b/fs/gfs2/xattr.c index ea09e41dbb49..3e96dce21c1c 100644 --- a/fs/gfs2/xattr.c +++ b/fs/gfs2/xattr.c | |||
@@ -231,7 +231,6 @@ static int ea_dealloc_unstuffed(struct gfs2_inode *ip, struct buffer_head *bh, | |||
231 | struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode); | 231 | struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode); |
232 | struct gfs2_rgrpd *rgd; | 232 | struct gfs2_rgrpd *rgd; |
233 | struct gfs2_holder rg_gh; | 233 | struct gfs2_holder rg_gh; |
234 | struct buffer_head *dibh; | ||
235 | __be64 *dataptrs; | 234 | __be64 *dataptrs; |
236 | u64 bn = 0; | 235 | u64 bn = 0; |
237 | u64 bstart = 0; | 236 | u64 bstart = 0; |
@@ -308,13 +307,8 @@ static int ea_dealloc_unstuffed(struct gfs2_inode *ip, struct buffer_head *bh, | |||
308 | ea->ea_num_ptrs = 0; | 307 | ea->ea_num_ptrs = 0; |
309 | } | 308 | } |
310 | 309 | ||
311 | error = gfs2_meta_inode_buffer(ip, &dibh); | 310 | ip->i_inode.i_ctime = current_time(&ip->i_inode); |
312 | if (!error) { | 311 | __mark_inode_dirty(&ip->i_inode, I_DIRTY_SYNC | I_DIRTY_DATASYNC); |
313 | ip->i_inode.i_ctime = current_time(&ip->i_inode); | ||
314 | gfs2_trans_add_meta(ip->i_gl, dibh); | ||
315 | gfs2_dinode_out(ip, dibh->b_data); | ||
316 | brelse(dibh); | ||
317 | } | ||
318 | 312 | ||
319 | gfs2_trans_end(sdp); | 313 | gfs2_trans_end(sdp); |
320 | 314 | ||
@@ -749,7 +743,6 @@ static int ea_alloc_skeleton(struct gfs2_inode *ip, struct gfs2_ea_request *er, | |||
749 | ea_skeleton_call_t skeleton_call, void *private) | 743 | ea_skeleton_call_t skeleton_call, void *private) |
750 | { | 744 | { |
751 | struct gfs2_alloc_parms ap = { .target = blks }; | 745 | struct gfs2_alloc_parms ap = { .target = blks }; |
752 | struct buffer_head *dibh; | ||
753 | int error; | 746 | int error; |
754 | 747 | ||
755 | error = gfs2_rindex_update(GFS2_SB(&ip->i_inode)); | 748 | error = gfs2_rindex_update(GFS2_SB(&ip->i_inode)); |
@@ -774,13 +767,8 @@ static int ea_alloc_skeleton(struct gfs2_inode *ip, struct gfs2_ea_request *er, | |||
774 | if (error) | 767 | if (error) |
775 | goto out_end_trans; | 768 | goto out_end_trans; |
776 | 769 | ||
777 | error = gfs2_meta_inode_buffer(ip, &dibh); | 770 | ip->i_inode.i_ctime = current_time(&ip->i_inode); |
778 | if (!error) { | 771 | __mark_inode_dirty(&ip->i_inode, I_DIRTY_SYNC | I_DIRTY_DATASYNC); |
779 | ip->i_inode.i_ctime = current_time(&ip->i_inode); | ||
780 | gfs2_trans_add_meta(ip->i_gl, dibh); | ||
781 | gfs2_dinode_out(ip, dibh->b_data); | ||
782 | brelse(dibh); | ||
783 | } | ||
784 | 772 | ||
785 | out_end_trans: | 773 | out_end_trans: |
786 | gfs2_trans_end(GFS2_SB(&ip->i_inode)); | 774 | gfs2_trans_end(GFS2_SB(&ip->i_inode)); |
@@ -891,7 +879,6 @@ static int ea_set_simple_noalloc(struct gfs2_inode *ip, struct buffer_head *bh, | |||
891 | struct gfs2_ea_header *ea, struct ea_set *es) | 879 | struct gfs2_ea_header *ea, struct ea_set *es) |
892 | { | 880 | { |
893 | struct gfs2_ea_request *er = es->es_er; | 881 | struct gfs2_ea_request *er = es->es_er; |
894 | struct buffer_head *dibh; | ||
895 | int error; | 882 | int error; |
896 | 883 | ||
897 | error = gfs2_trans_begin(GFS2_SB(&ip->i_inode), RES_DINODE + 2 * RES_EATTR, 0); | 884 | error = gfs2_trans_begin(GFS2_SB(&ip->i_inode), RES_DINODE + 2 * RES_EATTR, 0); |
@@ -908,14 +895,9 @@ static int ea_set_simple_noalloc(struct gfs2_inode *ip, struct buffer_head *bh, | |||
908 | if (es->es_el) | 895 | if (es->es_el) |
909 | ea_set_remove_stuffed(ip, es->es_el); | 896 | ea_set_remove_stuffed(ip, es->es_el); |
910 | 897 | ||
911 | error = gfs2_meta_inode_buffer(ip, &dibh); | ||
912 | if (error) | ||
913 | goto out; | ||
914 | ip->i_inode.i_ctime = current_time(&ip->i_inode); | 898 | ip->i_inode.i_ctime = current_time(&ip->i_inode); |
915 | gfs2_trans_add_meta(ip->i_gl, dibh); | 899 | __mark_inode_dirty(&ip->i_inode, I_DIRTY_SYNC | I_DIRTY_DATASYNC); |
916 | gfs2_dinode_out(ip, dibh->b_data); | 900 | |
917 | brelse(dibh); | ||
918 | out: | ||
919 | gfs2_trans_end(GFS2_SB(&ip->i_inode)); | 901 | gfs2_trans_end(GFS2_SB(&ip->i_inode)); |
920 | return error; | 902 | return error; |
921 | } | 903 | } |
@@ -1111,7 +1093,6 @@ static int ea_remove_stuffed(struct gfs2_inode *ip, struct gfs2_ea_location *el) | |||
1111 | { | 1093 | { |
1112 | struct gfs2_ea_header *ea = el->el_ea; | 1094 | struct gfs2_ea_header *ea = el->el_ea; |
1113 | struct gfs2_ea_header *prev = el->el_prev; | 1095 | struct gfs2_ea_header *prev = el->el_prev; |
1114 | struct buffer_head *dibh; | ||
1115 | int error; | 1096 | int error; |
1116 | 1097 | ||
1117 | error = gfs2_trans_begin(GFS2_SB(&ip->i_inode), RES_DINODE + RES_EATTR, 0); | 1098 | error = gfs2_trans_begin(GFS2_SB(&ip->i_inode), RES_DINODE + RES_EATTR, 0); |
@@ -1132,13 +1113,8 @@ static int ea_remove_stuffed(struct gfs2_inode *ip, struct gfs2_ea_location *el) | |||
1132 | ea->ea_type = GFS2_EATYPE_UNUSED; | 1113 | ea->ea_type = GFS2_EATYPE_UNUSED; |
1133 | } | 1114 | } |
1134 | 1115 | ||
1135 | error = gfs2_meta_inode_buffer(ip, &dibh); | 1116 | ip->i_inode.i_ctime = current_time(&ip->i_inode); |
1136 | if (!error) { | 1117 | __mark_inode_dirty(&ip->i_inode, I_DIRTY_SYNC | I_DIRTY_DATASYNC); |
1137 | ip->i_inode.i_ctime = current_time(&ip->i_inode); | ||
1138 | gfs2_trans_add_meta(ip->i_gl, dibh); | ||
1139 | gfs2_dinode_out(ip, dibh->b_data); | ||
1140 | brelse(dibh); | ||
1141 | } | ||
1142 | 1118 | ||
1143 | gfs2_trans_end(GFS2_SB(&ip->i_inode)); | 1119 | gfs2_trans_end(GFS2_SB(&ip->i_inode)); |
1144 | 1120 | ||