aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/ufs/inode.c116
1 files changed, 76 insertions, 40 deletions
diff --git a/fs/ufs/inode.c b/fs/ufs/inode.c
index c57612d..7228204 100644
--- a/fs/ufs/inode.c
+++ b/fs/ufs/inode.c
@@ -152,7 +152,7 @@ out:
return ret;
}
-static void ufs_clear_block(struct inode *inode, struct buffer_head *bh)
+static void ufs_clear_frag(struct inode *inode, struct buffer_head *bh)
{
lock_buffer(bh);
memset(bh->b_data, 0, inode->i_sb->s_blocksize);
@@ -163,27 +163,52 @@ static void ufs_clear_block(struct inode *inode, struct buffer_head *bh)
sync_dirty_buffer(bh);
}
-static struct buffer_head *ufs_inode_getfrag(struct inode *inode,
- unsigned int fragment, unsigned int new_fragment,
- unsigned int required, int *err, int metadata,
- long *phys, int *new, struct page *locked_page)
+static struct buffer_head *
+ufs_clear_frags(struct inode *inode, sector_t beg,
+ unsigned int n)
+{
+ struct buffer_head *res, *bh;
+ sector_t end = beg + n;
+
+ res = sb_getblk(inode->i_sb, beg);
+ ufs_clear_frag(inode, res);
+ for (++beg; beg < end; ++beg) {
+ bh = sb_getblk(inode->i_sb, beg);
+ ufs_clear_frag(inode, bh);
+ }
+ return res;
+}
+
+/**
+ * ufs_inode_getfrag() - allocate new fragment(s)
+ * @inode - pointer to inode
+ * @fragment - number of `fragment' which hold pointer
+ * to new allocated fragment(s)
+ * @new_fragment - number of new allocated fragment(s)
+ * @required - how many fragment(s) we require
+ * @err - we set it if something wrong
+ * @phys - pointer to where we save physical number of new allocated fragments,
+ * NULL if we allocate not data(indirect blocks for example).
+ * @new - we set it if we allocate new block
+ * @locked_page - for ufs_new_fragments()
+ */
+static struct buffer_head *
+ufs_inode_getfrag(struct inode *inode, unsigned int fragment,
+ sector_t new_fragment, unsigned int required, int *err,
+ long *phys, int *new, struct page *locked_page)
{
struct ufs_inode_info *ufsi = UFS_I(inode);
- struct super_block * sb;
- struct ufs_sb_private_info * uspi;
+ struct super_block *sb = inode->i_sb;
+ struct ufs_sb_private_info *uspi = UFS_SB(sb)->s_uspi;
struct buffer_head * result;
unsigned block, blockoff, lastfrag, lastblock, lastblockoff;
unsigned tmp, goal;
__fs32 * p, * p2;
- unsigned flags = 0;
- UFSD("ENTER, ino %lu, fragment %u, new_fragment %u, required %u\n",
- inode->i_ino, fragment, new_fragment, required);
+ UFSD("ENTER, ino %lu, fragment %u, new_fragment %llu, required %u, "
+ "metadata %d\n", inode->i_ino, fragment,
+ (unsigned long long)new_fragment, required, !phys);
- sb = inode->i_sb;
- uspi = UFS_SB(sb)->s_uspi;
-
- flags = UFS_SB(sb)->s_flags;
/* TODO : to be done for write support
if ( (flags & UFS_TYPE_MASK) == UFS_TYPE_UFS2)
goto ufs2;
@@ -198,7 +223,7 @@ repeat:
tmp = fs32_to_cpu(sb, *p);
lastfrag = ufsi->i_lastfrag;
if (tmp && fragment < lastfrag) {
- if (metadata) {
+ if (!phys) {
result = sb_getblk(sb, uspi->s_sbbase + tmp + blockoff);
if (tmp == fs32_to_cpu(sb, *p)) {
UFSD("EXIT, result %u\n", tmp + blockoff);
@@ -265,9 +290,8 @@ repeat:
return NULL;
}
- if (metadata) {
- result = sb_getblk(inode->i_sb, tmp + blockoff);
- ufs_clear_block(inode, result);
+ if (!phys) {
+ result = ufs_clear_frags(inode, tmp + blockoff, required);
} else {
*phys = tmp + blockoff;
result = NULL;
@@ -298,23 +322,35 @@ repeat2:
*/
}
-static struct buffer_head *ufs_block_getfrag(struct inode *inode, struct buffer_head *bh,
- unsigned int fragment, unsigned int new_fragment,
- unsigned int blocksize, int * err, int metadata,
- long *phys, int *new, struct page *locked_page)
+/**
+ * ufs_inode_getblock() - allocate new block
+ * @inode - pointer to inode
+ * @bh - pointer to block which hold "pointer" to new allocated block
+ * @fragment - number of `fragment' which hold pointer
+ * to new allocated block
+ * @new_fragment - number of new allocated fragment
+ * (block will hold this fragment and also uspi->s_fpb-1)
+ * @err - see ufs_inode_getfrag()
+ * @phys - see ufs_inode_getfrag()
+ * @new - see ufs_inode_getfrag()
+ * @locked_page - see ufs_inode_getfrag()
+ */
+static struct buffer_head *
+ufs_inode_getblock(struct inode *inode, struct buffer_head *bh,
+ unsigned int fragment, sector_t new_fragment, int *err,
+ long *phys, int *new, struct page *locked_page)
{
- struct super_block * sb;
- struct ufs_sb_private_info * uspi;
+ struct super_block *sb = inode->i_sb;
+ struct ufs_sb_private_info *uspi = UFS_SB(sb)->s_uspi;
struct buffer_head * result;
unsigned tmp, goal, block, blockoff;
__fs32 * p;
- sb = inode->i_sb;
- uspi = UFS_SB(sb)->s_uspi;
block = ufs_fragstoblks (fragment);
blockoff = ufs_fragnum (fragment);
- UFSD("ENTER, ino %lu, fragment %u, new_fragment %u\n", inode->i_ino, fragment, new_fragment);
+ UFSD("ENTER, ino %lu, fragment %u, new_fragment %llu, metadata %d\n",
+ inode->i_ino, fragment, (unsigned long long)new_fragment, !phys);
result = NULL;
if (!bh)
@@ -330,7 +366,7 @@ static struct buffer_head *ufs_block_getfrag(struct inode *inode, struct buffer_
repeat:
tmp = fs32_to_cpu(sb, *p);
if (tmp) {
- if (metadata) {
+ if (!phys) {
result = sb_getblk(sb, uspi->s_sbbase + tmp + blockoff);
if (tmp == fs32_to_cpu(sb, *p))
goto out;
@@ -355,9 +391,8 @@ repeat:
}
- if (metadata) {
- result = sb_getblk(sb, tmp + blockoff);
- ufs_clear_block(inode, result);
+ if (!phys) {
+ result = ufs_clear_frags(inode, tmp + blockoff, uspi->s_fpb);
} else {
*phys = tmp + blockoff;
*new = 1;
@@ -375,11 +410,12 @@ out:
return result;
}
-/*
- * This function gets the block which contains the fragment.
+/**
+ * ufs_getfrag_bloc() - `get_block_t' function, interface between UFS and
+ * readpage, writepage and so on
*/
-int ufs_getfrag_block (struct inode *inode, sector_t fragment, struct buffer_head *bh_result, int create)
+int ufs_getfrag_block(struct inode *inode, sector_t fragment, struct buffer_head *bh_result, int create)
{
struct super_block * sb = inode->i_sb;
struct ufs_sb_private_info * uspi = UFS_SB(sb)->s_uspi;
@@ -421,15 +457,15 @@ int ufs_getfrag_block (struct inode *inode, sector_t fragment, struct buffer_hea
* it much more readable:
*/
#define GET_INODE_DATABLOCK(x) \
- ufs_inode_getfrag(inode, x, fragment, 1, &err, 0, &phys, &new, bh_result->b_page)
+ ufs_inode_getfrag(inode, x, fragment, 1, &err, &phys, &new, bh_result->b_page)
#define GET_INODE_PTR(x) \
- ufs_inode_getfrag(inode, x, fragment, uspi->s_fpb, &err, 1, NULL, NULL, bh_result->b_page)
+ ufs_inode_getfrag(inode, x, fragment, uspi->s_fpb, &err, NULL, NULL, bh_result->b_page)
#define GET_INDIRECT_DATABLOCK(x) \
- ufs_block_getfrag(inode, bh, x, fragment, sb->s_blocksize, \
- &err, 0, &phys, &new, bh_result->b_page);
+ ufs_inode_getblock(inode, bh, x, fragment, \
+ &err, &phys, &new, bh_result->b_page);
#define GET_INDIRECT_PTR(x) \
- ufs_block_getfrag(inode, bh, x, fragment, sb->s_blocksize, \
- &err, 1, NULL, NULL, bh_result->b_page);
+ ufs_inode_getblock(inode, bh, x, fragment, \
+ &err, NULL, NULL, bh_result->b_page);
if (ptr < UFS_NDIR_FRAGMENT) {
bh = GET_INODE_DATABLOCK(ptr);