diff options
Diffstat (limited to 'fs/ocfs2/buffer_head_io.c')
-rw-r--r-- | fs/ocfs2/buffer_head_io.c | 134 |
1 files changed, 104 insertions, 30 deletions
diff --git a/fs/ocfs2/buffer_head_io.c b/fs/ocfs2/buffer_head_io.c index f136639f5b41..7e947c672469 100644 --- a/fs/ocfs2/buffer_head_io.c +++ b/fs/ocfs2/buffer_head_io.c | |||
@@ -66,7 +66,7 @@ int ocfs2_write_block(struct ocfs2_super *osb, struct buffer_head *bh, | |||
66 | /* remove from dirty list before I/O. */ | 66 | /* remove from dirty list before I/O. */ |
67 | clear_buffer_dirty(bh); | 67 | clear_buffer_dirty(bh); |
68 | 68 | ||
69 | get_bh(bh); /* for end_buffer_write_sync() */ | 69 | get_bh(bh); /* for end_buffer_write_sync() */ |
70 | bh->b_end_io = end_buffer_write_sync; | 70 | bh->b_end_io = end_buffer_write_sync; |
71 | submit_bh(WRITE, bh); | 71 | submit_bh(WRITE, bh); |
72 | 72 | ||
@@ -88,22 +88,103 @@ out: | |||
88 | return ret; | 88 | return ret; |
89 | } | 89 | } |
90 | 90 | ||
91 | int ocfs2_read_blocks(struct ocfs2_super *osb, u64 block, int nr, | 91 | int ocfs2_read_blocks_sync(struct ocfs2_super *osb, u64 block, |
92 | struct buffer_head *bhs[], int flags, | 92 | unsigned int nr, struct buffer_head *bhs[]) |
93 | struct inode *inode) | 93 | { |
94 | int status = 0; | ||
95 | unsigned int i; | ||
96 | struct buffer_head *bh; | ||
97 | |||
98 | if (!nr) { | ||
99 | mlog(ML_BH_IO, "No buffers will be read!\n"); | ||
100 | goto bail; | ||
101 | } | ||
102 | |||
103 | for (i = 0 ; i < nr ; i++) { | ||
104 | if (bhs[i] == NULL) { | ||
105 | bhs[i] = sb_getblk(osb->sb, block++); | ||
106 | if (bhs[i] == NULL) { | ||
107 | status = -EIO; | ||
108 | mlog_errno(status); | ||
109 | goto bail; | ||
110 | } | ||
111 | } | ||
112 | bh = bhs[i]; | ||
113 | |||
114 | if (buffer_jbd(bh)) { | ||
115 | mlog(ML_ERROR, | ||
116 | "trying to sync read a jbd " | ||
117 | "managed bh (blocknr = %llu), skipping\n", | ||
118 | (unsigned long long)bh->b_blocknr); | ||
119 | continue; | ||
120 | } | ||
121 | |||
122 | if (buffer_dirty(bh)) { | ||
123 | /* This should probably be a BUG, or | ||
124 | * at least return an error. */ | ||
125 | mlog(ML_ERROR, | ||
126 | "trying to sync read a dirty " | ||
127 | "buffer! (blocknr = %llu), skipping\n", | ||
128 | (unsigned long long)bh->b_blocknr); | ||
129 | continue; | ||
130 | } | ||
131 | |||
132 | lock_buffer(bh); | ||
133 | if (buffer_jbd(bh)) { | ||
134 | mlog(ML_ERROR, | ||
135 | "block %llu had the JBD bit set " | ||
136 | "while I was in lock_buffer!", | ||
137 | (unsigned long long)bh->b_blocknr); | ||
138 | BUG(); | ||
139 | } | ||
140 | |||
141 | clear_buffer_uptodate(bh); | ||
142 | get_bh(bh); /* for end_buffer_read_sync() */ | ||
143 | bh->b_end_io = end_buffer_read_sync; | ||
144 | submit_bh(READ, bh); | ||
145 | } | ||
146 | |||
147 | for (i = nr; i > 0; i--) { | ||
148 | bh = bhs[i - 1]; | ||
149 | |||
150 | if (buffer_jbd(bh)) { | ||
151 | mlog(ML_ERROR, | ||
152 | "the journal got the buffer while it was " | ||
153 | "locked for io! (blocknr = %llu)\n", | ||
154 | (unsigned long long)bh->b_blocknr); | ||
155 | BUG(); | ||
156 | } | ||
157 | |||
158 | wait_on_buffer(bh); | ||
159 | if (!buffer_uptodate(bh)) { | ||
160 | /* Status won't be cleared from here on out, | ||
161 | * so we can safely record this and loop back | ||
162 | * to cleanup the other buffers. */ | ||
163 | status = -EIO; | ||
164 | put_bh(bh); | ||
165 | bhs[i - 1] = NULL; | ||
166 | } | ||
167 | } | ||
168 | |||
169 | bail: | ||
170 | return status; | ||
171 | } | ||
172 | |||
173 | int ocfs2_read_blocks(struct inode *inode, u64 block, int nr, | ||
174 | struct buffer_head *bhs[], int flags) | ||
94 | { | 175 | { |
95 | int status = 0; | 176 | int status = 0; |
96 | struct super_block *sb; | ||
97 | int i, ignore_cache = 0; | 177 | int i, ignore_cache = 0; |
98 | struct buffer_head *bh; | 178 | struct buffer_head *bh; |
99 | 179 | ||
100 | mlog_entry("(block=(%llu), nr=(%d), flags=%d, inode=%p)\n", | 180 | mlog_entry("(inode=%p, block=(%llu), nr=(%d), flags=%d)\n", |
101 | (unsigned long long)block, nr, flags, inode); | 181 | inode, (unsigned long long)block, nr, flags); |
102 | 182 | ||
183 | BUG_ON(!inode); | ||
103 | BUG_ON((flags & OCFS2_BH_READAHEAD) && | 184 | BUG_ON((flags & OCFS2_BH_READAHEAD) && |
104 | (!inode || !(flags & OCFS2_BH_CACHED))); | 185 | (flags & OCFS2_BH_IGNORE_CACHE)); |
105 | 186 | ||
106 | if (osb == NULL || osb->sb == NULL || bhs == NULL) { | 187 | if (bhs == NULL) { |
107 | status = -EINVAL; | 188 | status = -EINVAL; |
108 | mlog_errno(status); | 189 | mlog_errno(status); |
109 | goto bail; | 190 | goto bail; |
@@ -122,26 +203,19 @@ int ocfs2_read_blocks(struct ocfs2_super *osb, u64 block, int nr, | |||
122 | goto bail; | 203 | goto bail; |
123 | } | 204 | } |
124 | 205 | ||
125 | sb = osb->sb; | 206 | mutex_lock(&OCFS2_I(inode)->ip_io_mutex); |
126 | |||
127 | if (flags & OCFS2_BH_CACHED && !inode) | ||
128 | flags &= ~OCFS2_BH_CACHED; | ||
129 | |||
130 | if (inode) | ||
131 | mutex_lock(&OCFS2_I(inode)->ip_io_mutex); | ||
132 | for (i = 0 ; i < nr ; i++) { | 207 | for (i = 0 ; i < nr ; i++) { |
133 | if (bhs[i] == NULL) { | 208 | if (bhs[i] == NULL) { |
134 | bhs[i] = sb_getblk(sb, block++); | 209 | bhs[i] = sb_getblk(inode->i_sb, block++); |
135 | if (bhs[i] == NULL) { | 210 | if (bhs[i] == NULL) { |
136 | if (inode) | 211 | mutex_unlock(&OCFS2_I(inode)->ip_io_mutex); |
137 | mutex_unlock(&OCFS2_I(inode)->ip_io_mutex); | ||
138 | status = -EIO; | 212 | status = -EIO; |
139 | mlog_errno(status); | 213 | mlog_errno(status); |
140 | goto bail; | 214 | goto bail; |
141 | } | 215 | } |
142 | } | 216 | } |
143 | bh = bhs[i]; | 217 | bh = bhs[i]; |
144 | ignore_cache = 0; | 218 | ignore_cache = (flags & OCFS2_BH_IGNORE_CACHE); |
145 | 219 | ||
146 | /* There are three read-ahead cases here which we need to | 220 | /* There are three read-ahead cases here which we need to |
147 | * be concerned with. All three assume a buffer has | 221 | * be concerned with. All three assume a buffer has |
@@ -167,26 +241,27 @@ int ocfs2_read_blocks(struct ocfs2_super *osb, u64 block, int nr, | |||
167 | * before our is-it-in-flight check. | 241 | * before our is-it-in-flight check. |
168 | */ | 242 | */ |
169 | 243 | ||
170 | if (flags & OCFS2_BH_CACHED && | 244 | if (!ignore_cache && !ocfs2_buffer_uptodate(inode, bh)) { |
171 | !ocfs2_buffer_uptodate(inode, bh)) { | ||
172 | mlog(ML_UPTODATE, | 245 | mlog(ML_UPTODATE, |
173 | "bh (%llu), inode %llu not uptodate\n", | 246 | "bh (%llu), inode %llu not uptodate\n", |
174 | (unsigned long long)bh->b_blocknr, | 247 | (unsigned long long)bh->b_blocknr, |
175 | (unsigned long long)OCFS2_I(inode)->ip_blkno); | 248 | (unsigned long long)OCFS2_I(inode)->ip_blkno); |
249 | /* We're using ignore_cache here to say | ||
250 | * "go to disk" */ | ||
176 | ignore_cache = 1; | 251 | ignore_cache = 1; |
177 | } | 252 | } |
178 | 253 | ||
179 | /* XXX: Can we ever get this and *not* have the cached | 254 | /* XXX: Can we ever get this and *not* have the cached |
180 | * flag set? */ | 255 | * flag set? */ |
181 | if (buffer_jbd(bh)) { | 256 | if (buffer_jbd(bh)) { |
182 | if (!(flags & OCFS2_BH_CACHED) || ignore_cache) | 257 | if (ignore_cache) |
183 | mlog(ML_BH_IO, "trying to sync read a jbd " | 258 | mlog(ML_BH_IO, "trying to sync read a jbd " |
184 | "managed bh (blocknr = %llu)\n", | 259 | "managed bh (blocknr = %llu)\n", |
185 | (unsigned long long)bh->b_blocknr); | 260 | (unsigned long long)bh->b_blocknr); |
186 | continue; | 261 | continue; |
187 | } | 262 | } |
188 | 263 | ||
189 | if (!(flags & OCFS2_BH_CACHED) || ignore_cache) { | 264 | if (ignore_cache) { |
190 | if (buffer_dirty(bh)) { | 265 | if (buffer_dirty(bh)) { |
191 | /* This should probably be a BUG, or | 266 | /* This should probably be a BUG, or |
192 | * at least return an error. */ | 267 | * at least return an error. */ |
@@ -221,7 +296,7 @@ int ocfs2_read_blocks(struct ocfs2_super *osb, u64 block, int nr, | |||
221 | * previously read-ahead buffer may have | 296 | * previously read-ahead buffer may have |
222 | * completed I/O while we were waiting for the | 297 | * completed I/O while we were waiting for the |
223 | * buffer lock. */ | 298 | * buffer lock. */ |
224 | if ((flags & OCFS2_BH_CACHED) | 299 | if (!(flags & OCFS2_BH_IGNORE_CACHE) |
225 | && !(flags & OCFS2_BH_READAHEAD) | 300 | && !(flags & OCFS2_BH_READAHEAD) |
226 | && ocfs2_buffer_uptodate(inode, bh)) { | 301 | && ocfs2_buffer_uptodate(inode, bh)) { |
227 | unlock_buffer(bh); | 302 | unlock_buffer(bh); |
@@ -265,15 +340,14 @@ int ocfs2_read_blocks(struct ocfs2_super *osb, u64 block, int nr, | |||
265 | /* Always set the buffer in the cache, even if it was | 340 | /* Always set the buffer in the cache, even if it was |
266 | * a forced read, or read-ahead which hasn't yet | 341 | * a forced read, or read-ahead which hasn't yet |
267 | * completed. */ | 342 | * completed. */ |
268 | if (inode) | 343 | ocfs2_set_buffer_uptodate(inode, bh); |
269 | ocfs2_set_buffer_uptodate(inode, bh); | ||
270 | } | 344 | } |
271 | if (inode) | 345 | mutex_unlock(&OCFS2_I(inode)->ip_io_mutex); |
272 | mutex_unlock(&OCFS2_I(inode)->ip_io_mutex); | ||
273 | 346 | ||
274 | mlog(ML_BH_IO, "block=(%llu), nr=(%d), cached=%s, flags=0x%x\n", | 347 | mlog(ML_BH_IO, "block=(%llu), nr=(%d), cached=%s, flags=0x%x\n", |
275 | (unsigned long long)block, nr, | 348 | (unsigned long long)block, nr, |
276 | (!(flags & OCFS2_BH_CACHED) || ignore_cache) ? "no" : "yes", flags); | 349 | ((flags & OCFS2_BH_IGNORE_CACHE) || ignore_cache) ? "no" : "yes", |
350 | flags); | ||
277 | 351 | ||
278 | bail: | 352 | bail: |
279 | 353 | ||