[PATCH 4/9] Amiga SmartFileSystem, revision 2

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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@xxxxxxxx>
+ *
+ */
+
+#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

--
To unsubscribe from this list: send the line "unsubscribe linux-fsdevel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Linux Ext4 Filesystem]     [Union Filesystem]     [Filesystem Testing]     [Ceph Users]     [Ecryptfs]     [AutoFS]     [Kernel Newbies]     [Share Photos]     [Security]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux Cachefs]     [Reiser Filesystem]     [Linux RAID]     [Samba]     [Device Mapper]     [CEPH Development]
  Powered by Linux