From: Pavel Fedin <sonic.amiga@gmail.com>
To: linux-fsdevel@vger.kernel.org
Subject: [PATCH 4/9] Amiga SmartFileSystem
Date: Mon, 9 Feb 2009 09:55:00 +0300 [thread overview]
Message-ID: <187c6cc60902082255l1475ac1al80b8fc7e206b0bf2@mail.gmail.com> (raw)
diff -ruN linux-source-2.6.24.orig/fs/asfs/extents.c
linux-source-2.6.24/fs/asfs/extents.c
--- linux-source-2.6.24.orig/fs/asfs/extents.c 1970-01-01
03:00:00.000000000 +0300
+++ linux-source-2.6.24/fs/asfs/extents.c 2008-12-14
23:05:05.000000000 +0300
@@ -0,0 +1,586 @@
+/*
+ *
+ * Amiga Smart File System, Linux implementation
+ * version: 1.0beta11
+ *
+ * This file contains some parts of the original amiga version of
+ * SmartFilesystem source code.
+ *
+ * SmartFilesystem is copyrighted (C) 2003 by: John Hendrikx,
+ * Ralph Schmidt, Emmanuel Lesueur, David Gerber and Marcin Kurek
+ *
+ * Adapted and modified by Marek 'March' Szyprowski <marek@amiga.pl>
+ *
+ */
+
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/slab.h>
+#include <linux/fs.h>
+#include <linux/buffer_head.h>
+#include <linux/vfs.h>
+#include "asfs_fs.h"
+
+#include <asm/byteorder.h>
+
+ /* This function looks for the BNode equal to the key. If no
+ exact match is available then the BNode which is slightly
+ lower than key will be returned. If no such BNode exists
+ either, then the first BNode in this block is returned.
+
+ This function will return the first BNode even if there
+ are no BNode's at all in this block (this can only happen
+ for the Root of the tree). Be sure to check if the Root
+ is not empty before calling this function. */
+
+static struct BNode *searchforbnode(u32 key, struct BTreeContainer *tc)
+{
+ struct BNode *tn;
+ s16 n = be16_to_cpu(tc->nodecount) - 1;
+
+ tn = (struct BNode *) ((u8 *) tc->bnode + n * tc->nodesize);
+ for (;;) {
+ if (n <= 0 || key >= be32_to_cpu(tn->key))
+ return tn;
+
+ tn = (struct BNode *) ((u8 *) tn - tc->nodesize);
+ n--;
+ }
+}
+
+/* This function finds the BNode with the given key. If no exact match can be
+ found then this function will return either the next or previous closest
+ match (don't rely on this).
+
+ If there were no BNode's at all, then *returned_bh will be NULL. */
+
+static int findbnode(struct super_block *sb, u32 key, struct
buffer_head **returned_bh, struct BNode **returned_bnode)
+{
+ u32 rootblock = ASFS_SB(sb)->extentbnoderoot;
+
+ asfs_debug("findbnode: Looking for BNode with key %d\n", key);
+
+ while ((*returned_bh = asfs_breadcheck(sb, rootblock,
ASFS_BNODECONTAINER_ID))) {
+ struct fsBNodeContainer *bnc = (void *) (*returned_bh)->b_data;
+ struct BTreeContainer *btc = &bnc->btc;
+
+ if (btc->nodecount == 0) {
+ *returned_bnode = NULL;
+ break;
+ }
+
+ *returned_bnode = searchforbnode(key, btc);
+ if (btc->isleaf == TRUE)
+ break;
+
+ rootblock = be32_to_cpu((*returned_bnode)->data);
+ asfs_brelse(*returned_bh);
+ }
+
+ if (*returned_bh == NULL)
+ return -EIO;
+
+ return 0;
+}
+
+int asfs_getextent(struct super_block *sb, u32 key, struct
buffer_head **ret_bh, struct fsExtentBNode **ret_ebn)
+{
+ int result;
+ if ((result = findbnode(sb, key, ret_bh, (struct BNode
**)ret_ebn)) == 0)
+ if (be32_to_cpu((*ret_ebn)->key) != key) {
+ brelse(*ret_bh);
+ *ret_bh = NULL;
+ return -ENOENT;
+ }
+
+ return result;
+}
+
+#ifdef CONFIG_ASFS_RW
+
+ /* This routine inserts a node sorted into a BTreeContainer. It does
+ this by starting at the end, and moving the nodes one by one to
+ a higher slot until the empty slot has the correct position for
+ this key. Donot use this function on completely filled
+ BTreeContainers! */
+
+static struct BNode *insertbnode(u32 key, struct BTreeContainer *btc)
+{
+ struct BNode *bn;
+ bn = (struct BNode *) ((u8 *) btc->bnode + btc->nodesize *
(be16_to_cpu(btc->nodecount) - 1));
+
+ for (;;) {
+ if (bn < btc->bnode || key > be32_to_cpu(bn->key)) {
+ bn = (struct BNode *) ((u8 *) bn + btc->nodesize);
+ bn->key = cpu_to_be32(key);
+ btc->nodecount =
cpu_to_be16(be16_to_cpu(btc->nodecount) + 1);
+ break;
+ } else
+ memmove((u8 *)bn + btc->nodesize, bn, btc->nodesize);
+
+ bn = (struct BNode *) ((u8 *) bn - btc->nodesize);
+ }
+
+ return bn;
+}
+
+static int getparentbtreecontainer(struct super_block *sb, struct
buffer_head *bh, struct buffer_head **parent_bh)
+{
+ u32 rootblock = ASFS_SB(sb)->extentbnoderoot;
+ u32 childkey = be32_to_cpu(((struct fsBNodeContainer *)
bh->b_data)->btc.bnode[0].key);
+ u32 childblock = be32_to_cpu(((struct fsBNodeContainer *)
bh->b_data)->bheader.ownblock);
+
+ asfs_debug("getparentbtreecontainer: Getting parent of block
%d\n", childblock);
+
+ /* This function gets the BTreeContainer parent of the passed
in buffer_head. If
+ there is no parent this function sets dest_cont io_bh to NULL */
+
+ if (rootblock != childblock) {
+ while ((*parent_bh = asfs_breadcheck(sb, rootblock,
ASFS_BNODECONTAINER_ID))) {
+ struct fsBNodeContainer *bnc = (void *)
(*parent_bh)->b_data;
+ struct BTreeContainer *btc = &bnc->btc;
+ struct BNode *bn;
+ s16 n = be16_to_cpu(btc->nodecount);
+
+ if (btc->isleaf == TRUE) {
+ asfs_brelse(*parent_bh);
+ break;
+ }
+
+ while (n-- > 0)
+ if (be32_to_cpu(btc->bnode[n].data) ==
childblock)
+ return 0; /* Found parent!! */
+
+ bn = searchforbnode(childkey, btc); /*
This searchforbnode() doesn't have to get EXACT key matches. */
+ rootblock = be32_to_cpu(bn->data);
+ asfs_brelse(*parent_bh);
+ }
+ if (*parent_bh == NULL)
+ return -EIO;
+ }
+
+ *parent_bh = NULL;
+ return 0;
+}
+
+/* Spits a btreecontainer. It realses passed in bh! */
+
+static int splitbtreecontainer(struct super_block *sb, struct buffer_head *bh)
+{
+ struct buffer_head *bhparent;
+ struct BNode *bn;
+ int errorcode;
+
+ asfs_debug("splitbtreecontainer: splitting block %u\n",
be32_to_cpu(((struct fsBlockHeader *) bh->b_data)->ownblock));
+
+ if ((errorcode = getparentbtreecontainer(sb, bh, &bhparent)) == 0) {
+ if (bhparent == NULL) {
+ u32 newbcontblock;
+ u32 bcontblock;
+ /* We need to create Root tree-container -
adding new level to extent tree */
+
+ asfs_debug("splitbtreecontainer: creating root
tree-container.\n");
+
+ bhparent = bh;
+ if ((errorcode = asfs_allocadminspace(sb,
&newbcontblock)) == 0 && (bh = asfs_getzeroblk(sb, newbcontblock))) {
+ struct fsBNodeContainer *bnc = (void
*) bh->b_data;
+ struct fsBNodeContainer *bncparent =
(void *) bhparent->b_data;
+ struct BTreeContainer *btcparent =
&bncparent->btc;
+
+ bcontblock =
be32_to_cpu(bncparent->bheader.ownblock);
+ memcpy(bh->b_data, bhparent->b_data,
sb->s_blocksize);
+ bnc->bheader.ownblock =
cpu_to_be32(newbcontblock);
+ asfs_bstore(sb, bh);
+
+ memset(bhparent->b_data, '\0',
sb->s_blocksize); /* Not strictly needed, but makes things more
clear. */
+ bncparent->bheader.id =
cpu_to_be32(ASFS_BNODECONTAINER_ID);
+ bncparent->bheader.ownblock =
cpu_to_be32(bcontblock);
+ btcparent->isleaf = FALSE;
+ btcparent->nodesize = sizeof(struct BNode);
+ btcparent->nodecount = 0;
+
+ bn = insertbnode(0, btcparent);
+ bn->data = cpu_to_be32(newbcontblock);
+
+ asfs_bstore(sb, bhparent);
+ }
+ if (bh == NULL)
+ errorcode = -EIO;
+ }
+
+ if (errorcode == 0) {
+ struct fsBNodeContainer *bncparent = (void *)
bhparent->b_data;
+ struct BTreeContainer *btcparent = &bncparent->btc;
+ int branches1 = (sb->s_blocksize -
sizeof(struct fsBNodeContainer)) / btcparent->nodesize;
+
+ if (be16_to_cpu(btcparent->nodecount) == branches1) {
+ /* We need to split the parent
tree-container first! */
+ if ((errorcode =
splitbtreecontainer(sb, bhparent)) == 0) {
+ /* bhparent might have changed
after the split and has been released */
+ if ((errorcode =
getparentbtreecontainer(sb, bh, &bhparent)) == 0) {
+ bncparent = (void *)
bhparent->b_data;
+ btcparent = &bncparent->btc;
+ }
+ }
+ }
+
+ if (errorcode == 0) {
+ u32 newbcontblock;
+ struct buffer_head *bhnew;
+
+ /* We can split this container and add
it to the parent
+ because the parent has enough room. */
+
+ if ((errorcode =
asfs_allocadminspace(sb, &newbcontblock)) == 0 && (bhnew =
asfs_getzeroblk(sb, newbcontblock))) {
+ struct fsBNodeContainer
*bncnew = (void *) bhnew->b_data;
+ struct BTreeContainer *btcnew
= &bncnew->btc;
+ struct fsBNodeContainer *bnc =
(void *) bh->b_data;
+ struct BTreeContainer *btc = &bnc->btc;
+ int branches2 =
(sb->s_blocksize - sizeof(struct fsBNodeContainer)) / btc->nodesize;
+ u32 newkey;
+
+ bncnew->bheader.id =
cpu_to_be32(ASFS_BNODECONTAINER_ID);
+ bncnew->bheader.ownblock =
cpu_to_be32(newbcontblock);
+
+ btcnew->isleaf = btc->isleaf;
+ btcnew->nodesize = btc->nodesize;
+
+ btcnew->nodecount =
cpu_to_be16(branches2 - branches2 / 2);
+
+ memcpy(btcnew->bnode, (u8 *)
btc->bnode + branches2 / 2 * btc->nodesize, (branches2 - branches2 /
2) * btc->nodesize);
+ newkey =
be32_to_cpu(btcnew->bnode[0].key);
+
+ asfs_bstore(sb, bhnew);
+ asfs_brelse(bhnew);
+
+ btc->nodecount =
cpu_to_be16(branches2 / 2);
+ asfs_bstore(sb, bh);
+
+ bn = insertbnode(newkey, btcparent);
+ bn->data = cpu_to_be32(newbcontblock);
+ asfs_bstore(sb, bhparent);
+ }
+ }
+ }
+ asfs_brelse(bhparent);
+ }
+ asfs_brelse(bh);
+
+ return errorcode;
+}
+
+/* Returns created extentbnode - returned_bh need to saved and
realesed in caller funkction! */
+
+static int createextentbnode(struct super_block *sb, u32 key, struct
buffer_head **returned_bh, struct BNode **returned_bnode)
+{
+ int errorcode;
+
+ asfs_debug("createbnode: Creating BNode with key %d\n", key);
+
+ while ((errorcode = findbnode(sb, key, returned_bh,
returned_bnode)) == 0) {
+ struct fsBNodeContainer *bnc = (void *) (*returned_bh)->b_data;
+ struct BTreeContainer *btc = &bnc->btc;
+ int extbranches = (sb->s_blocksize - sizeof(struct
fsBNodeContainer)) / btc->nodesize;
+
+ asfs_debug("createbnode: findbnode found block %d\n",
be32_to_cpu(((struct fsBlockHeader *)
(*returned_bh)->b_data)->ownblock));
+
+ if (be16_to_cpu(btc->nodecount) < extbranches) {
+ /* Simply insert new node in this BTreeContainer */
+ asfs_debug("createbnode: Simple insert\n");
+ *returned_bnode = insertbnode(key, btc);
+ break;
+ } else if ((errorcode = splitbtreecontainer(sb,
*returned_bh)) != 0)
+ break;
+
+ /* Loop and try insert it the normal way again :-) */
+ }
+
+ return (errorcode);
+}
+
+
+/* This routine removes a node from a BTreeContainer indentified
+ by its key. If no such key exists this routine does nothing.
+ It correctly handles empty BTreeContainers. */
+
+static void removebnode(u32 key, struct BTreeContainer *btc)
+{
+ struct BNode *bn = btc->bnode;
+ int n = 0;
+
+ asfs_debug("removebnode: key %d\n", key);
+
+ while (n < be16_to_cpu(btc->nodecount)) {
+ if (be32_to_cpu(bn->key) == key) {
+ btc->nodecount =
cpu_to_be16(be16_to_cpu(btc->nodecount) - 1);
+ memmove(bn, (u8 *) bn + btc->nodesize,
(be16_to_cpu(btc->nodecount) - n) * btc->nodesize);
+ break;
+ }
+ bn = (struct BNode *) ((u8 *) bn + btc->nodesize);
+ n++;
+ }
+}
+
+int asfs_deletebnode(struct super_block *sb, struct buffer_head *bh, u32 key)
+{
+ struct fsBNodeContainer *bnc1 = (void *) bh->b_data;
+ struct BTreeContainer *btc = &bnc1->btc;
+ u16 branches = (sb->s_blocksize - sizeof(struct
fsBNodeContainer)) / btc->nodesize;
+ int errorcode = 0;
+
+ /* Deletes specified internal node. */
+
+ removebnode(key, btc);
+ asfs_bstore(sb, bh);
+
+ /* Now checks if the container still contains enough nodes,
+ and takes action accordingly. */
+
+ asfs_debug("deletebnode: branches = %d, btc->nodecount =
%d\n", branches, be16_to_cpu(btc->nodecount));
+
+ if (be16_to_cpu(btc->nodecount) < (branches + 1) / 2) {
+ struct buffer_head *bhparent;
+ struct buffer_head *bhsec;
+
+ /* nodecount has become to low. We need to merge this Container
+ with a neighbouring Container, or we need to steal
a few nodes
+ from a neighbouring Container. */
+
+ /* We get the parent of the container here, so we can
find out what
+ containers neighbour the container which currently
hasn't got enough nodes. */
+
+ if ((errorcode = getparentbtreecontainer(sb, bh,
&bhparent)) == 0) {
+ if (bhparent != NULL) {
+ struct fsBNodeContainer *bncparent =
(void *) bhparent->b_data;
+ struct BTreeContainer *btcparent =
&bncparent->btc;
+ s16 n;
+
+ asfs_debug("deletebnode: get parent
returned block %d.\n", be32_to_cpu(((struct fsBlockHeader *)
bhparent->b_data)->ownblock));
+
+ for (n = 0; n <
be16_to_cpu(btcparent->nodecount); n++)
+ if (btcparent->bnode[n].data
== bnc1->bheader.ownblock)
+ break;
+ /* n is now the offset of our own bnode. */
+
+ if (n <
be16_to_cpu(btcparent->nodecount) - 1) { /* Check if we have a
next neighbour. */
+ asfs_debug("deletebnode: using
next container - merging blocks %d and %d\n",
be32_to_cpu(bnc1->bheader.ownblock),
be32_to_cpu(btcparent->bnode[n+1].data));
+
+ if ((bhsec =
asfs_breadcheck(sb, be32_to_cpu(btcparent->bnode[n + 1].data),
ASFS_BNODECONTAINER_ID))) {
+ struct
fsBNodeContainer *bnc_next = (void *) bhsec->b_data;
+ struct BTreeContainer
*btc_next = &bnc_next->btc;
+
+ if
(be16_to_cpu(btc_next->nodecount) + be16_to_cpu(btc->nodecount) >
branches) { /* Check if we need to steal nodes. */
+ s16
nodestosteal = (be16_to_cpu(btc_next->nodecount) +
be16_to_cpu(btc->nodecount)) / 2 - be16_to_cpu(btc->nodecount);
+
+ /* Merging
them is not possible. Steal a few nodes then. */
+ memcpy((u8 *)
btc->bnode + be16_to_cpu(btc->nodecount) * btc->nodesize,
btc_next->bnode, nodestosteal * btc->nodesize);
+ btc->nodecount
= cpu_to_be16(be16_to_cpu(btc->nodecount) + nodestosteal);
+ asfs_bstore(sb, bh);
+
+
memcpy(btc_next->bnode, (u8 *) btc_next->bnode + btc_next->nodesize *
nodestosteal,
+
btc->nodesize * (be16_to_cpu(btc_next->nodecount) - nodestosteal));
+
btc_next->nodecount = cpu_to_be16(be16_to_cpu(btc_next->nodecount) -
nodestosteal);
+ asfs_bstore(sb, bhsec);
+
+
btcparent->bnode[n + 1].key = btc_next->bnode[0].key;
+
asfs_bstore(sb, bhparent);
+ } else { /*
Merging is possible. */
+ memcpy((u8 *)
btc->bnode + btc->nodesize * be16_to_cpu(btc->nodecount),
btc_next->bnode, btc->nodesize * be16_to_cpu(btc_next->nodecount));
+ btc->nodecount
= cpu_to_be16(be16_to_cpu(btc->nodecount) +
be16_to_cpu(btc_next->nodecount));
+ asfs_bstore(sb, bh);
+
+ if ((errorcode
= asfs_freeadminspace(sb, be32_to_cpu(((struct fsBlockHeader *)
bhsec->b_data)->ownblock))) == 0)
+
errorcode = asfs_deletebnode(sb, bhparent,
be32_to_cpu(btcparent->bnode[n + 1].key));
+ }
+ asfs_brelse(bhsec);
+ }
+ } else if (n > 0) { /* Check if we
have a previous neighbour. */
+ asfs_debug("deletebnode: using
prev container.\n");
+
+ if ((bhsec =
asfs_breadcheck(sb, be32_to_cpu(btcparent->bnode[n - 1].data),
ASFS_BNODECONTAINER_ID)) == 0) {
+ struct
fsBNodeContainer *bnc2 = (void *) bhsec->b_data;
+ struct BTreeContainer
*btc2 = &bnc2->btc;
+
+ if
(be16_to_cpu(btc2->nodecount) + be16_to_cpu(btc->nodecount) >
branches) {
+ /* Merging
them is not possible. Steal a few nodes then. */
+ s16
nodestosteal = (be16_to_cpu(btc2->nodecount) +
be16_to_cpu(btc->nodecount)) / 2 - be16_to_cpu(btc->nodecount);
+
+ memmove((u8 *)
btc->bnode + nodestosteal * btc->nodesize, btc->bnode,
be16_to_cpu(btc->nodecount) * btc->nodesize);
+ btc->nodecount
= cpu_to_be16(be16_to_cpu(btc->nodecount) + nodestosteal);
+
memcpy(btc->bnode, (u8 *) btc2->bnode + (be16_to_cpu(btc2->nodecount)
- nodestosteal) * btc2->nodesize, nodestosteal * btc->nodesize);
+
+ asfs_bstore(sb, bh);
+
+
btc2->nodecount = cpu_to_be16(be16_to_cpu(btc2->nodecount) -
nodestosteal);
+ asfs_bstore(sb, bhsec);
+
+
btcparent->bnode[n].key = btc->bnode[0].key;
+
asfs_bstore(sb, bhparent);
+ } else { /*
Merging is possible. */
+ memcpy((u8 *)
btc2->bnode + be16_to_cpu(btc2->nodecount) * btc2->nodesize,
btc->bnode, be16_to_cpu(btc->nodecount) * btc->nodesize);
+
btc2->nodecount = cpu_to_be16(be16_to_cpu(btc2->nodecount) +
be16_to_cpu(btc->nodecount));
+ asfs_bstore(sb, bhsec);
+
+ if ((errorcode
= asfs_freeadminspace(sb, be32_to_cpu(((struct fsBlockHeader *)
bhsec->b_data)->ownblock))) == 0)
+
errorcode = asfs_deletebnode(sb, bhparent,
be32_to_cpu(btcparent->bnode[n].key));
+ }
+ asfs_brelse(bhsec);
+ }
+ }
+ /* else
+ {
+ // Never happens, except for root
and then we don't care.
+ } */
+ } else if (btc->nodecount == 1) {
+ /* No parent, so must be root. */
+
+ asfs_debug("deletebnode: no parent so
must be root\n");
+
+ if (btc->isleaf == FALSE) {
+ struct fsBNodeContainer *bnc3
= (void *) bh->b_data;
+
+ /* The current root has only 1
node. We now copy the data of this node into the
+ root and promote that data
to be the new root. The rootblock number stays the
+ same that way. */
+
+ if ((bhsec =
asfs_breadcheck(sb, be32_to_cpu(btc->bnode[0].data),
ASFS_BNODECONTAINER_ID))) {
+ u32 blockno =
be32_to_cpu(((struct fsBlockHeader *) bh->b_data)->ownblock);
+ memcpy(bh->b_data,
bhsec->b_data, sb->s_blocksize);
+ bnc3->bheader.ownblock
= cpu_to_be32(blockno);
+
+ asfs_bstore(sb, bh);
+ errorcode =
asfs_freeadminspace(sb, be32_to_cpu(((struct fsBlockHeader *)
bhsec->b_data)->ownblock));
+ asfs_brelse(bhsec);
+ } else
+ errorcode = -EIO;
+ }
+ /* If not, then root contains leafs. */
+ }
+
+ asfs_debug("deletebnode: almost done\n");
+ /* otherwise, it must be the root, and the
root is allowed
+ to contain less than the minimum amount of nodes. */
+
+ }
+ if (bhparent != NULL)
+ asfs_brelse(bhparent);
+ }
+
+ return errorcode;
+}
+
+ /* Deletes an fsExtentBNode structure by key and any
fsExtentBNodes linked to it.
+ This function DOES NOT fix the next pointer in a possible
fsExtentBNode which
+ might have been pointing to the first BNode we are deleting.
Make sure you check
+ this yourself, if needed.
+
+ If key is zero, than this function does nothing. */
+
+int asfs_deleteextents(struct super_block *sb, u32 key)
+{
+ struct buffer_head *bh;
+ struct fsExtentBNode *ebn;
+ int errorcode = 0;
+
+ asfs_debug("deleteextents: Entry -- deleting extents from key
%d\n", key);
+
+ while (key != 0 && (errorcode = findbnode(sb, key, &bh,
(struct BNode **) &ebn)) == 0) {
+ /* node to be deleted located. */
+ key = be32_to_cpu(ebn->next);
+ if ((errorcode = asfs_freespace(sb,
be32_to_cpu(ebn->key), be16_to_cpu(ebn->blocks))) != 0)
+ break;
+
+ if ((errorcode = asfs_deletebnode(sb, bh,
be32_to_cpu(ebn->key))) != 0)
+ break;
+
+ asfs_brelse(bh);
+ }
+
+ return (errorcode);
+}
+
+ /* This function adds /blocks/ blocks starting at block /newspace/ to a file
+ identified by /objectnode/ and /lastextentbnode/.
/io_lastextentbnode/ can
+ be zero if there is no ExtentBNode chain attached to this file yet.
+ /blocks/ ranges from 1 to 8192. To be able to extend Extents which are
+ almost full, it is wise to make this value no higher than 8192 blocks.
+ /io_lastextentbnode/ will contain the new lastextentbnode value when this
+ function completes.
+ If there was no chain yet, then this function will create a new one. */
+
+int asfs_addblocks(struct super_block *sb, u16 blocks, u32 newspace,
u32 objectnode, u32 *io_lastextentbnode)
+{
+ struct buffer_head *bh;
+ struct fsExtentBNode *ebn;
+ int errorcode = 0;
+
+ if (*io_lastextentbnode != 0) {
+ /* There was already a ExtentBNode chain for this
file. Extending it. */
+
+ asfs_debug(" addblocks: Extending existing
ExtentBNode chain.\n");
+
+ if ((errorcode = asfs_getextent(sb,
*io_lastextentbnode, &bh, &ebn)) == 0) {
+ if (be32_to_cpu(ebn->key) +
be16_to_cpu(ebn->blocks) == newspace && be16_to_cpu(ebn->blocks) +
blocks < 65536) {
+ /* It is possible to extent the last
ExtentBNode! */
+ asfs_debug(" addblocks: Extending
last ExtentBNode.\n");
+
+ ebn->blocks =
cpu_to_be16(be16_to_cpu(ebn->blocks) + blocks);
+
+ asfs_bstore(sb, bh);
+ asfs_brelse(bh);
+ } else {
+ /* It isn't possible to extent the
last ExtentBNode so we create
+ a new one and link it to the last
ExtentBNode. */
+
+ ebn->next = cpu_to_be32(newspace);
+ asfs_bstore(sb, bh);
+ asfs_brelse(bh);
+
+ if ((errorcode = createextentbnode(sb,
newspace, &bh, (struct BNode **) &ebn)) == 0) {
+ asfs_debug(" addblocks:
Created new ExtentBNode.\n");
+
+ ebn->key = cpu_to_be32(newspace);
+ ebn->prev =
cpu_to_be32(*io_lastextentbnode);
+ ebn->next = 0;
+ ebn->blocks = cpu_to_be16(blocks);
+
+ *io_lastextentbnode = newspace;
+
+ asfs_bstore(sb, bh);
+ asfs_brelse(bh);
+
+
ASFS_SB(sb)->block_rovingblockptr = newspace + blocks;
+
+ /* to be changed in the future */
+/* if
(ASFS_SB(sb)->block_rovingblockptr >= ASFS_SB(sb)->totalblocks)
+
ASFS_SB(sb)->block_rovingblockptr = 0;*/
+ }
+ }
+ }
+ } else {
+ /* There is no ExtentBNode chain yet for this file.
Attaching one! */
+ if ((errorcode = createextentbnode(sb, newspace, &bh,
(struct BNode **) &ebn)) == 0) {
+ asfs_debug(" addblocks: Created new
ExtentBNode chain.\n");
+
+ ebn->key = cpu_to_be32(newspace);
+ ebn->prev = cpu_to_be32(objectnode + 0x80000000);
+ ebn->next = 0;
+ ebn->blocks = cpu_to_be16(blocks);
+
+ *io_lastextentbnode = newspace;
+
+ asfs_bstore(sb, bh);
+ asfs_brelse(bh);
+
+ ASFS_SB(sb)->block_rovingblockptr = newspace + blocks;
+
+/* if (ASFS_SB(sb)->block_rovingblockptr >=
ASFS_SB(sb)->totalblocks)
+ ASFS_SB(sb)->block_rovingblockptr = 0;*/
+ }
+ }
+
+ asfs_debug(" addblocks: done.\n");
+
+ return errorcode;
+}
+#endif
next reply other threads:[~2009-02-09 6:55 UTC|newest]
Thread overview: 3+ messages / expand[flat|nested] mbox.gz Atom feed top
2009-02-09 6:55 Pavel Fedin [this message]
2009-02-09 8:40 ` [PATCH 4/9] Amiga SmartFileSystem Matthew Wilcox
-- strict thread matches above, loose matches on Subject: below --
2008-12-26 12:08 Pavel Fedin
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=187c6cc60902082255l1475ac1al80b8fc7e206b0bf2@mail.gmail.com \
--to=sonic.amiga@gmail.com \
--cc=linux-fsdevel@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).