diff options
Diffstat (limited to 'fs/ocfs2/buffer_head_io.c')
-rw-r--r-- | fs/ocfs2/buffer_head_io.c | 84 |
1 files changed, 83 insertions, 1 deletions
diff --git a/fs/ocfs2/buffer_head_io.c b/fs/ocfs2/buffer_head_io.c index f136639f5b41..ca4ab7ce85bf 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,6 +88,88 @@ out: | |||
88 | return ret; | 88 | return ret; |
89 | } | 89 | } |
90 | 90 | ||
91 | int ocfs2_read_blocks_sync(struct ocfs2_super *osb, u64 block, | ||
92 | unsigned int nr, struct buffer_head *bhs[]) | ||
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 | |||
91 | int ocfs2_read_blocks(struct ocfs2_super *osb, u64 block, int nr, | 173 | int ocfs2_read_blocks(struct ocfs2_super *osb, u64 block, int nr, |
92 | struct buffer_head *bhs[], int flags, | 174 | struct buffer_head *bhs[], int flags, |
93 | struct inode *inode) | 175 | struct inode *inode) |