* [PATCH 6/9] Amiga SmartFileSystem
@ 2008-12-26 12:07 Pavel Fedin
0 siblings, 0 replies; 2+ messages in thread
From: Pavel Fedin @ 2008-12-26 12:07 UTC (permalink / raw)
To: linux-fsdevel
diff -ruN linux-source-2.6.24.orig/fs/asfs/Makefile linux-source-2.6.24/fs/asfs/Makefile
--- linux-source-2.6.24.orig/fs/asfs/Makefile 1970-01-01 03:00:00.000000000 +0300
+++ linux-source-2.6.24/fs/asfs/Makefile 2008-12-14 23:05:05.000000000 +0300
@@ -0,0 +1,8 @@
+#
+# Makefile for the linux asfs filesystem routines.
+#
+
+obj-$(CONFIG_ASFS_FS) += asfs.o
+
+asfs-y += dir.o extents.o file.o inode.o namei.o nodes.o objects.o super.o symlink.o
+asfs-$(CONFIG_ASFS_RW) += adminspace.o bitfuncs.o
diff -ruN linux-source-2.6.24.orig/fs/asfs/namei.c linux-source-2.6.24/fs/asfs/namei.c
--- linux-source-2.6.24.orig/fs/asfs/namei.c 1970-01-01 03:00:00.000000000 +0300
+++ linux-source-2.6.24/fs/asfs/namei.c 2008-12-14 23:05:05.000000000 +0300
@@ -0,0 +1,197 @@
+/*
+ *
+ * Amiga Smart File System, Linux implementation
+ * version: 1.0beta10
+ *
+ * Copyright (C) 2003,2004,2005 Marek 'March' Szyprowski <marek@amiga.pl>
+ *
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ *
+ */
+
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <linux/fs.h>
+#include <linux/buffer_head.h>
+#include <linux/vfs.h>
+#include <linux/string.h>
+#include <linux/nls.h>
+#include "asfs_fs.h"
+
+static inline u8 asfs_upperchar(u8 c)
+{
+ if ((c >= 224 && c <= 254 && c != 247) || (c >= 'a' && c <= 'z'))
+ c -= 32;
+ return (c);
+}
+
+u8 asfs_lowerchar(u8 c)
+{
+ if ((c >= 192 && c <= 222 && c != 215) || (c >= 'A' && c <= 'Z'))
+ c += 32;
+ return (c);
+}
+
+static inline u8 asfs_nls_upperchar(u8 c, struct nls_table *t)
+{
+ if (t) {
+ u8 nc = t->charset2upper[c];
+ return nc ? nc : c;
+ } else
+ return asfs_upperchar(c);
+}
+
+/* Check if the name is valid for a asfs object. */
+
+inline int asfs_check_name(const u8 *name, int len)
+{
+ int i;
+
+ if (len > ASFS_MAXFN)
+ return -ENAMETOOLONG;
+
+ for (i = 0; i < len; i++)
+ if (name[i] < ' ' || name[i] == ':' || (name[i] > 0x7e && name[i] < 0xa0))
+ return -EINVAL;
+
+ return 0;
+}
+
+/* Note: the dentry argument is the parent dentry. */
+
+static int asfs_hash_dentry(struct dentry *dentry, struct qstr *qstr)
+{
+ struct super_block *sb = dentry->d_inode->i_sb;
+ const u8 *name = qstr->name;
+ unsigned long hash;
+ int i;
+ struct nls_table *nls_io = ASFS_SB(sb)->nls_io;
+
+ i = asfs_check_name(qstr->name,qstr->len);
+ if (i)
+ return i;
+
+ hash = init_name_hash();
+
+ if (ASFS_SB(sb)->flags & ASFS_ROOTBITS_CASESENSITIVE)
+ for (i=qstr->len; i > 0; name++, i--)
+ hash = partial_name_hash(*name, hash);
+ else
+ for (i=qstr->len; i > 0; name++, i--)
+ hash = partial_name_hash(asfs_nls_upperchar(*name, nls_io), hash);
+
+ qstr->hash = end_name_hash(hash);
+
+ return 0;
+}
+
+static int asfs_compare_dentry(struct dentry *dentry, struct qstr *a, struct qstr *b)
+{
+ struct super_block *sb = dentry->d_inode->i_sb;
+ const u8 *aname = a->name;
+ const u8 *bname = b->name;
+ int len;
+ struct nls_table *nls_io = ASFS_SB(sb)->nls_io;
+
+ /* 'a' is the qstr of an already existing dentry, so the name
+ * must be valid. 'b' must be validated first.
+ */
+
+ if (asfs_check_name(b->name,b->len))
+ return 1;
+
+ if (a->len != b->len)
+ return 1;
+
+ if (ASFS_SB(sb)->flags & ASFS_ROOTBITS_CASESENSITIVE) {
+ for (len=a->len; len > 0; len--)
+ if (*aname++ != *bname++)
+ return 1;
+ } else {
+ for (len=a->len; len > 0; len--)
+ if (asfs_nls_upperchar(*aname++, nls_io) != asfs_nls_upperchar(*bname++, nls_io))
+ return 1;
+ }
+
+ return 0;
+}
+
+struct dentry_operations asfs_dentry_operations = {
+ d_hash: asfs_hash_dentry,
+ d_compare: asfs_compare_dentry,
+};
+
+int asfs_namecmp(u8 *s, u8 *ct, int casesensitive, struct nls_table *t)
+{
+ if (casesensitive) {
+ while (*s == *ct && *ct != '\0' && *ct != '/') {
+ s++;
+ ct++;
+ }
+ } else {
+ while (asfs_nls_upperchar(*s, t) == asfs_nls_upperchar(*ct, t) && *ct != '\0'
+ && *ct != '/') {
+ s++;
+ ct++;
+ }
+ }
+ return (*s == '\0' && (*ct == '\0' || *ct == '/')) ? 0 : *ct - *s;
+}
+
+u16 asfs_hash(u8 *name, int casesensitive)
+{
+ u16 hashval = 0;
+ while (name[hashval] != 0 && name[hashval] != '/')
+ hashval++;
+ if (casesensitive) {
+ u8 c = *name;
+ while (c != 0 && c != '/') {
+ hashval = hashval * 13 + c;
+ c = *++name;
+ }
+ } else {
+ u8 c = *name;
+ while (c != 0 && c != '/') {
+ hashval = hashval * 13 + asfs_upperchar(c);
+ c = *++name;
+ }
+ }
+ return hashval;
+}
+
+void asfs_translate(u8 *to, u8 *from, struct nls_table *nls_to, struct nls_table *nls_from, int limit)
+{
+ wchar_t uni;
+ int i, len;
+ int from_len, to_len = limit;
+
+ if (nls_to) {
+ from_len = strlen(from);
+ for (i=0; i < from_len && to_len > 1; ) {
+ len = nls_from->char2uni(&from[i], from_len-i, &uni);
+ if (len > 0) {
+ i += len;
+ len = nls_to->uni2char(uni, to, to_len);
+ if (len > 0) {
+ to += len;
+ to_len -= len;
+ }
+ } else
+ i++;
+ if (len < 0) {
+ *to++ = '?';
+ to_len--;
+ }
+ }
+ *to = '\0';
+ } else {
+ strncpy (to, from, limit);
+ to[limit-1] = '\0';
+ }
+}
diff -ruN linux-source-2.6.24.orig/fs/asfs/nodes.c linux-source-2.6.24/fs/asfs/nodes.c
--- linux-source-2.6.24.orig/fs/asfs/nodes.c 1970-01-01 03:00:00.000000000 +0300
+++ linux-source-2.6.24/fs/asfs/nodes.c 2008-12-14 23:05:05.000000000 +0300
@@ -0,0 +1,455 @@
+/*
+ *
+ * Amiga Smart File System, Linux implementation
+ * version: 1.0beta7
+ *
+ * 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>
+
+/* Finds a specific node by number. */
+int asfs_getnode(struct super_block *sb, u32 nodeno, struct buffer_head **ret_bh, struct fsObjectNode **ret_node)
+{
+ struct buffer_head *bh;
+ struct fsNodeContainer *nodecont;
+ u32 nodeindex = ASFS_SB(sb)->objectnoderoot;
+
+ while ((bh = asfs_breadcheck(sb, nodeindex, ASFS_NODECONTAINER_ID))) {
+ nodecont = (struct fsNodeContainer *) bh->b_data;
+
+ if (be32_to_cpu(nodecont->nodes) == 1) {
+ *ret_node = (struct fsObjectNode *) ((u8 *) nodecont->node + NODE_STRUCT_SIZE * (nodeno - be32_to_cpu(nodecont->nodenumber)));
+ *ret_bh = bh;
+ return 0;
+ } else {
+ u16 containerentry = (nodeno - be32_to_cpu(nodecont->nodenumber)) / be32_to_cpu(nodecont->nodes);
+ nodeindex = be32_to_cpu(nodecont->node[containerentry]) >> (sb->s_blocksize_bits - ASFS_BLCKFACCURACY);
+ }
+ asfs_brelse(bh);
+ }
+ if (bh == NULL)
+ return -EIO;
+ return -ENOENT;
+}
+
+#ifdef CONFIG_ASFS_RW
+
+ /* Looks for the parent of the passed-in buffer_head (fsNodeContainer)
+ starting from the root. It returns an error if any error occured.
+ If error is 0 and io_bh is NULL as well, then there was no parent (ie,
+ you asked parent of the root). Otherwise io_bh should contain the
+ parent of the passed-in NodeContainer. */
+
+static int parentnodecontainer(struct super_block *sb, struct buffer_head **io_bh)
+{
+ u32 noderoot = ASFS_SB(sb)->objectnoderoot;
+ u32 childblock = be32_to_cpu(((struct fsBlockHeader *) (*io_bh)->b_data)->ownblock);
+ u32 nodenumber = be32_to_cpu(((struct fsNodeContainer *) (*io_bh)->b_data)->nodenumber);
+ int errorcode = 0;
+
+ if (noderoot == childblock) {
+ *io_bh = NULL;
+ return 0;
+ }
+
+ while ((*io_bh = asfs_breadcheck(sb, noderoot, ASFS_NODECONTAINER_ID))) {
+ struct fsNodeContainer *nc = (void *) (*io_bh)->b_data;
+
+ if (be32_to_cpu(nc->nodes) == 1) {
+ /* We've descended the tree to a leaf NodeContainer, something
+ which should never happen if the passed-in io_bh had
+ contained a valid fsNodeContainer. */
+ printk("ASFS: Failed to locate the parent NodeContainer - node tree is corrupted!\n");
+ *io_bh = NULL;
+ return -EIO;
+ } else {
+ u16 containerentry = (nodenumber - be32_to_cpu(nc->nodenumber)) / be32_to_cpu(nc->nodes);
+ noderoot = be32_to_cpu(nc->node[containerentry]) >> (sb->s_blocksize_bits - ASFS_BLCKFACCURACY);
+ }
+
+ if (noderoot == childblock)
+ break;
+
+ asfs_brelse(*io_bh);
+ }
+
+ if (*io_bh == NULL)
+ return -EIO;
+
+ return errorcode;
+}
+
+
+static int isfull(struct super_block *sb, struct fsNodeContainer *nc)
+{
+ u32 *p = nc->node;
+ s16 n = NODECONT_BLOCK_COUNT;
+
+ while (--n >= 0) {
+ if (*p == 0 || (be32_to_cpu(*p) & 0x00000001) == 0) {
+ break;
+ }
+ p++;
+ }
+
+ return n < 0;
+}
+
+static int markparentfull(struct super_block *sb, struct buffer_head *bh)
+{
+ u32 nodenumber = be32_to_cpu(((struct fsNodeContainer *) (bh->b_data))->nodenumber);
+ int errorcode;
+
+ if ((errorcode = parentnodecontainer(sb, &bh)) == 0 && bh != 0) {
+ struct fsNodeContainer *nc = (void *) bh->b_data;
+ u16 containerentry = (nodenumber - be32_to_cpu(nc->nodenumber)) / be32_to_cpu(nc->nodes);
+
+ nc->node[containerentry] = cpu_to_be32(be32_to_cpu(nc->node[containerentry]) | 0x00000001);
+
+ asfs_bstore(sb, bh);
+
+ if (isfull(sb, nc)) { /* This container now is full as well! Mark the next higher up container too then! */
+ return markparentfull(sb, bh);
+ }
+ asfs_brelse(bh);
+ }
+
+ return errorcode;
+}
+
+static int addnewnodelevel(struct super_block *sb, u16 nodesize)
+{
+ struct buffer_head *bh;
+ u32 noderoot = ASFS_SB(sb)->objectnoderoot;
+ int errorcode;
+
+ /* Adds a new level to the Node tree. */
+
+ asfs_debug("addnewnodelevel: Entry\n");
+
+ if ((bh = asfs_breadcheck(sb, noderoot, ASFS_NODECONTAINER_ID))) {
+ struct buffer_head *newbh;
+ u32 newblock;
+
+ if ((errorcode = asfs_allocadminspace(sb, &newblock)) == 0 && (newbh = asfs_getzeroblk(sb, newblock))) {
+ struct fsNodeContainer *nc = (void *) bh->b_data;
+ struct fsNodeContainer *newnc = (void *) newbh->b_data;
+
+ /* The newly allocated block will become a copy of the current root. */
+
+ newnc->bheader.id = cpu_to_be32(ASFS_NODECONTAINER_ID);
+ newnc->bheader.ownblock = cpu_to_be32(newblock);
+ newnc->nodenumber = nc->nodenumber;
+ newnc->nodes = nc->nodes;
+ memcpy(newnc->node, nc->node, sb->s_blocksize - sizeof(struct fsNodeContainer));
+
+ asfs_bstore(sb, newbh);
+ asfs_brelse(newbh);
+
+ /* The current root will now be transformed into a new root. */
+
+ if (be32_to_cpu(nc->nodes) == 1)
+ nc->nodes = cpu_to_be32((sb->s_blocksize - sizeof(struct fsNodeContainer)) / nodesize);
+ else
+ nc->nodes = cpu_to_be32(be32_to_cpu(nc->nodes) * NODECONT_BLOCK_COUNT);
+
+ nc->node[0] = cpu_to_be32((newblock << (sb->s_blocksize_bits - ASFS_BLCKFACCURACY)) + 1); /* Tree is full from that point! */
+ memset(&nc->node[1], 0, sb->s_blocksize - sizeof(struct fsNodeContainer) - 4);
+
+ asfs_bstore(sb, bh);
+ }
+ asfs_brelse(bh);
+ } else
+ errorcode = -EIO;
+
+ return errorcode;
+}
+
+static int createnodecontainer(struct super_block *sb, u32 nodenumber, u32 nodes, u32 * returned_block)
+{
+ struct buffer_head *bh;
+ int errorcode;
+ u32 newblock;
+
+ asfs_debug("createnodecontainer: nodenumber = %u, nodes = %u\n", nodenumber, nodes);
+
+ if ((errorcode = asfs_allocadminspace(sb, &newblock)) == 0 && (bh = asfs_getzeroblk(sb, newblock))) {
+ struct fsNodeContainer *nc = (void *) bh->b_data;
+
+ nc->bheader.id = cpu_to_be32(ASFS_NODECONTAINER_ID);
+ nc->bheader.ownblock = cpu_to_be32(newblock);
+
+ nc->nodenumber = cpu_to_be32(nodenumber);
+ nc->nodes = cpu_to_be32(nodes);
+
+ asfs_bstore(sb, bh);
+ asfs_brelse(bh);
+ *returned_block = newblock;
+ }
+
+ return errorcode;
+}
+
+ /* This function creates a new fsNode structure in a fsNodeContainer. If needed
+ it will create a new fsNodeContainers and a new fsNodeIndexContainer. */
+
+int asfs_createnode(struct super_block *sb, struct buffer_head **returned_bh, struct fsNode **returned_node, u32 * returned_nodeno)
+{
+ u16 nodecount = (sb->s_blocksize - sizeof(struct fsNodeContainer)) / NODE_STRUCT_SIZE;
+ u32 noderoot = ASFS_SB(sb)->objectnoderoot;
+ u32 nodeindex = noderoot;
+ int errorcode = 0;
+
+ while ((*returned_bh = asfs_breadcheck(sb, nodeindex, ASFS_NODECONTAINER_ID))) {
+ struct fsNodeContainer *nc = (void *) (*returned_bh)->b_data;
+
+ if (be32_to_cpu(nc->nodes) == 1) { /* Is it a leaf-container? */
+ struct fsNode *n;
+ s16 i = nodecount;
+
+ n = (struct fsNode *) nc->node;
+
+ while (i-- > 0) {
+ if (n->data == 0)
+ break;
+
+ n = (struct fsNode *) ((u8 *) n + NODE_STRUCT_SIZE);
+ }
+
+ if (i >= 0) {
+ /* Found an empty fsNode structure! */
+ *returned_node = n;
+ *returned_nodeno = be32_to_cpu(nc->nodenumber) + ((u8 *) n - (u8 *) nc->node) / NODE_STRUCT_SIZE;
+
+ asfs_debug("createnode: Created Node %d\n", *returned_nodeno);
+
+ /* Below we continue to look through the NodeContainer block. We skip the entry
+ we found to be unused, and see if there are any more unused entries. If we
+ do not find any more unused entries then this container is now full. */
+
+ n = (struct fsNode *) ((u8 *) n + NODE_STRUCT_SIZE);
+
+ while (i-- > 0) {
+ if (n->data == 0)
+ break;
+
+ n = (struct fsNode *) ((u8 *) n + NODE_STRUCT_SIZE);
+ }
+
+ if (i < 0) {
+ /* No more empty fsNode structures in this block. Mark parent full. */
+ errorcode = markparentfull(sb, *returned_bh);
+ }
+
+ return errorcode;
+ } else {
+ /* What happened now is that we found a leaf-container which was
+ completely filled. In practice this should only happen when there
+ is only a single NodeContainer (only this container), or when there
+ was an error in one of the full-bits in a higher level container. */
+
+ if (noderoot != nodeindex) {
+ /*** Hmmm... it looks like there was a damaged full-bit or something.
+ In this case we'd probably better call markcontainerfull. */
+
+ printk("ASFS: Couldn't find empty Node in NodeContainer while NodeIndexContainer indicated there should be one!\n");
+
+ errorcode = -ENOSPC;
+ break;
+ } else {
+ /* Container is completely filled. */
+
+ if ((errorcode = addnewnodelevel(sb, NODE_STRUCT_SIZE)) != 0)
+ return errorcode;
+
+ nodeindex = noderoot;
+ }
+ }
+ } else { /* This isn't a leaf container */
+ u32 *p = nc->node;
+ s16 i = NODECONT_BLOCK_COUNT;
+
+ /* We've read a normal container */
+
+ while (i-- > 0) {
+ if (*p != 0 && (be32_to_cpu(*p) & 0x00000001) == 0)
+ break;
+
+ p++;
+ }
+
+ if (i >= 0) {
+ /* Found a not completely filled Container */
+
+ nodeindex = be32_to_cpu(*p) >> (sb->s_blocksize_bits - ASFS_BLCKFACCURACY);
+ } else {
+ /* Everything in the NodeIndexContainer was completely filled. There possibly
+ are some unused pointers in this block however. */
+
+ asfs_debug("createnode: NodeContainer at block has no empty Nodes.\n");
+
+ p = nc->node;
+ i = NODECONT_BLOCK_COUNT;
+
+ while (i-- > 0) {
+ if (*p == 0)
+ break;
+
+ p++;
+ }
+
+ if (i >= 0) {
+ u32 newblock;
+ u32 nodes;
+
+ /* Found an unused Container pointer */
+
+ if (be32_to_cpu(nc->nodes) == (sb->s_blocksize - sizeof(struct fsNodeContainer)) / NODE_STRUCT_SIZE) {
+ nodes = 1;
+ } else {
+ nodes = be32_to_cpu(nc->nodes) / NODECONT_BLOCK_COUNT;
+ }
+
+ if ((errorcode = createnodecontainer(sb, be32_to_cpu(nc->nodenumber) + (p - nc->node) * be32_to_cpu(nc->nodes), nodes, &newblock)) != 0) {
+ break;
+ }
+
+ *p = cpu_to_be32(newblock << (sb->s_blocksize_bits - ASFS_BLCKFACCURACY));
+
+ asfs_bstore(sb, *returned_bh);
+ } else {
+ /* Container is completely filled. This must be the top-level NodeIndex container
+ as otherwise the full-bit would have been wrong! */
+
+ if ((errorcode = addnewnodelevel(sb, NODE_STRUCT_SIZE)) != 0)
+ break;
+
+ nodeindex = noderoot;
+ }
+ }
+ }
+ asfs_brelse(*returned_bh);
+ }
+
+ if (*returned_bh == NULL)
+ return -EIO;
+
+ return (errorcode);
+}
+
+static int markparentempty(struct super_block *sb, struct buffer_head *bh)
+{
+ u32 nodenumber = be32_to_cpu(((struct fsNodeContainer *) bh->b_data)->nodenumber);
+ int errorcode;
+
+ if ((errorcode = parentnodecontainer(sb, &bh)) == 0 && bh != 0) {
+ struct fsNodeContainer *nc = (void *) bh->b_data;
+ int wasfull;
+ u16 containerentry = (nodenumber - be32_to_cpu(nc->nodenumber)) / be32_to_cpu(nc->nodes);
+
+ wasfull = isfull(sb, nc);
+
+ nc->node[containerentry] = cpu_to_be32(be32_to_cpu(nc->node[containerentry]) & ~0x00000001);
+
+ asfs_bstore(sb, bh);
+
+ if (wasfull) {
+ /* This container was completely full before! Mark the next higher up container too then! */
+ return markparentempty(sb, bh);
+ }
+ asfs_brelse(bh);
+ }
+
+ return errorcode;
+}
+
+static int freecontainer(struct super_block *sb, struct buffer_head *bh)
+{
+ u32 nodenumber = be32_to_cpu(((struct fsNodeContainer *) bh->b_data)->nodenumber);
+ int errorcode;
+
+ if ((errorcode = parentnodecontainer(sb, &bh)) == 0 && bh != NULL) { /* This line also prevents the freeing of the noderoot. */
+ struct fsNodeContainer *nc = (void *) bh->b_data;
+ u16 containerindex = (nodenumber - be32_to_cpu(nc->nodenumber)) / be32_to_cpu(nc->nodes);
+
+ if ((errorcode = asfs_freeadminspace(sb, be32_to_cpu(nc->node[containerindex]) >> (sb->s_blocksize_bits - ASFS_BLCKFACCURACY))) == 0) {
+ u32 *p = nc->node;
+ s16 n = NODECONT_BLOCK_COUNT;
+
+ nc->node[containerindex] = 0;
+ asfs_bstore(sb, bh);
+
+ while (n-- > 0)
+ if (*p++ != 0)
+ break;
+
+ if (n < 0) { /* This container is now completely empty! Free this NodeIndexContainer too then! */
+ return freecontainer(sb, bh);
+ }
+ }
+ asfs_brelse(bh);
+ }
+
+ return errorcode;
+}
+
+static int internaldeletenode(struct super_block *sb, struct buffer_head *bh, struct fsNode *n)
+{
+ struct fsNodeContainer *nc = (void *) bh->b_data;
+ u16 nodecount = (sb->s_blocksize - sizeof(struct fsNodeContainer)) / NODE_STRUCT_SIZE;
+ s16 i = nodecount;
+ s16 empty = 0;
+ int errorcode = 0;
+
+ n->data = 0;
+ n = (struct fsNode *) nc->node;
+
+ while (i-- > 0) {
+ if (n->data == 0)
+ empty++;
+
+ n = (struct fsNode *) ((u8 *) n + NODE_STRUCT_SIZE);
+ }
+
+ asfs_bstore(sb, bh);
+
+ if (empty == 1) /* NodeContainer was completely full before, so we need to mark it empty now. */
+ errorcode = markparentempty(sb, bh);
+ else if (empty == nodecount) /* NodeContainer is now completely empty! Free it! */
+ errorcode = freecontainer(sb, bh);
+
+ return (errorcode);
+}
+
+int asfs_deletenode(struct super_block *sb, u32 objectnode)
+{
+ struct buffer_head *bh;
+ struct fsObjectNode *on;
+ int errorcode;
+
+ asfs_debug("deletenode: Deleting Node %d\n", objectnode);
+
+ if ((errorcode = asfs_getnode(sb, objectnode, &bh, &on)) == 0)
+ errorcode = internaldeletenode(sb, bh, (struct fsNode *) on);
+
+ asfs_brelse(bh);
+ return (errorcode);
+}
+
+#endif
^ permalink raw reply [flat|nested] 2+ messages in thread
* [PATCH 6/9] Amiga SmartFileSystem
@ 2009-02-09 6:55 Pavel Fedin
0 siblings, 0 replies; 2+ messages in thread
From: Pavel Fedin @ 2009-02-09 6:55 UTC (permalink / raw)
To: linux-fsdevel
diff -ruN linux-source-2.6.24.orig/fs/asfs/Makefile
linux-source-2.6.24/fs/asfs/Makefile
--- linux-source-2.6.24.orig/fs/asfs/Makefile 1970-01-01
03:00:00.000000000 +0300
+++ linux-source-2.6.24/fs/asfs/Makefile 2008-12-14
23:05:05.000000000 +0300
@@ -0,0 +1,8 @@
+#
+# Makefile for the linux asfs filesystem routines.
+#
+
+obj-$(CONFIG_ASFS_FS) += asfs.o
+
+asfs-y += dir.o extents.o file.o inode.o namei.o nodes.o objects.o
super.o symlink.o
+asfs-$(CONFIG_ASFS_RW) += adminspace.o bitfuncs.o
diff -ruN linux-source-2.6.24.orig/fs/asfs/namei.c
linux-source-2.6.24/fs/asfs/namei.c
--- linux-source-2.6.24.orig/fs/asfs/namei.c 1970-01-01
03:00:00.000000000 +0300
+++ linux-source-2.6.24/fs/asfs/namei.c 2008-12-14 23:05:05.000000000 +0300
@@ -0,0 +1,197 @@
+/*
+ *
+ * Amiga Smart File System, Linux implementation
+ * version: 1.0beta10
+ *
+ * Copyright (C) 2003,2004,2005 Marek 'March' Szyprowski <marek@amiga.pl>
+ *
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ *
+ */
+
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <linux/fs.h>
+#include <linux/buffer_head.h>
+#include <linux/vfs.h>
+#include <linux/string.h>
+#include <linux/nls.h>
+#include "asfs_fs.h"
+
+static inline u8 asfs_upperchar(u8 c)
+{
+ if ((c >= 224 && c <= 254 && c != 247) || (c >= 'a' && c <= 'z'))
+ c -= 32;
+ return (c);
+}
+
+u8 asfs_lowerchar(u8 c)
+{
+ if ((c >= 192 && c <= 222 && c != 215) || (c >= 'A' && c <= 'Z'))
+ c += 32;
+ return (c);
+}
+
+static inline u8 asfs_nls_upperchar(u8 c, struct nls_table *t)
+{
+ if (t) {
+ u8 nc = t->charset2upper[c];
+ return nc ? nc : c;
+ } else
+ return asfs_upperchar(c);
+}
+
+/* Check if the name is valid for a asfs object. */
+
+inline int asfs_check_name(const u8 *name, int len)
+{
+ int i;
+
+ if (len > ASFS_MAXFN)
+ return -ENAMETOOLONG;
+
+ for (i = 0; i < len; i++)
+ if (name[i] < ' ' || name[i] == ':' || (name[i] > 0x7e
&& name[i] < 0xa0))
+ return -EINVAL;
+
+ return 0;
+}
+
+/* Note: the dentry argument is the parent dentry. */
+
+static int asfs_hash_dentry(struct dentry *dentry, struct qstr *qstr)
+{
+ struct super_block *sb = dentry->d_inode->i_sb;
+ const u8 *name = qstr->name;
+ unsigned long hash;
+ int i;
+ struct nls_table *nls_io = ASFS_SB(sb)->nls_io;
+
+ i = asfs_check_name(qstr->name,qstr->len);
+ if (i)
+ return i;
+
+ hash = init_name_hash();
+
+ if (ASFS_SB(sb)->flags & ASFS_ROOTBITS_CASESENSITIVE)
+ for (i=qstr->len; i > 0; name++, i--)
+ hash = partial_name_hash(*name, hash);
+ else
+ for (i=qstr->len; i > 0; name++, i--)
+ hash =
partial_name_hash(asfs_nls_upperchar(*name, nls_io), hash);
+
+ qstr->hash = end_name_hash(hash);
+
+ return 0;
+}
+
+static int asfs_compare_dentry(struct dentry *dentry, struct qstr *a,
struct qstr *b)
+{
+ struct super_block *sb = dentry->d_inode->i_sb;
+ const u8 *aname = a->name;
+ const u8 *bname = b->name;
+ int len;
+ struct nls_table *nls_io = ASFS_SB(sb)->nls_io;
+
+ /* 'a' is the qstr of an already existing dentry, so the name
+ * must be valid. 'b' must be validated first.
+ */
+
+ if (asfs_check_name(b->name,b->len))
+ return 1;
+
+ if (a->len != b->len)
+ return 1;
+
+ if (ASFS_SB(sb)->flags & ASFS_ROOTBITS_CASESENSITIVE) {
+ for (len=a->len; len > 0; len--)
+ if (*aname++ != *bname++)
+ return 1;
+ } else {
+ for (len=a->len; len > 0; len--)
+ if (asfs_nls_upperchar(*aname++, nls_io) !=
asfs_nls_upperchar(*bname++, nls_io))
+ return 1;
+ }
+
+ return 0;
+}
+
+struct dentry_operations asfs_dentry_operations = {
+ d_hash: asfs_hash_dentry,
+ d_compare: asfs_compare_dentry,
+};
+
+int asfs_namecmp(u8 *s, u8 *ct, int casesensitive, struct nls_table *t)
+{
+ if (casesensitive) {
+ while (*s == *ct && *ct != '\0' && *ct != '/') {
+ s++;
+ ct++;
+ }
+ } else {
+ while (asfs_nls_upperchar(*s, t) ==
asfs_nls_upperchar(*ct, t) && *ct != '\0'
+ && *ct != '/') {
+ s++;
+ ct++;
+ }
+ }
+ return (*s == '\0' && (*ct == '\0' || *ct == '/')) ? 0 : *ct - *s;
+}
+
+u16 asfs_hash(u8 *name, int casesensitive)
+{
+ u16 hashval = 0;
+ while (name[hashval] != 0 && name[hashval] != '/')
+ hashval++;
+ if (casesensitive) {
+ u8 c = *name;
+ while (c != 0 && c != '/') {
+ hashval = hashval * 13 + c;
+ c = *++name;
+ }
+ } else {
+ u8 c = *name;
+ while (c != 0 && c != '/') {
+ hashval = hashval * 13 + asfs_upperchar(c);
+ c = *++name;
+ }
+ }
+ return hashval;
+}
+
+void asfs_translate(u8 *to, u8 *from, struct nls_table *nls_to,
struct nls_table *nls_from, int limit)
+{
+ wchar_t uni;
+ int i, len;
+ int from_len, to_len = limit;
+
+ if (nls_to) {
+ from_len = strlen(from);
+ for (i=0; i < from_len && to_len > 1; ) {
+ len = nls_from->char2uni(&from[i], from_len-i, &uni);
+ if (len > 0) {
+ i += len;
+ len = nls_to->uni2char(uni, to, to_len);
+ if (len > 0) {
+ to += len;
+ to_len -= len;
+ }
+ } else
+ i++;
+ if (len < 0) {
+ *to++ = '?';
+ to_len--;
+ }
+ }
+ *to = '\0';
+ } else {
+ strncpy (to, from, limit);
+ to[limit-1] = '\0';
+ }
+}
diff -ruN linux-source-2.6.24.orig/fs/asfs/nodes.c
linux-source-2.6.24/fs/asfs/nodes.c
--- linux-source-2.6.24.orig/fs/asfs/nodes.c 1970-01-01
03:00:00.000000000 +0300
+++ linux-source-2.6.24/fs/asfs/nodes.c 2008-12-14 23:05:05.000000000 +0300
@@ -0,0 +1,455 @@
+/*
+ *
+ * Amiga Smart File System, Linux implementation
+ * version: 1.0beta7
+ *
+ * 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>
+
+/* Finds a specific node by number. */
+int asfs_getnode(struct super_block *sb, u32 nodeno, struct
buffer_head **ret_bh, struct fsObjectNode **ret_node)
+{
+ struct buffer_head *bh;
+ struct fsNodeContainer *nodecont;
+ u32 nodeindex = ASFS_SB(sb)->objectnoderoot;
+
+ while ((bh = asfs_breadcheck(sb, nodeindex, ASFS_NODECONTAINER_ID))) {
+ nodecont = (struct fsNodeContainer *) bh->b_data;
+
+ if (be32_to_cpu(nodecont->nodes) == 1) {
+ *ret_node = (struct fsObjectNode *) ((u8 *)
nodecont->node + NODE_STRUCT_SIZE * (nodeno -
be32_to_cpu(nodecont->nodenumber)));
+ *ret_bh = bh;
+ return 0;
+ } else {
+ u16 containerentry = (nodeno -
be32_to_cpu(nodecont->nodenumber)) / be32_to_cpu(nodecont->nodes);
+ nodeindex =
be32_to_cpu(nodecont->node[containerentry]) >> (sb->s_blocksize_bits -
ASFS_BLCKFACCURACY);
+ }
+ asfs_brelse(bh);
+ }
+ if (bh == NULL)
+ return -EIO;
+ return -ENOENT;
+}
+
+#ifdef CONFIG_ASFS_RW
+
+ /* Looks for the parent of the passed-in buffer_head (fsNodeContainer)
+ starting from the root. It returns an error if any error occured.
+ If error is 0 and io_bh is NULL as well, then there was no
parent (ie,
+ you asked parent of the root). Otherwise io_bh should contain the
+ parent of the passed-in NodeContainer. */
+
+static int parentnodecontainer(struct super_block *sb, struct
buffer_head **io_bh)
+{
+ u32 noderoot = ASFS_SB(sb)->objectnoderoot;
+ u32 childblock = be32_to_cpu(((struct fsBlockHeader *)
(*io_bh)->b_data)->ownblock);
+ u32 nodenumber = be32_to_cpu(((struct fsNodeContainer *)
(*io_bh)->b_data)->nodenumber);
+ int errorcode = 0;
+
+ if (noderoot == childblock) {
+ *io_bh = NULL;
+ return 0;
+ }
+
+ while ((*io_bh = asfs_breadcheck(sb, noderoot,
ASFS_NODECONTAINER_ID))) {
+ struct fsNodeContainer *nc = (void *) (*io_bh)->b_data;
+
+ if (be32_to_cpu(nc->nodes) == 1) {
+ /* We've descended the tree to a leaf
NodeContainer, something
+ which should never happen if the passed-in io_bh had
+ contained a valid fsNodeContainer. */
+ printk("ASFS: Failed to locate the parent
NodeContainer - node tree is corrupted!\n");
+ *io_bh = NULL;
+ return -EIO;
+ } else {
+ u16 containerentry = (nodenumber -
be32_to_cpu(nc->nodenumber)) / be32_to_cpu(nc->nodes);
+ noderoot =
be32_to_cpu(nc->node[containerentry]) >> (sb->s_blocksize_bits -
ASFS_BLCKFACCURACY);
+ }
+
+ if (noderoot == childblock)
+ break;
+
+ asfs_brelse(*io_bh);
+ }
+
+ if (*io_bh == NULL)
+ return -EIO;
+
+ return errorcode;
+}
+
+
+static int isfull(struct super_block *sb, struct fsNodeContainer *nc)
+{
+ u32 *p = nc->node;
+ s16 n = NODECONT_BLOCK_COUNT;
+
+ while (--n >= 0) {
+ if (*p == 0 || (be32_to_cpu(*p) & 0x00000001) == 0) {
+ break;
+ }
+ p++;
+ }
+
+ return n < 0;
+}
+
+static int markparentfull(struct super_block *sb, struct buffer_head *bh)
+{
+ u32 nodenumber = be32_to_cpu(((struct fsNodeContainer *)
(bh->b_data))->nodenumber);
+ int errorcode;
+
+ if ((errorcode = parentnodecontainer(sb, &bh)) == 0 && bh != 0) {
+ struct fsNodeContainer *nc = (void *) bh->b_data;
+ u16 containerentry = (nodenumber -
be32_to_cpu(nc->nodenumber)) / be32_to_cpu(nc->nodes);
+
+ nc->node[containerentry] =
cpu_to_be32(be32_to_cpu(nc->node[containerentry]) | 0x00000001);
+
+ asfs_bstore(sb, bh);
+
+ if (isfull(sb, nc)) { /* This container now is full
as well! Mark the next higher up container too then! */
+ return markparentfull(sb, bh);
+ }
+ asfs_brelse(bh);
+ }
+
+ return errorcode;
+}
+
+static int addnewnodelevel(struct super_block *sb, u16 nodesize)
+{
+ struct buffer_head *bh;
+ u32 noderoot = ASFS_SB(sb)->objectnoderoot;
+ int errorcode;
+
+ /* Adds a new level to the Node tree. */
+
+ asfs_debug("addnewnodelevel: Entry\n");
+
+ if ((bh = asfs_breadcheck(sb, noderoot, ASFS_NODECONTAINER_ID))) {
+ struct buffer_head *newbh;
+ u32 newblock;
+
+ if ((errorcode = asfs_allocadminspace(sb, &newblock))
== 0 && (newbh = asfs_getzeroblk(sb, newblock))) {
+ struct fsNodeContainer *nc = (void *) bh->b_data;
+ struct fsNodeContainer *newnc = (void *) newbh->b_data;
+
+ /* The newly allocated block will become a
copy of the current root. */
+
+ newnc->bheader.id = cpu_to_be32(ASFS_NODECONTAINER_ID);
+ newnc->bheader.ownblock = cpu_to_be32(newblock);
+ newnc->nodenumber = nc->nodenumber;
+ newnc->nodes = nc->nodes;
+ memcpy(newnc->node, nc->node, sb->s_blocksize
- sizeof(struct fsNodeContainer));
+
+ asfs_bstore(sb, newbh);
+ asfs_brelse(newbh);
+
+ /* The current root will now be transformed
into a new root. */
+
+ if (be32_to_cpu(nc->nodes) == 1)
+ nc->nodes =
cpu_to_be32((sb->s_blocksize - sizeof(struct fsNodeContainer)) /
nodesize);
+ else
+ nc->nodes =
cpu_to_be32(be32_to_cpu(nc->nodes) * NODECONT_BLOCK_COUNT);
+
+ nc->node[0] = cpu_to_be32((newblock <<
(sb->s_blocksize_bits - ASFS_BLCKFACCURACY)) + 1); /* Tree is
full from that point! */
+ memset(&nc->node[1], 0, sb->s_blocksize -
sizeof(struct fsNodeContainer) - 4);
+
+ asfs_bstore(sb, bh);
+ }
+ asfs_brelse(bh);
+ } else
+ errorcode = -EIO;
+
+ return errorcode;
+}
+
+static int createnodecontainer(struct super_block *sb, u32
nodenumber, u32 nodes, u32 * returned_block)
+{
+ struct buffer_head *bh;
+ int errorcode;
+ u32 newblock;
+
+ asfs_debug("createnodecontainer: nodenumber = %u, nodes =
%u\n", nodenumber, nodes);
+
+ if ((errorcode = asfs_allocadminspace(sb, &newblock)) == 0 &&
(bh = asfs_getzeroblk(sb, newblock))) {
+ struct fsNodeContainer *nc = (void *) bh->b_data;
+
+ nc->bheader.id = cpu_to_be32(ASFS_NODECONTAINER_ID);
+ nc->bheader.ownblock = cpu_to_be32(newblock);
+
+ nc->nodenumber = cpu_to_be32(nodenumber);
+ nc->nodes = cpu_to_be32(nodes);
+
+ asfs_bstore(sb, bh);
+ asfs_brelse(bh);
+ *returned_block = newblock;
+ }
+
+ return errorcode;
+}
+
+ /* This function creates a new fsNode structure in a
fsNodeContainer. If needed
+ it will create a new fsNodeContainers and a new
fsNodeIndexContainer. */
+
+int asfs_createnode(struct super_block *sb, struct buffer_head
**returned_bh, struct fsNode **returned_node, u32 * returned_nodeno)
+{
+ u16 nodecount = (sb->s_blocksize - sizeof(struct
fsNodeContainer)) / NODE_STRUCT_SIZE;
+ u32 noderoot = ASFS_SB(sb)->objectnoderoot;
+ u32 nodeindex = noderoot;
+ int errorcode = 0;
+
+ while ((*returned_bh = asfs_breadcheck(sb, nodeindex,
ASFS_NODECONTAINER_ID))) {
+ struct fsNodeContainer *nc = (void *) (*returned_bh)->b_data;
+
+ if (be32_to_cpu(nc->nodes) == 1) { /* Is it a
leaf-container? */
+ struct fsNode *n;
+ s16 i = nodecount;
+
+ n = (struct fsNode *) nc->node;
+
+ while (i-- > 0) {
+ if (n->data == 0)
+ break;
+
+ n = (struct fsNode *) ((u8 *) n +
NODE_STRUCT_SIZE);
+ }
+
+ if (i >= 0) {
+ /* Found an empty fsNode structure! */
+ *returned_node = n;
+ *returned_nodeno =
be32_to_cpu(nc->nodenumber) + ((u8 *) n - (u8 *) nc->node) /
NODE_STRUCT_SIZE;
+
+ asfs_debug("createnode: Created Node
%d\n", *returned_nodeno);
+
+ /* Below we continue to look through
the NodeContainer block. We skip the entry
+ we found to be unused, and see if
there are any more unused entries. If we
+ do not find any more unused entries
then this container is now full. */
+
+ n = (struct fsNode *) ((u8 *) n +
NODE_STRUCT_SIZE);
+
+ while (i-- > 0) {
+ if (n->data == 0)
+ break;
+
+ n = (struct fsNode *) ((u8 *)
n + NODE_STRUCT_SIZE);
+ }
+
+ if (i < 0) {
+ /* No more empty fsNode
structures in this block. Mark parent full. */
+ errorcode = markparentfull(sb,
*returned_bh);
+ }
+
+ return errorcode;
+ } else {
+ /* What happened now is that we found
a leaf-container which was
+ completely filled. In practice
this should only happen when there
+ is only a single NodeContainer
(only this container), or when there
+ was an error in one of the
full-bits in a higher level container. */
+
+ if (noderoot != nodeindex) {
+ /*** Hmmm... it looks like
there was a damaged full-bit or something.
+ In this case we'd
probably better call markcontainerfull. */
+
+ printk("ASFS: Couldn't find
empty Node in NodeContainer while NodeIndexContainer indicated there
should be one!\n");
+
+ errorcode = -ENOSPC;
+ break;
+ } else {
+ /* Container is completely filled. */
+
+ if ((errorcode =
addnewnodelevel(sb, NODE_STRUCT_SIZE)) != 0)
+ return errorcode;
+
+ nodeindex = noderoot;
+ }
+ }
+ } else { /* This isn't a leaf container */
+ u32 *p = nc->node;
+ s16 i = NODECONT_BLOCK_COUNT;
+
+ /* We've read a normal container */
+
+ while (i-- > 0) {
+ if (*p != 0 && (be32_to_cpu(*p) &
0x00000001) == 0)
+ break;
+
+ p++;
+ }
+
+ if (i >= 0) {
+ /* Found a not completely filled Container */
+
+ nodeindex = be32_to_cpu(*p) >>
(sb->s_blocksize_bits - ASFS_BLCKFACCURACY);
+ } else {
+ /* Everything in the
NodeIndexContainer was completely filled. There possibly
+ are some unused pointers in this
block however. */
+
+ asfs_debug("createnode: NodeContainer
at block has no empty Nodes.\n");
+
+ p = nc->node;
+ i = NODECONT_BLOCK_COUNT;
+
+ while (i-- > 0) {
+ if (*p == 0)
+ break;
+
+ p++;
+ }
+
+ if (i >= 0) {
+ u32 newblock;
+ u32 nodes;
+
+ /* Found an unused Container pointer */
+
+ if (be32_to_cpu(nc->nodes) ==
(sb->s_blocksize - sizeof(struct fsNodeContainer)) / NODE_STRUCT_SIZE)
{
+ nodes = 1;
+ } else {
+ nodes =
be32_to_cpu(nc->nodes) / NODECONT_BLOCK_COUNT;
+ }
+
+ if ((errorcode =
createnodecontainer(sb, be32_to_cpu(nc->nodenumber) + (p - nc->node) *
be32_to_cpu(nc->nodes), nodes, &newblock)) != 0) {
+ break;
+ }
+
+ *p = cpu_to_be32(newblock <<
(sb->s_blocksize_bits - ASFS_BLCKFACCURACY));
+
+ asfs_bstore(sb, *returned_bh);
+ } else {
+ /* Container is completely
filled. This must be the top-level NodeIndex container
+ as otherwise the full-bit
would have been wrong! */
+
+ if ((errorcode =
addnewnodelevel(sb, NODE_STRUCT_SIZE)) != 0)
+ break;
+
+ nodeindex = noderoot;
+ }
+ }
+ }
+ asfs_brelse(*returned_bh);
+ }
+
+ if (*returned_bh == NULL)
+ return -EIO;
+
+ return (errorcode);
+}
+
+static int markparentempty(struct super_block *sb, struct buffer_head *bh)
+{
+ u32 nodenumber = be32_to_cpu(((struct fsNodeContainer *)
bh->b_data)->nodenumber);
+ int errorcode;
+
+ if ((errorcode = parentnodecontainer(sb, &bh)) == 0 && bh != 0) {
+ struct fsNodeContainer *nc = (void *) bh->b_data;
+ int wasfull;
+ u16 containerentry = (nodenumber -
be32_to_cpu(nc->nodenumber)) / be32_to_cpu(nc->nodes);
+
+ wasfull = isfull(sb, nc);
+
+ nc->node[containerentry] =
cpu_to_be32(be32_to_cpu(nc->node[containerentry]) & ~0x00000001);
+
+ asfs_bstore(sb, bh);
+
+ if (wasfull) {
+ /* This container was completely full before!
Mark the next higher up container too then! */
+ return markparentempty(sb, bh);
+ }
+ asfs_brelse(bh);
+ }
+
+ return errorcode;
+}
+
+static int freecontainer(struct super_block *sb, struct buffer_head *bh)
+{
+ u32 nodenumber = be32_to_cpu(((struct fsNodeContainer *)
bh->b_data)->nodenumber);
+ int errorcode;
+
+ if ((errorcode = parentnodecontainer(sb, &bh)) == 0 && bh !=
NULL) { /* This line also prevents the freeing of the noderoot. */
+ struct fsNodeContainer *nc = (void *) bh->b_data;
+ u16 containerindex = (nodenumber -
be32_to_cpu(nc->nodenumber)) / be32_to_cpu(nc->nodes);
+
+ if ((errorcode = asfs_freeadminspace(sb,
be32_to_cpu(nc->node[containerindex]) >> (sb->s_blocksize_bits -
ASFS_BLCKFACCURACY))) == 0) {
+ u32 *p = nc->node;
+ s16 n = NODECONT_BLOCK_COUNT;
+
+ nc->node[containerindex] = 0;
+ asfs_bstore(sb, bh);
+
+ while (n-- > 0)
+ if (*p++ != 0)
+ break;
+
+ if (n < 0) { /* This container is now
completely empty! Free this NodeIndexContainer too then! */
+ return freecontainer(sb, bh);
+ }
+ }
+ asfs_brelse(bh);
+ }
+
+ return errorcode;
+}
+
+static int internaldeletenode(struct super_block *sb, struct
buffer_head *bh, struct fsNode *n)
+{
+ struct fsNodeContainer *nc = (void *) bh->b_data;
+ u16 nodecount = (sb->s_blocksize - sizeof(struct
fsNodeContainer)) / NODE_STRUCT_SIZE;
+ s16 i = nodecount;
+ s16 empty = 0;
+ int errorcode = 0;
+
+ n->data = 0;
+ n = (struct fsNode *) nc->node;
+
+ while (i-- > 0) {
+ if (n->data == 0)
+ empty++;
+
+ n = (struct fsNode *) ((u8 *) n + NODE_STRUCT_SIZE);
+ }
+
+ asfs_bstore(sb, bh);
+
+ if (empty == 1) /* NodeContainer was completely full
before, so we need to mark it empty now. */
+ errorcode = markparentempty(sb, bh);
+ else if (empty == nodecount) /* NodeContainer is now
completely empty! Free it! */
+ errorcode = freecontainer(sb, bh);
+
+ return (errorcode);
+}
+
+int asfs_deletenode(struct super_block *sb, u32 objectnode)
+{
+ struct buffer_head *bh;
+ struct fsObjectNode *on;
+ int errorcode;
+
+ asfs_debug("deletenode: Deleting Node %d\n", objectnode);
+
+ if ((errorcode = asfs_getnode(sb, objectnode, &bh, &on)) == 0)
+ errorcode = internaldeletenode(sb, bh, (struct fsNode *) on);
+
+ asfs_brelse(bh);
+ return (errorcode);
+}
+
+#endif
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2009-02-12 8:05 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2009-02-09 6:55 [PATCH 6/9] Amiga SmartFileSystem Pavel Fedin
-- strict thread matches above, loose matches on Subject: below --
2008-12-26 12:07 Pavel Fedin
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).