diff options
-rw-r--r-- | fs/gfs2/inode.c | 4 | ||||
-rw-r--r-- | fs/gfs2/inode.h | 6 | ||||
-rw-r--r-- | fs/gfs2/ops_address.c | 78 | ||||
-rw-r--r-- | fs/gfs2/ops_address.h | 2 | ||||
-rw-r--r-- | fs/gfs2/ops_file.c | 13 |
5 files changed, 72 insertions, 31 deletions
diff --git a/fs/gfs2/inode.c b/fs/gfs2/inode.c index af493fc6c8ce..532784eb5ba4 100644 --- a/fs/gfs2/inode.c +++ b/fs/gfs2/inode.c | |||
@@ -136,7 +136,6 @@ void gfs2_set_iop(struct inode *inode) | |||
136 | if (S_ISREG(mode)) { | 136 | if (S_ISREG(mode)) { |
137 | inode->i_op = &gfs2_file_iops; | 137 | inode->i_op = &gfs2_file_iops; |
138 | inode->i_fop = &gfs2_file_fops; | 138 | inode->i_fop = &gfs2_file_fops; |
139 | inode->i_mapping->a_ops = &gfs2_file_aops; | ||
140 | } else if (S_ISDIR(mode)) { | 139 | } else if (S_ISDIR(mode)) { |
141 | inode->i_op = &gfs2_dir_iops; | 140 | inode->i_op = &gfs2_dir_iops; |
142 | inode->i_fop = &gfs2_dir_fops; | 141 | inode->i_fop = &gfs2_dir_fops; |
@@ -290,6 +289,9 @@ static int gfs2_dinode_in(struct gfs2_inode *ip, const void *buf) | |||
290 | di->di_entries = be32_to_cpu(str->di_entries); | 289 | di->di_entries = be32_to_cpu(str->di_entries); |
291 | 290 | ||
292 | di->di_eattr = be64_to_cpu(str->di_eattr); | 291 | di->di_eattr = be64_to_cpu(str->di_eattr); |
292 | if (S_ISREG(ip->i_inode.i_mode)) | ||
293 | gfs2_set_aops(&ip->i_inode); | ||
294 | |||
293 | return 0; | 295 | return 0; |
294 | } | 296 | } |
295 | 297 | ||
diff --git a/fs/gfs2/inode.h b/fs/gfs2/inode.h index bed3dc212a18..d44650662615 100644 --- a/fs/gfs2/inode.h +++ b/fs/gfs2/inode.h | |||
@@ -26,6 +26,12 @@ static inline int gfs2_is_writeback(const struct gfs2_inode *ip) | |||
26 | return (sdp->sd_args.ar_data == GFS2_DATA_WRITEBACK) && !gfs2_is_jdata(ip); | 26 | return (sdp->sd_args.ar_data == GFS2_DATA_WRITEBACK) && !gfs2_is_jdata(ip); |
27 | } | 27 | } |
28 | 28 | ||
29 | static inline int gfs2_is_ordered(const struct gfs2_inode *ip) | ||
30 | { | ||
31 | const struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode); | ||
32 | return (sdp->sd_args.ar_data == GFS2_DATA_ORDERED) && !gfs2_is_jdata(ip); | ||
33 | } | ||
34 | |||
29 | static inline int gfs2_is_dir(const struct gfs2_inode *ip) | 35 | static inline int gfs2_is_dir(const struct gfs2_inode *ip) |
30 | { | 36 | { |
31 | return S_ISDIR(ip->i_inode.i_mode); | 37 | return S_ISDIR(ip->i_inode.i_mode); |
diff --git a/fs/gfs2/ops_address.c b/fs/gfs2/ops_address.c index ed154af86171..207014f363d8 100644 --- a/fs/gfs2/ops_address.c +++ b/fs/gfs2/ops_address.c | |||
@@ -162,28 +162,18 @@ out_ignore: | |||
162 | } | 162 | } |
163 | 163 | ||
164 | /** | 164 | /** |
165 | * gfs2_writepages - Write a bunch of dirty pages back to disk | 165 | * gfs2_writeback_writepages - Write a bunch of dirty pages back to disk |
166 | * @mapping: The mapping to write | 166 | * @mapping: The mapping to write |
167 | * @wbc: Write-back control | 167 | * @wbc: Write-back control |
168 | * | 168 | * |
169 | * For journaled files and/or ordered writes this just falls back to the | 169 | * For the data=writeback case we can already ignore buffer heads |
170 | * kernel's default writepages path for now. We will probably want to change | ||
171 | * that eventually (i.e. when we look at allocate on flush). | ||
172 | * | ||
173 | * For the data=writeback case though we can already ignore buffer heads | ||
174 | * and write whole extents at once. This is a big reduction in the | 170 | * and write whole extents at once. This is a big reduction in the |
175 | * number of I/O requests we send and the bmap calls we make in this case. | 171 | * number of I/O requests we send and the bmap calls we make in this case. |
176 | */ | 172 | */ |
177 | static int gfs2_writepages(struct address_space *mapping, | 173 | static int gfs2_writeback_writepages(struct address_space *mapping, |
178 | struct writeback_control *wbc) | 174 | struct writeback_control *wbc) |
179 | { | 175 | { |
180 | struct inode *inode = mapping->host; | 176 | return mpage_writepages(mapping, wbc, gfs2_get_block_noalloc); |
181 | struct gfs2_inode *ip = GFS2_I(inode); | ||
182 | |||
183 | if (gfs2_is_writeback(ip)) | ||
184 | return mpage_writepages(mapping, wbc, gfs2_get_block_noalloc); | ||
185 | |||
186 | return generic_writepages(mapping, wbc); | ||
187 | } | 177 | } |
188 | 178 | ||
189 | /** | 179 | /** |
@@ -644,11 +634,7 @@ failed: | |||
644 | 634 | ||
645 | static int gfs2_set_page_dirty(struct page *page) | 635 | static int gfs2_set_page_dirty(struct page *page) |
646 | { | 636 | { |
647 | struct gfs2_inode *ip = GFS2_I(page->mapping->host); | 637 | SetPageChecked(page); |
648 | struct gfs2_sbd *sdp = GFS2_SB(page->mapping->host); | ||
649 | |||
650 | if (sdp->sd_args.ar_data == GFS2_DATA_ORDERED || gfs2_is_jdata(ip)) | ||
651 | SetPageChecked(page); | ||
652 | return __set_page_dirty_buffers(page); | 638 | return __set_page_dirty_buffers(page); |
653 | } | 639 | } |
654 | 640 | ||
@@ -738,13 +724,9 @@ static int gfs2_ok_for_dio(struct gfs2_inode *ip, int rw, loff_t offset) | |||
738 | { | 724 | { |
739 | /* | 725 | /* |
740 | * Should we return an error here? I can't see that O_DIRECT for | 726 | * Should we return an error here? I can't see that O_DIRECT for |
741 | * a journaled file makes any sense. For now we'll silently fall | 727 | * a stuffed file makes any sense. For now we'll silently fall |
742 | * back to buffered I/O, likewise we do the same for stuffed | 728 | * back to buffered I/O |
743 | * files since they are (a) small and (b) unaligned. | ||
744 | */ | 729 | */ |
745 | if (gfs2_is_jdata(ip)) | ||
746 | return 0; | ||
747 | |||
748 | if (gfs2_is_stuffed(ip)) | 730 | if (gfs2_is_stuffed(ip)) |
749 | return 0; | 731 | return 0; |
750 | 732 | ||
@@ -855,9 +837,22 @@ cannot_release: | |||
855 | return 0; | 837 | return 0; |
856 | } | 838 | } |
857 | 839 | ||
858 | const struct address_space_operations gfs2_file_aops = { | 840 | static const struct address_space_operations gfs2_writeback_aops = { |
841 | .writepage = gfs2_writepage, | ||
842 | .writepages = gfs2_writeback_writepages, | ||
843 | .readpage = gfs2_readpage, | ||
844 | .readpages = gfs2_readpages, | ||
845 | .sync_page = block_sync_page, | ||
846 | .write_begin = gfs2_write_begin, | ||
847 | .write_end = gfs2_write_end, | ||
848 | .bmap = gfs2_bmap, | ||
849 | .invalidatepage = gfs2_invalidatepage, | ||
850 | .releasepage = gfs2_releasepage, | ||
851 | .direct_IO = gfs2_direct_IO, | ||
852 | }; | ||
853 | |||
854 | static const struct address_space_operations gfs2_ordered_aops = { | ||
859 | .writepage = gfs2_writepage, | 855 | .writepage = gfs2_writepage, |
860 | .writepages = gfs2_writepages, | ||
861 | .readpage = gfs2_readpage, | 856 | .readpage = gfs2_readpage, |
862 | .readpages = gfs2_readpages, | 857 | .readpages = gfs2_readpages, |
863 | .sync_page = block_sync_page, | 858 | .sync_page = block_sync_page, |
@@ -870,3 +865,30 @@ const struct address_space_operations gfs2_file_aops = { | |||
870 | .direct_IO = gfs2_direct_IO, | 865 | .direct_IO = gfs2_direct_IO, |
871 | }; | 866 | }; |
872 | 867 | ||
868 | static const struct address_space_operations gfs2_jdata_aops = { | ||
869 | .writepage = gfs2_writepage, | ||
870 | .readpage = gfs2_readpage, | ||
871 | .readpages = gfs2_readpages, | ||
872 | .sync_page = block_sync_page, | ||
873 | .write_begin = gfs2_write_begin, | ||
874 | .write_end = gfs2_write_end, | ||
875 | .set_page_dirty = gfs2_set_page_dirty, | ||
876 | .bmap = gfs2_bmap, | ||
877 | .invalidatepage = gfs2_invalidatepage, | ||
878 | .releasepage = gfs2_releasepage, | ||
879 | }; | ||
880 | |||
881 | void gfs2_set_aops(struct inode *inode) | ||
882 | { | ||
883 | struct gfs2_inode *ip = GFS2_I(inode); | ||
884 | |||
885 | if (gfs2_is_writeback(ip)) | ||
886 | inode->i_mapping->a_ops = &gfs2_writeback_aops; | ||
887 | else if (gfs2_is_ordered(ip)) | ||
888 | inode->i_mapping->a_ops = &gfs2_ordered_aops; | ||
889 | else if (gfs2_is_jdata(ip)) | ||
890 | inode->i_mapping->a_ops = &gfs2_jdata_aops; | ||
891 | else | ||
892 | BUG(); | ||
893 | } | ||
894 | |||
diff --git a/fs/gfs2/ops_address.h b/fs/gfs2/ops_address.h index e8fe83fcd583..d3b76d0cdc81 100644 --- a/fs/gfs2/ops_address.h +++ b/fs/gfs2/ops_address.h | |||
@@ -14,12 +14,12 @@ | |||
14 | #include <linux/buffer_head.h> | 14 | #include <linux/buffer_head.h> |
15 | #include <linux/mm.h> | 15 | #include <linux/mm.h> |
16 | 16 | ||
17 | extern const struct address_space_operations gfs2_file_aops; | ||
18 | extern int gfs2_get_block(struct inode *inode, sector_t lblock, | 17 | extern int gfs2_get_block(struct inode *inode, sector_t lblock, |
19 | struct buffer_head *bh_result, int create); | 18 | struct buffer_head *bh_result, int create); |
20 | extern int gfs2_releasepage(struct page *page, gfp_t gfp_mask); | 19 | extern int gfs2_releasepage(struct page *page, gfp_t gfp_mask); |
21 | extern int gfs2_internal_read(struct gfs2_inode *ip, | 20 | extern int gfs2_internal_read(struct gfs2_inode *ip, |
22 | struct file_ra_state *ra_state, | 21 | struct file_ra_state *ra_state, |
23 | char *buf, loff_t *pos, unsigned size); | 22 | char *buf, loff_t *pos, unsigned size); |
23 | extern void gfs2_set_aops(struct inode *inode); | ||
24 | 24 | ||
25 | #endif /* __OPS_ADDRESS_DOT_H__ */ | 25 | #endif /* __OPS_ADDRESS_DOT_H__ */ |
diff --git a/fs/gfs2/ops_file.c b/fs/gfs2/ops_file.c index 6f3aeb059c61..ad5daaa6babc 100644 --- a/fs/gfs2/ops_file.c +++ b/fs/gfs2/ops_file.c | |||
@@ -38,6 +38,7 @@ | |||
38 | #include "trans.h" | 38 | #include "trans.h" |
39 | #include "util.h" | 39 | #include "util.h" |
40 | #include "eaops.h" | 40 | #include "eaops.h" |
41 | #include "ops_address.h" | ||
41 | 42 | ||
42 | /** | 43 | /** |
43 | * gfs2_llseek - seek to a location in a file | 44 | * gfs2_llseek - seek to a location in a file |
@@ -245,7 +246,16 @@ static int do_gfs2_set_flags(struct file *filp, u32 reqflags, u32 mask) | |||
245 | if (error) | 246 | if (error) |
246 | goto out; | 247 | goto out; |
247 | } | 248 | } |
248 | 249 | if ((flags ^ new_flags) & GFS2_DIF_JDATA) { | |
250 | if (flags & GFS2_DIF_JDATA) | ||
251 | gfs2_log_flush(sdp, ip->i_gl); | ||
252 | error = filemap_fdatawrite(inode->i_mapping); | ||
253 | if (error) | ||
254 | goto out; | ||
255 | error = filemap_fdatawait(inode->i_mapping); | ||
256 | if (error) | ||
257 | goto out; | ||
258 | } | ||
249 | error = gfs2_trans_begin(sdp, RES_DINODE, 0); | 259 | error = gfs2_trans_begin(sdp, RES_DINODE, 0); |
250 | if (error) | 260 | if (error) |
251 | goto out; | 261 | goto out; |
@@ -257,6 +267,7 @@ static int do_gfs2_set_flags(struct file *filp, u32 reqflags, u32 mask) | |||
257 | gfs2_dinode_out(ip, bh->b_data); | 267 | gfs2_dinode_out(ip, bh->b_data); |
258 | brelse(bh); | 268 | brelse(bh); |
259 | gfs2_set_inode_flags(inode); | 269 | gfs2_set_inode_flags(inode); |
270 | gfs2_set_aops(inode); | ||
260 | out_trans_end: | 271 | out_trans_end: |
261 | gfs2_trans_end(sdp); | 272 | gfs2_trans_end(sdp); |
262 | out: | 273 | out: |