[PATCH 3/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/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@xxxxxxxx
+
+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@xxxxxxxx>
+ *
+ *
+ * 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);
+}

--
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