diff options
Diffstat (limited to 'fs/ocfs2/buffer_head_io.c')
-rw-r--r-- | fs/ocfs2/buffer_head_io.c | 65 |
1 files changed, 63 insertions, 2 deletions
diff --git a/fs/ocfs2/buffer_head_io.c b/fs/ocfs2/buffer_head_io.c index c9037414f4f6..f136639f5b41 100644 --- a/fs/ocfs2/buffer_head_io.c +++ b/fs/ocfs2/buffer_head_io.c | |||
@@ -79,7 +79,7 @@ int ocfs2_write_block(struct ocfs2_super *osb, struct buffer_head *bh, | |||
79 | * information for this bh as it's not marked locally | 79 | * information for this bh as it's not marked locally |
80 | * uptodate. */ | 80 | * uptodate. */ |
81 | ret = -EIO; | 81 | ret = -EIO; |
82 | brelse(bh); | 82 | put_bh(bh); |
83 | } | 83 | } |
84 | 84 | ||
85 | mutex_unlock(&OCFS2_I(inode)->ip_io_mutex); | 85 | mutex_unlock(&OCFS2_I(inode)->ip_io_mutex); |
@@ -256,7 +256,7 @@ int ocfs2_read_blocks(struct ocfs2_super *osb, u64 block, int nr, | |||
256 | * for this bh as it's not marked locally | 256 | * for this bh as it's not marked locally |
257 | * uptodate. */ | 257 | * uptodate. */ |
258 | status = -EIO; | 258 | status = -EIO; |
259 | brelse(bh); | 259 | put_bh(bh); |
260 | bhs[i] = NULL; | 260 | bhs[i] = NULL; |
261 | continue; | 261 | continue; |
262 | } | 262 | } |
@@ -280,3 +280,64 @@ bail: | |||
280 | mlog_exit(status); | 280 | mlog_exit(status); |
281 | return status; | 281 | return status; |
282 | } | 282 | } |
283 | |||
284 | /* Check whether the blkno is the super block or one of the backups. */ | ||
285 | static void ocfs2_check_super_or_backup(struct super_block *sb, | ||
286 | sector_t blkno) | ||
287 | { | ||
288 | int i; | ||
289 | u64 backup_blkno; | ||
290 | |||
291 | if (blkno == OCFS2_SUPER_BLOCK_BLKNO) | ||
292 | return; | ||
293 | |||
294 | for (i = 0; i < OCFS2_MAX_BACKUP_SUPERBLOCKS; i++) { | ||
295 | backup_blkno = ocfs2_backup_super_blkno(sb, i); | ||
296 | if (backup_blkno == blkno) | ||
297 | return; | ||
298 | } | ||
299 | |||
300 | BUG(); | ||
301 | } | ||
302 | |||
303 | /* | ||
304 | * Write super block and backups doesn't need to collaborate with journal, | ||
305 | * so we don't need to lock ip_io_mutex and inode doesn't need to bea passed | ||
306 | * into this function. | ||
307 | */ | ||
308 | int ocfs2_write_super_or_backup(struct ocfs2_super *osb, | ||
309 | struct buffer_head *bh) | ||
310 | { | ||
311 | int ret = 0; | ||
312 | |||
313 | mlog_entry_void(); | ||
314 | |||
315 | BUG_ON(buffer_jbd(bh)); | ||
316 | ocfs2_check_super_or_backup(osb->sb, bh->b_blocknr); | ||
317 | |||
318 | if (ocfs2_is_hard_readonly(osb) || ocfs2_is_soft_readonly(osb)) { | ||
319 | ret = -EROFS; | ||
320 | goto out; | ||
321 | } | ||
322 | |||
323 | lock_buffer(bh); | ||
324 | set_buffer_uptodate(bh); | ||
325 | |||
326 | /* remove from dirty list before I/O. */ | ||
327 | clear_buffer_dirty(bh); | ||
328 | |||
329 | get_bh(bh); /* for end_buffer_write_sync() */ | ||
330 | bh->b_end_io = end_buffer_write_sync; | ||
331 | submit_bh(WRITE, bh); | ||
332 | |||
333 | wait_on_buffer(bh); | ||
334 | |||
335 | if (!buffer_uptodate(bh)) { | ||
336 | ret = -EIO; | ||
337 | put_bh(bh); | ||
338 | } | ||
339 | |||
340 | out: | ||
341 | mlog_exit(ret); | ||
342 | return ret; | ||
343 | } | ||