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>
This commit is contained in:
parent
619cfac091
commit
0f3c1294be
1 changed files with 66 additions and 64 deletions
118
fs/ufs/inode.c
118
fs/ufs/inode.c
|
@ -205,6 +205,40 @@ changed:
|
||||||
goto again;
|
goto again;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Unpacking tails: we have a file with partial final block and
|
||||||
|
* we had been asked to extend it. If the fragment being written
|
||||||
|
* is within the same block, we need to extend the tail just to cover
|
||||||
|
* that fragment. Otherwise the tail is extended to full block.
|
||||||
|
*
|
||||||
|
* Note that we might need to create a _new_ tail, but that will
|
||||||
|
* be handled elsewhere; this is strictly for resizing old
|
||||||
|
* ones.
|
||||||
|
*/
|
||||||
|
static bool
|
||||||
|
ufs_extend_tail(struct inode *inode, u64 writes_to,
|
||||||
|
int *err, struct page *locked_page)
|
||||||
|
{
|
||||||
|
struct ufs_inode_info *ufsi = UFS_I(inode);
|
||||||
|
struct super_block *sb = inode->i_sb;
|
||||||
|
struct ufs_sb_private_info *uspi = UFS_SB(sb)->s_uspi;
|
||||||
|
unsigned lastfrag = ufsi->i_lastfrag; /* it's a short file, so unsigned is enough */
|
||||||
|
unsigned block = ufs_fragstoblks(lastfrag);
|
||||||
|
unsigned new_size;
|
||||||
|
void *p;
|
||||||
|
u64 tmp;
|
||||||
|
|
||||||
|
if (writes_to < (lastfrag | uspi->s_fpbmask))
|
||||||
|
new_size = (writes_to & uspi->s_fpbmask) + 1;
|
||||||
|
else
|
||||||
|
new_size = uspi->s_fpb;
|
||||||
|
|
||||||
|
p = ufs_get_direct_data_ptr(uspi, ufsi, block);
|
||||||
|
tmp = ufs_new_fragments(inode, p, lastfrag, ufs_data_ptr_to_cpu(sb, p),
|
||||||
|
new_size, err, locked_page);
|
||||||
|
return tmp != 0;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ufs_inode_getfrag() - allocate new fragment(s)
|
* ufs_inode_getfrag() - allocate new fragment(s)
|
||||||
* @inode: pointer to inode
|
* @inode: pointer to inode
|
||||||
|
@ -226,13 +260,10 @@ ufs_inode_getfrag(struct inode *inode, u64 fragment,
|
||||||
struct ufs_inode_info *ufsi = UFS_I(inode);
|
struct ufs_inode_info *ufsi = UFS_I(inode);
|
||||||
struct super_block *sb = inode->i_sb;
|
struct super_block *sb = inode->i_sb;
|
||||||
struct ufs_sb_private_info *uspi = UFS_SB(sb)->s_uspi;
|
struct ufs_sb_private_info *uspi = UFS_SB(sb)->s_uspi;
|
||||||
unsigned blockoff, lastblockoff;
|
unsigned blockoff;
|
||||||
u64 tmp, goal, lastfrag, block, lastblock;
|
u64 tmp, goal, lastfrag, block;
|
||||||
void *p, *p2;
|
unsigned nfrags = uspi->s_fpb;
|
||||||
|
void *p;
|
||||||
UFSD("ENTER, ino %lu, fragment %llu, new_fragment %llu, required %u, "
|
|
||||||
"metadata %d\n", inode->i_ino, (unsigned long long)fragment,
|
|
||||||
(unsigned long long)new_fragment, required, !phys);
|
|
||||||
|
|
||||||
/* TODO : to be done for write support
|
/* TODO : to be done for write support
|
||||||
if ( (flags & UFS_TYPE_MASK) == UFS_TYPE_UFS2)
|
if ( (flags & UFS_TYPE_MASK) == UFS_TYPE_UFS2)
|
||||||
|
@ -242,66 +273,27 @@ ufs_inode_getfrag(struct inode *inode, u64 fragment,
|
||||||
block = ufs_fragstoblks (fragment);
|
block = ufs_fragstoblks (fragment);
|
||||||
blockoff = ufs_fragnum (fragment);
|
blockoff = ufs_fragnum (fragment);
|
||||||
p = ufs_get_direct_data_ptr(uspi, ufsi, block);
|
p = ufs_get_direct_data_ptr(uspi, ufsi, block);
|
||||||
|
|
||||||
goal = 0;
|
|
||||||
|
|
||||||
tmp = ufs_data_ptr_to_cpu(sb, p);
|
tmp = ufs_data_ptr_to_cpu(sb, p);
|
||||||
|
if (tmp)
|
||||||
lastfrag = ufsi->i_lastfrag;
|
|
||||||
if (tmp && fragment < lastfrag)
|
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
lastblock = ufs_fragstoblks (lastfrag);
|
|
||||||
lastblockoff = ufs_fragnum (lastfrag);
|
|
||||||
/*
|
|
||||||
* We will extend file into new block beyond last allocated block
|
|
||||||
*/
|
|
||||||
if (lastblock < block) {
|
|
||||||
/*
|
|
||||||
* We must reallocate last allocated block
|
|
||||||
*/
|
|
||||||
if (lastblockoff) {
|
|
||||||
p2 = ufs_get_direct_data_ptr(uspi, ufsi, lastblock);
|
|
||||||
tmp = ufs_new_fragments(inode, p2, lastfrag,
|
|
||||||
ufs_data_ptr_to_cpu(sb, p2),
|
|
||||||
uspi->s_fpb - lastblockoff,
|
|
||||||
err, locked_page);
|
|
||||||
if (!tmp)
|
|
||||||
return 0;
|
|
||||||
lastfrag = ufsi->i_lastfrag;
|
lastfrag = ufsi->i_lastfrag;
|
||||||
}
|
|
||||||
tmp = ufs_data_ptr_to_cpu(sb,
|
/* will that be a new tail? */
|
||||||
ufs_get_direct_data_ptr(uspi, ufsi,
|
if (new_fragment < UFS_NDIR_FRAGMENT && new_fragment >= lastfrag)
|
||||||
lastblock));
|
nfrags = (new_fragment & uspi->s_fpbmask) + 1;
|
||||||
if (tmp)
|
|
||||||
goal = tmp + uspi->s_fpb;
|
goal = 0;
|
||||||
tmp = ufs_new_fragments (inode, p, fragment - blockoff,
|
|
||||||
goal, required + blockoff,
|
|
||||||
err,
|
|
||||||
phys != NULL ? locked_page : NULL);
|
|
||||||
} else if (lastblock == block) {
|
|
||||||
/*
|
|
||||||
* We will extend last allocated block
|
|
||||||
*/
|
|
||||||
tmp = ufs_new_fragments(inode, p, fragment -
|
|
||||||
(blockoff - lastblockoff),
|
|
||||||
ufs_data_ptr_to_cpu(sb, p),
|
|
||||||
required + (blockoff - lastblockoff),
|
|
||||||
err, phys != NULL ? locked_page : NULL);
|
|
||||||
} else /* (lastblock > block) */ {
|
|
||||||
/*
|
|
||||||
* We will allocate new block before last allocated block
|
|
||||||
*/
|
|
||||||
if (block) {
|
if (block) {
|
||||||
tmp = ufs_data_ptr_to_cpu(sb,
|
goal = ufs_data_ptr_to_cpu(sb,
|
||||||
ufs_get_direct_data_ptr(uspi, ufsi, block - 1));
|
ufs_get_direct_data_ptr(uspi, ufsi, block - 1));
|
||||||
if (tmp)
|
if (goal)
|
||||||
goal = tmp + uspi->s_fpb;
|
goal += uspi->s_fpb;
|
||||||
}
|
}
|
||||||
tmp = ufs_new_fragments(inode, p, fragment - blockoff,
|
tmp = ufs_new_fragments(inode, p, fragment - blockoff,
|
||||||
goal, uspi->s_fpb, err,
|
goal, uspi->s_fpb, err,
|
||||||
phys != NULL ? locked_page : NULL);
|
phys != NULL ? locked_page : NULL);
|
||||||
}
|
|
||||||
if (!tmp) {
|
if (!tmp) {
|
||||||
*err = -ENOSPC;
|
*err = -ENOSPC;
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -419,7 +411,6 @@ static int ufs_getfrag_block(struct inode *inode, sector_t fragment, struct buff
|
||||||
unsigned long ptr,phys;
|
unsigned long ptr,phys;
|
||||||
u64 phys64 = 0;
|
u64 phys64 = 0;
|
||||||
unsigned frag = fragment & uspi->s_fpbmask;
|
unsigned frag = fragment & uspi->s_fpbmask;
|
||||||
unsigned mask = uspi->s_apbmask >> uspi->s_fpbshift;
|
|
||||||
|
|
||||||
if (!create) {
|
if (!create) {
|
||||||
phys64 = ufs_frag_map(inode, offsets, depth);
|
phys64 = ufs_frag_map(inode, offsets, depth);
|
||||||
|
@ -444,6 +435,17 @@ static int ufs_getfrag_block(struct inode *inode, sector_t fragment, struct buff
|
||||||
goto abort_too_big;
|
goto abort_too_big;
|
||||||
|
|
||||||
err = 0;
|
err = 0;
|
||||||
|
|
||||||
|
if (UFS_I(inode)->i_lastfrag < UFS_NDIR_FRAGMENT) {
|
||||||
|
unsigned lastfrag = UFS_I(inode)->i_lastfrag;
|
||||||
|
unsigned tailfrags = lastfrag & uspi->s_fpbmask;
|
||||||
|
if (tailfrags && fragment >= lastfrag) {
|
||||||
|
if (!ufs_extend_tail(inode, fragment,
|
||||||
|
&err, bh_result->b_page))
|
||||||
|
goto abort;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ptr = fragment;
|
ptr = fragment;
|
||||||
|
|
||||||
if (depth == 1) {
|
if (depth == 1) {
|
||||||
|
|
Loading…
Add table
Reference in a new issue