diff options
Diffstat (limited to 'fs')
-rw-r--r-- | fs/gfs2/bmap.c | 67 | ||||
-rw-r--r-- | fs/gfs2/bmap.h | 7 | ||||
-rw-r--r-- | fs/gfs2/dir.c | 2 | ||||
-rw-r--r-- | fs/gfs2/ops_address.c | 3 | ||||
-rw-r--r-- | fs/gfs2/ops_vm.c | 2 | ||||
-rw-r--r-- | fs/gfs2/page.c | 60 | ||||
-rw-r--r-- | fs/gfs2/page.h | 2 |
7 files changed, 66 insertions, 77 deletions
diff --git a/fs/gfs2/bmap.c b/fs/gfs2/bmap.c index 98fa07c2b710..72b19c5d7807 100644 --- a/fs/gfs2/bmap.c +++ b/fs/gfs2/bmap.c | |||
@@ -48,6 +48,65 @@ struct strip_mine { | |||
48 | }; | 48 | }; |
49 | 49 | ||
50 | /** | 50 | /** |
51 | * gfs2_unstuffer_page - unstuff a stuffed inode into a block cached by a page | ||
52 | * @ip: the inode | ||
53 | * @dibh: the dinode buffer | ||
54 | * @block: the block number that was allocated | ||
55 | * @private: any locked page held by the caller process | ||
56 | * | ||
57 | * Returns: errno | ||
58 | */ | ||
59 | |||
60 | static int gfs2_unstuffer_page(struct gfs2_inode *ip, struct buffer_head *dibh, | ||
61 | uint64_t block, struct page *page) | ||
62 | { | ||
63 | struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode); | ||
64 | struct inode *inode = &ip->i_inode; | ||
65 | struct buffer_head *bh; | ||
66 | int release = 0; | ||
67 | |||
68 | if (!page || page->index) { | ||
69 | page = grab_cache_page(inode->i_mapping, 0); | ||
70 | if (!page) | ||
71 | return -ENOMEM; | ||
72 | release = 1; | ||
73 | } | ||
74 | |||
75 | if (!PageUptodate(page)) { | ||
76 | void *kaddr = kmap(page); | ||
77 | |||
78 | memcpy(kaddr, dibh->b_data + sizeof(struct gfs2_dinode), | ||
79 | ip->i_di.di_size); | ||
80 | memset(kaddr + ip->i_di.di_size, 0, | ||
81 | PAGE_CACHE_SIZE - ip->i_di.di_size); | ||
82 | kunmap(page); | ||
83 | |||
84 | SetPageUptodate(page); | ||
85 | } | ||
86 | |||
87 | if (!page_has_buffers(page)) | ||
88 | create_empty_buffers(page, 1 << inode->i_blkbits, | ||
89 | (1 << BH_Uptodate)); | ||
90 | |||
91 | bh = page_buffers(page); | ||
92 | |||
93 | if (!buffer_mapped(bh)) | ||
94 | map_bh(bh, inode->i_sb, block); | ||
95 | |||
96 | set_buffer_uptodate(bh); | ||
97 | if ((sdp->sd_args.ar_data == GFS2_DATA_ORDERED) || gfs2_is_jdata(ip)) | ||
98 | gfs2_trans_add_bh(ip->i_gl, bh, 0); | ||
99 | mark_buffer_dirty(bh); | ||
100 | |||
101 | if (release) { | ||
102 | unlock_page(page); | ||
103 | page_cache_release(page); | ||
104 | } | ||
105 | |||
106 | return 0; | ||
107 | } | ||
108 | |||
109 | /** | ||
51 | * gfs2_unstuff_dinode - Unstuff a dinode when the data has grown too big | 110 | * gfs2_unstuff_dinode - Unstuff a dinode when the data has grown too big |
52 | * @ip: The GFS2 inode to unstuff | 111 | * @ip: The GFS2 inode to unstuff |
53 | * @unstuffer: the routine that handles unstuffing a non-zero length file | 112 | * @unstuffer: the routine that handles unstuffing a non-zero length file |
@@ -59,8 +118,7 @@ struct strip_mine { | |||
59 | * Returns: errno | 118 | * Returns: errno |
60 | */ | 119 | */ |
61 | 120 | ||
62 | int gfs2_unstuff_dinode(struct gfs2_inode *ip, gfs2_unstuffer_t unstuffer, | 121 | int gfs2_unstuff_dinode(struct gfs2_inode *ip, struct page *page) |
63 | void *private) | ||
64 | { | 122 | { |
65 | struct buffer_head *bh, *dibh; | 123 | struct buffer_head *bh, *dibh; |
66 | uint64_t block = 0; | 124 | uint64_t block = 0; |
@@ -90,7 +148,7 @@ int gfs2_unstuff_dinode(struct gfs2_inode *ip, gfs2_unstuffer_t unstuffer, | |||
90 | } else { | 148 | } else { |
91 | block = gfs2_alloc_data(ip); | 149 | block = gfs2_alloc_data(ip); |
92 | 150 | ||
93 | error = unstuffer(ip, dibh, block, private); | 151 | error = gfs2_unstuffer_page(ip, dibh, block, page); |
94 | if (error) | 152 | if (error) |
95 | goto out_brelse; | 153 | goto out_brelse; |
96 | } | 154 | } |
@@ -786,8 +844,7 @@ static int do_grow(struct gfs2_inode *ip, uint64_t size) | |||
786 | 844 | ||
787 | if (size > sdp->sd_sb.sb_bsize - sizeof(struct gfs2_dinode)) { | 845 | if (size > sdp->sd_sb.sb_bsize - sizeof(struct gfs2_dinode)) { |
788 | if (gfs2_is_stuffed(ip)) { | 846 | if (gfs2_is_stuffed(ip)) { |
789 | error = gfs2_unstuff_dinode(ip, gfs2_unstuffer_page, | 847 | error = gfs2_unstuff_dinode(ip, NULL); |
790 | NULL); | ||
791 | if (error) | 848 | if (error) |
792 | goto out_end_trans; | 849 | goto out_end_trans; |
793 | } | 850 | } |
diff --git a/fs/gfs2/bmap.h b/fs/gfs2/bmap.h index 06ccb2d808ad..1a265412f7ee 100644 --- a/fs/gfs2/bmap.h +++ b/fs/gfs2/bmap.h | |||
@@ -10,12 +10,7 @@ | |||
10 | #ifndef __BMAP_DOT_H__ | 10 | #ifndef __BMAP_DOT_H__ |
11 | #define __BMAP_DOT_H__ | 11 | #define __BMAP_DOT_H__ |
12 | 12 | ||
13 | typedef int (*gfs2_unstuffer_t) (struct gfs2_inode * ip, | 13 | int gfs2_unstuff_dinode(struct gfs2_inode *ip, struct page *page); |
14 | struct buffer_head * dibh, uint64_t block, | ||
15 | void *private); | ||
16 | int gfs2_unstuff_dinode(struct gfs2_inode *ip, gfs2_unstuffer_t unstuffer, | ||
17 | void *private); | ||
18 | |||
19 | int gfs2_block_map(struct inode *inode, u64 lblock, int *new, u64 *dblock, int *boundary); | 14 | int gfs2_block_map(struct inode *inode, u64 lblock, int *new, u64 *dblock, int *boundary); |
20 | int gfs2_extent_map(struct inode *inode, u64 lblock, int *new, u64 *dblock, unsigned *extlen); | 15 | int gfs2_extent_map(struct inode *inode, u64 lblock, int *new, u64 *dblock, unsigned *extlen); |
21 | 16 | ||
diff --git a/fs/gfs2/dir.c b/fs/gfs2/dir.c index f62223b9e53d..563b99e419b6 100644 --- a/fs/gfs2/dir.c +++ b/fs/gfs2/dir.c | |||
@@ -173,7 +173,7 @@ static int gfs2_dir_write_data(struct gfs2_inode *ip, const char *buf, | |||
173 | return -EINVAL; | 173 | return -EINVAL; |
174 | 174 | ||
175 | if (gfs2_is_stuffed(ip)) { | 175 | if (gfs2_is_stuffed(ip)) { |
176 | error = gfs2_unstuff_dinode(ip, NULL, NULL); | 176 | error = gfs2_unstuff_dinode(ip, NULL); |
177 | if (error) | 177 | if (error) |
178 | return error; | 178 | return error; |
179 | } | 179 | } |
diff --git a/fs/gfs2/ops_address.c b/fs/gfs2/ops_address.c index d33f6aa79731..93e00a8af8cf 100644 --- a/fs/gfs2/ops_address.c +++ b/fs/gfs2/ops_address.c | |||
@@ -395,8 +395,7 @@ static int gfs2_prepare_write(struct file *file, struct page *page, | |||
395 | 395 | ||
396 | if (gfs2_is_stuffed(ip)) { | 396 | if (gfs2_is_stuffed(ip)) { |
397 | if (end > sdp->sd_sb.sb_bsize - sizeof(struct gfs2_dinode)) { | 397 | if (end > sdp->sd_sb.sb_bsize - sizeof(struct gfs2_dinode)) { |
398 | error = gfs2_unstuff_dinode(ip, gfs2_unstuffer_page, | 398 | error = gfs2_unstuff_dinode(ip, page); |
399 | page); | ||
400 | if (error == 0) | 399 | if (error == 0) |
401 | goto prepare_write; | 400 | goto prepare_write; |
402 | } else if (!PageUptodate(page)) | 401 | } else if (!PageUptodate(page)) |
diff --git a/fs/gfs2/ops_vm.c b/fs/gfs2/ops_vm.c index 08709f19ea98..910722d4c483 100644 --- a/fs/gfs2/ops_vm.c +++ b/fs/gfs2/ops_vm.c | |||
@@ -104,7 +104,7 @@ static int alloc_page_backing(struct gfs2_inode *ip, struct page *page) | |||
104 | goto out_ipres; | 104 | goto out_ipres; |
105 | 105 | ||
106 | if (gfs2_is_stuffed(ip)) { | 106 | if (gfs2_is_stuffed(ip)) { |
107 | error = gfs2_unstuff_dinode(ip, gfs2_unstuffer_page, NULL); | 107 | error = gfs2_unstuff_dinode(ip, NULL); |
108 | if (error) | 108 | if (error) |
109 | goto out_trans; | 109 | goto out_trans; |
110 | } | 110 | } |
diff --git a/fs/gfs2/page.c b/fs/gfs2/page.c index b93caf294b9f..0d6befed1ae5 100644 --- a/fs/gfs2/page.c +++ b/fs/gfs2/page.c | |||
@@ -114,66 +114,6 @@ void gfs2_page_sync(struct gfs2_glock *gl, int flags) | |||
114 | } | 114 | } |
115 | 115 | ||
116 | /** | 116 | /** |
117 | * gfs2_unstuffer_page - unstuff a stuffed inode into a block cached by a page | ||
118 | * @ip: the inode | ||
119 | * @dibh: the dinode buffer | ||
120 | * @block: the block number that was allocated | ||
121 | * @private: any locked page held by the caller process | ||
122 | * | ||
123 | * Returns: errno | ||
124 | */ | ||
125 | |||
126 | int gfs2_unstuffer_page(struct gfs2_inode *ip, struct buffer_head *dibh, | ||
127 | uint64_t block, void *private) | ||
128 | { | ||
129 | struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode); | ||
130 | struct inode *inode = &ip->i_inode; | ||
131 | struct page *page = (struct page *)private; | ||
132 | struct buffer_head *bh; | ||
133 | int release = 0; | ||
134 | |||
135 | if (!page || page->index) { | ||
136 | page = grab_cache_page(inode->i_mapping, 0); | ||
137 | if (!page) | ||
138 | return -ENOMEM; | ||
139 | release = 1; | ||
140 | } | ||
141 | |||
142 | if (!PageUptodate(page)) { | ||
143 | void *kaddr = kmap(page); | ||
144 | |||
145 | memcpy(kaddr, dibh->b_data + sizeof(struct gfs2_dinode), | ||
146 | ip->i_di.di_size); | ||
147 | memset(kaddr + ip->i_di.di_size, 0, | ||
148 | PAGE_CACHE_SIZE - ip->i_di.di_size); | ||
149 | kunmap(page); | ||
150 | |||
151 | SetPageUptodate(page); | ||
152 | } | ||
153 | |||
154 | if (!page_has_buffers(page)) | ||
155 | create_empty_buffers(page, 1 << inode->i_blkbits, | ||
156 | (1 << BH_Uptodate)); | ||
157 | |||
158 | bh = page_buffers(page); | ||
159 | |||
160 | if (!buffer_mapped(bh)) | ||
161 | map_bh(bh, inode->i_sb, block); | ||
162 | |||
163 | set_buffer_uptodate(bh); | ||
164 | if ((sdp->sd_args.ar_data == GFS2_DATA_ORDERED) || gfs2_is_jdata(ip)) | ||
165 | gfs2_trans_add_bh(ip->i_gl, bh, 0); | ||
166 | mark_buffer_dirty(bh); | ||
167 | |||
168 | if (release) { | ||
169 | unlock_page(page); | ||
170 | page_cache_release(page); | ||
171 | } | ||
172 | |||
173 | return 0; | ||
174 | } | ||
175 | |||
176 | /** | ||
177 | * gfs2_block_truncate_page - Deal with zeroing out data for truncate | 117 | * gfs2_block_truncate_page - Deal with zeroing out data for truncate |
178 | * | 118 | * |
179 | * This is partly borrowed from ext3. | 119 | * This is partly borrowed from ext3. |
diff --git a/fs/gfs2/page.h b/fs/gfs2/page.h index 2c853a90ac04..67a4f4b79aa6 100644 --- a/fs/gfs2/page.h +++ b/fs/gfs2/page.h | |||
@@ -14,8 +14,6 @@ void gfs2_pte_inval(struct gfs2_glock *gl); | |||
14 | void gfs2_page_inval(struct gfs2_glock *gl); | 14 | void gfs2_page_inval(struct gfs2_glock *gl); |
15 | void gfs2_page_sync(struct gfs2_glock *gl, int flags); | 15 | void gfs2_page_sync(struct gfs2_glock *gl, int flags); |
16 | 16 | ||
17 | int gfs2_unstuffer_page(struct gfs2_inode *ip, struct buffer_head *dibh, | ||
18 | uint64_t block, void *private); | ||
19 | int gfs2_block_truncate_page(struct address_space *mapping); | 17 | int gfs2_block_truncate_page(struct address_space *mapping); |
20 | void gfs2_page_add_databufs(struct gfs2_inode *ip, struct page *page, | 18 | void gfs2_page_add_databufs(struct gfs2_inode *ip, struct page *page, |
21 | unsigned int from, unsigned int to); | 19 | unsigned int from, unsigned int to); |