diff options
-rw-r--r-- | fs/ext4/inline.c | 24 | ||||
-rw-r--r-- | fs/ext4/inode.c | 69 | ||||
-rw-r--r-- | fs/ext4/xattr.h | 12 |
3 files changed, 85 insertions, 20 deletions
diff --git a/fs/ext4/inline.c b/fs/ext4/inline.c index 320ff6fe5d8c..01274b1e7d40 100644 --- a/fs/ext4/inline.c +++ b/fs/ext4/inline.c | |||
@@ -747,6 +747,30 @@ out: | |||
747 | return copied; | 747 | return copied; |
748 | } | 748 | } |
749 | 749 | ||
750 | struct buffer_head * | ||
751 | ext4_journalled_write_inline_data(struct inode *inode, | ||
752 | unsigned len, | ||
753 | struct page *page) | ||
754 | { | ||
755 | int ret; | ||
756 | void *kaddr; | ||
757 | struct ext4_iloc iloc; | ||
758 | |||
759 | ret = ext4_get_inode_loc(inode, &iloc); | ||
760 | if (ret) { | ||
761 | ext4_std_error(inode->i_sb, ret); | ||
762 | return NULL; | ||
763 | } | ||
764 | |||
765 | down_write(&EXT4_I(inode)->xattr_sem); | ||
766 | kaddr = kmap_atomic(page); | ||
767 | ext4_write_inline_data(inode, &iloc, kaddr, 0, len); | ||
768 | kunmap_atomic(kaddr); | ||
769 | up_write(&EXT4_I(inode)->xattr_sem); | ||
770 | |||
771 | return iloc.bh; | ||
772 | } | ||
773 | |||
750 | 774 | ||
751 | int ext4_destroy_inline_data(handle_t *handle, struct inode *inode) | 775 | int ext4_destroy_inline_data(handle_t *handle, struct inode *inode) |
752 | { | 776 | { |
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index 70c8d5f323f0..5c91622cfe01 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c | |||
@@ -1124,16 +1124,21 @@ static int ext4_journalled_write_end(struct file *file, | |||
1124 | 1124 | ||
1125 | BUG_ON(!ext4_handle_valid(handle)); | 1125 | BUG_ON(!ext4_handle_valid(handle)); |
1126 | 1126 | ||
1127 | if (copied < len) { | 1127 | if (ext4_has_inline_data(inode)) |
1128 | if (!PageUptodate(page)) | 1128 | copied = ext4_write_inline_data_end(inode, pos, len, |
1129 | copied = 0; | 1129 | copied, page); |
1130 | page_zero_new_buffers(page, from+copied, to); | 1130 | else { |
1131 | } | 1131 | if (copied < len) { |
1132 | if (!PageUptodate(page)) | ||
1133 | copied = 0; | ||
1134 | page_zero_new_buffers(page, from+copied, to); | ||
1135 | } | ||
1132 | 1136 | ||
1133 | ret = ext4_walk_page_buffers(handle, page_buffers(page), from, | 1137 | ret = ext4_walk_page_buffers(handle, page_buffers(page), from, |
1134 | to, &partial, write_end_fn); | 1138 | to, &partial, write_end_fn); |
1135 | if (!partial) | 1139 | if (!partial) |
1136 | SetPageUptodate(page); | 1140 | SetPageUptodate(page); |
1141 | } | ||
1137 | new_i_size = pos + copied; | 1142 | new_i_size = pos + copied; |
1138 | if (new_i_size > inode->i_size) | 1143 | if (new_i_size > inode->i_size) |
1139 | i_size_write(inode, pos+copied); | 1144 | i_size_write(inode, pos+copied); |
@@ -1911,15 +1916,29 @@ static int __ext4_journalled_writepage(struct page *page, | |||
1911 | { | 1916 | { |
1912 | struct address_space *mapping = page->mapping; | 1917 | struct address_space *mapping = page->mapping; |
1913 | struct inode *inode = mapping->host; | 1918 | struct inode *inode = mapping->host; |
1914 | struct buffer_head *page_bufs; | 1919 | struct buffer_head *page_bufs = NULL; |
1915 | handle_t *handle = NULL; | 1920 | handle_t *handle = NULL; |
1916 | int ret = 0; | 1921 | int ret = 0, err = 0; |
1917 | int err; | 1922 | int inline_data = ext4_has_inline_data(inode); |
1923 | struct buffer_head *inode_bh = NULL; | ||
1918 | 1924 | ||
1919 | ClearPageChecked(page); | 1925 | ClearPageChecked(page); |
1920 | page_bufs = page_buffers(page); | 1926 | |
1921 | BUG_ON(!page_bufs); | 1927 | if (inline_data) { |
1922 | ext4_walk_page_buffers(handle, page_bufs, 0, len, NULL, bget_one); | 1928 | BUG_ON(page->index != 0); |
1929 | BUG_ON(len > ext4_get_max_inline_size(inode)); | ||
1930 | inode_bh = ext4_journalled_write_inline_data(inode, len, page); | ||
1931 | if (inode_bh == NULL) | ||
1932 | goto out; | ||
1933 | } else { | ||
1934 | page_bufs = page_buffers(page); | ||
1935 | if (!page_bufs) { | ||
1936 | BUG(); | ||
1937 | goto out; | ||
1938 | } | ||
1939 | ext4_walk_page_buffers(handle, page_bufs, 0, len, | ||
1940 | NULL, bget_one); | ||
1941 | } | ||
1923 | /* As soon as we unlock the page, it can go away, but we have | 1942 | /* As soon as we unlock the page, it can go away, but we have |
1924 | * references to buffers so we are safe */ | 1943 | * references to buffers so we are safe */ |
1925 | unlock_page(page); | 1944 | unlock_page(page); |
@@ -1932,11 +1951,18 @@ static int __ext4_journalled_writepage(struct page *page, | |||
1932 | 1951 | ||
1933 | BUG_ON(!ext4_handle_valid(handle)); | 1952 | BUG_ON(!ext4_handle_valid(handle)); |
1934 | 1953 | ||
1935 | ret = ext4_walk_page_buffers(handle, page_bufs, 0, len, NULL, | 1954 | if (inline_data) { |
1936 | do_journal_get_write_access); | 1955 | ret = ext4_journal_get_write_access(handle, inode_bh); |
1937 | 1956 | ||
1938 | err = ext4_walk_page_buffers(handle, page_bufs, 0, len, NULL, | 1957 | err = ext4_handle_dirty_metadata(handle, inode, inode_bh); |
1939 | write_end_fn); | 1958 | |
1959 | } else { | ||
1960 | ret = ext4_walk_page_buffers(handle, page_bufs, 0, len, NULL, | ||
1961 | do_journal_get_write_access); | ||
1962 | |||
1963 | err = ext4_walk_page_buffers(handle, page_bufs, 0, len, NULL, | ||
1964 | write_end_fn); | ||
1965 | } | ||
1940 | if (ret == 0) | 1966 | if (ret == 0) |
1941 | ret = err; | 1967 | ret = err; |
1942 | EXT4_I(inode)->i_datasync_tid = handle->h_transaction->t_tid; | 1968 | EXT4_I(inode)->i_datasync_tid = handle->h_transaction->t_tid; |
@@ -1944,9 +1970,12 @@ static int __ext4_journalled_writepage(struct page *page, | |||
1944 | if (!ret) | 1970 | if (!ret) |
1945 | ret = err; | 1971 | ret = err; |
1946 | 1972 | ||
1947 | ext4_walk_page_buffers(handle, page_bufs, 0, len, NULL, bput_one); | 1973 | if (!ext4_has_inline_data(inode)) |
1974 | ext4_walk_page_buffers(handle, page_bufs, 0, len, | ||
1975 | NULL, bput_one); | ||
1948 | ext4_set_inode_state(inode, EXT4_STATE_JDATA); | 1976 | ext4_set_inode_state(inode, EXT4_STATE_JDATA); |
1949 | out: | 1977 | out: |
1978 | brelse(inode_bh); | ||
1950 | return ret; | 1979 | return ret; |
1951 | } | 1980 | } |
1952 | 1981 | ||
diff --git a/fs/ext4/xattr.h b/fs/ext4/xattr.h index db5672206238..7095ac13fbc2 100644 --- a/fs/ext4/xattr.h +++ b/fs/ext4/xattr.h | |||
@@ -150,6 +150,10 @@ extern int ext4_write_inline_data_end(struct inode *inode, | |||
150 | loff_t pos, unsigned len, | 150 | loff_t pos, unsigned len, |
151 | unsigned copied, | 151 | unsigned copied, |
152 | struct page *page); | 152 | struct page *page); |
153 | extern struct buffer_head * | ||
154 | ext4_journalled_write_inline_data(struct inode *inode, | ||
155 | unsigned len, | ||
156 | struct page *page); | ||
153 | # else /* CONFIG_EXT4_FS_XATTR */ | 157 | # else /* CONFIG_EXT4_FS_XATTR */ |
154 | 158 | ||
155 | static inline int | 159 | static inline int |
@@ -288,6 +292,14 @@ static inline int ext4_write_inline_data_end(struct inode *inode, | |||
288 | { | 292 | { |
289 | return 0; | 293 | return 0; |
290 | } | 294 | } |
295 | |||
296 | static inline struct buffer_head * | ||
297 | ext4_journalled_write_inline_data(struct inode *inode, | ||
298 | unsigned len, | ||
299 | struct page *page) | ||
300 | { | ||
301 | return NULL; | ||
302 | } | ||
291 | # endif /* CONFIG_EXT4_FS_XATTR */ | 303 | # endif /* CONFIG_EXT4_FS_XATTR */ |
292 | 304 | ||
293 | #ifdef CONFIG_EXT4_FS_SECURITY | 305 | #ifdef CONFIG_EXT4_FS_SECURITY |