* [PATCH 3/9] Amiga SmartFileSystem
@ 2008-12-26 12:08 Pavel Fedin
0 siblings, 0 replies; 2+ messages in thread
From: Pavel Fedin @ 2008-12-26 12:08 UTC (permalink / raw)
To: linux-fsdevel
diff -ruN linux-source-2.6.24.orig/fs/asfs/bitfuncs.h linux-source-2.6.24/fs/asfs/bitfuncs.h
--- linux-source-2.6.24.orig/fs/asfs/bitfuncs.h 1970-01-01 03:00:00.000000000 +0300
+++ linux-source-2.6.24/fs/asfs/bitfuncs.h 2008-12-14 23:42:39.000000000 +0300
@@ -0,0 +1,58 @@
+/*
+ *
+ * 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.
+ *
+ */
+
+#ifndef __BITFUNCS_H
+#define __BITFUNCS_H
+
+#include <linux/types.h>
+#include <asm/byteorder.h>
+
+#include <linux/bitops.h>
+
+/* Finds first set bit in /data/ starting at /bitoffset/. This function
+ considers the MSB to be the first bit. */
+static inline int bfffo(u32 data, int bitoffset)
+{
+ u32 mask = 0xffffffff >> bitoffset;
+ data &= mask;
+ return data == 0 ? -1 : 32-fls(data);
+}
+
+/* Finds first zero bit in /data/ starting at /bitoffset/. This function
+ considers the MSB to be the first bit. */
+static inline int bfffz(u32 data, int bitoffset)
+{
+ return bfffo(~data, bitoffset);
+}
+
+/* Sets /bits/ bits starting from /bitoffset/ in /data/.
+ /bits/ must be between 1 and 32. */
+static inline u32 bfset(u32 data, int bitoffset, int bits)
+{
+ u32 mask = ~((1 << (32 - bits)) - 1);
+ mask >>= bitoffset;
+ return data | mask;
+}
+
+/* Clears /bits/ bits starting from /bitoffset/ in /data/.
+ /bits/ must be between 1 and 32. */
+static inline u32 bfclr(u32 data, int bitoffset, int bits)
+{
+ u32 mask = ~((1 << (32 - bits)) - 1);
+ mask >>= bitoffset;
+ return data & ~mask;
+}
+
+/* bm??? functions assumes that in-memory bitmap is in bigendian byte order */
+int bmffo(u32 *, int, int);
+int bmffz(u32 *, int, int);
+int bmclr(u32 *, int, int, int);
+int bmset(u32 *, int, int, int);
+
+#endif
diff -ruN linux-source-2.6.24.orig/fs/asfs/Changes linux-source-2.6.24/fs/asfs/Changes
--- linux-source-2.6.24.orig/fs/asfs/Changes 1970-01-01 03:00:00.000000000 +0300
+++ linux-source-2.6.24/fs/asfs/Changes 2008-12-14 23:05:05.000000000 +0300
@@ -0,0 +1,120 @@
+
+Amiga Smart File System, Linux implementation
+
+Please direct bug reports to: marek@amiga.pl
+
+History:
+
+v1.0beta12 (03.12.2006)
+- adapted to 2.6.19 kernel VFS changes
+- fixed symlink write crash
+
+v1.0beta11 (22.09.2006)
+- adapted to 2.6.18 kernel VFS changes
+- made some functions static to reduce overhead in kernel namespace
+
+v1.0beta10 (13.06.2005)
+- fixed ugly bug introduced in beta9 that caused kernel crash on x86
+ (thanks to Emiliano for reporting it!)
+
+v1.0beta9 (17.03.2005)
+- added NLS support (thanks to Pavel Fedin!)
+
+v1.0beta8 (07.01.2005)
+- adapted to 2.6.10 kernel VFS changes
+- added workaround for buggy Mandrake kernel headers
+
+v1.0beta7 (25.06.2004)
+- small changes in documentation
+- code clean up: bitfuncs.c, super.c, inode.c, *.h, Makefile, added
+ asfs_ prefix to function names, made some functions static
+ (big thanks to Christoph Hellwig for advice!)
+- fixed minor bugs (inode leak in super.c, not-realesed buffer during
+ object renaming in inode.c)
+- now files/dirs are created with global ownership/permission bits
+
+v1.0beta6 (04.06.2004)
+- fixed: ASFS_SB(sb)->flags was always zero in 2.6.x code
+
+v1.0beta5 (07.05.2004)
+- finally fixed a problem with file size attrib. not being written
+ to disk
+- fixed some problems with GCC 3.x and debug enabled
+
+v1.0beta4 (12.04.2004)
+- removed dummy asfs_notify_change (this fixes major bug introduced
+ in 1.0beta3 - file size wasn't written to disk) until it will
+ be implemented completely
+
+v1.0beta3 (22.03.2004) - still beta
+- updated for 2.6.x kernels VFS changes
+- code clean-up
+- added dummy asfs_notify_change (chmod now returns no errors)
+- added symlinks write support
+- fixed: ASFS_SB(sb)->flags was always zero
+
+v1.0beta2 (11.01.2004) - special version for Pegasos][ kernel
+- separated read and write functions, can be compiled also
+ as read-only fs
+
+v1.0beta1 (02.12.2003) - first public beta with write support
+- added dentry hashing/comparing routines
+- code clean-up
+
+v1.0aplha4 (30.11.2003) - preparing for first public beta
+- fixed some problems with renaming/moving files
+- fixed two major bugs, which didn't occur when fs was mounted
+ on loopback device (newly allocated blocks were not written to
+ disk and state bits were not set correctly on newly mapped file
+ blocks)
+- fixed many small bugs in io code (some buffers were not freed)
+- added/modified sb locks in asfs_lookup and asfs_getblock
+- fixed serious bug in file block allocation routines
+
+v1.0aplha3 (23.11.2003)
+- added (hopefully) all byteswap code, should now work again on
+ little-endian systems (also with write support!)
+- updated documentation
+
+v1.0alpha2 (13.11.2003)
+- now alocates file blocks in chunks during one request
+- fixed some dead-locks, other fixes
+
+v1.0alpha (02.11.2003) - first working version with full write support
+- too much to list it here ;)
+
+... (working on write support)
+
+v0.7 (12.10.2003) - internal realase
+- added asfs_breadcheck, modified asfs_get_node, asfs_search_BTree,
+ no more from_be32/16 macros, other...
+- code splitted into several files
+
+v0.6 (04.09.2003) - final read-only version
+- added support for HashTables, directory scaning should be
+ MUCH faster now
+- added checking of block IDs before reading any data from block
+
+v0.5 (19.07.2003)
+- added simple but effective extent cache - real speed-up
+ in reading large files
+- added read support for symlinks - based on AFFS symlinks
+
+v0.4 (10.07.2003)
+- third code clean-up (thanks to Roman Zippel for advice)
+- now uses generic readpage and readinode routines
+
+v0.3beta (17.06.2003)
+- second code clean-up
+
+v0.2beta2 (15.06.2003)
+- fixed yet another stupid bug - driver can't read root block on little-endian systems
+v0.2beta (15.06.2003)
+- fixed stupid bug - now files have 'file' flag (S_IFREG) set...
+- added mount options to set uid, gid and mode of files and dirs
+- made hidden files & dirs really hidden (= not listed in directories)
+- code clean-up
+
+v0.1beta (11.06.2003)
+- after many kernel crashes, finally got it!
+- first working read-only filesystem driver
diff -ruN linux-source-2.6.24.orig/fs/asfs/dir.c linux-source-2.6.24/fs/asfs/dir.c
--- linux-source-2.6.24.orig/fs/asfs/dir.c 1970-01-01 03:00:00.000000000 +0300
+++ linux-source-2.6.24/fs/asfs/dir.c 2008-12-14 23:05:05.000000000 +0300
@@ -0,0 +1,240 @@
+/*
+ *
+ * Amiga Smart File System, Linux implementation
+ * version: 1.0beta7
+ *
+ * Copyright (C) 2003,2004 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/fs.h>
+#include <linux/buffer_head.h>
+#include <linux/vfs.h>
+#include "asfs_fs.h"
+
+#include <asm/byteorder.h>
+
+extern struct dentry_operations asfs_dentry_operations;
+
+int asfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
+{
+ struct inode *dir = filp->f_path.dentry->d_inode;
+ struct super_block *sb = dir->i_sb;
+ struct nls_table *nls_io = ASFS_SB(sb)->nls_io;
+ struct nls_table *nls_disk = ASFS_SB(sb)->nls_disk;
+ u8 buf[512];
+ unsigned long f_pos;
+ int stored = 0;
+
+ struct buffer_head *bh;
+ struct fsObjectContainer *objcont;
+ struct fsObject *obj;
+ u32 block;
+ int startnode;
+ int add;
+
+ asfs_debug("asfs_readdir:\n");
+
+ if (filp->f_pos == ASFS_SB(sb)->totalblocks)
+ return stored;
+
+ f_pos = filp->f_pos;
+
+ if (f_pos == 0) {
+ filp->private_data = (void *)0;
+ if (filldir(dirent, ".", 1, f_pos, dir->i_ino, DT_DIR) < 0)
+ return 0;
+ filp->f_pos = f_pos = 1;
+ stored++;
+ }
+ if (f_pos == 1) {
+ if (filldir(dirent, "..", 2, f_pos, parent_ino(filp->f_path.dentry), DT_DIR) < 0)
+ return stored;
+ filp->f_pos = f_pos = 2;
+ stored++;
+ }
+
+ if (ASFS_I(dir)->firstblock == 0) { /* empty directory */
+ filp->f_pos = ASFS_SB(sb)->totalblocks;
+ ASFS_I(dir)->modified = 0;
+ return stored;
+ }
+
+ if (f_pos == 2) { /* reading directory from its beginning */
+ block = ASFS_I(dir)->firstblock;
+ add = 1;
+ startnode = 0;
+ } else {
+ startnode = (int)filp->private_data;
+ add = 0;
+ if (ASFS_I(dir)->modified == 0)
+ block = f_pos;
+ else
+ block = ASFS_I(dir)->firstblock;
+ }
+
+ do {
+ if (!(bh = asfs_breadcheck(sb, block, ASFS_OBJECTCONTAINER_ID)))
+ return stored;
+ objcont = (struct fsObjectContainer *) bh->b_data;
+ obj = &(objcont->object[0]);
+
+ while (be32_to_cpu(obj->objectnode) > 0 &&
+ ((char *)obj - (char *)objcont) + sizeof(struct fsObject) + 2 < sb->s_blocksize) {
+
+ if (!add && be32_to_cpu(obj->objectnode) == startnode)
+ add++;
+
+ if (add && !(obj->bits & OTYPE_HIDDEN)) {
+ unsigned int type;
+ asfs_translate(buf, obj->name, nls_io, nls_disk, 512);
+ asfs_debug("ASFS: DirFilling: entry #%d \"%s\" (node %u offset %u), type %x\n", \
+ stored, buf, be32_to_cpu(obj->objectnode), block, obj->bits);
+ filp->f_pos = block;
+
+ if (obj->bits & OTYPE_DIR)
+ type = DT_DIR;
+ else if (obj->bits & OTYPE_LINK && !(obj->bits & OTYPE_HARDLINK))
+ type = DT_LNK;
+ else
+ type = DT_REG;
+
+ if (filldir(dirent, buf, strlen(buf), block, be32_to_cpu(obj->objectnode), type) < 0) {
+ filp->private_data = (void *)be32_to_cpu(obj->objectnode);
+ ASFS_I(dir)->modified = 0;
+ asfs_debug("ASFS: DirFilling: to be continued...\n");
+ asfs_brelse(bh);
+ return stored;
+ }
+ stored++;
+ }
+ obj = asfs_nextobject(obj);
+ }
+ block = be32_to_cpu(objcont->next);
+ asfs_brelse(bh);
+
+ } while (block != 0);
+
+ filp->f_pos = ASFS_SB(sb)->totalblocks;
+ ASFS_I(dir)->modified = 0;
+
+ return stored;
+}
+
+static struct fsObject *asfs_find_obj_by_name_nls(struct super_block *sb, struct fsObjectContainer *objcont, u8 * name)
+{
+ struct fsObject *obj;
+ u8 buf[512];
+
+ obj = &(objcont->object[0]);
+ while (be32_to_cpu(obj->objectnode) > 0 && ((char *) obj - (char *) objcont) + sizeof(struct fsObject) + 2 < sb->s_blocksize) {
+ asfs_translate(buf, obj->name, ASFS_SB(sb)->nls_io, ASFS_SB(sb)->nls_disk, 512);
+ if (asfs_namecmp(buf, name, ASFS_SB(sb)->flags & ASFS_ROOTBITS_CASESENSITIVE, ASFS_SB(sb)->nls_io) == 0) {
+ asfs_debug("Object found! Node %u, Name %s, Type %x, inCont %u\n", be32_to_cpu(obj->objectnode), obj->name, obj->bits, be32_to_cpu(objcont->bheader.ownblock));
+ return obj;
+ }
+ obj = asfs_nextobject(obj);
+ }
+ return NULL;
+}
+
+struct dentry *asfs_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
+{
+ int res = -EACCES; /* placeholder for "no data here" */
+ struct inode *inode;
+ struct super_block *sb = dir->i_sb;
+ u8 *name = (u8 *) dentry->d_name.name;
+ struct buffer_head *bh;
+ struct fsObject *obj;
+ u8 bufname[ASFS_MAXFN_BUF];
+
+ asfs_translate(bufname, name, ASFS_SB(sb)->nls_disk, ASFS_SB(sb)->nls_io, ASFS_MAXFN_BUF);
+
+ asfs_debug("asfs_lookup: (searching \"%s\"...) ", name);
+
+ lock_super(sb);
+
+ if ((!strchr(name, '?')) && (ASFS_I(dir)->hashtable != 0)) { /* hashtable block is available and name can be reverse translated, quick search */
+ struct fsObjectNode *node_p;
+ struct buffer_head *node_bh;
+ u32 node;
+ u16 hash16;
+
+ asfs_debug("(quick search) ");
+
+ if (!(bh = asfs_breadcheck(sb, ASFS_I(dir)->hashtable, ASFS_HASHTABLE_ID))) {
+ unlock_super(sb);
+ return ERR_PTR(res);
+ }
+ hash16 = asfs_hash(bufname, ASFS_SB(sb)->flags & ASFS_ROOTBITS_CASESENSITIVE);
+ node = be32_to_cpu(((struct fsHashTable *) bh->b_data)->hashentry[HASHCHAIN(hash16)]);
+ asfs_brelse(bh);
+
+ while (node != 0) {
+ if (asfs_getnode(sb, node, &node_bh, &node_p) != 0)
+ goto not_found;
+ if (be16_to_cpu(node_p->hash16) == hash16) {
+ if (!(bh = asfs_breadcheck(sb, be32_to_cpu(node_p->node.data), ASFS_OBJECTCONTAINER_ID))) {
+ asfs_brelse(node_bh);
+ unlock_super(sb);
+ return ERR_PTR(res);
+ }
+ if ((obj = asfs_find_obj_by_name(sb, (struct fsObjectContainer *) bh->b_data, bufname)) != NULL) {
+ asfs_brelse(node_bh);
+ goto found_inode;
+ }
+ asfs_brelse(bh);
+ }
+ node = be32_to_cpu(node_p->next);
+ asfs_brelse(node_bh);
+ }
+ } else { /* hashtable not available or name can't be reverse-translated, long search */
+ struct fsObjectContainer *objcont;
+ u32 block;
+
+ asfs_debug("(long search) ");
+ block = ASFS_I(dir)->firstblock;
+ while (block != 0) {
+ if (!(bh = asfs_breadcheck(sb, block, ASFS_OBJECTCONTAINER_ID))) {
+ unlock_super(sb);
+ return ERR_PTR(res);
+ }
+ objcont = (struct fsObjectContainer *) bh->b_data;
+ if ((obj = asfs_find_obj_by_name_nls(sb, objcont, name)) != NULL)
+ goto found_inode;
+ block = be32_to_cpu(objcont->next);
+ asfs_brelse(bh);
+ }
+ }
+
+not_found:
+ unlock_super(sb);
+ inode = NULL;
+ asfs_debug("object not found.\n");
+ if (0) {
+found_inode:
+ unlock_super(sb);
+ if (!(inode = iget_locked(sb, be32_to_cpu(obj->objectnode)))) {
+ asfs_debug("ASFS: Strange - no inode allocated.\n");
+ return ERR_PTR(res);
+ }
+ if (inode->i_state & I_NEW) {
+ asfs_read_locked_inode(inode, obj);
+ unlock_new_inode(inode);
+ }
+ asfs_brelse(bh);
+ }
+ res = 0;
+ dentry->d_op = &asfs_dentry_operations;
+ d_add(dentry, inode);
+ return ERR_PTR(res);
+}
^ permalink raw reply [flat|nested] 2+ messages in thread
* [PATCH 3/9] Amiga SmartFileSystem
@ 2009-02-09 6:54 Pavel Fedin
0 siblings, 0 replies; 2+ messages in thread
From: Pavel Fedin @ 2009-02-09 6:54 UTC (permalink / raw)
To: linux-fsdevel
diff -ruN linux-source-2.6.24.orig/fs/asfs/bitfuncs.h
linux-source-2.6.24/fs/asfs/bitfuncs.h
--- linux-source-2.6.24.orig/fs/asfs/bitfuncs.h 1970-01-01
03:00:00.000000000 +0300
+++ linux-source-2.6.24/fs/asfs/bitfuncs.h 2008-12-14
23:42:39.000000000 +0300
@@ -0,0 +1,58 @@
+/*
+ *
+ * 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.
+ *
+ */
+
+#ifndef __BITFUNCS_H
+#define __BITFUNCS_H
+
+#include <linux/types.h>
+#include <asm/byteorder.h>
+
+#include <linux/bitops.h>
+
+/* Finds first set bit in /data/ starting at /bitoffset/. This function
+ considers the MSB to be the first bit. */
+static inline int bfffo(u32 data, int bitoffset)
+{
+ u32 mask = 0xffffffff >> bitoffset;
+ data &= mask;
+ return data == 0 ? -1 : 32-fls(data);
+}
+
+/* Finds first zero bit in /data/ starting at /bitoffset/. This function
+ considers the MSB to be the first bit. */
+static inline int bfffz(u32 data, int bitoffset)
+{
+ return bfffo(~data, bitoffset);
+}
+
+/* Sets /bits/ bits starting from /bitoffset/ in /data/.
+ /bits/ must be between 1 and 32. */
+static inline u32 bfset(u32 data, int bitoffset, int bits)
+{
+ u32 mask = ~((1 << (32 - bits)) - 1);
+ mask >>= bitoffset;
+ return data | mask;
+}
+
+/* Clears /bits/ bits starting from /bitoffset/ in /data/.
+ /bits/ must be between 1 and 32. */
+static inline u32 bfclr(u32 data, int bitoffset, int bits)
+{
+ u32 mask = ~((1 << (32 - bits)) - 1);
+ mask >>= bitoffset;
+ return data & ~mask;
+}
+
+/* bm??? functions assumes that in-memory bitmap is in bigendian byte order */
+int bmffo(u32 *, int, int);
+int bmffz(u32 *, int, int);
+int bmclr(u32 *, int, int, int);
+int bmset(u32 *, int, int, int);
+
+#endif
diff -ruN linux-source-2.6.24.orig/fs/asfs/Changes
linux-source-2.6.24/fs/asfs/Changes
--- linux-source-2.6.24.orig/fs/asfs/Changes 1970-01-01
03:00:00.000000000 +0300
+++ linux-source-2.6.24/fs/asfs/Changes 2008-12-14 23:05:05.000000000 +0300
@@ -0,0 +1,120 @@
+
+Amiga Smart File System, Linux implementation
+
+Please direct bug reports to: marek@amiga.pl
+
+History:
+
+v1.0beta12 (03.12.2006)
+- adapted to 2.6.19 kernel VFS changes
+- fixed symlink write crash
+
+v1.0beta11 (22.09.2006)
+- adapted to 2.6.18 kernel VFS changes
+- made some functions static to reduce overhead in kernel namespace
+
+v1.0beta10 (13.06.2005)
+- fixed ugly bug introduced in beta9 that caused kernel crash on x86
+ (thanks to Emiliano for reporting it!)
+
+v1.0beta9 (17.03.2005)
+- added NLS support (thanks to Pavel Fedin!)
+
+v1.0beta8 (07.01.2005)
+- adapted to 2.6.10 kernel VFS changes
+- added workaround for buggy Mandrake kernel headers
+
+v1.0beta7 (25.06.2004)
+- small changes in documentation
+- code clean up: bitfuncs.c, super.c, inode.c, *.h, Makefile, added
+ asfs_ prefix to function names, made some functions static
+ (big thanks to Christoph Hellwig for advice!)
+- fixed minor bugs (inode leak in super.c, not-realesed buffer during
+ object renaming in inode.c)
+- now files/dirs are created with global ownership/permission bits
+
+v1.0beta6 (04.06.2004)
+- fixed: ASFS_SB(sb)->flags was always zero in 2.6.x code
+
+v1.0beta5 (07.05.2004)
+- finally fixed a problem with file size attrib. not being written
+ to disk
+- fixed some problems with GCC 3.x and debug enabled
+
+v1.0beta4 (12.04.2004)
+- removed dummy asfs_notify_change (this fixes major bug introduced
+ in 1.0beta3 - file size wasn't written to disk) until it will
+ be implemented completely
+
+v1.0beta3 (22.03.2004) - still beta
+- updated for 2.6.x kernels VFS changes
+- code clean-up
+- added dummy asfs_notify_change (chmod now returns no errors)
+- added symlinks write support
+- fixed: ASFS_SB(sb)->flags was always zero
+
+v1.0beta2 (11.01.2004) - special version for Pegasos][ kernel
+- separated read and write functions, can be compiled also
+ as read-only fs
+
+v1.0beta1 (02.12.2003) - first public beta with write support
+- added dentry hashing/comparing routines
+- code clean-up
+
+v1.0aplha4 (30.11.2003) - preparing for first public beta
+- fixed some problems with renaming/moving files
+- fixed two major bugs, which didn't occur when fs was mounted
+ on loopback device (newly allocated blocks were not written to
+ disk and state bits were not set correctly on newly mapped file
+ blocks)
+- fixed many small bugs in io code (some buffers were not freed)
+- added/modified sb locks in asfs_lookup and asfs_getblock
+- fixed serious bug in file block allocation routines
+
+v1.0aplha3 (23.11.2003)
+- added (hopefully) all byteswap code, should now work again on
+ little-endian systems (also with write support!)
+- updated documentation
+
+v1.0alpha2 (13.11.2003)
+- now alocates file blocks in chunks during one request
+- fixed some dead-locks, other fixes
+
+v1.0alpha (02.11.2003) - first working version with full write support
+- too much to list it here ;)
+
+... (working on write support)
+
+v0.7 (12.10.2003) - internal realase
+- added asfs_breadcheck, modified asfs_get_node, asfs_search_BTree,
+ no more from_be32/16 macros, other...
+- code splitted into several files
+
+v0.6 (04.09.2003) - final read-only version
+- added support for HashTables, directory scaning should be
+ MUCH faster now
+- added checking of block IDs before reading any data from block
+
+v0.5 (19.07.2003)
+- added simple but effective extent cache - real speed-up
+ in reading large files
+- added read support for symlinks - based on AFFS symlinks
+
+v0.4 (10.07.2003)
+- third code clean-up (thanks to Roman Zippel for advice)
+- now uses generic readpage and readinode routines
+
+v0.3beta (17.06.2003)
+- second code clean-up
+
+v0.2beta2 (15.06.2003)
+- fixed yet another stupid bug - driver can't read root block on
little-endian systems
+v0.2beta (15.06.2003)
+- fixed stupid bug - now files have 'file' flag (S_IFREG) set...
+- added mount options to set uid, gid and mode of files and dirs
+- made hidden files & dirs really hidden (= not listed in directories)
+- code clean-up
+
+v0.1beta (11.06.2003)
+- after many kernel crashes, finally got it!
+- first working read-only filesystem driver
diff -ruN linux-source-2.6.24.orig/fs/asfs/dir.c
linux-source-2.6.24/fs/asfs/dir.c
--- linux-source-2.6.24.orig/fs/asfs/dir.c 1970-01-01
03:00:00.000000000 +0300
+++ linux-source-2.6.24/fs/asfs/dir.c 2008-12-14 23:05:05.000000000 +0300
@@ -0,0 +1,240 @@
+/*
+ *
+ * Amiga Smart File System, Linux implementation
+ * version: 1.0beta7
+ *
+ * Copyright (C) 2003,2004 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/fs.h>
+#include <linux/buffer_head.h>
+#include <linux/vfs.h>
+#include "asfs_fs.h"
+
+#include <asm/byteorder.h>
+
+extern struct dentry_operations asfs_dentry_operations;
+
+int asfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
+{
+ struct inode *dir = filp->f_path.dentry->d_inode;
+ struct super_block *sb = dir->i_sb;
+ struct nls_table *nls_io = ASFS_SB(sb)->nls_io;
+ struct nls_table *nls_disk = ASFS_SB(sb)->nls_disk;
+ u8 buf[512];
+ unsigned long f_pos;
+ int stored = 0;
+
+ struct buffer_head *bh;
+ struct fsObjectContainer *objcont;
+ struct fsObject *obj;
+ u32 block;
+ int startnode;
+ int add;
+
+ asfs_debug("asfs_readdir:\n");
+
+ if (filp->f_pos == ASFS_SB(sb)->totalblocks)
+ return stored;
+
+ f_pos = filp->f_pos;
+
+ if (f_pos == 0) {
+ filp->private_data = (void *)0;
+ if (filldir(dirent, ".", 1, f_pos, dir->i_ino, DT_DIR) < 0)
+ return 0;
+ filp->f_pos = f_pos = 1;
+ stored++;
+ }
+ if (f_pos == 1) {
+ if (filldir(dirent, "..", 2, f_pos,
parent_ino(filp->f_path.dentry), DT_DIR) < 0)
+ return stored;
+ filp->f_pos = f_pos = 2;
+ stored++;
+ }
+
+ if (ASFS_I(dir)->firstblock == 0) { /* empty directory */
+ filp->f_pos = ASFS_SB(sb)->totalblocks;
+ ASFS_I(dir)->modified = 0;
+ return stored;
+ }
+
+ if (f_pos == 2) { /* reading directory from its beginning */
+ block = ASFS_I(dir)->firstblock;
+ add = 1;
+ startnode = 0;
+ } else {
+ startnode = (int)filp->private_data;
+ add = 0;
+ if (ASFS_I(dir)->modified == 0)
+ block = f_pos;
+ else
+ block = ASFS_I(dir)->firstblock;
+ }
+
+ do {
+ if (!(bh = asfs_breadcheck(sb, block, ASFS_OBJECTCONTAINER_ID)))
+ return stored;
+ objcont = (struct fsObjectContainer *) bh->b_data;
+ obj = &(objcont->object[0]);
+
+ while (be32_to_cpu(obj->objectnode) > 0 &&
+ ((char *)obj - (char *)objcont) + sizeof(struct
fsObject) + 2 < sb->s_blocksize) {
+
+ if (!add && be32_to_cpu(obj->objectnode) == startnode)
+ add++;
+
+ if (add && !(obj->bits & OTYPE_HIDDEN)) {
+ unsigned int type;
+ asfs_translate(buf, obj->name, nls_io,
nls_disk, 512);
+ asfs_debug("ASFS: DirFilling: entry
#%d \"%s\" (node %u offset %u), type %x\n", \
+ stored, buf,
be32_to_cpu(obj->objectnode), block, obj->bits);
+ filp->f_pos = block;
+
+ if (obj->bits & OTYPE_DIR)
+ type = DT_DIR;
+ else if (obj->bits & OTYPE_LINK &&
!(obj->bits & OTYPE_HARDLINK))
+ type = DT_LNK;
+ else
+ type = DT_REG;
+
+ if (filldir(dirent, buf, strlen(buf),
block, be32_to_cpu(obj->objectnode), type) < 0) {
+ filp->private_data = (void
*)be32_to_cpu(obj->objectnode);
+ ASFS_I(dir)->modified = 0;
+ asfs_debug("ASFS: DirFilling:
to be continued...\n");
+ asfs_brelse(bh);
+ return stored;
+ }
+ stored++;
+ }
+ obj = asfs_nextobject(obj);
+ }
+ block = be32_to_cpu(objcont->next);
+ asfs_brelse(bh);
+
+ } while (block != 0);
+
+ filp->f_pos = ASFS_SB(sb)->totalblocks;
+ ASFS_I(dir)->modified = 0;
+
+ return stored;
+}
+
+static struct fsObject *asfs_find_obj_by_name_nls(struct super_block
*sb, struct fsObjectContainer *objcont, u8 * name)
+{
+ struct fsObject *obj;
+ u8 buf[512];
+
+ obj = &(objcont->object[0]);
+ while (be32_to_cpu(obj->objectnode) > 0 && ((char *) obj -
(char *) objcont) + sizeof(struct fsObject) + 2 < sb->s_blocksize) {
+ asfs_translate(buf, obj->name, ASFS_SB(sb)->nls_io,
ASFS_SB(sb)->nls_disk, 512);
+ if (asfs_namecmp(buf, name, ASFS_SB(sb)->flags &
ASFS_ROOTBITS_CASESENSITIVE, ASFS_SB(sb)->nls_io) == 0) {
+ asfs_debug("Object found! Node %u, Name %s,
Type %x, inCont %u\n", be32_to_cpu(obj->objectnode), obj->name,
obj->bits, be32_to_cpu(objcont->bheader.ownblock));
+ return obj;
+ }
+ obj = asfs_nextobject(obj);
+ }
+ return NULL;
+}
+
+struct dentry *asfs_lookup(struct inode *dir, struct dentry *dentry,
struct nameidata *nd)
+{
+ int res = -EACCES; /* placeholder for "no data here" */
+ struct inode *inode;
+ struct super_block *sb = dir->i_sb;
+ u8 *name = (u8 *) dentry->d_name.name;
+ struct buffer_head *bh;
+ struct fsObject *obj;
+ u8 bufname[ASFS_MAXFN_BUF];
+
+ asfs_translate(bufname, name, ASFS_SB(sb)->nls_disk,
ASFS_SB(sb)->nls_io, ASFS_MAXFN_BUF);
+
+ asfs_debug("asfs_lookup: (searching \"%s\"...) ", name);
+
+ lock_super(sb);
+
+ if ((!strchr(name, '?')) && (ASFS_I(dir)->hashtable != 0)) {
/* hashtable block is available and name can be reverse translated,
quick search */
+ struct fsObjectNode *node_p;
+ struct buffer_head *node_bh;
+ u32 node;
+ u16 hash16;
+
+ asfs_debug("(quick search) ");
+
+ if (!(bh = asfs_breadcheck(sb, ASFS_I(dir)->hashtable,
ASFS_HASHTABLE_ID))) {
+ unlock_super(sb);
+ return ERR_PTR(res);
+ }
+ hash16 = asfs_hash(bufname, ASFS_SB(sb)->flags &
ASFS_ROOTBITS_CASESENSITIVE);
+ node = be32_to_cpu(((struct fsHashTable *)
bh->b_data)->hashentry[HASHCHAIN(hash16)]);
+ asfs_brelse(bh);
+
+ while (node != 0) {
+ if (asfs_getnode(sb, node, &node_bh, &node_p) != 0)
+ goto not_found;
+ if (be16_to_cpu(node_p->hash16) == hash16) {
+ if (!(bh = asfs_breadcheck(sb,
be32_to_cpu(node_p->node.data), ASFS_OBJECTCONTAINER_ID))) {
+ asfs_brelse(node_bh);
+ unlock_super(sb);
+ return ERR_PTR(res);
+ }
+ if ((obj = asfs_find_obj_by_name(sb,
(struct fsObjectContainer *) bh->b_data, bufname)) != NULL) {
+ asfs_brelse(node_bh);
+ goto found_inode;
+ }
+ asfs_brelse(bh);
+ }
+ node = be32_to_cpu(node_p->next);
+ asfs_brelse(node_bh);
+ }
+ } else { /* hashtable not available or name can't be
reverse-translated, long search */
+ struct fsObjectContainer *objcont;
+ u32 block;
+
+ asfs_debug("(long search) ");
+ block = ASFS_I(dir)->firstblock;
+ while (block != 0) {
+ if (!(bh = asfs_breadcheck(sb, block,
ASFS_OBJECTCONTAINER_ID))) {
+ unlock_super(sb);
+ return ERR_PTR(res);
+ }
+ objcont = (struct fsObjectContainer *) bh->b_data;
+ if ((obj = asfs_find_obj_by_name_nls(sb,
objcont, name)) != NULL)
+ goto found_inode;
+ block = be32_to_cpu(objcont->next);
+ asfs_brelse(bh);
+ }
+ }
+
+not_found:
+ unlock_super(sb);
+ inode = NULL;
+ asfs_debug("object not found.\n");
+ if (0) {
+found_inode:
+ unlock_super(sb);
+ if (!(inode = iget_locked(sb, be32_to_cpu(obj->objectnode)))) {
+ asfs_debug("ASFS: Strange - no inode allocated.\n");
+ return ERR_PTR(res);
+ }
+ if (inode->i_state & I_NEW) {
+ asfs_read_locked_inode(inode, obj);
+ unlock_new_inode(inode);
+ }
+ asfs_brelse(bh);
+ }
+ res = 0;
+ dentry->d_op = &asfs_dentry_operations;
+ d_add(dentry, inode);
+ return ERR_PTR(res);
+}
^ 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 --
2008-12-26 12:08 [PATCH 3/9] Amiga SmartFileSystem Pavel Fedin
2009-02-09 6:54 Pavel Fedin
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.