aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ufs
diff options
context:
space:
mode:
authorAl Viro <viro@zeniv.linux.org.uk>2015-06-19 13:40:25 -0400
committerAl Viro <viro@zeniv.linux.org.uk>2015-07-06 17:40:00 -0400
commit0f3c1294bedcc4544c68d6b84699bdaa334b11b8 (patch)
treed93de0d55dcf8cc9d6e30aa6044dcad07ed4452a /fs/ufs
parent619cfac09134b4de7a4f232cf3636cf43728577d (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.c128
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 */
218static bool
219ufs_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) {