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