Commit 0d7f311c authored by Alan Cox's avatar Alan Cox Committed by Linus Torvalds

[PATCH] merge befs file system from 2.4 (no core changes)

parent d7831e74
......@@ -963,6 +963,28 @@ CONFIG_VXFS_FS
module, say M here and read <file:Documentation/modules.txt>. If
unsure, say N.
CONFIG_BEFS_FS
The BeOS File System (BeFS) is the native file system of Be, Inc's
BeOS. Notable features include support for arbitrary attributes
on files and directories, and database-like indices on selected
attributes. (Also note that this driver doesn't make those features
available at this time). It is a 64 bit filesystem, so it supports
extreemly large volumes and files.
If you use this filesystem, you should also say Y to at least one
of the NLS (native language support) options below.
If you don't know what this is about, say N.
If you want to compile this as a module ( = code which can be
inserted in and removed from the running kernel whenever you want),
say M here and read Documentation/modules.txt. The module will be
called befs.o.
CONFIG_BEFS_DEBUG
If you say Y here, you can use the 'debug' mount option to enable
debugging output from the driver.
CIFS (Common Internet File System) support
CONFIG_CIFS
This is the client VFS module for the Common Internet File System
......
......@@ -24,6 +24,9 @@ dep_tristate 'Amiga FFS file system support (EXPERIMENTAL)' CONFIG_AFFS_FS $CONF
dep_tristate 'Apple Macintosh file system support (EXPERIMENTAL)' CONFIG_HFS_FS $CONFIG_EXPERIMENTAL
dep_tristate 'BeOS file systemv(BeFS) support (read only) (EXPERIMENTAL)' CONFIG_BEFS_FS $CONFIG_EXPERIMENTAL
dep_mbool ' Debug BeFS' CONFIG_BEFS_DEBUG $CONFIG_BEFS_FS
dep_tristate 'BFS file system support (EXPERIMENTAL)' CONFIG_BFS_FS $CONFIG_EXPERIMENTAL
tristate 'Ext3 journalling file system support' CONFIG_EXT3_FS
......
......@@ -87,5 +87,6 @@ obj-$(CONFIG_SUN_OPENPROMFS) += openpromfs/
obj-$(CONFIG_JFS_FS) += jfs/
obj-$(CONFIG_XFS_FS) += xfs/
obj-$(CONFIG_AFS_FS) += afs/
obj-$(CONFIG_BEFS_FS) += befs/
include $(TOPDIR)/Rules.make
This diff is collapsed.
#
# Makefile for the linux BeOS filesystem routines.
#
# Note! Dependencies are done automagically by 'make dep', which also
# removes any old dependencies. DON'T put your own dependencies here
# unless it's something special (ie not a .c file).
#
# Note 2! The CFLAGS definitions are now in the main makefile...
obj-$(CONFIG_BEFS_FS) += befs.o
befs-objs := datastream.o btree.o super.o inode.o debug.o io.o linuxvfs.o
include $(TOPDIR)/Rules.make
TODO
==========
* Convert comments to the Kernel-Doc format.
* Befs_fs.h has gotten big and messy. No reason not to break it up into
smaller peices.
* See if Alexander Viro's option parser made it into the kernel tree.
Use that if we can. (include/linux/parser.h)
* See if we really need separate types for on-disk and in-memory
representations of the superblock and inode.
/*
* linux/fs/befs/attribute.c
*
* Copyright (C) 2002 Will Dyson <will_dyson@pobox.com>
*
* Many thanks to Dominic Giampaolo, author of "Practical File System
* Design with the Be File System", for such a helpful book.
*
*/
#include <linux/fs.h>
#include <linux/kernel.h>
#include <linux/string.h>
#include "befs.h"
#include "endian.h"
#define SD_DATA(sd)\
(void*)((char*)sd + sizeof(*sd) + (sd->name_size - sizeof(sd->name)))
#define SD_NEXT(sd)\
(befs_small_data*)((char*)sd + sizeof(*sd) + (sd->name_size - \
sizeof(sd->name) + sd->data_size))
int
list_small_data(struct super_block *sb, befs_inode * inode, filldir_t filldir);
befs_small_data *
find_small_data(struct super_block *sb, befs_inode * inode,
const char *name);
int
read_small_data(struct super_block *sb, befs_inode * inode,
befs_small_data * sdata, void *buf, size_t bufsize);
/**
*
*
*
*
*
*/
befs_small_data *
find_small_data(struct super_block *sb, befs_inode * inode, const char *name)
{
befs_small_data *sdata = inode->small_data;
while (sdata->type != 0) {
if (strcmp(name, sdata->name) != 0) {
return sdata;
}
sdata = SD_NEXT(sdata);
}
return NULL;
}
/**
*
*
*
*
*
*/
int
read_small_data(struct super_block *sb, befs_inode * inode,
const char *name, void *buf, size_t bufsize)
{
befs_small_data *sdata;
sdata = find_small_data(sb, inode, name);
if (sdata == NULL)
return BEFS_ERR;
else if (sdata->data_size > bufsize)
return BEFS_ERR;
memcpy(buf, SD_DATA(sdata), sdata->data_size);
return BEFS_OK;
}
/**
*
*
*
*
*
*/
int
list_small_data(struct super_block *sb, befs_inode * inode)
{
}
/**
*
*
*
*
*
*/
int
list_attr(struct super_block *sb, befs_inode * inode)
{
}
/**
*
*
*
*
*
*/
int
read_attr(struct super_block *sb, befs_inode * inode)
{
}
/*
* befs.h
*
* Copyright (C) 2001-2002 Will Dyson <will_dyson@pobox.com>
* Copyright (C) 1999 Makoto Kato (m_kato@ga2.so-net.ne.jp)
*/
#ifndef _LINUX_BEFS_H
#define _LINUX_BEFS_H
#include "befs_fs_types.h"
/* used in debug.c */
#define BEFS_VERSION "0.9.3"
/* Sector_t makes this sillyness obsolete */
typedef u64 befs_blocknr_t;
typedef u32 vfs_blocknr_t;
/*
* BeFS in memory structures
*/
typedef struct befs_mount_options {
gid_t gid;
uid_t uid;
int use_gid;
int use_uid;
int debug;
char *iocharset;
} befs_mount_options;
typedef struct befs_sb_info {
u32 magic1;
u32 block_size;
u32 block_shift;
int byte_order;
befs_off_t num_blocks;
befs_off_t used_blocks;
u32 inode_size;
u32 magic2;
/* Allocation group information */
u32 blocks_per_ag;
u32 ag_shift;
u32 num_ags;
/* jornal log entry */
befs_block_run log_blocks;
befs_off_t log_start;
befs_off_t log_end;
befs_inode_addr root_dir;
befs_inode_addr indices;
u32 magic3;
befs_mount_options mount_opts;
struct nls_table *nls;
} befs_sb_info;
typedef struct befs_inode_info {
u32 i_flags;
u32 i_type;
befs_inode_addr i_inode_num;
befs_inode_addr i_parent;
befs_inode_addr i_attribute;
union {
befs_data_stream ds;
char symlink[BEFS_SYMLINK_LEN];
} i_data;
struct inode vfs_inode;
} befs_inode_info;
enum befs_err {
BEFS_OK,
BEFS_ERR,
BEFS_BAD_INODE,
BEFS_BT_END,
BEFS_BT_EMPTY,
BEFS_BT_MATCH,
BEFS_BT_PARMATCH,
BEFS_BT_NOT_FOUND
};
/****************************/
/* debug.c */
void befs_error(const struct super_block *sb, const char *fmt, ...);
void befs_warning(const struct super_block *sb, const char *fmt, ...);
void befs_debug(const struct super_block *sb, const char *fmt, ...);
void befs_dump_super_block(const struct super_block *sb, befs_super_block *);
void befs_dump_inode(const struct super_block *sb, befs_inode *);
void befs_dump_index_entry(const struct super_block *sb, befs_btree_super *);
void befs_dump_index_node(const struct super_block *sb, befs_btree_nodehead *);
void befs_dump_inode_addr(const struct super_block *sb, befs_inode_addr);
/****************************/
/* Gets a pointer to the private portion of the super_block
* structure from the public part
*/
static inline befs_sb_info *
BEFS_SB(const struct super_block *super)
{
return (befs_sb_info *) super->s_fs_info;
}
static inline befs_inode_info *
BEFS_I(const struct inode *inode)
{
return list_entry(inode, struct befs_inode_info, vfs_inode);
}
static inline befs_blocknr_t
iaddr2blockno(struct super_block *sb, befs_inode_addr * iaddr)
{
return ((iaddr->allocation_group << BEFS_SB(sb)->ag_shift) +
iaddr->start);
}
static inline befs_inode_addr
blockno2iaddr(struct super_block *sb, befs_blocknr_t blockno)
{
befs_inode_addr iaddr;
iaddr.allocation_group = blockno >> BEFS_SB(sb)->ag_shift;
iaddr.start =
blockno - (iaddr.allocation_group << BEFS_SB(sb)->ag_shift);
iaddr.len = 1;
return iaddr;
}
static inline unsigned int
befs_iaddrs_per_block(struct super_block *sb)
{
return BEFS_SB(sb)->block_size / sizeof (befs_inode_addr);
}
static inline int
befs_iaddr_is_empty(befs_inode_addr * iaddr)
{
return (!iaddr->allocation_group) && (!iaddr->start) && (!iaddr->len);
}
static inline size_t
befs_brun_size(struct super_block *sb, befs_block_run run)
{
return BEFS_SB(sb)->block_size * run.len;
}
#endif /* _LINUX_BEFS_H */
/*
* include/linux/befs_fs_types.h
*
* Copyright (C) 2001 Will Dyson (will@cs.earlham.edu)
*
*
*
* from linux/include/linux/befs_fs.h
*
* Copyright (C) 1999 Makoto Kato (m_kato@ga2.so-net.ne.jp)
*
*/
#ifndef _LINUX_BEFS_FS_TYPES
#define _LINUX_BEFS_FS_TYPES
#ifdef __KERNEL__
#include <linux/types.h>
#endif /*__KERNEL__*/
#define PACKED __attribute__ ((__packed__))
/*
* Max name lengths of BFS
*/
#define BEFS_NAME_LEN 255
#define BEFS_SYMLINK_LEN 144
#define BEFS_NUM_DIRECT_BLOCKS 12
#define B_OS_NAME_LENGTH 32
/* The datastream blocks mapped by the double-indirect
* block are always 4 fs blocks long.
* This eliminates the need for linear searches among
* the potentially huge number of indirect blocks
*
* Err. Should that be 4 fs blocks or 4k???
* It matters on large blocksize volumes
*/
#define BEFS_DBLINDIR_BRUN_LEN 4
/*
* Flags of superblock
*/
enum super_flags {
BEFS_BYTESEX_BE,
BEFS_BYTESEX_LE,
BEFS_CLEAN = 0x434c454e,
BEFS_DIRTY = 0x44495254,
BEFS_SUPER_MAGIC1 = 0x42465331, /* BFS1 */
BEFS_SUPER_MAGIC2 = 0xdd121031,
BEFS_SUPER_MAGIC3 = 0x15b6830e,
};
#define BEFS_BYTEORDER_NATIVE 0x42494745
#define BEFS_SUPER_MAGIC BEFS_SUPER_MAGIC1
/*
* Flags of inode
*/
#define BEFS_INODE_MAGIC1 0x3bbe0ad9
enum inode_flags {
BEFS_INODE_IN_USE = 0x00000001,
BEFS_ATTR_INODE = 0x00000004,
BEFS_INODE_LOGGED = 0x00000008,
BEFS_INODE_DELETED = 0x00000010,
BEFS_LONG_SYMLINK = 0x00000040,
BEFS_PERMANENT_FLAG = 0x0000ffff,
BEFS_INODE_NO_CREATE = 0x00010000,
BEFS_INODE_WAS_WRITTEN = 0x00020000,
BEFS_NO_TRANSACTION = 0x00040000,
};
/*
* On-Disk datastructures of BeFS
*/
typedef u64 befs_off_t;
typedef u64 befs_time_t;
typedef void befs_binode_etc;
/* Block runs */
typedef struct {
u32 allocation_group;
u16 start;
u16 len;
} PACKED befs_block_run;
typedef befs_block_run befs_inode_addr;
/*
* The Superblock Structure
*/
typedef struct {
char name[B_OS_NAME_LENGTH];
u32 magic1;
u32 fs_byte_order;
u32 block_size;
u32 block_shift;
befs_off_t num_blocks;
befs_off_t used_blocks;
u32 inode_size;
u32 magic2;
u32 blocks_per_ag;
u32 ag_shift;
u32 num_ags;
u32 flags;
befs_block_run log_blocks;
befs_off_t log_start;
befs_off_t log_end;
u32 magic3;
befs_inode_addr root_dir;
befs_inode_addr indices;
} PACKED befs_super_block;
/*
* Note: the indirect and dbl_indir block_runs may
* be longer than one block!
*/
typedef struct {
befs_block_run direct[BEFS_NUM_DIRECT_BLOCKS];
befs_off_t max_direct_range;
befs_block_run indirect;
befs_off_t max_indirect_range;
befs_block_run double_indirect;
befs_off_t max_double_indirect_range;
befs_off_t size;
} PACKED befs_data_stream;
/* Attribute */
typedef struct {
u32 type;
u16 name_size;
u16 data_size;
char name[1];
} PACKED befs_small_data;
/* Inode structure */
typedef struct {
u32 magic1;
befs_inode_addr inode_num;
u32 uid;
u32 gid;
u32 mode;
u32 flags;
befs_time_t create_time;
befs_time_t last_modified_time;
befs_inode_addr parent;
befs_inode_addr attributes;
u32 type;
u32 inode_size;
u32 etc; /* not use */
union {
befs_data_stream datastream;
char symlink[BEFS_SYMLINK_LEN];
} data;
u32 pad[4]; /* not use */
befs_small_data small_data[1];
} PACKED befs_inode;
/*
* B+tree superblock
*/
#define BEFS_BTREE_MAGIC 0x69f6c2e8
enum btree_types {
BTREE_STRING_TYPE = 0,
BTREE_INT32_TYPE = 1,
BTREE_UINT32_TYPE = 2,
BTREE_INT64_TYPE = 3,
BTREE_UINT64_TYPE = 4,
BTREE_FLOAT_TYPE = 5,
BTREE_DOUBLE_TYPE = 6
};
typedef struct {
u32 magic;
u32 node_size;
u32 max_depth;
u32 data_type;
befs_off_t root_node_ptr;
befs_off_t free_node_ptr;
befs_off_t max_size;
} PACKED befs_btree_super;
/*
* Header stucture of each btree node
*/
typedef struct {
befs_off_t left;
befs_off_t right;
befs_off_t overflow;
u16 all_key_count;
u16 all_key_length;
} PACKED befs_btree_nodehead;
#endif /* _LINUX_BEFS_FS_TYPES */
This diff is collapsed.
/*
* btree.h
*
*/
int befs_btree_find(struct super_block *sb, befs_data_stream * ds,
const char *key, befs_off_t * value);
int befs_btree_read(struct super_block *sb, befs_data_stream * ds,
loff_t key_no, size_t bufsize, char *keybuf,
size_t * keysize, befs_off_t * value);
This diff is collapsed.
/*
* datastream.h
*
*/
struct buffer_head *befs_read_datastream(struct super_block *sb,
befs_data_stream * ds, befs_off_t pos,
uint * off);
int befs_fblock2brun(struct super_block *sb, befs_data_stream * data,
befs_blocknr_t fblock, befs_block_run * run);
size_t befs_read_lsymlink(struct super_block *sb, befs_data_stream * data,
void *buff, befs_off_t len);
befs_blocknr_t befs_count_blocks(struct super_block *sb, befs_data_stream * ds);
extern const befs_inode_addr BAD_IADDR;
/*
* linux/fs/befs/debug.c
*
* Copyright (C) 2001 Will Dyson (will_dyson at pobox.com)
*
* With help from the ntfs-tng driver by Anton Altparmakov
*
* Copyright (C) 1999 Makoto Kato (m_kato@ga2.so-net.ne.jp)
*
* debug functions
*/
#ifdef __KERNEL__
#include <stdarg.h>
#include <linux/string.h>
#include <linux/spinlock.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#endif /* __KERNEL__ */
#include "befs.h"
#include "endian.h"
#define ERRBUFSIZE 1024
void
befs_error(const struct super_block *sb, const char *fmt, ...)
{
va_list args;
char err_buf[ERRBUFSIZE];
va_start(args, fmt);
vsnprintf(err_buf, ERRBUFSIZE, fmt, args);
va_end(args);
printk(KERN_ERR "BeFS(%s): %s\n", sb->s_id, err_buf);
befs_debug(sb, err_buf);
}
void
befs_warning(const struct super_block *sb, const char *fmt, ...)
{
va_list args;
char err_buf[ERRBUFSIZE];
va_start(args, fmt);
vsnprintf(err_buf, ERRBUFSIZE, fmt, args);
va_end(args);
printk(KERN_WARNING "BeFS(%s): %s\n", sb->s_id, err_buf);
befs_debug(sb, err_buf);
}
void
befs_debug(const struct super_block *sb, const char *fmt, ...)
{
#ifdef CONFIG_BEFS_DEBUG
va_list args;
char err_buf[ERRBUFSIZE];
if (BEFS_SB(sb)->mount_opts.debug) {
va_start(args, fmt);
vsnprintf(err_buf, ERRBUFSIZE, fmt, args);
va_end(args);
printk(KERN_DEBUG "BeFS(%s): %s\n", sb->s_id, err_buf);
}
#endif //CONFIG_BEFS_DEBUG
}
void
befs_dump_inode(const struct super_block *sb, befs_inode * inode)
{
#ifdef CONFIG_BEFS_DEBUG
befs_block_run tmp_run;
befs_debug(sb, "befs_inode infomation");
befs_debug(sb, " magic1 %08x", fs32_to_cpu(sb, inode->magic1));
tmp_run = fsrun_to_cpu(sb, inode->inode_num);
befs_debug(sb, " inode_num %u, %hu, %hu",
tmp_run.allocation_group, tmp_run.start, tmp_run.len);
befs_debug(sb, " uid %u", fs32_to_cpu(sb, inode->uid));
befs_debug(sb, " gid %u", fs32_to_cpu(sb, inode->gid));
befs_debug(sb, " mode %08x", fs32_to_cpu(sb, inode->mode));
befs_debug(sb, " flags %08x", fs32_to_cpu(sb, inode->flags));
befs_debug(sb, " create_time %Lu",
fs64_to_cpu(sb, inode->create_time));
befs_debug(sb, " last_modified_time %Lu",
fs64_to_cpu(sb, inode->last_modified_time));
tmp_run = fsrun_to_cpu(sb, inode->parent);
befs_debug(sb, " parent [%u, %hu, %hu]",
tmp_run.allocation_group, tmp_run.start, tmp_run.len);
tmp_run = fsrun_to_cpu(sb, inode->attributes);
befs_debug(sb, " attributes [%u, %hu, %hu]",
tmp_run.allocation_group, tmp_run.start, tmp_run.len);
befs_debug(sb, " type %08x", fs32_to_cpu(sb, inode->type));
befs_debug(sb, " inode_size %u", fs32_to_cpu(sb, inode->inode_size));
if (S_ISLNK(inode->mode)) {
befs_debug(sb, " Symbolic link [%s]", inode->data.symlink);
} else {
int i;
for (i = 0; i < BEFS_NUM_DIRECT_BLOCKS; i++) {
tmp_run =
fsrun_to_cpu(sb, inode->data.datastream.direct[i]);
befs_debug(sb, " direct %d [%u, %hu, %hu]", i,
tmp_run.allocation_group, tmp_run.start,
tmp_run.len);
}
befs_debug(sb, " max_direct_range %Lu",
fs64_to_cpu(sb,
inode->data.datastream.
max_direct_range));
tmp_run = fsrun_to_cpu(sb, inode->data.datastream.indirect);
befs_debug(sb, " indirect [%u, %hu, %hu]",
tmp_run.allocation_group,
tmp_run.start, tmp_run.len);
befs_debug(sb, " max_indirect_range %Lu",
fs64_to_cpu(sb,
inode->data.datastream.
max_indirect_range));
tmp_run =
fsrun_to_cpu(sb, inode->data.datastream.double_indirect);
befs_debug(sb, " double indirect [%u, %hu, %hu]",
tmp_run.allocation_group, tmp_run.start,
tmp_run.len);
befs_debug(sb, " max_double_indirect_range %Lu",
fs64_to_cpu(sb,
inode->data.datastream.
max_double_indirect_range));
befs_debug(sb, " size %Lu",
fs64_to_cpu(sb, inode->data.datastream.size));
}
#endif //CONFIG_BEFS_DEBUG
}
/*
* Display super block structure for debug.
*/
void
befs_dump_super_block(const struct super_block *sb, befs_super_block * sup)
{
#ifdef CONFIG_BEFS_DEBUG
befs_block_run tmp_run;
befs_debug(sb, "befs_super_block information");
befs_debug(sb, " name %s", sup->name);
befs_debug(sb, " magic1 %08x", fs32_to_cpu(sb, sup->magic1));
befs_debug(sb, " fs_byte_order %08x",
fs32_to_cpu(sb, sup->fs_byte_order));
befs_debug(sb, " block_size %u", fs32_to_cpu(sb, sup->block_size));
befs_debug(sb, " block_shift %u", fs32_to_cpu(sb, sup->block_shift));
befs_debug(sb, " num_blocks %Lu", fs64_to_cpu(sb, sup->num_blocks));
befs_debug(sb, " used_blocks %Lu", fs64_to_cpu(sb, sup->used_blocks));
befs_debug(sb, " magic2 %08x", fs32_to_cpu(sb, sup->magic2));
befs_debug(sb, " blocks_per_ag %u",
fs32_to_cpu(sb, sup->blocks_per_ag));
befs_debug(sb, " ag_shift %u", fs32_to_cpu(sb, sup->ag_shift));
befs_debug(sb, " num_ags %u", fs32_to_cpu(sb, sup->num_ags));
befs_debug(sb, " flags %08x", fs32_to_cpu(sb, sup->flags));
tmp_run = fsrun_to_cpu(sb, sup->log_blocks);
befs_debug(sb, " log_blocks %u, %hu, %hu",
tmp_run.allocation_group, tmp_run.start, tmp_run.len);
befs_debug(sb, " log_start %Ld", fs64_to_cpu(sb, sup->log_start));
befs_debug(sb, " log_end %Ld", fs64_to_cpu(sb, sup->log_end));
befs_debug(sb, " magic3 %08x", fs32_to_cpu(sb, sup->magic3));
tmp_run = fsrun_to_cpu(sb, sup->root_dir);
befs_debug(sb, " root_dir %u, %hu, %hu",
tmp_run.allocation_group, tmp_run.start, tmp_run.len);
tmp_run = fsrun_to_cpu(sb, sup->indices);
befs_debug(sb, " indices %u, %hu, %hu",
tmp_run.allocation_group, tmp_run.start, tmp_run.len);
#endif //CONFIG_BEFS_DEBUG
}
void
befs_dump_small_data(const struct super_block *sb, befs_small_data * sd)
{
}
void
befs_dump_run(const struct super_block *sb, befs_block_run run)
{
#ifdef CONFIG_BEFS_DEBUG
run = fsrun_to_cpu(sb, run);
befs_debug(sb, "[%u, %hu, %hu]",
run.allocation_group, run.start, run.len);
#endif //CONFIG_BEFS_DEBUG
}
void
befs_dump_index_entry(const struct super_block *sb, befs_btree_super * super)
{
#ifdef CONFIG_BEFS_DEBUG
befs_debug(sb, "Btree super structure");
befs_debug(sb, " magic %08x", fs32_to_cpu(sb, super->magic));
befs_debug(sb, " node_size %u", fs32_to_cpu(sb, super->node_size));
befs_debug(sb, " max_depth %08x", fs32_to_cpu(sb, super->max_depth));
befs_debug(sb, " data_type %08x", fs32_to_cpu(sb, super->data_type));
befs_debug(sb, " root_node_pointer %016LX",
fs64_to_cpu(sb, super->root_node_ptr));
befs_debug(sb, " free_node_pointer %016LX",
fs64_to_cpu(sb, super->free_node_ptr));
befs_debug(sb, " maximum size %016LX",
fs64_to_cpu(sb, super->max_size));
#endif //CONFIG_BEFS_DEBUG
}
void
befs_dump_index_node(const struct super_block *sb, befs_btree_nodehead * node)
{
#ifdef CONFIG_BEFS_DEBUG
befs_debug(sb, "Btree node structure");
befs_debug(sb, " left %016LX", fs64_to_cpu(sb, node->left));
befs_debug(sb, " right %016LX", fs64_to_cpu(sb, node->right));
befs_debug(sb, " overflow %016LX", fs64_to_cpu(sb, node->overflow));
befs_debug(sb, " all_key_count %hu",
fs16_to_cpu(sb, node->all_key_count));
befs_debug(sb, " all_key_length %hu",
fs16_to_cpu(sb, node->all_key_length));
#endif //CONFIG_BEFS_DEBUG
}
/*
* linux/fs/befs/endian.h
*
* Copyright (C) 2001 Will Dyson <will_dyson@pobox.com>
*
* Partially based on similar funtions in the sysv driver.
*/
#ifndef LINUX_BEFS_ENDIAN
#define LINUX_BEFS_ENDIAN
#include <linux/byteorder/generic.h>
#include "befs.h"
static inline u64
fs64_to_cpu(const struct super_block *sb, u64 n)
{
if (BEFS_SB(sb)->byte_order == BEFS_BYTESEX_LE)
return le64_to_cpu(n);
else
return be64_to_cpu(n);
}
static inline u64
cpu_to_fs64(const struct super_block *sb, u64 n)
{
if (BEFS_SB(sb)->byte_order == BEFS_BYTESEX_LE)
return cpu_to_le64(n);
else
return cpu_to_be64(n);
}
static inline u32
fs32_to_cpu(const struct super_block *sb, u32 n)
{
if (BEFS_SB(sb)->byte_order == BEFS_BYTESEX_LE)
return le32_to_cpu(n);
else
return be32_to_cpu(n);
}
static inline u32
cpu_to_fs32(const struct super_block *sb, u32 n)
{
if (BEFS_SB(sb)->byte_order == BEFS_BYTESEX_LE)
return cpu_to_le32(n);
else
return cpu_to_be32(n);
}
static inline u16
fs16_to_cpu(const struct super_block *sb, u16 n)
{
if (BEFS_SB(sb)->byte_order == BEFS_BYTESEX_LE)
return le16_to_cpu(n);
else
return be16_to_cpu(n);
}
static inline u16
cpu_to_fs16(const struct super_block *sb, u16 n)
{
if (BEFS_SB(sb)->byte_order == BEFS_BYTESEX_LE)
return cpu_to_le16(n);
else
return cpu_to_be16(n);
}
/* Composite types below here */
static inline befs_block_run
fsrun_to_cpu(const struct super_block *sb, befs_block_run n)
{
befs_block_run run;
if (BEFS_SB(sb)->byte_order == BEFS_BYTESEX_LE) {
run.allocation_group = le32_to_cpu(n.allocation_group);
run.start = le16_to_cpu(n.start);
run.len = le16_to_cpu(n.len);
} else {
run.allocation_group = be32_to_cpu(n.allocation_group);
run.start = be16_to_cpu(n.start);
run.len = be16_to_cpu(n.len);
}
return run;
}
static inline befs_block_run
cpu_to_fsrun(const struct super_block *sb, befs_block_run n)
{
befs_block_run run;
if (BEFS_SB(sb)->byte_order == BEFS_BYTESEX_LE) {
run.allocation_group = cpu_to_le32(n.allocation_group);
run.start = cpu_to_le16(n.start);
run.len = cpu_to_le16(n.len);
} else {
run.allocation_group = cpu_to_be32(n.allocation_group);
run.start = cpu_to_be16(n.start);
run.len = cpu_to_be16(n.len);
}
return run;
}
static inline befs_data_stream
fsds_to_cpu(const struct super_block *sb, befs_data_stream n)
{
befs_data_stream data;
int i;
for (i = 0; i < BEFS_NUM_DIRECT_BLOCKS; ++i)
data.direct[i] = fsrun_to_cpu(sb, n.direct[i]);
data.max_direct_range = fs64_to_cpu(sb, n.max_direct_range);
data.indirect = fsrun_to_cpu(sb, n.indirect);
data.max_indirect_range = fs64_to_cpu(sb, n.max_indirect_range);
data.double_indirect = fsrun_to_cpu(sb, n.double_indirect);
data.max_double_indirect_range = fs64_to_cpu(sb,
n.
max_double_indirect_range);
data.size = fs64_to_cpu(sb, n.size);
return data;
}
#endif //LINUX_BEFS_ENDIAN
/*
* inode.c
*
* Copyright (C) 2001 Will Dyson <will_dyson@pobox.com>
*/
#include <linux/fs.h>
#include "befs.h"
#include "inode.h"
#include "endian.h"
/*
Validates the correctness of the befs inode
Returns BEFS_OK if the inode should be used, otherwise
returns BEFS_BAD_INODE
*/
int
befs_check_inode(struct super_block *sb, befs_inode * raw_inode,
befs_blocknr_t inode)
{
u32 magic1 = fs32_to_cpu(sb, raw_inode->magic1);
befs_inode_addr ino_num = fsrun_to_cpu(sb, raw_inode->inode_num);
u32 flags = fs32_to_cpu(sb, raw_inode->flags);
/* check magic header. */
if (magic1 != BEFS_INODE_MAGIC1) {
befs_error(sb,
"Inode has a bad magic header - inode = %lu", inode);
return BEFS_BAD_INODE;
}
/*
* Sanity check2: inodes store their own block address. Check it.
*/
if (inode != iaddr2blockno(sb, &ino_num)) {
befs_error(sb, "inode blocknr field disagrees with vfs "
"VFS: %lu, Inode %lu",
inode, iaddr2blockno(sb, &ino_num));
return BEFS_BAD_INODE;
}
/*
* check flag
*/
if (!(flags & BEFS_INODE_IN_USE)) {
befs_error(sb, "inode is not used - inode = %lu", inode);
return BEFS_BAD_INODE;
}
return BEFS_OK;
}
/*
* inode.h
*
*/
int befs_check_inode(struct super_block *sb, befs_inode * raw_inode,
befs_blocknr_t inode);
/*
* linux/fs/befs/io.c
*
* Copyright (C) 2001 Will Dyson <will_dyson@pobox.com
*
* Based on portions of file.c and inode.c
* by Makoto Kato (m_kato@ga2.so-net.ne.jp)
*
* Many thanks to Dominic Giampaolo, author of Practical File System
* Design with the Be File System, for such a helpful book.
*
*/
#include <linux/buffer_head.h>
#include "befs.h"
#include "io.h"
/*
* Converts befs notion of disk addr to a disk offset and uses
* linux kernel function sb_bread() to get the buffer containing
* the offset. -Will Dyson
*
*/
struct buffer_head *
befs_bread_iaddr(struct super_block *sb, befs_inode_addr iaddr)
{
struct buffer_head *bh = NULL;
befs_blocknr_t block = 0;
vfs_blocknr_t vfs_block = 0;
befs_sb_info *befs_sb = BEFS_SB(sb);
befs_debug(sb, "---> Enter befs_read_iaddr() "
"[%u, %hu, %hu]",
iaddr.allocation_group, iaddr.start, iaddr.len);
if (iaddr.allocation_group > befs_sb->num_ags) {
befs_error(sb, "BEFS: Invalid allocation group %u, max is %u",
iaddr.allocation_group, befs_sb->num_ags);
goto error;
}
block = iaddr2blockno(sb, &iaddr);
vfs_block = (vfs_blocknr_t) block;
if (vfs_block != block) {
befs_error(sb, "Error converting to host blocknr_t. %Lu "
"is larger than the host can use", block);
goto error;
}
befs_debug(sb, "befs_read_iaddr: offset = %lu", block);
bh = sb_bread(sb, vfs_block);
if (bh == NULL) {
befs_error(sb, "Failed to read block %lu", block);
goto error;
}
befs_debug(sb, "<--- befs_read_iaddr()");
return bh;
error:
befs_debug(sb, "<--- befs_read_iaddr() ERROR");
return NULL;
}
struct buffer_head *
befs_bread(struct super_block *sb, befs_blocknr_t block)
{
struct buffer_head *bh = NULL;
vfs_blocknr_t vfs_block = (vfs_blocknr_t) block;
befs_debug(sb, "---> Enter befs_read() %Lu", block);
if (vfs_block != block) {
befs_error(sb, "Error converting to host blocknr_t. %Lu "
"is larger than the host can use", block);
goto error;
}
bh = sb_bread(sb, vfs_block);
if (bh == NULL) {
befs_error(sb, "Failed to read block %lu", vfs_block);
goto error;
}
befs_debug(sb, "<--- befs_read()");
return bh;
error:
befs_debug(sb, "<--- befs_read() ERROR");
return NULL;
}
/*
* io.h
*/
struct buffer_head *befs_bread_iaddr(struct super_block *sb,
befs_inode_addr iaddr);
struct buffer_head *befs_bread(struct super_block *sb, befs_blocknr_t block);
This diff is collapsed.
/*
* super.c
*
* Copyright (C) 2001-2002 Will Dyson <will_dyson@pobox.com>
*
* Licensed under the GNU GPL. See the file COPYING for details.
*
*/
#include <linux/fs.h>
#include "befs.h"
#include "super.h"
#include "endian.h"
/**
* load_befs_sb -- Read from disk and properly byteswap all the fields
* of the befs superblock
*
*
*
*
*/
int
befs_load_sb(struct super_block *sb, befs_super_block * disk_sb)
{
befs_sb_info *befs_sb = BEFS_SB(sb);
/* Check the byte order of the filesystem */
if (le32_to_cpu(disk_sb->fs_byte_order) == BEFS_BYTEORDER_NATIVE)
befs_sb->byte_order = BEFS_BYTESEX_LE;
else if (be32_to_cpu(disk_sb->fs_byte_order) == BEFS_BYTEORDER_NATIVE)
befs_sb->byte_order = BEFS_BYTESEX_BE;
befs_sb->magic1 = fs32_to_cpu(sb, disk_sb->magic1);
befs_sb->magic2 = fs32_to_cpu(sb, disk_sb->magic2);
befs_sb->magic3 = fs32_to_cpu(sb, disk_sb->magic3);
befs_sb->block_size = fs32_to_cpu(sb, disk_sb->block_size);
befs_sb->block_shift = fs32_to_cpu(sb, disk_sb->block_shift);
befs_sb->num_blocks = fs64_to_cpu(sb, disk_sb->num_blocks);
befs_sb->used_blocks = fs64_to_cpu(sb, disk_sb->used_blocks);
befs_sb->inode_size = fs32_to_cpu(sb, disk_sb->inode_size);
befs_sb->blocks_per_ag = fs32_to_cpu(sb, disk_sb->blocks_per_ag);
befs_sb->ag_shift = fs32_to_cpu(sb, disk_sb->ag_shift);
befs_sb->num_ags = fs32_to_cpu(sb, disk_sb->num_ags);
befs_sb->log_blocks = fsrun_to_cpu(sb, disk_sb->log_blocks);
befs_sb->log_start = fs64_to_cpu(sb, disk_sb->log_start);
befs_sb->log_end = fs64_to_cpu(sb, disk_sb->log_end);
befs_sb->root_dir = fsrun_to_cpu(sb, disk_sb->root_dir);
befs_sb->indices = fsrun_to_cpu(sb, disk_sb->indices);
befs_sb->nls = NULL;
return BEFS_OK;
}
int
befs_check_sb(struct super_block *sb)
{
befs_sb_info *befs_sb = BEFS_SB(sb);
/* Check magic headers of super block */
if ((befs_sb->magic1 != BEFS_SUPER_MAGIC1)
|| (befs_sb->magic2 != BEFS_SUPER_MAGIC2)
|| (befs_sb->magic3 != BEFS_SUPER_MAGIC3)) {
befs_error(sb, "invalid magic header");
return BEFS_ERR;
}
/*
* Check blocksize of BEFS.
*
* Blocksize of BEFS is 1024, 2048, 4096 or 8192.
*/
if ((befs_sb->block_size != 1024)
&& (befs_sb->block_size != 2048)
&& (befs_sb->block_size != 4096)
&& (befs_sb->block_size != 8192)) {
befs_error(sb, "invalid blocksize: %u", befs_sb->block_size);
return BEFS_ERR;
}
if (befs_sb->block_size > PAGE_SIZE) {
befs_error(sb, "blocksize(%u) cannot be larger"
"than system pagesize(%lu)", befs_sb->block_size,
PAGE_SIZE);
return BEFS_ERR;
}
/*
* block_shift and block_size encode the same information
* in different ways as a consistency check.
*/
if ((1 << befs_sb->block_shift) != befs_sb->block_size) {
befs_error(sb, "block_shift disagrees with block_size. "
"Corruption likely.");
return BEFS_ERR;
}
if (befs_sb->log_start != befs_sb->log_end) {
befs_error(sb, "Filesystem not clean! There are blocks in the "
"journal. You must boot into BeOS and mount this volume "
"to make it clean.");
return BEFS_ERR;
}
return BEFS_OK;
}
/*
* super.h
*/
int befs_load_sb(struct super_block *sb, befs_super_block * disk_sb);
int befs_check_sb(struct super_block *sb);
......@@ -12,7 +12,8 @@ fi
# msdos and Joliet want NLS
if [ "$CONFIG_JOLIET" = "y" -o "$CONFIG_FAT_FS" != "n" \
-o "$CONFIG_NTFS_FS" != "n" -o "$CONFIG_NCPFS_NLS" = "y" \
-o "$CONFIG_SMB_NLS" = "y" -o "$CONFIG_JFS_FS" != "n" -o "$CONFIG_CIFS" != "n" ]; then
-o "$CONFIG_SMB_NLS" = "y" -o "$CONFIG_JFS_FS" != "n" \
-o "$CONFIG_CIFS" != "n" -o "$CONFIG_BEFS_FS" != "n" ]; then
define_bool CONFIG_NLS y
else
define_bool CONFIG_NLS n
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment