diff --git a/sdbfs/kernel/Makefile b/sdbfs/kernel/Makefile index ed29311c6227068dc13f4e7e75381591ea7881a4..44f5de2c4ddb88098436234de04bbc97eb773661 100644 --- a/sdbfs/kernel/Makefile +++ b/sdbfs/kernel/Makefile @@ -9,8 +9,8 @@ obj-m += sdb-iomem.o sdbfs-y = sdbfs-core.o sdbfs-y += sdbfs-file.o -sdbfs-y += sdbfs-devmem.o -sdbfs-y += sdbfs-device.o +sdbfs-y += sdbfs-inode.o +sdbfs-y += sdbfs-client.o all: modules diff --git a/sdbfs/kernel/sdbfs-device.c b/sdbfs/kernel/sdbfs-client.c similarity index 100% rename from sdbfs/kernel/sdbfs-device.c rename to sdbfs/kernel/sdbfs-client.c diff --git a/sdbfs/kernel/sdbfs-core.c b/sdbfs/kernel/sdbfs-core.c index 63be89c3ccd6ea5e048eb3aea9a0fdaa487d0b73..aa9d16dbae8c62d1641b84292f6bc89712d20c77 100644 --- a/sdbfs/kernel/sdbfs-core.c +++ b/sdbfs/kernel/sdbfs-core.c @@ -14,361 +14,14 @@ #include <linux/err.h> #include <linux/fs.h> #include <linux/sdb.h> /* in ../include, by now */ -#include <linux/uaccess.h> -#include "sdbfs.h" #include "sdbfs-int.h" -#define SDB_SIZE (sizeof(struct sdb_device)) - -static void sdbfs_fix_endian(struct sdbfs_dev *sd, void *ptr, int len) -{ - uint32_t *p = ptr; - int i; - - if (!(sd->flags & SDBFS_F_FIXENDIAN)) - return; - if (len & 3) - return; /* Hmmm... */ - - for (i = 0; i < len / 4; i++) - p[i] = htonl(p[i]); -} - -/* This is called by readdir and by lookup, when needed */ -static int sdbfs_read_whole_dir(struct sdbfs_inode *inode) -{ - struct sdbfs_info *info; - struct super_block *sb = inode->ino.i_sb; - struct sdbfs_dev *sd = sb->s_fs_info; - unsigned long offset; - int i, j, n; - - if (inode->nfiles) - return 0; - - printk("%s\n", __func__); - - /* Get the interconnect and see how many */ - info = kmalloc(sizeof(*info), GFP_KERNEL); - if (!info) - return -ENOMEM; - n = sd->ops->read(sd, inode->base_sdb, &info->s_i, SDB_SIZE); - if (n != SDB_SIZE) { - kfree(info); - return -EIO; - } - sdbfs_fix_endian(sd, &info->s_i, SDB_SIZE); - - if (info->s_i.sdb_magic != htonl(SDB_MAGIC)) { - pr_err("%s: wrong magic (%08x) at offset 0x%lx\n", __func__, - info->s_i.sdb_magic, inode->base_sdb); - kfree(info); - return -EINVAL; - } - inode->nfiles = be16_to_cpu(info->s_i.sdb_records); - kfree(info); - - printk("nfiles %i\n", inode->nfiles); - - info = kmalloc(sizeof(*info) * inode->nfiles, GFP_KERNEL); - if (!info) { - inode->nfiles = 0; - return -ENOMEM; - } - - offset = inode->base_sdb; - printk("reading at 0x%lx\n", offset); - - inode->files = info; - for (i = 0; i < inode->nfiles; i++) { - info = inode->files + i; - n = sd->ops->read(sd, offset, &info->s_d, SDB_SIZE); - if (n != SDB_SIZE) { - /* FIXME: iput? */ - kfree(inode->files); - inode->nfiles = 0; - return -EIO; - } - sdbfs_fix_endian(sd, &info->s_d, SDB_SIZE); - strncpy(info->name, - info->s_d.sdb_component.product.name, 19); - for (j = 19; j; j--) { - info->name[j] = '\0'; - if (info->name[j-1] != ' ') - break; - } - info->namelen = j; - offset += SDB_SIZE; - } - return 0; -} - -static int sdbfs_readdir(struct file * filp, - void * dirent, filldir_t filldir) -{ - struct inode *ino = filp->f_dentry->d_inode; - struct sdbfs_inode *inode; - struct sdbfs_info *info; - unsigned long offset; - int i, type, done = 0; - - printk("%s\n", __func__); - - /* dot and dotdot are special */ - if (filp->f_pos == 0) { - if (filldir(dirent, ".", 1, 0, ino->i_ino, DT_DIR) < 0) - return done; - done++; - filp->f_pos++; - } - if (filp->f_pos == 1) { - if (filldir(dirent, "..", 2, 1, - parent_ino(filp->f_dentry), DT_DIR) < 0) - return done; - done++; - filp->f_pos++; - } - - /* Then our stuff */ - inode = container_of(ino, struct sdbfs_inode, ino); - sdbfs_read_whole_dir(inode); - offset = inode->base_sdb; - - for (i = filp->f_pos - 2; i < inode->nfiles; i++) { - info = inode->files + i; - if (info->s_e.record_type == sdb_type_bridge) - type = DT_DIR; - else - type = DT_REG; - - if (filldir(dirent, info->name, info->namelen, - SDBFS_INO(offset), i + 2 /* ? */, type) < 0) - return done; - filp->f_pos++; - done++; - } - return done; -} - -static const struct file_operations sdbfs_dir_fops = { - .read = generic_read_dir, - .readdir = sdbfs_readdir, - .llseek = default_llseek, -}; - -static ssize_t sdbfs_read(struct file *f, char __user *buf, size_t count, - loff_t *offp) -{ - struct inode *ino = f->f_dentry->d_inode; - struct super_block *sb = ino->i_sb; - struct sdbfs_dev *sd = sb->s_fs_info; - struct sdbfs_inode *inode; - char kbuf[16]; - unsigned long start, size; - ssize_t i, done; - - inode = container_of(ino, struct sdbfs_inode, ino); - start = be64_to_cpu(inode->info.s_d.sdb_component.addr_first); - size = be64_to_cpu(inode->info.s_d.sdb_component.addr_last) + 1 - start; - - if (*offp > size) - return 0; - if (*offp + count > size) - count = size - *offp; - done = 0; - while (done < count) { - /* Horribly inefficient, just copy a few bytes at a time */ - int n = sizeof(kbuf) > count ? count : sizeof(kbuf); - - /* FIXME: error checking */ - i = sd->ops->read(sd, start + *offp, kbuf, n); - if (i < 0) { - if (done) - return done; - return i; - } - if (copy_to_user(buf, kbuf, i)) - return -EFAULT; - buf += i; - done += i; - if (i != n) { - /* Partial read: done for this time */ - break; - } - } - *offp += done; - return done; -} - -static const struct file_operations sdbfs_fops = { - .read = sdbfs_read, -}; -static struct inode *sdbfs_iget(struct sdbfs_inode *parent, - struct super_block *sb, unsigned long inum); - -static struct dentry *sdbfs_lookup(struct inode *dir, - struct dentry *dentry, struct nameidata *nd) -{ - struct inode *ino = NULL; - struct sdbfs_inode *inode = container_of(dir, struct sdbfs_inode, ino); - struct sdbfs_info *info; - unsigned long offset = inode->base_sdb; - int i, n, len; - - printk("%s\n", __func__); - sdbfs_read_whole_dir(inode); - n = inode->nfiles; - len = dentry->d_name.len; - for (i = 0; i < n; i++) { - info = inode->files + i; - if (info->namelen != len) - continue; - if (!strncmp(info->name, dentry->d_name.name, len)) - break; - } - if (i != n) { - offset = offset + SDB_SIZE * i; - ino = sdbfs_iget(inode, dir->i_sb, SDBFS_INO(offset)); - } - d_add(dentry, ino); - return 0; -} - -static const struct inode_operations sdbfs_dir_iops = { - .lookup = sdbfs_lookup, -}; - -static struct kmem_cache *sdbfs_inode_cache; - -static struct inode *sdbfs_alloc_inode(struct super_block *sb) -{ - struct sdbfs_inode *inode; - - printk("%s\n", __func__); - inode = kmem_cache_alloc(sdbfs_inode_cache, GFP_KERNEL); - if (!inode) - return NULL; - inode_init_once(&inode->ino); - printk("%s: return %p\n", __func__, &inode->ino); - return &inode->ino; -} - -static void sdbfs_destroy_inode(struct inode *ino) -{ - struct sdbfs_inode *inode; - - inode = container_of(ino, struct sdbfs_inode, ino); - kfree(inode->files); - kmem_cache_free(sdbfs_inode_cache, inode); -} - static const struct super_operations sdbfs_super_ops = { .alloc_inode = sdbfs_alloc_inode, .destroy_inode = sdbfs_destroy_inode, }; -static struct inode *sdbfs_iget_root(struct super_block *sb, - struct inode *ino) -{ - struct sdbfs_dev *sd = sb->s_fs_info; - struct sdbfs_inode *inode = container_of(ino, struct sdbfs_inode, ino); - struct sdb_bridge *b = &inode->info.s_b; - - /* The root directory is a fake "bridge" structure */ - memset(b, 0, sizeof(*b)); - b->sdb_child = cpu_to_be64(sd->entrypoint); - b->sdb_component.addr_first = 0; - b->sdb_component.addr_last = cpu_to_be64(sd->size); - b->sdb_component.product.record_type = sdb_type_bridge; - - /* So, this is a directory, and it links to the first interconnect */ - inode->base_data = 0; - inode->base_sdb = sd->entrypoint; - ino->i_size = sd->size; - ino->i_mode = S_IFDIR | 0555; - ino->i_op = &sdbfs_dir_iops; - ino->i_fop = &sdbfs_dir_fops; - - return ino; -} - -static struct inode *sdbfs_iget(struct sdbfs_inode *parent, - struct super_block *sb, unsigned long inum) -{ - struct inode *ino; - struct sdbfs_dev *sd = sb->s_fs_info; - struct sdbfs_inode *inode; - uint32_t offset; - unsigned long size, base_data; /* target offset */ - int n; - int type; - - printk("%s: inum 0x%lx\n", __func__, inum); - ino = iget_locked(sb, inum); - if (!ino) - return ERR_PTR(-ENOMEM); - if (!(ino->i_state & I_NEW)) - return ino; - - /* general setup; no link concept: the structure is immutable */ - set_nlink(ino, 1); - ino->i_mtime.tv_sec = ino->i_atime.tv_sec = ino->i_ctime.tv_sec = 0; - ino->i_mtime.tv_nsec = ino->i_atime.tv_nsec = ino->i_ctime.tv_nsec = 0; - - if (unlikely(!parent)) { /* inum == SDBFS_ROOT */ - sdbfs_iget_root(sb, ino); - unlock_new_inode(ino); - return ino; - } - - inode = container_of(ino, struct sdbfs_inode, ino); - offset = SDBFS_OFFSET(inum); - - n = sd->ops->read(sd, offset, &inode->info.s_d, SDB_SIZE); - if (n != SDB_SIZE) - return ERR_PTR(-EIO); - sdbfs_fix_endian(sd, &inode->info.s_d, SDB_SIZE); - - - base_data = be64_to_cpu(inode->info.s_d.sdb_component.addr_first); - size = be64_to_cpu(inode->info.s_d.sdb_component.addr_last) - - base_data + 1; - - type = inode->info.s_e.record_type; - switch (type) { - case sdb_type_interconnect: - case sdb_type_device: - /* You can access internal registers/data */ - ino->i_fop = &sdbfs_fops; /* FIXME: Which bus type? */ - ino->i_mode = S_IFREG | 0444; - ino->i_size = size; - inode->base_data = parent->base_data + base_data; - break; - - case sdb_type_bridge: - /* A bridge is a subdirectory */ - ino->i_mode = S_IFDIR | 0555; - ino->i_op = &sdbfs_dir_iops; - ino->i_fop = &sdbfs_dir_fops; - inode->base_data = parent->base_data + base_data; - inode->base_sdb = parent->base_data - + be64_to_cpu(inode->info.s_b.sdb_child); - break; - - default: - if (type & 0x80) /* informative only */ - pr_info("%s: ignoring unknown record 0x%02x\n", - __func__, type); - else - pr_err("%s: unsupported record 0x%02x\n", - __func__, type); - break; - } - unlock_new_inode(ino); - return ino; -} - static int sdbfs_fill_super(struct super_block *sb, void *data, int silent) { struct inode *inode; @@ -454,7 +107,9 @@ static struct file_system_type sdbfs_fs_type = { .kill_sb = sdbfs_kill_sb, }; -static int sdbfs_init(void) +struct kmem_cache *sdbfs_inode_cache; + +static int __init sdbfs_init(void) { sdbfs_inode_cache = KMEM_CACHE(sdbfs_inode, 0); if (!sdbfs_inode_cache) @@ -463,7 +118,7 @@ static int sdbfs_init(void) return 0; } -static void sdbfs_exit(void) +static void __exit sdbfs_exit(void) { unregister_filesystem(&sdbfs_fs_type); kmem_cache_destroy(sdbfs_inode_cache); diff --git a/sdbfs/kernel/sdbfs-devmem.c b/sdbfs/kernel/sdbfs-devmem.c deleted file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000 diff --git a/sdbfs/kernel/sdbfs-file.c b/sdbfs/kernel/sdbfs-file.c index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..15a742f8ec4d3aa0598d3d22a23ab398afeb4bb9 100644 --- a/sdbfs/kernel/sdbfs-file.c +++ b/sdbfs/kernel/sdbfs-file.c @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2012 CERN (www.cern.ch) + * Author: Alessandro Rubini <rubini@gnudd.com> + * + * Released according to the GNU GPL, version 2 or any later version. + * + * This work is part of the White Rabbit project, a research effort led + * by CERN, the European Institute for Nuclear Research. + */ +#include <linux/kernel.h> +#include <linux/fs.h> +#include <linux/uaccess.h> + +#include "sdbfs-int.h" + +static ssize_t sdbfs_read(struct file *f, char __user *buf, size_t count, + loff_t *offp) +{ + struct inode *ino = f->f_dentry->d_inode; + struct super_block *sb = ino->i_sb; + struct sdbfs_dev *sd = sb->s_fs_info; + struct sdbfs_inode *inode; + char kbuf[16]; + unsigned long start, size; + ssize_t i, done; + + inode = container_of(ino, struct sdbfs_inode, ino); + start = be64_to_cpu(inode->info.s_d.sdb_component.addr_first); + size = be64_to_cpu(inode->info.s_d.sdb_component.addr_last) + 1 - start; + + if (*offp > size) + return 0; + if (*offp + count > size) + count = size - *offp; + done = 0; + while (done < count) { + /* Horribly inefficient, just copy a few bytes at a time */ + int n = sizeof(kbuf) > count ? count : sizeof(kbuf); + + /* FIXME: error checking */ + i = sd->ops->read(sd, start + *offp, kbuf, n); + if (i < 0) { + if (done) + return done; + return i; + } + if (copy_to_user(buf, kbuf, i)) + return -EFAULT; + buf += i; + done += i; + if (i != n) { + /* Partial read: done for this time */ + break; + } + } + *offp += done; + return done; +} + +const struct file_operations sdbfs_fops = { + .read = sdbfs_read, +}; diff --git a/sdbfs/kernel/sdbfs-inode.c b/sdbfs/kernel/sdbfs-inode.c new file mode 100644 index 0000000000000000000000000000000000000000..6f21b5838453a4c8cce8d2090e37a4e3e520a032 --- /dev/null +++ b/sdbfs/kernel/sdbfs-inode.c @@ -0,0 +1,309 @@ +/* + * Copyright (C) 2012 CERN (www.cern.ch) + * Author: Alessandro Rubini <rubini@gnudd.com> + * + * Released according to the GNU GPL, version 2 or any later version. + * + * This work is part of the White Rabbit project, a research effort led + * by CERN, the European Institute for Nuclear Research. + */ +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/slab.h> +#include <linux/err.h> +#include <linux/fs.h> +#include <linux/sdb.h> /* in ../include, by now */ + +#include "sdbfs-int.h" + +static void sdbfs_fix_endian(struct sdbfs_dev *sd, void *ptr, int len) +{ + uint32_t *p = ptr; + int i; + + if (!(sd->flags & SDBFS_F_FIXENDIAN)) + return; + if (len & 3) + return; /* Hmmm... */ + + for (i = 0; i < len / 4; i++) + p[i] = htonl(p[i]); +} + +/* This is called by readdir and by lookup, when needed */ +static int sdbfs_read_whole_dir(struct sdbfs_inode *inode) +{ + struct sdbfs_info *info; + struct super_block *sb = inode->ino.i_sb; + struct sdbfs_dev *sd = sb->s_fs_info; + unsigned long offset; + int i, j, n; + + if (inode->nfiles) + return 0; + + printk("%s\n", __func__); + + /* Get the interconnect and see how many */ + info = kmalloc(sizeof(*info), GFP_KERNEL); + if (!info) + return -ENOMEM; + n = sd->ops->read(sd, inode->base_sdb, &info->s_i, SDB_SIZE); + if (n != SDB_SIZE) { + kfree(info); + return -EIO; + } + sdbfs_fix_endian(sd, &info->s_i, SDB_SIZE); + + if (info->s_i.sdb_magic != htonl(SDB_MAGIC)) { + pr_err("%s: wrong magic (%08x) at offset 0x%lx\n", __func__, + info->s_i.sdb_magic, inode->base_sdb); + kfree(info); + return -EINVAL; + } + inode->nfiles = be16_to_cpu(info->s_i.sdb_records); + kfree(info); + + printk("nfiles %i\n", inode->nfiles); + + info = kmalloc(sizeof(*info) * inode->nfiles, GFP_KERNEL); + if (!info) { + inode->nfiles = 0; + return -ENOMEM; + } + + offset = inode->base_sdb; + printk("reading at 0x%lx\n", offset); + + inode->files = info; + for (i = 0; i < inode->nfiles; i++) { + info = inode->files + i; + n = sd->ops->read(sd, offset, &info->s_d, SDB_SIZE); + if (n != SDB_SIZE) { + /* FIXME: iput? */ + kfree(inode->files); + inode->nfiles = 0; + return -EIO; + } + sdbfs_fix_endian(sd, &info->s_d, SDB_SIZE); + strncpy(info->name, + info->s_d.sdb_component.product.name, 19); + for (j = 19; j; j--) { + info->name[j] = '\0'; + if (info->name[j-1] != ' ') + break; + } + info->namelen = j; + offset += SDB_SIZE; + } + return 0; +} + +static int sdbfs_readdir(struct file * filp, + void * dirent, filldir_t filldir) +{ + struct inode *ino = filp->f_dentry->d_inode; + struct sdbfs_inode *inode; + struct sdbfs_info *info; + unsigned long offset; + int i, type, done = 0; + + printk("%s\n", __func__); + + /* dot and dotdot are special */ + if (filp->f_pos == 0) { + if (filldir(dirent, ".", 1, 0, ino->i_ino, DT_DIR) < 0) + return done; + done++; + filp->f_pos++; + } + if (filp->f_pos == 1) { + if (filldir(dirent, "..", 2, 1, + parent_ino(filp->f_dentry), DT_DIR) < 0) + return done; + done++; + filp->f_pos++; + } + + /* Then our stuff */ + inode = container_of(ino, struct sdbfs_inode, ino); + sdbfs_read_whole_dir(inode); + offset = inode->base_sdb; + + for (i = filp->f_pos - 2; i < inode->nfiles; i++) { + info = inode->files + i; + if (info->s_e.record_type == sdb_type_bridge) + type = DT_DIR; + else + type = DT_REG; + + if (filldir(dirent, info->name, info->namelen, + SDBFS_INO(offset), i + 2 /* ? */, type) < 0) + return done; + filp->f_pos++; + done++; + } + return done; +} + +static const struct file_operations sdbfs_dir_fops = { + .read = generic_read_dir, + .readdir = sdbfs_readdir, + .llseek = default_llseek, +}; + +static struct dentry *sdbfs_lookup(struct inode *dir, + struct dentry *dentry, struct nameidata *nd) +{ + struct inode *ino = NULL; + struct sdbfs_inode *inode = container_of(dir, struct sdbfs_inode, ino); + struct sdbfs_info *info; + unsigned long offset = inode->base_sdb; + int i, n, len; + + printk("%s\n", __func__); + sdbfs_read_whole_dir(inode); + n = inode->nfiles; + len = dentry->d_name.len; + for (i = 0; i < n; i++) { + info = inode->files + i; + if (info->namelen != len) + continue; + if (!strncmp(info->name, dentry->d_name.name, len)) + break; + } + if (i != n) { + offset = offset + SDB_SIZE * i; + ino = sdbfs_iget(inode, dir->i_sb, SDBFS_INO(offset)); + } + d_add(dentry, ino); + return 0; +} + +static const struct inode_operations sdbfs_dir_iops = { + .lookup = sdbfs_lookup, +}; + + +struct inode *sdbfs_alloc_inode(struct super_block *sb) +{ + struct sdbfs_inode *inode; + + printk("%s\n", __func__); + inode = kmem_cache_alloc(sdbfs_inode_cache, GFP_KERNEL); + if (!inode) + return NULL; + inode_init_once(&inode->ino); + printk("%s: return %p\n", __func__, &inode->ino); + return &inode->ino; +} + +void sdbfs_destroy_inode(struct inode *ino) +{ + struct sdbfs_inode *inode; + + inode = container_of(ino, struct sdbfs_inode, ino); + kfree(inode->files); + kmem_cache_free(sdbfs_inode_cache, inode); +} + +static struct inode *sdbfs_iget_root(struct super_block *sb, + struct inode *ino) +{ + struct sdbfs_dev *sd = sb->s_fs_info; + struct sdbfs_inode *inode = container_of(ino, struct sdbfs_inode, ino); + struct sdb_bridge *b = &inode->info.s_b; + + /* The root directory is a fake "bridge" structure */ + memset(b, 0, sizeof(*b)); + b->sdb_child = cpu_to_be64(sd->entrypoint); + b->sdb_component.addr_first = 0; + b->sdb_component.addr_last = cpu_to_be64(sd->size); + b->sdb_component.product.record_type = sdb_type_bridge; + + /* So, this is a directory, and it links to the first interconnect */ + inode->base_data = 0; + inode->base_sdb = sd->entrypoint; + ino->i_size = sd->size; + ino->i_mode = S_IFDIR | 0555; + ino->i_op = &sdbfs_dir_iops; + ino->i_fop = &sdbfs_dir_fops; + + return ino; +} + +struct inode *sdbfs_iget(struct sdbfs_inode *parent, + struct super_block *sb, unsigned long inum) +{ + struct inode *ino; + struct sdbfs_dev *sd = sb->s_fs_info; + struct sdbfs_inode *inode; + uint32_t offset; + unsigned long size, base_data; /* target offset */ + int n; + int type; + + printk("%s: inum 0x%lx\n", __func__, inum); + ino = iget_locked(sb, inum); + if (!ino) + return ERR_PTR(-ENOMEM); + if (!(ino->i_state & I_NEW)) + return ino; + + /* general setup; no link concept: the structure is immutable */ + set_nlink(ino, 1); + ino->i_mtime.tv_sec = ino->i_atime.tv_sec = ino->i_ctime.tv_sec = 0; + ino->i_mtime.tv_nsec = ino->i_atime.tv_nsec = ino->i_ctime.tv_nsec = 0; + + if (unlikely(!parent)) { /* inum == SDBFS_ROOT */ + sdbfs_iget_root(sb, ino); + unlock_new_inode(ino); + return ino; + } + + inode = container_of(ino, struct sdbfs_inode, ino); + offset = SDBFS_OFFSET(inum); + + n = sd->ops->read(sd, offset, &inode->info.s_d, SDB_SIZE); + if (n != SDB_SIZE) + return ERR_PTR(-EIO); + sdbfs_fix_endian(sd, &inode->info.s_d, SDB_SIZE); + + + base_data = be64_to_cpu(inode->info.s_d.sdb_component.addr_first); + size = be64_to_cpu(inode->info.s_d.sdb_component.addr_last) + - base_data + 1; + + type = inode->info.s_e.record_type; + switch (type) { + case sdb_type_interconnect: + case sdb_type_device: + /* You can access internal registers/data */ + ino->i_fop = &sdbfs_fops; /* FIXME: Which bus type? */ + ino->i_mode = S_IFREG | 0444; + ino->i_size = size; + inode->base_data = parent->base_data + base_data; + break; + + case sdb_type_bridge: + /* A bridge is a subdirectory */ + ino->i_mode = S_IFDIR | 0555; + ino->i_op = &sdbfs_dir_iops; + ino->i_fop = &sdbfs_dir_fops; + inode->base_data = parent->base_data + base_data; + inode->base_sdb = parent->base_data + + be64_to_cpu(inode->info.s_b.sdb_child); + break; + + default: + if (type & 0x80) /* informative only */ + pr_info("%s: ignoring unknown record 0x%02x\n", + __func__, type); + else + pr_err("%s: unsupported record 0x%02x\n", + __func__, type); + break; + } + unlock_new_inode(ino); + return ino; +} diff --git a/sdbfs/kernel/sdbfs-int.h b/sdbfs/kernel/sdbfs-int.h index 05a54f79748fe29b58105d318042fe451ce258a6..f20cdb9a3bffc548f76c5fad3d7518039171f812 100644 --- a/sdbfs/kernel/sdbfs-int.h +++ b/sdbfs/kernel/sdbfs-int.h @@ -12,11 +12,16 @@ #include <linux/fs.h> #include <linux/sdb.h> +#include "sdbfs.h" + /* This is our mapping of inode numbers */ #define SDBFS_ROOT 1 #define SDBFS_INO(offset) ((offset) + 2) #define SDBFS_OFFSET(ino) ((ino) & ~15) +#define SDB_SIZE (sizeof(struct sdb_device)) + + struct sdbfs_info { /* unnamed union to save typing */ union { @@ -55,4 +60,18 @@ static inline uint64_t ntohll(uint64_t ll) return htonll(ll); } +/* Material in sdbfs-file.c */ +extern const struct file_operations sdbfs_fops; + +/* Material in sdbfs-inode.c */ +struct inode *sdbfs_alloc_inode(struct super_block *sb); +void sdbfs_destroy_inode(struct inode *ino); +struct inode *sdbfs_iget(struct sdbfs_inode *parent, + struct super_block *sb, unsigned long inum); +extern struct kmem_cache *sdbfs_inode_cache; + + + + + #endif /* __SDBFS_INT_H__ */