162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * io.c 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Buffer cache handling 662306a36Sopenharmony_ci * 762306a36Sopenharmony_ci * Copyright (C) 2002, 2004 Oracle. All rights reserved. 862306a36Sopenharmony_ci */ 962306a36Sopenharmony_ci 1062306a36Sopenharmony_ci#include <linux/fs.h> 1162306a36Sopenharmony_ci#include <linux/types.h> 1262306a36Sopenharmony_ci#include <linux/highmem.h> 1362306a36Sopenharmony_ci#include <linux/bio.h> 1462306a36Sopenharmony_ci 1562306a36Sopenharmony_ci#include <cluster/masklog.h> 1662306a36Sopenharmony_ci 1762306a36Sopenharmony_ci#include "ocfs2.h" 1862306a36Sopenharmony_ci 1962306a36Sopenharmony_ci#include "alloc.h" 2062306a36Sopenharmony_ci#include "inode.h" 2162306a36Sopenharmony_ci#include "journal.h" 2262306a36Sopenharmony_ci#include "uptodate.h" 2362306a36Sopenharmony_ci#include "buffer_head_io.h" 2462306a36Sopenharmony_ci#include "ocfs2_trace.h" 2562306a36Sopenharmony_ci 2662306a36Sopenharmony_ci/* 2762306a36Sopenharmony_ci * Bits on bh->b_state used by ocfs2. 2862306a36Sopenharmony_ci * 2962306a36Sopenharmony_ci * These MUST be after the JBD2 bits. Hence, we use BH_JBDPrivateStart. 3062306a36Sopenharmony_ci */ 3162306a36Sopenharmony_cienum ocfs2_state_bits { 3262306a36Sopenharmony_ci BH_NeedsValidate = BH_JBDPrivateStart, 3362306a36Sopenharmony_ci}; 3462306a36Sopenharmony_ci 3562306a36Sopenharmony_ci/* Expand the magic b_state functions */ 3662306a36Sopenharmony_ciBUFFER_FNS(NeedsValidate, needs_validate); 3762306a36Sopenharmony_ci 3862306a36Sopenharmony_ciint ocfs2_write_block(struct ocfs2_super *osb, struct buffer_head *bh, 3962306a36Sopenharmony_ci struct ocfs2_caching_info *ci) 4062306a36Sopenharmony_ci{ 4162306a36Sopenharmony_ci int ret = 0; 4262306a36Sopenharmony_ci 4362306a36Sopenharmony_ci trace_ocfs2_write_block((unsigned long long)bh->b_blocknr, ci); 4462306a36Sopenharmony_ci 4562306a36Sopenharmony_ci BUG_ON(bh->b_blocknr < OCFS2_SUPER_BLOCK_BLKNO); 4662306a36Sopenharmony_ci BUG_ON(buffer_jbd(bh)); 4762306a36Sopenharmony_ci 4862306a36Sopenharmony_ci /* No need to check for a soft readonly file system here. non 4962306a36Sopenharmony_ci * journalled writes are only ever done on system files which 5062306a36Sopenharmony_ci * can get modified during recovery even if read-only. */ 5162306a36Sopenharmony_ci if (ocfs2_is_hard_readonly(osb)) { 5262306a36Sopenharmony_ci ret = -EROFS; 5362306a36Sopenharmony_ci mlog_errno(ret); 5462306a36Sopenharmony_ci goto out; 5562306a36Sopenharmony_ci } 5662306a36Sopenharmony_ci 5762306a36Sopenharmony_ci ocfs2_metadata_cache_io_lock(ci); 5862306a36Sopenharmony_ci 5962306a36Sopenharmony_ci lock_buffer(bh); 6062306a36Sopenharmony_ci set_buffer_uptodate(bh); 6162306a36Sopenharmony_ci 6262306a36Sopenharmony_ci /* remove from dirty list before I/O. */ 6362306a36Sopenharmony_ci clear_buffer_dirty(bh); 6462306a36Sopenharmony_ci 6562306a36Sopenharmony_ci get_bh(bh); /* for end_buffer_write_sync() */ 6662306a36Sopenharmony_ci bh->b_end_io = end_buffer_write_sync; 6762306a36Sopenharmony_ci submit_bh(REQ_OP_WRITE, bh); 6862306a36Sopenharmony_ci 6962306a36Sopenharmony_ci wait_on_buffer(bh); 7062306a36Sopenharmony_ci 7162306a36Sopenharmony_ci if (buffer_uptodate(bh)) { 7262306a36Sopenharmony_ci ocfs2_set_buffer_uptodate(ci, bh); 7362306a36Sopenharmony_ci } else { 7462306a36Sopenharmony_ci /* We don't need to remove the clustered uptodate 7562306a36Sopenharmony_ci * information for this bh as it's not marked locally 7662306a36Sopenharmony_ci * uptodate. */ 7762306a36Sopenharmony_ci ret = -EIO; 7862306a36Sopenharmony_ci mlog_errno(ret); 7962306a36Sopenharmony_ci } 8062306a36Sopenharmony_ci 8162306a36Sopenharmony_ci ocfs2_metadata_cache_io_unlock(ci); 8262306a36Sopenharmony_ciout: 8362306a36Sopenharmony_ci return ret; 8462306a36Sopenharmony_ci} 8562306a36Sopenharmony_ci 8662306a36Sopenharmony_ci/* Caller must provide a bhs[] with all NULL or non-NULL entries, so it 8762306a36Sopenharmony_ci * will be easier to handle read failure. 8862306a36Sopenharmony_ci */ 8962306a36Sopenharmony_ciint ocfs2_read_blocks_sync(struct ocfs2_super *osb, u64 block, 9062306a36Sopenharmony_ci unsigned int nr, struct buffer_head *bhs[]) 9162306a36Sopenharmony_ci{ 9262306a36Sopenharmony_ci int status = 0; 9362306a36Sopenharmony_ci unsigned int i; 9462306a36Sopenharmony_ci struct buffer_head *bh; 9562306a36Sopenharmony_ci int new_bh = 0; 9662306a36Sopenharmony_ci 9762306a36Sopenharmony_ci trace_ocfs2_read_blocks_sync((unsigned long long)block, nr); 9862306a36Sopenharmony_ci 9962306a36Sopenharmony_ci if (!nr) 10062306a36Sopenharmony_ci goto bail; 10162306a36Sopenharmony_ci 10262306a36Sopenharmony_ci /* Don't put buffer head and re-assign it to NULL if it is allocated 10362306a36Sopenharmony_ci * outside since the caller can't be aware of this alternation! 10462306a36Sopenharmony_ci */ 10562306a36Sopenharmony_ci new_bh = (bhs[0] == NULL); 10662306a36Sopenharmony_ci 10762306a36Sopenharmony_ci for (i = 0 ; i < nr ; i++) { 10862306a36Sopenharmony_ci if (bhs[i] == NULL) { 10962306a36Sopenharmony_ci bhs[i] = sb_getblk(osb->sb, block++); 11062306a36Sopenharmony_ci if (bhs[i] == NULL) { 11162306a36Sopenharmony_ci status = -ENOMEM; 11262306a36Sopenharmony_ci mlog_errno(status); 11362306a36Sopenharmony_ci break; 11462306a36Sopenharmony_ci } 11562306a36Sopenharmony_ci } 11662306a36Sopenharmony_ci bh = bhs[i]; 11762306a36Sopenharmony_ci 11862306a36Sopenharmony_ci if (buffer_jbd(bh)) { 11962306a36Sopenharmony_ci trace_ocfs2_read_blocks_sync_jbd( 12062306a36Sopenharmony_ci (unsigned long long)bh->b_blocknr); 12162306a36Sopenharmony_ci continue; 12262306a36Sopenharmony_ci } 12362306a36Sopenharmony_ci 12462306a36Sopenharmony_ci if (buffer_dirty(bh)) { 12562306a36Sopenharmony_ci /* This should probably be a BUG, or 12662306a36Sopenharmony_ci * at least return an error. */ 12762306a36Sopenharmony_ci mlog(ML_ERROR, 12862306a36Sopenharmony_ci "trying to sync read a dirty " 12962306a36Sopenharmony_ci "buffer! (blocknr = %llu), skipping\n", 13062306a36Sopenharmony_ci (unsigned long long)bh->b_blocknr); 13162306a36Sopenharmony_ci continue; 13262306a36Sopenharmony_ci } 13362306a36Sopenharmony_ci 13462306a36Sopenharmony_ci lock_buffer(bh); 13562306a36Sopenharmony_ci if (buffer_jbd(bh)) { 13662306a36Sopenharmony_ci#ifdef CATCH_BH_JBD_RACES 13762306a36Sopenharmony_ci mlog(ML_ERROR, 13862306a36Sopenharmony_ci "block %llu had the JBD bit set " 13962306a36Sopenharmony_ci "while I was in lock_buffer!", 14062306a36Sopenharmony_ci (unsigned long long)bh->b_blocknr); 14162306a36Sopenharmony_ci BUG(); 14262306a36Sopenharmony_ci#else 14362306a36Sopenharmony_ci unlock_buffer(bh); 14462306a36Sopenharmony_ci continue; 14562306a36Sopenharmony_ci#endif 14662306a36Sopenharmony_ci } 14762306a36Sopenharmony_ci 14862306a36Sopenharmony_ci get_bh(bh); /* for end_buffer_read_sync() */ 14962306a36Sopenharmony_ci bh->b_end_io = end_buffer_read_sync; 15062306a36Sopenharmony_ci submit_bh(REQ_OP_READ, bh); 15162306a36Sopenharmony_ci } 15262306a36Sopenharmony_ci 15362306a36Sopenharmony_ciread_failure: 15462306a36Sopenharmony_ci for (i = nr; i > 0; i--) { 15562306a36Sopenharmony_ci bh = bhs[i - 1]; 15662306a36Sopenharmony_ci 15762306a36Sopenharmony_ci if (unlikely(status)) { 15862306a36Sopenharmony_ci if (new_bh && bh) { 15962306a36Sopenharmony_ci /* If middle bh fails, let previous bh 16062306a36Sopenharmony_ci * finish its read and then put it to 16162306a36Sopenharmony_ci * aovoid bh leak 16262306a36Sopenharmony_ci */ 16362306a36Sopenharmony_ci if (!buffer_jbd(bh)) 16462306a36Sopenharmony_ci wait_on_buffer(bh); 16562306a36Sopenharmony_ci put_bh(bh); 16662306a36Sopenharmony_ci bhs[i - 1] = NULL; 16762306a36Sopenharmony_ci } else if (bh && buffer_uptodate(bh)) { 16862306a36Sopenharmony_ci clear_buffer_uptodate(bh); 16962306a36Sopenharmony_ci } 17062306a36Sopenharmony_ci continue; 17162306a36Sopenharmony_ci } 17262306a36Sopenharmony_ci 17362306a36Sopenharmony_ci /* No need to wait on the buffer if it's managed by JBD. */ 17462306a36Sopenharmony_ci if (!buffer_jbd(bh)) 17562306a36Sopenharmony_ci wait_on_buffer(bh); 17662306a36Sopenharmony_ci 17762306a36Sopenharmony_ci if (!buffer_uptodate(bh)) { 17862306a36Sopenharmony_ci /* Status won't be cleared from here on out, 17962306a36Sopenharmony_ci * so we can safely record this and loop back 18062306a36Sopenharmony_ci * to cleanup the other buffers. */ 18162306a36Sopenharmony_ci status = -EIO; 18262306a36Sopenharmony_ci goto read_failure; 18362306a36Sopenharmony_ci } 18462306a36Sopenharmony_ci } 18562306a36Sopenharmony_ci 18662306a36Sopenharmony_cibail: 18762306a36Sopenharmony_ci return status; 18862306a36Sopenharmony_ci} 18962306a36Sopenharmony_ci 19062306a36Sopenharmony_ci/* Caller must provide a bhs[] with all NULL or non-NULL entries, so it 19162306a36Sopenharmony_ci * will be easier to handle read failure. 19262306a36Sopenharmony_ci */ 19362306a36Sopenharmony_ciint ocfs2_read_blocks(struct ocfs2_caching_info *ci, u64 block, int nr, 19462306a36Sopenharmony_ci struct buffer_head *bhs[], int flags, 19562306a36Sopenharmony_ci int (*validate)(struct super_block *sb, 19662306a36Sopenharmony_ci struct buffer_head *bh)) 19762306a36Sopenharmony_ci{ 19862306a36Sopenharmony_ci int status = 0; 19962306a36Sopenharmony_ci int i, ignore_cache = 0; 20062306a36Sopenharmony_ci struct buffer_head *bh; 20162306a36Sopenharmony_ci struct super_block *sb = ocfs2_metadata_cache_get_super(ci); 20262306a36Sopenharmony_ci int new_bh = 0; 20362306a36Sopenharmony_ci 20462306a36Sopenharmony_ci trace_ocfs2_read_blocks_begin(ci, (unsigned long long)block, nr, flags); 20562306a36Sopenharmony_ci 20662306a36Sopenharmony_ci BUG_ON(!ci); 20762306a36Sopenharmony_ci BUG_ON((flags & OCFS2_BH_READAHEAD) && 20862306a36Sopenharmony_ci (flags & OCFS2_BH_IGNORE_CACHE)); 20962306a36Sopenharmony_ci 21062306a36Sopenharmony_ci if (bhs == NULL) { 21162306a36Sopenharmony_ci status = -EINVAL; 21262306a36Sopenharmony_ci mlog_errno(status); 21362306a36Sopenharmony_ci goto bail; 21462306a36Sopenharmony_ci } 21562306a36Sopenharmony_ci 21662306a36Sopenharmony_ci if (nr < 0) { 21762306a36Sopenharmony_ci mlog(ML_ERROR, "asked to read %d blocks!\n", nr); 21862306a36Sopenharmony_ci status = -EINVAL; 21962306a36Sopenharmony_ci mlog_errno(status); 22062306a36Sopenharmony_ci goto bail; 22162306a36Sopenharmony_ci } 22262306a36Sopenharmony_ci 22362306a36Sopenharmony_ci if (nr == 0) { 22462306a36Sopenharmony_ci status = 0; 22562306a36Sopenharmony_ci goto bail; 22662306a36Sopenharmony_ci } 22762306a36Sopenharmony_ci 22862306a36Sopenharmony_ci /* Don't put buffer head and re-assign it to NULL if it is allocated 22962306a36Sopenharmony_ci * outside since the caller can't be aware of this alternation! 23062306a36Sopenharmony_ci */ 23162306a36Sopenharmony_ci new_bh = (bhs[0] == NULL); 23262306a36Sopenharmony_ci 23362306a36Sopenharmony_ci ocfs2_metadata_cache_io_lock(ci); 23462306a36Sopenharmony_ci for (i = 0 ; i < nr ; i++) { 23562306a36Sopenharmony_ci if (bhs[i] == NULL) { 23662306a36Sopenharmony_ci bhs[i] = sb_getblk(sb, block++); 23762306a36Sopenharmony_ci if (bhs[i] == NULL) { 23862306a36Sopenharmony_ci ocfs2_metadata_cache_io_unlock(ci); 23962306a36Sopenharmony_ci status = -ENOMEM; 24062306a36Sopenharmony_ci mlog_errno(status); 24162306a36Sopenharmony_ci /* Don't forget to put previous bh! */ 24262306a36Sopenharmony_ci break; 24362306a36Sopenharmony_ci } 24462306a36Sopenharmony_ci } 24562306a36Sopenharmony_ci bh = bhs[i]; 24662306a36Sopenharmony_ci ignore_cache = (flags & OCFS2_BH_IGNORE_CACHE); 24762306a36Sopenharmony_ci 24862306a36Sopenharmony_ci /* There are three read-ahead cases here which we need to 24962306a36Sopenharmony_ci * be concerned with. All three assume a buffer has 25062306a36Sopenharmony_ci * previously been submitted with OCFS2_BH_READAHEAD 25162306a36Sopenharmony_ci * and it hasn't yet completed I/O. 25262306a36Sopenharmony_ci * 25362306a36Sopenharmony_ci * 1) The current request is sync to disk. This rarely 25462306a36Sopenharmony_ci * happens these days, and never when performance 25562306a36Sopenharmony_ci * matters - the code can just wait on the buffer 25662306a36Sopenharmony_ci * lock and re-submit. 25762306a36Sopenharmony_ci * 25862306a36Sopenharmony_ci * 2) The current request is cached, but not 25962306a36Sopenharmony_ci * readahead. ocfs2_buffer_uptodate() will return 26062306a36Sopenharmony_ci * false anyway, so we'll wind up waiting on the 26162306a36Sopenharmony_ci * buffer lock to do I/O. We re-check the request 26262306a36Sopenharmony_ci * with after getting the lock to avoid a re-submit. 26362306a36Sopenharmony_ci * 26462306a36Sopenharmony_ci * 3) The current request is readahead (and so must 26562306a36Sopenharmony_ci * also be a caching one). We short circuit if the 26662306a36Sopenharmony_ci * buffer is locked (under I/O) and if it's in the 26762306a36Sopenharmony_ci * uptodate cache. The re-check from #2 catches the 26862306a36Sopenharmony_ci * case that the previous read-ahead completes just 26962306a36Sopenharmony_ci * before our is-it-in-flight check. 27062306a36Sopenharmony_ci */ 27162306a36Sopenharmony_ci 27262306a36Sopenharmony_ci if (!ignore_cache && !ocfs2_buffer_uptodate(ci, bh)) { 27362306a36Sopenharmony_ci trace_ocfs2_read_blocks_from_disk( 27462306a36Sopenharmony_ci (unsigned long long)bh->b_blocknr, 27562306a36Sopenharmony_ci (unsigned long long)ocfs2_metadata_cache_owner(ci)); 27662306a36Sopenharmony_ci /* We're using ignore_cache here to say 27762306a36Sopenharmony_ci * "go to disk" */ 27862306a36Sopenharmony_ci ignore_cache = 1; 27962306a36Sopenharmony_ci } 28062306a36Sopenharmony_ci 28162306a36Sopenharmony_ci trace_ocfs2_read_blocks_bh((unsigned long long)bh->b_blocknr, 28262306a36Sopenharmony_ci ignore_cache, buffer_jbd(bh), buffer_dirty(bh)); 28362306a36Sopenharmony_ci 28462306a36Sopenharmony_ci if (buffer_jbd(bh)) { 28562306a36Sopenharmony_ci continue; 28662306a36Sopenharmony_ci } 28762306a36Sopenharmony_ci 28862306a36Sopenharmony_ci if (ignore_cache) { 28962306a36Sopenharmony_ci if (buffer_dirty(bh)) { 29062306a36Sopenharmony_ci /* This should probably be a BUG, or 29162306a36Sopenharmony_ci * at least return an error. */ 29262306a36Sopenharmony_ci continue; 29362306a36Sopenharmony_ci } 29462306a36Sopenharmony_ci 29562306a36Sopenharmony_ci /* A read-ahead request was made - if the 29662306a36Sopenharmony_ci * buffer is already under read-ahead from a 29762306a36Sopenharmony_ci * previously submitted request than we are 29862306a36Sopenharmony_ci * done here. */ 29962306a36Sopenharmony_ci if ((flags & OCFS2_BH_READAHEAD) 30062306a36Sopenharmony_ci && ocfs2_buffer_read_ahead(ci, bh)) 30162306a36Sopenharmony_ci continue; 30262306a36Sopenharmony_ci 30362306a36Sopenharmony_ci lock_buffer(bh); 30462306a36Sopenharmony_ci if (buffer_jbd(bh)) { 30562306a36Sopenharmony_ci#ifdef CATCH_BH_JBD_RACES 30662306a36Sopenharmony_ci mlog(ML_ERROR, "block %llu had the JBD bit set " 30762306a36Sopenharmony_ci "while I was in lock_buffer!", 30862306a36Sopenharmony_ci (unsigned long long)bh->b_blocknr); 30962306a36Sopenharmony_ci BUG(); 31062306a36Sopenharmony_ci#else 31162306a36Sopenharmony_ci unlock_buffer(bh); 31262306a36Sopenharmony_ci continue; 31362306a36Sopenharmony_ci#endif 31462306a36Sopenharmony_ci } 31562306a36Sopenharmony_ci 31662306a36Sopenharmony_ci /* Re-check ocfs2_buffer_uptodate() as a 31762306a36Sopenharmony_ci * previously read-ahead buffer may have 31862306a36Sopenharmony_ci * completed I/O while we were waiting for the 31962306a36Sopenharmony_ci * buffer lock. */ 32062306a36Sopenharmony_ci if (!(flags & OCFS2_BH_IGNORE_CACHE) 32162306a36Sopenharmony_ci && !(flags & OCFS2_BH_READAHEAD) 32262306a36Sopenharmony_ci && ocfs2_buffer_uptodate(ci, bh)) { 32362306a36Sopenharmony_ci unlock_buffer(bh); 32462306a36Sopenharmony_ci continue; 32562306a36Sopenharmony_ci } 32662306a36Sopenharmony_ci 32762306a36Sopenharmony_ci get_bh(bh); /* for end_buffer_read_sync() */ 32862306a36Sopenharmony_ci if (validate) 32962306a36Sopenharmony_ci set_buffer_needs_validate(bh); 33062306a36Sopenharmony_ci bh->b_end_io = end_buffer_read_sync; 33162306a36Sopenharmony_ci submit_bh(REQ_OP_READ, bh); 33262306a36Sopenharmony_ci continue; 33362306a36Sopenharmony_ci } 33462306a36Sopenharmony_ci } 33562306a36Sopenharmony_ci 33662306a36Sopenharmony_ciread_failure: 33762306a36Sopenharmony_ci for (i = (nr - 1); i >= 0; i--) { 33862306a36Sopenharmony_ci bh = bhs[i]; 33962306a36Sopenharmony_ci 34062306a36Sopenharmony_ci if (!(flags & OCFS2_BH_READAHEAD)) { 34162306a36Sopenharmony_ci if (unlikely(status)) { 34262306a36Sopenharmony_ci /* Clear the buffers on error including those 34362306a36Sopenharmony_ci * ever succeeded in reading 34462306a36Sopenharmony_ci */ 34562306a36Sopenharmony_ci if (new_bh && bh) { 34662306a36Sopenharmony_ci /* If middle bh fails, let previous bh 34762306a36Sopenharmony_ci * finish its read and then put it to 34862306a36Sopenharmony_ci * aovoid bh leak 34962306a36Sopenharmony_ci */ 35062306a36Sopenharmony_ci if (!buffer_jbd(bh)) 35162306a36Sopenharmony_ci wait_on_buffer(bh); 35262306a36Sopenharmony_ci put_bh(bh); 35362306a36Sopenharmony_ci bhs[i] = NULL; 35462306a36Sopenharmony_ci } else if (bh && buffer_uptodate(bh)) { 35562306a36Sopenharmony_ci clear_buffer_uptodate(bh); 35662306a36Sopenharmony_ci } 35762306a36Sopenharmony_ci continue; 35862306a36Sopenharmony_ci } 35962306a36Sopenharmony_ci /* We know this can't have changed as we hold the 36062306a36Sopenharmony_ci * owner sem. Avoid doing any work on the bh if the 36162306a36Sopenharmony_ci * journal has it. */ 36262306a36Sopenharmony_ci if (!buffer_jbd(bh)) 36362306a36Sopenharmony_ci wait_on_buffer(bh); 36462306a36Sopenharmony_ci 36562306a36Sopenharmony_ci if (!buffer_uptodate(bh)) { 36662306a36Sopenharmony_ci /* Status won't be cleared from here on out, 36762306a36Sopenharmony_ci * so we can safely record this and loop back 36862306a36Sopenharmony_ci * to cleanup the other buffers. Don't need to 36962306a36Sopenharmony_ci * remove the clustered uptodate information 37062306a36Sopenharmony_ci * for this bh as it's not marked locally 37162306a36Sopenharmony_ci * uptodate. */ 37262306a36Sopenharmony_ci status = -EIO; 37362306a36Sopenharmony_ci clear_buffer_needs_validate(bh); 37462306a36Sopenharmony_ci goto read_failure; 37562306a36Sopenharmony_ci } 37662306a36Sopenharmony_ci 37762306a36Sopenharmony_ci if (buffer_needs_validate(bh)) { 37862306a36Sopenharmony_ci /* We never set NeedsValidate if the 37962306a36Sopenharmony_ci * buffer was held by the journal, so 38062306a36Sopenharmony_ci * that better not have changed */ 38162306a36Sopenharmony_ci BUG_ON(buffer_jbd(bh)); 38262306a36Sopenharmony_ci clear_buffer_needs_validate(bh); 38362306a36Sopenharmony_ci status = validate(sb, bh); 38462306a36Sopenharmony_ci if (status) 38562306a36Sopenharmony_ci goto read_failure; 38662306a36Sopenharmony_ci } 38762306a36Sopenharmony_ci } 38862306a36Sopenharmony_ci 38962306a36Sopenharmony_ci /* Always set the buffer in the cache, even if it was 39062306a36Sopenharmony_ci * a forced read, or read-ahead which hasn't yet 39162306a36Sopenharmony_ci * completed. */ 39262306a36Sopenharmony_ci ocfs2_set_buffer_uptodate(ci, bh); 39362306a36Sopenharmony_ci } 39462306a36Sopenharmony_ci ocfs2_metadata_cache_io_unlock(ci); 39562306a36Sopenharmony_ci 39662306a36Sopenharmony_ci trace_ocfs2_read_blocks_end((unsigned long long)block, nr, 39762306a36Sopenharmony_ci flags, ignore_cache); 39862306a36Sopenharmony_ci 39962306a36Sopenharmony_cibail: 40062306a36Sopenharmony_ci 40162306a36Sopenharmony_ci return status; 40262306a36Sopenharmony_ci} 40362306a36Sopenharmony_ci 40462306a36Sopenharmony_ci/* Check whether the blkno is the super block or one of the backups. */ 40562306a36Sopenharmony_cistatic void ocfs2_check_super_or_backup(struct super_block *sb, 40662306a36Sopenharmony_ci sector_t blkno) 40762306a36Sopenharmony_ci{ 40862306a36Sopenharmony_ci int i; 40962306a36Sopenharmony_ci u64 backup_blkno; 41062306a36Sopenharmony_ci 41162306a36Sopenharmony_ci if (blkno == OCFS2_SUPER_BLOCK_BLKNO) 41262306a36Sopenharmony_ci return; 41362306a36Sopenharmony_ci 41462306a36Sopenharmony_ci for (i = 0; i < OCFS2_MAX_BACKUP_SUPERBLOCKS; i++) { 41562306a36Sopenharmony_ci backup_blkno = ocfs2_backup_super_blkno(sb, i); 41662306a36Sopenharmony_ci if (backup_blkno == blkno) 41762306a36Sopenharmony_ci return; 41862306a36Sopenharmony_ci } 41962306a36Sopenharmony_ci 42062306a36Sopenharmony_ci BUG(); 42162306a36Sopenharmony_ci} 42262306a36Sopenharmony_ci 42362306a36Sopenharmony_ci/* 42462306a36Sopenharmony_ci * Write super block and backups doesn't need to collaborate with journal, 42562306a36Sopenharmony_ci * so we don't need to lock ip_io_mutex and ci doesn't need to bea passed 42662306a36Sopenharmony_ci * into this function. 42762306a36Sopenharmony_ci */ 42862306a36Sopenharmony_ciint ocfs2_write_super_or_backup(struct ocfs2_super *osb, 42962306a36Sopenharmony_ci struct buffer_head *bh) 43062306a36Sopenharmony_ci{ 43162306a36Sopenharmony_ci int ret = 0; 43262306a36Sopenharmony_ci struct ocfs2_dinode *di = (struct ocfs2_dinode *)bh->b_data; 43362306a36Sopenharmony_ci 43462306a36Sopenharmony_ci BUG_ON(buffer_jbd(bh)); 43562306a36Sopenharmony_ci ocfs2_check_super_or_backup(osb->sb, bh->b_blocknr); 43662306a36Sopenharmony_ci 43762306a36Sopenharmony_ci if (ocfs2_is_hard_readonly(osb) || ocfs2_is_soft_readonly(osb)) { 43862306a36Sopenharmony_ci ret = -EROFS; 43962306a36Sopenharmony_ci mlog_errno(ret); 44062306a36Sopenharmony_ci goto out; 44162306a36Sopenharmony_ci } 44262306a36Sopenharmony_ci 44362306a36Sopenharmony_ci lock_buffer(bh); 44462306a36Sopenharmony_ci set_buffer_uptodate(bh); 44562306a36Sopenharmony_ci 44662306a36Sopenharmony_ci /* remove from dirty list before I/O. */ 44762306a36Sopenharmony_ci clear_buffer_dirty(bh); 44862306a36Sopenharmony_ci 44962306a36Sopenharmony_ci get_bh(bh); /* for end_buffer_write_sync() */ 45062306a36Sopenharmony_ci bh->b_end_io = end_buffer_write_sync; 45162306a36Sopenharmony_ci ocfs2_compute_meta_ecc(osb->sb, bh->b_data, &di->i_check); 45262306a36Sopenharmony_ci submit_bh(REQ_OP_WRITE, bh); 45362306a36Sopenharmony_ci 45462306a36Sopenharmony_ci wait_on_buffer(bh); 45562306a36Sopenharmony_ci 45662306a36Sopenharmony_ci if (!buffer_uptodate(bh)) { 45762306a36Sopenharmony_ci ret = -EIO; 45862306a36Sopenharmony_ci mlog_errno(ret); 45962306a36Sopenharmony_ci } 46062306a36Sopenharmony_ci 46162306a36Sopenharmony_ciout: 46262306a36Sopenharmony_ci return ret; 46362306a36Sopenharmony_ci} 464