All of lore.kernel.org
 help / color / mirror / Atom feed
From: Pavel Fedin <sonic.amiga@gmail.com>
To: Phillip Lougher <phillip@lougher.demon.co.uk>
Cc: linux-fsdevel@vger.kernel.org
Subject: [PATCH 4/9] Amiga SmartFileSystem, revision 2
Date: Fri, 13 Feb 2009 09:55:34 +0300	[thread overview]
Message-ID: <1746553045.20090213095534@gmail.com> (raw)
In-Reply-To: <4994506C.1000209@lougher.demon.co.uk>

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


  parent reply	other threads:[~2009-02-13  6:55 UTC|newest]

Thread overview: 15+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2009-02-09 13:18 Corrupted ASFS patch Pavel Fedin
2009-02-09 13:31 ` maximilian attems
2009-02-12  8:24   ` Re[2]: " Pavel Fedin
2009-02-12  9:42     ` Phillip Lougher
2009-02-12 10:52       ` Re[2]: " Pavel Fedin
2009-02-12 16:38         ` Phillip Lougher
2009-02-13  6:53           ` [PATCH 1/9] Amiga SmartFileSystem, revision 2 Pavel Fedin
2009-02-13  6:54           ` [PATCH 2/9] " Pavel Fedin
2009-02-13  6:55           ` [PATCH 3/9] " Pavel Fedin
2009-02-13  6:55           ` Pavel Fedin [this message]
2009-02-13  6:56           ` [PATCH 5/9] " Pavel Fedin
2009-02-13  6:56           ` [PATCH 6/9] " Pavel Fedin
2009-02-13  6:56           ` [PATCH 7/9] " Pavel Fedin
2009-02-13  6:57           ` [PATCH 8/9] " Pavel Fedin
2009-02-13  6:57           ` [PATCH 9/9] " 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=1746553045.20090213095534@gmail.com \
    --to=sonic.amiga@gmail.com \
    --cc=linux-fsdevel@vger.kernel.org \
    --cc=phillip@lougher.demon.co.uk \
    /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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.