diff options
author | Steven Whitehouse <swhiteho@redhat.com> | 2011-08-15 09:20:36 -0400 |
---|---|---|
committer | Steven Whitehouse <swhiteho@redhat.com> | 2011-10-21 07:39:26 -0400 |
commit | ab9bbda0204dfd0e5342562d9979d1241b14ea5f (patch) | |
tree | 621e623d99fbef1432da17b6390c92d7f13224a4 | |
parent | f18185291d605ea9e442e00e2cf6c917a84d9837 (diff) |
GFS2: Use ->dirty_inode()
The aim of this patch is to use the newly enhanced ->dirty_inode()
super block operation to deal with atime updates, rather than
piggy backing that code into ->write_inode() as is currently
done.
The net result is a simplification of the code in various places
and a reduction of the number of gfs2_dinode_out() calls since
this is now implied by ->dirty_inode().
Some of the mark_inode_dirty() calls have been moved under glocks
in order to take advantage of then being able to avoid locking in
->dirty_inode() when we already have suitable locks.
One consequence is that generic_write_end() now correctly deals
with file size updates, so that we do not need a separate check
for that afterwards. This also, indirectly, means that fdatasync
should work correctly on GFS2 - the current code always syncs the
metadata whether it needs to or not.
Has survived testing with postmark (with and without atime) and
also fsx.
Signed-off-by: Steven Whitehouse <swhiteho@redhat.com>
-rw-r--r-- | fs/gfs2/acl.c | 5 | ||||
-rw-r--r-- | fs/gfs2/aops.c | 6 | ||||
-rw-r--r-- | fs/gfs2/dir.c | 10 | ||||
-rw-r--r-- | fs/gfs2/file.c | 1 | ||||
-rw-r--r-- | fs/gfs2/inode.c | 43 | ||||
-rw-r--r-- | fs/gfs2/inode.h | 2 | ||||
-rw-r--r-- | fs/gfs2/quota.c | 13 | ||||
-rw-r--r-- | fs/gfs2/super.c | 97 | ||||
-rw-r--r-- | fs/gfs2/xattr.c | 5 |
9 files changed, 85 insertions, 97 deletions
diff --git a/fs/gfs2/acl.c b/fs/gfs2/acl.c index 34501b64bc47..65978d7885c8 100644 --- a/fs/gfs2/acl.c +++ b/fs/gfs2/acl.c | |||
@@ -82,7 +82,7 @@ static int gfs2_set_mode(struct inode *inode, umode_t mode) | |||
82 | iattr.ia_valid = ATTR_MODE; | 82 | iattr.ia_valid = ATTR_MODE; |
83 | iattr.ia_mode = mode; | 83 | iattr.ia_mode = mode; |
84 | 84 | ||
85 | error = gfs2_setattr_simple(GFS2_I(inode), &iattr); | 85 | error = gfs2_setattr_simple(inode, &iattr); |
86 | } | 86 | } |
87 | 87 | ||
88 | return error; | 88 | return error; |
@@ -160,6 +160,7 @@ out: | |||
160 | 160 | ||
161 | int gfs2_acl_chmod(struct gfs2_inode *ip, struct iattr *attr) | 161 | int gfs2_acl_chmod(struct gfs2_inode *ip, struct iattr *attr) |
162 | { | 162 | { |
163 | struct inode *inode = &ip->i_inode; | ||
163 | struct posix_acl *acl; | 164 | struct posix_acl *acl; |
164 | char *data; | 165 | char *data; |
165 | unsigned int len; | 166 | unsigned int len; |
@@ -169,7 +170,7 @@ int gfs2_acl_chmod(struct gfs2_inode *ip, struct iattr *attr) | |||
169 | if (IS_ERR(acl)) | 170 | if (IS_ERR(acl)) |
170 | return PTR_ERR(acl); | 171 | return PTR_ERR(acl); |
171 | if (!acl) | 172 | if (!acl) |
172 | return gfs2_setattr_simple(ip, attr); | 173 | return gfs2_setattr_simple(inode, attr); |
173 | 174 | ||
174 | error = posix_acl_chmod(&acl, GFP_NOFS, attr->ia_mode); | 175 | error = posix_acl_chmod(&acl, GFP_NOFS, attr->ia_mode); |
175 | if (error) | 176 | if (error) |
diff --git a/fs/gfs2/aops.c b/fs/gfs2/aops.c index f9fbbe96c222..212fe74927ba 100644 --- a/fs/gfs2/aops.c +++ b/fs/gfs2/aops.c | |||
@@ -787,7 +787,6 @@ static int gfs2_stuffed_write_end(struct inode *inode, struct buffer_head *dibh, | |||
787 | u64 to = pos + copied; | 787 | u64 to = pos + copied; |
788 | void *kaddr; | 788 | void *kaddr; |
789 | unsigned char *buf = dibh->b_data + sizeof(struct gfs2_dinode); | 789 | unsigned char *buf = dibh->b_data + sizeof(struct gfs2_dinode); |
790 | struct gfs2_dinode *di = (struct gfs2_dinode *)dibh->b_data; | ||
791 | 790 | ||
792 | BUG_ON((pos + len) > (dibh->b_size - sizeof(struct gfs2_dinode))); | 791 | BUG_ON((pos + len) > (dibh->b_size - sizeof(struct gfs2_dinode))); |
793 | kaddr = kmap_atomic(page, KM_USER0); | 792 | kaddr = kmap_atomic(page, KM_USER0); |
@@ -804,7 +803,6 @@ static int gfs2_stuffed_write_end(struct inode *inode, struct buffer_head *dibh, | |||
804 | if (copied) { | 803 | if (copied) { |
805 | if (inode->i_size < to) | 804 | if (inode->i_size < to) |
806 | i_size_write(inode, to); | 805 | i_size_write(inode, to); |
807 | gfs2_dinode_out(ip, di); | ||
808 | mark_inode_dirty(inode); | 806 | mark_inode_dirty(inode); |
809 | } | 807 | } |
810 | 808 | ||
@@ -873,10 +871,6 @@ static int gfs2_write_end(struct file *file, struct address_space *mapping, | |||
873 | gfs2_page_add_databufs(ip, page, from, to); | 871 | gfs2_page_add_databufs(ip, page, from, to); |
874 | 872 | ||
875 | ret = generic_write_end(file, mapping, pos, len, copied, page, fsdata); | 873 | ret = generic_write_end(file, mapping, pos, len, copied, page, fsdata); |
876 | if (ret > 0) { | ||
877 | gfs2_dinode_out(ip, dibh->b_data); | ||
878 | mark_inode_dirty(inode); | ||
879 | } | ||
880 | 874 | ||
881 | if (inode == sdp->sd_rindex) { | 875 | if (inode == sdp->sd_rindex) { |
882 | adjust_fs_space(inode); | 876 | adjust_fs_space(inode); |
diff --git a/fs/gfs2/dir.c b/fs/gfs2/dir.c index 2045d70753f1..898e62ed5b85 100644 --- a/fs/gfs2/dir.c +++ b/fs/gfs2/dir.c | |||
@@ -1681,7 +1681,6 @@ int gfs2_dir_del(struct gfs2_inode *dip, const struct dentry *dentry) | |||
1681 | const struct qstr *name = &dentry->d_name; | 1681 | const struct qstr *name = &dentry->d_name; |
1682 | struct gfs2_dirent *dent, *prev = NULL; | 1682 | struct gfs2_dirent *dent, *prev = NULL; |
1683 | struct buffer_head *bh; | 1683 | struct buffer_head *bh; |
1684 | int error; | ||
1685 | 1684 | ||
1686 | /* Returns _either_ the entry (if its first in block) or the | 1685 | /* Returns _either_ the entry (if its first in block) or the |
1687 | previous entry otherwise */ | 1686 | previous entry otherwise */ |
@@ -1710,22 +1709,15 @@ int gfs2_dir_del(struct gfs2_inode *dip, const struct dentry *dentry) | |||
1710 | } | 1709 | } |
1711 | brelse(bh); | 1710 | brelse(bh); |
1712 | 1711 | ||
1713 | error = gfs2_meta_inode_buffer(dip, &bh); | ||
1714 | if (error) | ||
1715 | return error; | ||
1716 | |||
1717 | if (!dip->i_entries) | 1712 | if (!dip->i_entries) |
1718 | gfs2_consist_inode(dip); | 1713 | gfs2_consist_inode(dip); |
1719 | gfs2_trans_add_bh(dip->i_gl, bh, 1); | ||
1720 | dip->i_entries--; | 1714 | dip->i_entries--; |
1721 | dip->i_inode.i_mtime = dip->i_inode.i_ctime = CURRENT_TIME; | 1715 | dip->i_inode.i_mtime = dip->i_inode.i_ctime = CURRENT_TIME; |
1722 | if (S_ISDIR(dentry->d_inode->i_mode)) | 1716 | if (S_ISDIR(dentry->d_inode->i_mode)) |
1723 | drop_nlink(&dip->i_inode); | 1717 | drop_nlink(&dip->i_inode); |
1724 | gfs2_dinode_out(dip, bh->b_data); | ||
1725 | brelse(bh); | ||
1726 | mark_inode_dirty(&dip->i_inode); | 1718 | mark_inode_dirty(&dip->i_inode); |
1727 | 1719 | ||
1728 | return error; | 1720 | return 0; |
1729 | } | 1721 | } |
1730 | 1722 | ||
1731 | /** | 1723 | /** |
diff --git a/fs/gfs2/file.c b/fs/gfs2/file.c index 9d12286d8111..4416a1cfa1fe 100644 --- a/fs/gfs2/file.c +++ b/fs/gfs2/file.c | |||
@@ -802,7 +802,6 @@ static int fallocate_chunk(struct inode *inode, loff_t offset, loff_t len, | |||
802 | from = 0; | 802 | from = 0; |
803 | } | 803 | } |
804 | 804 | ||
805 | gfs2_dinode_out(ip, dibh->b_data); | ||
806 | mark_inode_dirty(inode); | 805 | mark_inode_dirty(inode); |
807 | 806 | ||
808 | brelse(dibh); | 807 | brelse(dibh); |
diff --git a/fs/gfs2/inode.c b/fs/gfs2/inode.c index 044efe273b97..a0b53d3bd8fa 100644 --- a/fs/gfs2/inode.c +++ b/fs/gfs2/inode.c | |||
@@ -729,8 +729,8 @@ static int gfs2_create_inode(struct inode *dir, struct dentry *dentry, | |||
729 | gfs2_inplace_release(dip); | 729 | gfs2_inplace_release(dip); |
730 | gfs2_quota_unlock(dip); | 730 | gfs2_quota_unlock(dip); |
731 | gfs2_alloc_put(dip); | 731 | gfs2_alloc_put(dip); |
732 | gfs2_glock_dq_uninit_m(2, ghs); | ||
733 | mark_inode_dirty(inode); | 732 | mark_inode_dirty(inode); |
733 | gfs2_glock_dq_uninit_m(2, ghs); | ||
734 | d_instantiate(dentry, inode); | 734 | d_instantiate(dentry, inode); |
735 | return 0; | 735 | return 0; |
736 | 736 | ||
@@ -926,8 +926,9 @@ static int gfs2_link(struct dentry *old_dentry, struct inode *dir, | |||
926 | gfs2_trans_add_bh(ip->i_gl, dibh, 1); | 926 | gfs2_trans_add_bh(ip->i_gl, dibh, 1); |
927 | inc_nlink(&ip->i_inode); | 927 | inc_nlink(&ip->i_inode); |
928 | ip->i_inode.i_ctime = CURRENT_TIME; | 928 | ip->i_inode.i_ctime = CURRENT_TIME; |
929 | gfs2_dinode_out(ip, dibh->b_data); | 929 | ihold(inode); |
930 | mark_inode_dirty(&ip->i_inode); | 930 | d_instantiate(dentry, inode); |
931 | mark_inode_dirty(inode); | ||
931 | 932 | ||
932 | out_brelse: | 933 | out_brelse: |
933 | brelse(dibh); | 934 | brelse(dibh); |
@@ -949,11 +950,6 @@ out_child: | |||
949 | out_parent: | 950 | out_parent: |
950 | gfs2_holder_uninit(ghs); | 951 | gfs2_holder_uninit(ghs); |
951 | gfs2_holder_uninit(ghs + 1); | 952 | gfs2_holder_uninit(ghs + 1); |
952 | if (!error) { | ||
953 | ihold(inode); | ||
954 | d_instantiate(dentry, inode); | ||
955 | mark_inode_dirty(inode); | ||
956 | } | ||
957 | return error; | 953 | return error; |
958 | } | 954 | } |
959 | 955 | ||
@@ -1026,8 +1022,6 @@ static int gfs2_unlink_inode(struct gfs2_inode *dip, | |||
1026 | clear_nlink(inode); | 1022 | clear_nlink(inode); |
1027 | else | 1023 | else |
1028 | drop_nlink(inode); | 1024 | drop_nlink(inode); |
1029 | gfs2_trans_add_bh(ip->i_gl, bh, 1); | ||
1030 | gfs2_dinode_out(ip, bh->b_data); | ||
1031 | mark_inode_dirty(inode); | 1025 | mark_inode_dirty(inode); |
1032 | if (inode->i_nlink == 0) | 1026 | if (inode->i_nlink == 0) |
1033 | gfs2_unlink_di(inode); | 1027 | gfs2_unlink_di(inode); |
@@ -1565,21 +1559,10 @@ int gfs2_permission(struct inode *inode, int mask) | |||
1565 | return error; | 1559 | return error; |
1566 | } | 1560 | } |
1567 | 1561 | ||
1568 | static int __gfs2_setattr_simple(struct gfs2_inode *ip, struct iattr *attr) | 1562 | static int __gfs2_setattr_simple(struct inode *inode, struct iattr *attr) |
1569 | { | 1563 | { |
1570 | struct inode *inode = &ip->i_inode; | ||
1571 | struct buffer_head *dibh; | ||
1572 | int error; | ||
1573 | |||
1574 | error = gfs2_meta_inode_buffer(ip, &dibh); | ||
1575 | if (error) | ||
1576 | return error; | ||
1577 | |||
1578 | setattr_copy(inode, attr); | 1564 | setattr_copy(inode, attr); |
1579 | mark_inode_dirty(inode); | 1565 | mark_inode_dirty(inode); |
1580 | gfs2_trans_add_bh(ip->i_gl, dibh, 1); | ||
1581 | gfs2_dinode_out(ip, dibh->b_data); | ||
1582 | brelse(dibh); | ||
1583 | return 0; | 1566 | return 0; |
1584 | } | 1567 | } |
1585 | 1568 | ||
@@ -1591,19 +1574,19 @@ static int __gfs2_setattr_simple(struct gfs2_inode *ip, struct iattr *attr) | |||
1591 | * Returns: errno | 1574 | * Returns: errno |
1592 | */ | 1575 | */ |
1593 | 1576 | ||
1594 | int gfs2_setattr_simple(struct gfs2_inode *ip, struct iattr *attr) | 1577 | int gfs2_setattr_simple(struct inode *inode, struct iattr *attr) |
1595 | { | 1578 | { |
1596 | int error; | 1579 | int error; |
1597 | 1580 | ||
1598 | if (current->journal_info) | 1581 | if (current->journal_info) |
1599 | return __gfs2_setattr_simple(ip, attr); | 1582 | return __gfs2_setattr_simple(inode, attr); |
1600 | 1583 | ||
1601 | error = gfs2_trans_begin(GFS2_SB(&ip->i_inode), RES_DINODE, 0); | 1584 | error = gfs2_trans_begin(GFS2_SB(inode), RES_DINODE, 0); |
1602 | if (error) | 1585 | if (error) |
1603 | return error; | 1586 | return error; |
1604 | 1587 | ||
1605 | error = __gfs2_setattr_simple(ip, attr); | 1588 | error = __gfs2_setattr_simple(inode, attr); |
1606 | gfs2_trans_end(GFS2_SB(&ip->i_inode)); | 1589 | gfs2_trans_end(GFS2_SB(inode)); |
1607 | return error; | 1590 | return error; |
1608 | } | 1591 | } |
1609 | 1592 | ||
@@ -1641,7 +1624,7 @@ static int setattr_chown(struct inode *inode, struct iattr *attr) | |||
1641 | if (error) | 1624 | if (error) |
1642 | goto out_gunlock_q; | 1625 | goto out_gunlock_q; |
1643 | 1626 | ||
1644 | error = gfs2_setattr_simple(ip, attr); | 1627 | error = gfs2_setattr_simple(inode, attr); |
1645 | if (error) | 1628 | if (error) |
1646 | goto out_end_trans; | 1629 | goto out_end_trans; |
1647 | 1630 | ||
@@ -1697,12 +1680,12 @@ static int gfs2_setattr(struct dentry *dentry, struct iattr *attr) | |||
1697 | else if ((attr->ia_valid & ATTR_MODE) && IS_POSIXACL(inode)) | 1680 | else if ((attr->ia_valid & ATTR_MODE) && IS_POSIXACL(inode)) |
1698 | error = gfs2_acl_chmod(ip, attr); | 1681 | error = gfs2_acl_chmod(ip, attr); |
1699 | else | 1682 | else |
1700 | error = gfs2_setattr_simple(ip, attr); | 1683 | error = gfs2_setattr_simple(inode, attr); |
1701 | 1684 | ||
1702 | out: | 1685 | out: |
1703 | gfs2_glock_dq_uninit(&i_gh); | ||
1704 | if (!error) | 1686 | if (!error) |
1705 | mark_inode_dirty(inode); | 1687 | mark_inode_dirty(inode); |
1688 | gfs2_glock_dq_uninit(&i_gh); | ||
1706 | return error; | 1689 | return error; |
1707 | } | 1690 | } |
1708 | 1691 | ||
diff --git a/fs/gfs2/inode.h b/fs/gfs2/inode.h index 8d90e0c07672..276e7b52b658 100644 --- a/fs/gfs2/inode.h +++ b/fs/gfs2/inode.h | |||
@@ -109,7 +109,7 @@ extern int gfs2_inode_refresh(struct gfs2_inode *ip); | |||
109 | extern struct inode *gfs2_lookupi(struct inode *dir, const struct qstr *name, | 109 | extern struct inode *gfs2_lookupi(struct inode *dir, const struct qstr *name, |
110 | int is_root); | 110 | int is_root); |
111 | extern int gfs2_permission(struct inode *inode, int mask); | 111 | extern int gfs2_permission(struct inode *inode, int mask); |
112 | extern int gfs2_setattr_simple(struct gfs2_inode *ip, struct iattr *attr); | 112 | extern int gfs2_setattr_simple(struct inode *inode, struct iattr *attr); |
113 | extern struct inode *gfs2_lookup_simple(struct inode *dip, const char *name); | 113 | extern struct inode *gfs2_lookup_simple(struct inode *dip, const char *name); |
114 | extern void gfs2_dinode_out(const struct gfs2_inode *ip, void *buf); | 114 | extern void gfs2_dinode_out(const struct gfs2_inode *ip, void *buf); |
115 | 115 | ||
diff --git a/fs/gfs2/quota.c b/fs/gfs2/quota.c index 0e8bb13381e4..3a9a9749f496 100644 --- a/fs/gfs2/quota.c +++ b/fs/gfs2/quota.c | |||
@@ -638,7 +638,7 @@ static int gfs2_adjust_quota(struct gfs2_inode *ip, loff_t loc, | |||
638 | unsigned long index = loc >> PAGE_CACHE_SHIFT; | 638 | unsigned long index = loc >> PAGE_CACHE_SHIFT; |
639 | unsigned offset = loc & (PAGE_CACHE_SIZE - 1); | 639 | unsigned offset = loc & (PAGE_CACHE_SIZE - 1); |
640 | unsigned blocksize, iblock, pos; | 640 | unsigned blocksize, iblock, pos; |
641 | struct buffer_head *bh, *dibh; | 641 | struct buffer_head *bh; |
642 | struct page *page; | 642 | struct page *page; |
643 | void *kaddr, *ptr; | 643 | void *kaddr, *ptr; |
644 | struct gfs2_quota q, *qp; | 644 | struct gfs2_quota q, *qp; |
@@ -736,22 +736,13 @@ get_a_page: | |||
736 | goto get_a_page; | 736 | goto get_a_page; |
737 | } | 737 | } |
738 | 738 | ||
739 | /* Update the disk inode timestamp and size (if extended) */ | ||
740 | err = gfs2_meta_inode_buffer(ip, &dibh); | ||
741 | if (err) | ||
742 | goto out; | ||
743 | |||
744 | size = loc + sizeof(struct gfs2_quota); | 739 | size = loc + sizeof(struct gfs2_quota); |
745 | if (size > inode->i_size) | 740 | if (size > inode->i_size) |
746 | i_size_write(inode, size); | 741 | i_size_write(inode, size); |
747 | inode->i_mtime = inode->i_atime = CURRENT_TIME; | 742 | inode->i_mtime = inode->i_atime = CURRENT_TIME; |
748 | gfs2_trans_add_bh(ip->i_gl, dibh, 1); | ||
749 | gfs2_dinode_out(ip, dibh->b_data); | ||
750 | brelse(dibh); | ||
751 | mark_inode_dirty(inode); | 743 | mark_inode_dirty(inode); |
752 | |||
753 | out: | ||
754 | return err; | 744 | return err; |
745 | |||
755 | unlock_out: | 746 | unlock_out: |
756 | unlock_page(page); | 747 | unlock_page(page); |
757 | page_cache_release(page); | 748 | page_cache_release(page); |
diff --git a/fs/gfs2/super.c b/fs/gfs2/super.c index 9961de702d1b..b05fa5954550 100644 --- a/fs/gfs2/super.c +++ b/fs/gfs2/super.c | |||
@@ -752,47 +752,15 @@ static int gfs2_write_inode(struct inode *inode, struct writeback_control *wbc) | |||
752 | struct gfs2_sbd *sdp = GFS2_SB(inode); | 752 | struct gfs2_sbd *sdp = GFS2_SB(inode); |
753 | struct address_space *metamapping = gfs2_glock2aspace(ip->i_gl); | 753 | struct address_space *metamapping = gfs2_glock2aspace(ip->i_gl); |
754 | struct backing_dev_info *bdi = metamapping->backing_dev_info; | 754 | struct backing_dev_info *bdi = metamapping->backing_dev_info; |
755 | struct gfs2_holder gh; | 755 | int ret = 0; |
756 | struct buffer_head *bh; | 756 | |
757 | struct timespec atime; | ||
758 | struct gfs2_dinode *di; | ||
759 | int ret = -EAGAIN; | ||
760 | int unlock_required = 0; | ||
761 | |||
762 | /* Skip timestamp update, if this is from a memalloc */ | ||
763 | if (current->flags & PF_MEMALLOC) | ||
764 | goto do_flush; | ||
765 | if (!gfs2_glock_is_locked_by_me(ip->i_gl)) { | ||
766 | ret = gfs2_glock_nq_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, &gh); | ||
767 | if (ret) | ||
768 | goto do_flush; | ||
769 | unlock_required = 1; | ||
770 | } | ||
771 | ret = gfs2_meta_inode_buffer(ip, &bh); | ||
772 | if (ret == 0) { | ||
773 | di = (struct gfs2_dinode *)bh->b_data; | ||
774 | atime.tv_sec = be64_to_cpu(di->di_atime); | ||
775 | atime.tv_nsec = be32_to_cpu(di->di_atime_nsec); | ||
776 | if (timespec_compare(&inode->i_atime, &atime) > 0) { | ||
777 | ret = gfs2_trans_begin(sdp, RES_DINODE, 0); | ||
778 | if (ret == 0) { | ||
779 | gfs2_trans_add_bh(ip->i_gl, bh, 1); | ||
780 | gfs2_dinode_out(ip, bh->b_data); | ||
781 | gfs2_trans_end(sdp); | ||
782 | } | ||
783 | } | ||
784 | brelse(bh); | ||
785 | } | ||
786 | if (unlock_required) | ||
787 | gfs2_glock_dq_uninit(&gh); | ||
788 | do_flush: | ||
789 | if (wbc->sync_mode == WB_SYNC_ALL) | 757 | if (wbc->sync_mode == WB_SYNC_ALL) |
790 | gfs2_log_flush(GFS2_SB(inode), ip->i_gl); | 758 | gfs2_log_flush(GFS2_SB(inode), ip->i_gl); |
791 | if (bdi->dirty_exceeded) | 759 | if (bdi->dirty_exceeded) |
792 | gfs2_ail1_flush(sdp, wbc); | 760 | gfs2_ail1_flush(sdp, wbc); |
793 | else | 761 | else |
794 | filemap_fdatawrite(metamapping); | 762 | filemap_fdatawrite(metamapping); |
795 | if (!ret && (wbc->sync_mode == WB_SYNC_ALL)) | 763 | if (wbc->sync_mode == WB_SYNC_ALL) |
796 | ret = filemap_fdatawait(metamapping); | 764 | ret = filemap_fdatawait(metamapping); |
797 | if (ret) | 765 | if (ret) |
798 | mark_inode_dirty_sync(inode); | 766 | mark_inode_dirty_sync(inode); |
@@ -800,6 +768,64 @@ do_flush: | |||
800 | } | 768 | } |
801 | 769 | ||
802 | /** | 770 | /** |
771 | * gfs2_dirty_inode - check for atime updates | ||
772 | * @inode: The inode in question | ||
773 | * @flags: The type of dirty | ||
774 | * | ||
775 | * Unfortunately it can be called under any combination of inode | ||
776 | * glock and transaction lock, so we have to check carefully. | ||
777 | * | ||
778 | * At the moment this deals only with atime - it should be possible | ||
779 | * to expand that role in future, once a review of the locking has | ||
780 | * been carried out. | ||
781 | */ | ||
782 | |||
783 | static void gfs2_dirty_inode(struct inode *inode, int flags) | ||
784 | { | ||
785 | struct gfs2_inode *ip = GFS2_I(inode); | ||
786 | struct gfs2_sbd *sdp = GFS2_SB(inode); | ||
787 | struct buffer_head *bh; | ||
788 | struct gfs2_holder gh; | ||
789 | int need_unlock = 0; | ||
790 | int need_endtrans = 0; | ||
791 | int ret; | ||
792 | |||
793 | if (!(flags & (I_DIRTY_DATASYNC|I_DIRTY_SYNC))) | ||
794 | return; | ||
795 | |||
796 | if (!gfs2_glock_is_locked_by_me(ip->i_gl)) { | ||
797 | ret = gfs2_glock_nq_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, &gh); | ||
798 | if (ret) { | ||
799 | fs_err(sdp, "dirty_inode: glock %d\n", ret); | ||
800 | return; | ||
801 | } | ||
802 | need_unlock = 1; | ||
803 | } | ||
804 | |||
805 | if (current->journal_info == NULL) { | ||
806 | ret = gfs2_trans_begin(sdp, RES_DINODE, 0); | ||
807 | if (ret) { | ||
808 | fs_err(sdp, "dirty_inode: gfs2_trans_begin %d\n", ret); | ||
809 | goto out; | ||
810 | } | ||
811 | need_endtrans = 1; | ||
812 | } | ||
813 | |||
814 | ret = gfs2_meta_inode_buffer(ip, &bh); | ||
815 | if (ret == 0) { | ||
816 | gfs2_trans_add_bh(ip->i_gl, bh, 1); | ||
817 | gfs2_dinode_out(ip, bh->b_data); | ||
818 | brelse(bh); | ||
819 | } | ||
820 | |||
821 | if (need_endtrans) | ||
822 | gfs2_trans_end(sdp); | ||
823 | out: | ||
824 | if (need_unlock) | ||
825 | gfs2_glock_dq_uninit(&gh); | ||
826 | } | ||
827 | |||
828 | /** | ||
803 | * gfs2_make_fs_ro - Turn a Read-Write FS into a Read-Only one | 829 | * gfs2_make_fs_ro - Turn a Read-Write FS into a Read-Only one |
804 | * @sdp: the filesystem | 830 | * @sdp: the filesystem |
805 | * | 831 | * |
@@ -1578,6 +1604,7 @@ const struct super_operations gfs2_super_ops = { | |||
1578 | .alloc_inode = gfs2_alloc_inode, | 1604 | .alloc_inode = gfs2_alloc_inode, |
1579 | .destroy_inode = gfs2_destroy_inode, | 1605 | .destroy_inode = gfs2_destroy_inode, |
1580 | .write_inode = gfs2_write_inode, | 1606 | .write_inode = gfs2_write_inode, |
1607 | .dirty_inode = gfs2_dirty_inode, | ||
1581 | .evict_inode = gfs2_evict_inode, | 1608 | .evict_inode = gfs2_evict_inode, |
1582 | .put_super = gfs2_put_super, | 1609 | .put_super = gfs2_put_super, |
1583 | .sync_fs = gfs2_sync_fs, | 1610 | .sync_fs = gfs2_sync_fs, |
diff --git a/fs/gfs2/xattr.c b/fs/gfs2/xattr.c index 439b61c03262..695304cf01cc 100644 --- a/fs/gfs2/xattr.c +++ b/fs/gfs2/xattr.c | |||
@@ -1296,7 +1296,8 @@ fail: | |||
1296 | 1296 | ||
1297 | int gfs2_xattr_acl_chmod(struct gfs2_inode *ip, struct iattr *attr, char *data) | 1297 | int gfs2_xattr_acl_chmod(struct gfs2_inode *ip, struct iattr *attr, char *data) |
1298 | { | 1298 | { |
1299 | struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode); | 1299 | struct inode *inode = &ip->i_inode; |
1300 | struct gfs2_sbd *sdp = GFS2_SB(inode); | ||
1300 | struct gfs2_ea_location el; | 1301 | struct gfs2_ea_location el; |
1301 | int error; | 1302 | int error; |
1302 | 1303 | ||
@@ -1319,7 +1320,7 @@ int gfs2_xattr_acl_chmod(struct gfs2_inode *ip, struct iattr *attr, char *data) | |||
1319 | if (error) | 1320 | if (error) |
1320 | return error; | 1321 | return error; |
1321 | 1322 | ||
1322 | error = gfs2_setattr_simple(ip, attr); | 1323 | error = gfs2_setattr_simple(inode, attr); |
1323 | gfs2_trans_end(sdp); | 1324 | gfs2_trans_end(sdp); |
1324 | return error; | 1325 | return error; |
1325 | } | 1326 | } |