diff options
author | Al Viro <viro@zeniv.linux.org.uk> | 2015-06-19 13:40:25 -0400 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2015-07-06 17:40:00 -0400 |
commit | 0f3c1294bedcc4544c68d6b84699bdaa334b11b8 (patch) | |
tree | d93de0d55dcf8cc9d6e30aa6044dcad07ed4452a /fs/ufs | |
parent | 619cfac09134b4de7a4f232cf3636cf43728577d (diff) |
ufs_inode_getfrag(): split extending the partial blocks off
ufs_extend_tail() is handling that now.
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'fs/ufs')
-rw-r--r-- | fs/ufs/inode.c | 128 |
1 files changed, 65 insertions, 63 deletions
diff --git a/fs/ufs/inode.c b/fs/ufs/inode.c index 25d47df934e2..d652f64885fd 100644 --- a/fs/ufs/inode.c +++ b/fs/ufs/inode.c | |||
@@ -205,6 +205,40 @@ changed: | |||
205 | goto again; | 205 | goto again; |
206 | } | 206 | } |
207 | 207 | ||
208 | /* | ||
209 | * Unpacking tails: we have a file with partial final block and | ||
210 | * we had been asked to extend it. If the fragment being written | ||
211 | * is within the same block, we need to extend the tail just to cover | ||
212 | * that fragment. Otherwise the tail is extended to full block. | ||
213 | * | ||
214 | * Note that we might need to create a _new_ tail, but that will | ||
215 | * be handled elsewhere; this is strictly for resizing old | ||
216 | * ones. | ||
217 | */ | ||
218 | static bool | ||
219 | ufs_extend_tail(struct inode *inode, u64 writes_to, | ||
220 | int *err, struct page *locked_page) | ||
221 | { | ||
222 | struct ufs_inode_info *ufsi = UFS_I(inode); | ||
223 | struct super_block *sb = inode->i_sb; | ||
224 | struct ufs_sb_private_info *uspi = UFS_SB(sb)->s_uspi; | ||
225 | unsigned lastfrag = ufsi->i_lastfrag; /* it's a short file, so unsigned is enough */ | ||
226 | unsigned block = ufs_fragstoblks(lastfrag); | ||
227 | unsigned new_size; | ||
228 | void *p; | ||
229 | u64 tmp; | ||
230 | |||
231 | if (writes_to < (lastfrag | uspi->s_fpbmask)) | ||
232 | new_size = (writes_to & uspi->s_fpbmask) + 1; | ||
233 | else | ||
234 | new_size = uspi->s_fpb; | ||
235 | |||
236 | p = ufs_get_direct_data_ptr(uspi, ufsi, block); | ||
237 | tmp = ufs_new_fragments(inode, p, lastfrag, ufs_data_ptr_to_cpu(sb, p), | ||
238 | new_size, err, locked_page); | ||
239 | return tmp != 0; | ||
240 | } | ||
241 | |||
208 | /** | 242 | /** |
209 | * ufs_inode_getfrag() - allocate new fragment(s) | 243 | * ufs_inode_getfrag() - allocate new fragment(s) |
210 | * @inode: pointer to inode | 244 | * @inode: pointer to inode |
@@ -226,13 +260,10 @@ ufs_inode_getfrag(struct inode *inode, u64 fragment, | |||
226 | struct ufs_inode_info *ufsi = UFS_I(inode); | 260 | struct ufs_inode_info *ufsi = UFS_I(inode); |
227 | struct super_block *sb = inode->i_sb; | 261 | struct super_block *sb = inode->i_sb; |
228 | struct ufs_sb_private_info *uspi = UFS_SB(sb)->s_uspi; | 262 | struct ufs_sb_private_info *uspi = UFS_SB(sb)->s_uspi; |
229 | unsigned blockoff, lastblockoff; | 263 | unsigned blockoff; |
230 | u64 tmp, goal, lastfrag, block, lastblock; | 264 | u64 tmp, goal, lastfrag, block; |
231 | void *p, *p2; | 265 | unsigned nfrags = uspi->s_fpb; |
232 | 266 | void *p; | |
233 | UFSD("ENTER, ino %lu, fragment %llu, new_fragment %llu, required %u, " | ||
234 | "metadata %d\n", inode->i_ino, (unsigned long long)fragment, | ||
235 | (unsigned long long)new_fragment, required, !phys); | ||
236 | 267 | ||
237 | /* TODO : to be done for write support | 268 | /* TODO : to be done for write support |
238 | if ( (flags & UFS_TYPE_MASK) == UFS_TYPE_UFS2) | 269 | if ( (flags & UFS_TYPE_MASK) == UFS_TYPE_UFS2) |
@@ -242,66 +273,27 @@ ufs_inode_getfrag(struct inode *inode, u64 fragment, | |||
242 | block = ufs_fragstoblks (fragment); | 273 | block = ufs_fragstoblks (fragment); |
243 | blockoff = ufs_fragnum (fragment); | 274 | blockoff = ufs_fragnum (fragment); |
244 | p = ufs_get_direct_data_ptr(uspi, ufsi, block); | 275 | p = ufs_get_direct_data_ptr(uspi, ufsi, block); |
245 | |||
246 | goal = 0; | ||
247 | |||
248 | tmp = ufs_data_ptr_to_cpu(sb, p); | 276 | tmp = ufs_data_ptr_to_cpu(sb, p); |
277 | if (tmp) | ||
278 | goto out; | ||
249 | 279 | ||
250 | lastfrag = ufsi->i_lastfrag; | 280 | lastfrag = ufsi->i_lastfrag; |
251 | if (tmp && fragment < lastfrag) | ||
252 | goto out; | ||
253 | 281 | ||
254 | lastblock = ufs_fragstoblks (lastfrag); | 282 | /* will that be a new tail? */ |
255 | lastblockoff = ufs_fragnum (lastfrag); | 283 | if (new_fragment < UFS_NDIR_FRAGMENT && new_fragment >= lastfrag) |
256 | /* | 284 | nfrags = (new_fragment & uspi->s_fpbmask) + 1; |
257 | * We will extend file into new block beyond last allocated block | 285 | |
258 | */ | 286 | goal = 0; |
259 | if (lastblock < block) { | 287 | if (block) { |
260 | /* | 288 | goal = ufs_data_ptr_to_cpu(sb, |
261 | * We must reallocate last allocated block | 289 | ufs_get_direct_data_ptr(uspi, ufsi, block - 1)); |
262 | */ | 290 | if (goal) |
263 | if (lastblockoff) { | 291 | goal += uspi->s_fpb; |
264 | p2 = ufs_get_direct_data_ptr(uspi, ufsi, lastblock); | ||
265 | tmp = ufs_new_fragments(inode, p2, lastfrag, | ||
266 | ufs_data_ptr_to_cpu(sb, p2), | ||
267 | uspi->s_fpb - lastblockoff, | ||
268 | err, locked_page); | ||
269 | if (!tmp) | ||
270 | return 0; | ||
271 | lastfrag = ufsi->i_lastfrag; | ||
272 | } | ||
273 | tmp = ufs_data_ptr_to_cpu(sb, | ||
274 | ufs_get_direct_data_ptr(uspi, ufsi, | ||
275 | lastblock)); | ||
276 | if (tmp) | ||
277 | goal = tmp + uspi->s_fpb; | ||
278 | tmp = ufs_new_fragments (inode, p, fragment - blockoff, | ||
279 | goal, required + blockoff, | ||
280 | err, | ||
281 | phys != NULL ? locked_page : NULL); | ||
282 | } else if (lastblock == block) { | ||
283 | /* | ||
284 | * We will extend last allocated block | ||
285 | */ | ||
286 | tmp = ufs_new_fragments(inode, p, fragment - | ||
287 | (blockoff - lastblockoff), | ||
288 | ufs_data_ptr_to_cpu(sb, p), | ||
289 | required + (blockoff - lastblockoff), | ||
290 | err, phys != NULL ? locked_page : NULL); | ||
291 | } else /* (lastblock > block) */ { | ||
292 | /* | ||
293 | * We will allocate new block before last allocated block | ||
294 | */ | ||
295 | if (block) { | ||
296 | tmp = ufs_data_ptr_to_cpu(sb, | ||
297 | ufs_get_direct_data_ptr(uspi, ufsi, block - 1)); | ||
298 | if (tmp) | ||
299 | goal = tmp + uspi->s_fpb; | ||
300 | } | ||
301 | tmp = ufs_new_fragments(inode, p, fragment - blockoff, | ||
302 | goal, uspi->s_fpb, err, | ||
303 | phys != NULL ? locked_page : NULL); | ||
304 | } | 292 | } |
293 | tmp = ufs_new_fragments(inode, p, fragment - blockoff, | ||
294 | goal, uspi->s_fpb, err, | ||
295 | phys != NULL ? locked_page : NULL); | ||
296 | |||
305 | if (!tmp) { | 297 | if (!tmp) { |
306 | *err = -ENOSPC; | 298 | *err = -ENOSPC; |
307 | return 0; | 299 | return 0; |
@@ -419,7 +411,6 @@ static int ufs_getfrag_block(struct inode *inode, sector_t fragment, struct buff | |||
419 | unsigned long ptr,phys; | 411 | unsigned long ptr,phys; |
420 | u64 phys64 = 0; | 412 | u64 phys64 = 0; |
421 | unsigned frag = fragment & uspi->s_fpbmask; | 413 | unsigned frag = fragment & uspi->s_fpbmask; |
422 | unsigned mask = uspi->s_apbmask >> uspi->s_fpbshift; | ||
423 | 414 | ||
424 | if (!create) { | 415 | if (!create) { |
425 | phys64 = ufs_frag_map(inode, offsets, depth); | 416 | phys64 = ufs_frag_map(inode, offsets, depth); |
@@ -444,6 +435,17 @@ static int ufs_getfrag_block(struct inode *inode, sector_t fragment, struct buff | |||
444 | goto abort_too_big; | 435 | goto abort_too_big; |
445 | 436 | ||
446 | err = 0; | 437 | err = 0; |
438 | |||
439 | if (UFS_I(inode)->i_lastfrag < UFS_NDIR_FRAGMENT) { | ||
440 | unsigned lastfrag = UFS_I(inode)->i_lastfrag; | ||
441 | unsigned tailfrags = lastfrag & uspi->s_fpbmask; | ||
442 | if (tailfrags && fragment >= lastfrag) { | ||
443 | if (!ufs_extend_tail(inode, fragment, | ||
444 | &err, bh_result->b_page)) | ||
445 | goto abort; | ||
446 | } | ||
447 | } | ||
448 | |||
447 | ptr = fragment; | 449 | ptr = fragment; |
448 | 450 | ||
449 | if (depth == 1) { | 451 | if (depth == 1) { |