[PATCH] befs : Add small_data support through xattr handlers

From: Fabian Frederick
Date: Tue Dec 03 2013 - 00:52:50 EST


Beos Filesystem stores small attributes in first inode block automagically read during lookup.
Current driver implementation does nothing about it.

Those attributes feature both window manager and user metadata.

-This patch wakes up the small_data dump functionality when mounting in debug mode (iget)
-The same is done "for real" by creating a list_head merged in befs_inode_info.
-getfattr -n "attributename" is handled as well to retrieve small attributes
through xattr_handlers.

I hope someone (Andrew, Al ?) can help me improve that feature despite that driver is declared "Orphan" in maintainer list.

Signed off by Fabian Frederick
diff --git a/fs/befs/befs.h b/fs/befs/befs.h
index b266428..02eb7ae 100644
--- a/fs/befs/befs.h
+++ b/fs/befs/befs.h
@@ -57,6 +57,14 @@ typedef struct befs_sb_info {

} befs_sb_info;

+typedef struct befs_small_datamem {
+ u32 type;
+ char name[BEFS_ATTRIBUTE_LEN];
+ char value[BEFS_ATTRIBUTE_VALUE_LEN];
+ struct list_head list;
+
+} befs_small_datamem;
+
typedef struct befs_inode_info {
Âu32 i_flags;
Âu32 i_type;
@@ -71,6 +79,7 @@ typedef struct befs_inode_info {
Â} i_data;

Âstruct inode vfs_inode;
+ struct befs_small_datamem datamem;

} befs_inode_info;

@@ -96,6 +105,8 @@ 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_disk_btree_super *);
void befs_dump_index_node(const struct super_block *sb, befs_btree_nodehead *);
+void befs_dump_small_data(const struct super_block *sb, befs_small_data * sd);
+
/****************************/


diff --git a/fs/befs/befs_fs_types.h b/fs/befs/befs_fs_types.h
index eb557d9..47e2ac0 100644
--- a/fs/befs/befs_fs_types.h
+++ b/fs/befs/befs_fs_types.h
@@ -26,6 +26,8 @@

#define BEFS_NAME_LEN 255

+#define BEFS_ATTRIBUTE_LEN 255
+#define BEFS_ATTRIBUTE_VALUE_LEN 1024
#define BEFS_SYMLINK_LEN 144
#define BEFS_NUM_DIRECT_BLOCKS 12
#define B_OS_NAME_LENGTH 32
diff --git a/fs/befs/debug.c b/fs/befs/debug.c
index 622e737..d23dda2 100644
--- a/fs/befs/debug.c
+++ b/fs/befs/debug.c
@@ -222,13 +222,38 @@ befs_dump_super_block(const struct super_block *sb, befs_super_block * sup)
#endif //CONFIG_BEFS_DEBUG
}

-#if 0
-/* unused */
void
befs_dump_small_data(const struct super_block *sb, befs_small_data * sd)
{
+#ifdef CONFIG_BEFS_DEBUG
+
+ char *oft, *ioft;
+ ioft=(char*)sd;
+
+ while(1){
+ befs_debug(sb, "befs_small_data information");
+ befs_debug(sb, " Â type : %x", sd->type);
+ befs_debug(sb, " Â name size : %d", sd->name_size);
+ befs_debug(sb, " Â name size : %d", sd->data_size);
+ if(sd->name[0]==0x13)
+ befs_debug(sb, " Â name : %d", sd->data_size);
+ Â Â else befs_debug(sb, " Â name : %s", sd->name);
+ oft=sd->name;
+ while(oft[0])oft++; //eos
+ oft+=3; //padding
+ befs_debug(sb, " Â value :%s", oft);
+ oft=oft+(sd->data_size);
+ while(!oft[0])oft++;
+ sd=(befs_small_data*)oft;
+ befs_debug(sb, " Â ioft : %x oft : %x delta : %x", ioft, oft, oft-ioft);
+ if(oft-ioft > sb->s_blocksize-sizeof(befs_inode))
+ break;
+ }
+
+#endif //CONFIG_BEFS_DEBUG
}

+#if 0
/* unused */
void
befs_dump_run(const struct super_block *sb, befs_disk_block_run run)
diff --git a/fs/befs/linuxvfs.c b/fs/befs/linuxvfs.c
index daa15d6..ba7d3e8 100644
--- a/fs/befs/linuxvfs.c
+++ b/fs/befs/linuxvfs.c
@@ -3,6 +3,8 @@
Â*
Â* Copyright (C) 2001 Will Dyson <will_dyson@xxxxxxxxx
Â*
+ * 12/2013 : Fabian Frederick : Adding xattr support.
+ *
Â*/

#include <linux/module.h>
@@ -16,6 +18,7 @@
#include <linux/parser.h>
#include <linux/namei.h>
#include <linux/sched.h>
+#include <linux/xattr.h>

#include "befs.h"
#include "btree.h"
@@ -36,6 +39,7 @@ static int befs_get_block(struct inode *, sector_t, struct buffer_head *, int);
static int befs_readpage(struct file *file, struct page *page);
static sector_t befs_bmap(struct address_space *mapping, sector_t block);
static struct dentry *befs_lookup(struct inode *, struct dentry *, unsigned int);
+static void befs_getsmalldata(struct super_block *, befs_small_data *, struct befs_small_datamem *);
static struct inode *befs_iget(struct super_block *, unsigned long);
static struct inode *befs_alloc_inode(struct super_block *sb);
static void befs_destroy_inode(struct inode *inode);
@@ -43,6 +47,7 @@ static int befs_init_inodecache(void);
static void befs_destroy_inodecache(void);
static void *befs_follow_link(struct dentry *, struct nameidata *);
static void *befs_fast_follow_link(struct dentry *, struct nameidata *);
+static int befs_xattr_get(struct dentry *, const char *, void *, size_t, int);
static int befs_utf2nls(struct super_block *sb, const char *in, int in_len,
Âchar **out, int *out_len);
static int befs_nls2utf(struct super_block *sb, const char *in, int in_len,
@@ -74,6 +79,10 @@ static const struct inode_operations befs_dir_inode_operations = {
Â.lookup = befs_lookup,
};

+static const struct inode_operations befs_file_inode_operations = {
+ .getxattr = generic_getxattr,
+};
+
static const struct address_space_operations befs_aops = {
Â.readpage = befs_readpage,
Â.bmap = befs_bmap,
@@ -90,6 +99,16 @@ static const struct inode_operations befs_symlink_inode_operations = {
Â.put_link = kfree_put_link,
};

+static const struct xattr_handler befs_xattr_handler = {
+ .prefix = "",
+ .get = befs_xattr_get,
+};
+
+static const struct xattr_handler *befs_xattr_handlers[] = {
+ &befs_xattr_handler,
+ NULL
+};
+
/*
Â* Called by generic_file_read() to read a page of data
Â*
@@ -311,6 +330,35 @@ static void init_once(void *foo)
Âinode_init_once(&bi->vfs_inode);
}

+static void befs_getsmalldata(struct super_block *sb, befs_small_data *sd, struct befs_small_datamem *datamem)
+{
+ char *oft, *ioft;
+ struct befs_small_datamem *newdatamem;
+ struct befs_small_datamem *testdatamem;
+
+ ioft = (char*) sd;
+
+ INIT_LIST_HEAD(&datamem->list);
+
+ while(1){
+ newdatamem = kmalloc(sizeof(*newdatamem), GFP_KERNEL);
+ newdatamem->type=sd->type;
+ strcpy(newdatamem->name, sd->name);
+ oft = sd->name;
+ while(oft[0])oft++;
+ oft+=3; //padding
+ strcpy(newdatamem->value, oft);
+ INIT_LIST_HEAD(&newdatamem->list);
+ oft = oft+(sd->data_size);
+ while(!oft[0])oft++;
+ sd = oft;
+ list_add_tail(&(newdatamem->list), &(datamem->list));
+ if(oft-ioft > sb->s_blocksize-sizeof(befs_inode))
+ break;
+ }
+
+}
+
static struct inode *befs_iget(struct super_block *sb, unsigned long ino)
{
Âstruct buffer_head *bh = NULL;
@@ -411,7 +459,10 @@ static struct inode *befs_iget(struct super_block *sb, unsigned long ino)
Âinode->i_mapping->a_ops = &befs_aops;

Âif (S_ISREG(inode->i_mode)) {
+ inode->i_op = &befs_file_inode_operations;
Âinode->i_fop = &generic_ro_fops;
+ befs_dump_small_data(sb, raw_inode->small_data);
+ befs_getsmalldata(sb,raw_inode->small_data, &(befs_ino->datamem));
Â} else if (S_ISDIR(inode->i_mode)) {
Âinode->i_op = &befs_dir_inode_operations;
Âinode->i_fop = &befs_dir_operations;
@@ -521,6 +572,42 @@ befs_fast_follow_link(struct dentry *dentry, struct nameidata *nd)
Âreturn NULL;
}

+static int
+befs_xattr_get(struct dentry *dentry, const char *name,
+ void *buffer, size_t buffer_size, int type)
+{
+
+
+ struct befs_small_datamem *currentdatamem;
+ struct befs_small_datamem *datamem;
+ befs_inode_info *befs_ino = NULL;
+ int name_len, error;
+
+ if (name == NULL)
+ return -EINVAL;
+
+ name_len = strlen(name);
+ if(name_len > BEFS_ATTRIBUTE_LEN)
+ return -ERANGE;
+ error = -ENODATA;
+
+ befs_ino = BEFS_I(dentry->d_inode);
+ datamem=&(befs_ino->datamem);
+
+ list_for_each_entry(currentdatamem, &(datamem->list), list){
+ if(!strcmp(currentdatamem->name, name)){
+ if(buffer){
+ if(strlen(currentdatamem->value)<=buffer_size){
+ strcpy(buffer, currentdatamem->value);
+ error=strlen(currentdatamem->value);
+ Â} else Âerror=-ERANGE;
+ }else error=strlen(currentdatamem->value);
+
+ }
+ }
+ return(error);
+}
+
/*
Â* UTF-8 to NLS charset Âconvert routine
Â*
@@ -846,6 +933,7 @@ befs_fill_super(struct super_block *sb, void *data, int silent)
Âif (befs_load_sb(sb, disk_sb) != BEFS_OK)
Âgoto unacquire_bh;

+ sb->s_xattr = befs_xattr_handlers;
Âbefs_dump_super_block(sb, disk_sb);

Âbrelse(bh);
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/