lkml.org 
[lkml]   [2002]   [Jan]   [5]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
Patch in this message
/
From
Subject[CFT] Unbork fs.h + per-fs supers
Date
Adding VFS support for per-fs superblock size was dead simple compared to 
doing the inodes because superblocks are few enough that no slab cache is
needed, and also because of cleanup Al had already done.

I've gotten brave enough to run this on my own machine (which I'm doing right
now) so I'd be pleased if some folks would be equally brave and give this a
workout. If it works well, everything is in place to start moving the per-fs
includes out of fs.h, so the sooner it gets tested, the better.

Besides providing the VFS mechanism, this patch enables per-fs superblocks
and inodes for Ext2. I did not remove the get_empty_inode function in this
patch - that properly belongs in a separate patch.

To apply:

cd /your/source/tree
cat this/patch | patch -p0

--
Daniel

--- ../2.4.17.clean/drivers/block/rd.c Fri Dec 21 12:41:53 2001
+++ ./drivers/block/rd.c Sat Jan 5 08:05:11 2002
@@ -673,7 +673,7 @@
#endif
ram_device = MKDEV(MAJOR_NR, unit);

- if ((inode = get_empty_inode()) == NULL)
+ if ((inode = get_empty_inode(NULL)) == NULL)
return;
memset(&infile, 0, sizeof(infile));
memset(&in_dentry, 0, sizeof(in_dentry));
@@ -683,7 +683,7 @@
infile.f_op = &def_blk_fops;
init_special_inode(inode, S_IFBLK | S_IRUSR, kdev_t_to_nr(device));

- if ((out_inode = get_empty_inode()) == NULL)
+ if ((out_inode = get_empty_inode(NULL)) == NULL)
goto free_inode;
memset(&outfile, 0, sizeof(outfile));
memset(&out_dentry, 0, sizeof(out_dentry));
--- ../2.4.17.clean/fs/ext2/super.c Fri Dec 21 12:41:55 2001
+++ ./fs/ext2/super.c Sat Jan 5 08:05:11 2002
@@ -806,16 +806,23 @@
return 0;
}

-static DECLARE_FSTYPE_DEV(ext2_fs_type, "ext2", ext2_read_super);
-
+static struct file_system_type ext2_fs = {
+ owner: THIS_MODULE,
+ fs_flags: FS_REQUIRES_DEV,
+ name: "ext2",
+ read_super: ext2_read_super,
+ super_size: sizeof(struct ext2_sb_info),
+ inode_size: sizeof(struct ext2_inode_info)
+};
+
static int __init init_ext2_fs(void)
{
- return register_filesystem(&ext2_fs_type);
+ return register_filesystem(&ext2_fs);
}

static void __exit exit_ext2_fs(void)
{
- unregister_filesystem(&ext2_fs_type);
+ unregister_filesystem(&ext2_fs);
}

EXPORT_NO_SYMBOLS;
--- ../2.4.17.clean/fs/inode.c Fri Dec 21 12:41:55 2001
+++ ./fs/inode.c Sat Jan 5 08:05:11 2002
@@ -75,29 +75,32 @@

static kmem_cache_t * inode_cachep;

-#define alloc_inode() \
- ((struct inode *) kmem_cache_alloc(inode_cachep, SLAB_KERNEL))
+static inline struct inode *alloc_inode(struct super_block *sb)
+{
+ kmem_cache_t *cache = sb? sb->s_type->inode_cache: NULL;
+ return (struct inode *) kmem_cache_alloc (cache? cache: inode_cachep, SLAB_KERNEL);
+}
+
static void destroy_inode(struct inode *inode)
{
+ struct super_block *sb = inode->i_sb;
+ kmem_cache_t *cache = sb? sb->s_type->inode_cache: NULL;
if (inode_has_buffers(inode))
BUG();
- kmem_cache_free(inode_cachep, (inode));
+ kmem_cache_free (cache? cache: inode_cachep, inode);
}

-
/*
* These are initializations that only need to be done
* once, because the fields are idempotent across use
* of the inode, so let the slab aware of that.
*/
-static void init_once(void * foo, kmem_cache_t * cachep, unsigned long flags)
+static void init_once(void *p, kmem_cache_t *cache, unsigned long flags)
{
- struct inode * inode = (struct inode *) foo;
-
- if ((flags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) ==
- SLAB_CTOR_CONSTRUCTOR)
+ if ((flags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) == SLAB_CTOR_CONSTRUCTOR)
{
- memset(inode, 0, sizeof(*inode));
+ struct inode *inode = (struct inode *) p;
+ kmem_cache_clear (cache, inode);
init_waitqueue_head(&inode->i_wait);
INIT_LIST_HEAD(&inode->i_hash);
INIT_LIST_HEAD(&inode->i_data.clean_pages);
@@ -710,6 +713,7 @@

int shrink_icache_memory(int priority, int gfp_mask)
{
+ struct file_system_type *fs;
int count = 0;

/*
@@ -725,7 +729,15 @@
count = inodes_stat.nr_unused / priority;

prune_icache(count);
+#if 0
+ /* Manfred thinks this isn't necessary */
kmem_cache_shrink(inode_cachep);
+ write_lock(&file_systems_lock);
+ for (fs = file_systems; fs; fs = fs->next)
+ kmem_cache_shrink (fs->inode_cache);
+ write_unlock(&file_systems_lock);
+ kmem_cache_shrink(inode_cachep);
+#endif
return 0;
}

@@ -765,12 +777,14 @@
* i_sb, i_ino, i_count, i_state and the lists have
* been initialized elsewhere..
*/
-static void clean_inode(struct inode *inode)
+static void clean_inode(struct super_block *sb, struct inode *inode)
{
static struct address_space_operations empty_aops;
static struct inode_operations empty_iops;
static struct file_operations empty_fops;
- memset(&inode->u, 0, sizeof(inode->u));
+ unsigned given = sb? sb->s_type->inode_size: 0; // only rd.c has null sb
+ memset(&inode->u, 0, given? given: sizeof(inode->u));
+ inode->i_sb = sb;
inode->i_sock = 0;
inode->i_op = &empty_iops;
inode->i_fop = &empty_fops;
@@ -802,20 +816,19 @@
* lists.
*/

-struct inode * get_empty_inode(void)
+struct inode *get_empty_inode(struct super_block *sb)
{
static unsigned long last_ino;
- struct inode * inode;
+ struct inode *inode;

spin_lock_prefetch(&inode_lock);
-
- inode = alloc_inode();
+ inode = alloc_inode (sb);
if (inode)
{
spin_lock(&inode_lock);
inodes_stat.nr_inodes++;
list_add(&inode->i_list, &inode_in_use);
- inode->i_sb = NULL;
+ inode->i_sb = NULL; // need this?
inode->i_dev = 0;
inode->i_blkbits = 0;
inode->i_ino = ++last_ino;
@@ -823,7 +836,7 @@
atomic_set(&inode->i_count, 1);
inode->i_state = 0;
spin_unlock(&inode_lock);
- clean_inode(inode);
+ clean_inode(sb, inode);
}
return inode;
}
@@ -838,7 +851,7 @@
{
struct inode * inode;

- inode = alloc_inode();
+ inode = alloc_inode (sb);
if (inode) {
struct inode * old;

@@ -849,7 +862,6 @@
inodes_stat.nr_inodes++;
list_add(&inode->i_list, &inode_in_use);
list_add(&inode->i_hash, head);
- inode->i_sb = sb;
inode->i_dev = sb->s_dev;
inode->i_blkbits = sb->s_blocksize_bits;
inode->i_ino = ino;
@@ -857,8 +869,7 @@
atomic_set(&inode->i_count, 1);
inode->i_state = I_LOCK;
spin_unlock(&inode_lock);
-
- clean_inode(inode);
+ clean_inode(sb, inode);

/* reiserfs specific hack right here. We don't
** want this to last, and are looking for VFS changes
@@ -897,6 +908,21 @@
wait_on_inode(inode);
}
return inode;
+}
+
+int create_inode_cache(struct file_system_type *fs)
+{
+ if (fs->inode_size)
+ if (!(fs->inode_cache = kmem_cache_create (fs->name,
+ fs->inode_size + sizeof(struct inode) - sizeof(get_empty_inode(0)->u),
+ 0, SLAB_HWCACHE_ALIGN, init_once, NULL)))
+ return -ENOSPC;
+ return 0;
+}
+
+int destroy_inode_cache(struct file_system_type *fs)
+{
+ return kmem_cache_destroy (fs->inode_cache)? -EBUSY: 0;
}

static inline unsigned long hash(struct super_block *sb, unsigned long i_ino)
--- ../2.4.17.clean/fs/super.c Fri Dec 21 12:42:03 2001
+++ ./fs/super.c Sat Jan 5 08:53:44 2002
@@ -67,8 +67,8 @@
* Once the reference is obtained we can drop the spinlock.
*/

-static struct file_system_type *file_systems;
-static rwlock_t file_systems_lock = RW_LOCK_UNLOCKED;
+struct file_system_type *file_systems;
+rwlock_t file_systems_lock = RW_LOCK_UNLOCKED;

/* WARNING: This can be used only if we _already_ own a reference */
static void get_filesystem(struct file_system_type *fs)
@@ -105,10 +105,10 @@
* unregistered.
*/

-int register_filesystem(struct file_system_type * fs)
+int register_filesystem(struct file_system_type *fs)
{
- int res = 0;
- struct file_system_type ** p;
+ struct file_system_type **p;
+ int err = 0;

if (!fs)
return -EINVAL;
@@ -118,11 +118,12 @@
write_lock(&file_systems_lock);
p = find_filesystem(fs->name);
if (*p)
- res = -EBUSY;
+ err = -EBUSY;
else
- *p = fs;
+ if (!(err = create_inode_cache (fs)))
+ *p = fs;
write_unlock(&file_systems_lock);
- return res;
+ return err;
}

/**
@@ -137,23 +138,25 @@
* may be freed or reused.
*/

-int unregister_filesystem(struct file_system_type * fs)
+int unregister_filesystem(struct file_system_type *fs)
{
- struct file_system_type ** tmp;
-
+ struct file_system_type **p;
+ int err = -EINVAL;
write_lock(&file_systems_lock);
- tmp = &file_systems;
- while (*tmp) {
- if (fs == *tmp) {
- *tmp = fs->next;
+ p = &file_systems;
+ while (*p) {
+ if (*p == fs) {
+ if (fs->inode_cache && (err = destroy_inode_cache (fs)))
+ break;
+ *p = fs->next;
fs->next = NULL;
- write_unlock(&file_systems_lock);
- return 0;
+ err = 0;
+ break;
}
- tmp = &(*tmp)->next;
+ p = &(*p)->next;
}
write_unlock(&file_systems_lock);
- return -EINVAL;
+ return err;
}

static int fs_index(const char * __name)
@@ -419,11 +422,17 @@
* the request.
*/

-static struct super_block *alloc_super(void)
+static struct super_block *alloc_super(struct file_system_type *fs)
{
- struct super_block *s = kmalloc(sizeof(struct super_block), GFP_USER);
- if (s) {
- memset(s, 0, sizeof(struct super_block));
+ struct super_block *s;
+ unsigned size = sizeof(struct super_block);
+
+ if (fs->super_size)
+ size += fs->super_size - sizeof(alloc_super(0)->u);
+
+ printk(">>> %s super size is %i\n", fs->name, size);
+ if ((s = kmalloc(size, GFP_USER))) {
+ memset(s, 0, size);
INIT_LIST_HEAD(&s->s_dirty);
INIT_LIST_HEAD(&s->s_locked_inodes);
INIT_LIST_HEAD(&s->s_files);
@@ -446,7 +455,7 @@
void *data)
{
struct super_block * s;
- s = alloc_super();
+ s = alloc_super(type);
if (!s)
goto out;
s->s_dev = dev;
@@ -578,7 +587,7 @@
goto out1;

error = -ENOMEM;
- s = alloc_super();
+ s = alloc_super(fs_type);
if (!s)
goto out1;
down_write(&s->s_umount);
@@ -664,7 +673,7 @@
static struct super_block *get_sb_single(struct file_system_type *fs_type,
int flags, void *data)
{
- struct super_block * s = alloc_super();
+ struct super_block * s = alloc_super(fs_type);
if (!s)
return ERR_PTR(-ENOMEM);
down_write(&s->s_umount);
--- ../2.4.17.clean/include/linux/fs.h Fri Dec 21 12:42:03 2001
+++ ./include/linux/fs.h Sat Jan 5 08:05:11 2002
@@ -691,6 +691,9 @@
#include <linux/cramfs_fs_sb.h>
#include <linux/jffs2_fs_sb.h>

+extern struct file_system_type *file_systems;
+extern rwlock_t file_systems_lock;
+
extern struct list_head super_blocks;
extern spinlock_t sb_lock;

@@ -951,10 +954,14 @@
int fs_flags;
struct super_block *(*read_super) (struct super_block *, void *, int);
struct module *owner;
- struct file_system_type * next;
+ struct file_system_type *next;
struct list_head fs_supers;
+ unsigned super_size, inode_size;
+ struct kmem_cache_s *inode_cache;
};

+/* Backward compatible declarations, remove when all updated */
+
#define DECLARE_FSTYPE(var,type,read,flags) \
struct file_system_type var = { \
name: type, \
@@ -1328,20 +1335,21 @@
}

extern void clear_inode(struct inode *);
-extern struct inode * get_empty_inode(void);
+extern struct inode *get_empty_inode(struct super_block *sb);

-static inline struct inode * new_inode(struct super_block *sb)
+static inline struct inode *new_inode(struct super_block *sb)
{
- struct inode *inode = get_empty_inode();
+ struct inode *inode = get_empty_inode(sb);
if (inode) {
- inode->i_sb = sb;
inode->i_dev = sb->s_dev;
inode->i_blkbits = sb->s_blocksize_bits;
}
return inode;
}
-extern void remove_suid(struct inode *inode);

+extern int create_inode_cache(struct file_system_type *fs);
+extern int destroy_inode_cache(struct file_system_type *fs);
+extern void remove_suid(struct inode *inode);
extern void insert_inode_hash(struct inode *);
extern void remove_inode_hash(struct inode *);
extern struct file * get_empty_filp(void);
--- ../2.4.17.clean/include/linux/slab.h Fri Dec 21 12:42:04 2001
+++ ./include/linux/slab.h Sat Jan 5 08:05:42 2002
@@ -57,6 +57,7 @@
extern int kmem_cache_shrink(kmem_cache_t *);
extern void *kmem_cache_alloc(kmem_cache_t *, int);
extern void kmem_cache_free(kmem_cache_t *, void *);
+extern void kmem_cache_clear(kmem_cache_t *, void *);

extern void *kmalloc(size_t, int);
extern void kfree(const void *);
--- ../2.4.17.clean/mm/slab.c Fri Dec 21 12:42:05 2001
+++ ./mm/slab.c Sat Jan 5 08:05:11 2002
@@ -1078,6 +1078,16 @@
slabp->free = 0;
}

+void kmem_cache_clear(kmem_cache_t *cachep, void *objp)
+{
+ unsigned size = cachep->objsize;
+#if DEBUG
+ if (cachep->flags & SLAB_RED_ZONE)
+ size -= BYTES_PER_WORD*2;
+#endif
+ memset(objp, 0, size);
+}
+
/*
* Grow (by 1) the number of slabs within a cache. This is called by
* kmem_cache_alloc() when there are no active objs left in a cache.
--- ../2.4.17.clean/net/socket.c Fri Dec 21 12:42:06 2001
+++ ./net/socket.c Sat Jan 5 08:05:11 2002
@@ -438,11 +438,10 @@
struct inode * inode;
struct socket * sock;

- inode = get_empty_inode();
+ inode = get_empty_inode(sock_mnt->mnt_sb);
if (!inode)
return NULL;

- inode->i_sb = sock_mnt->mnt_sb;
sock = socki_lookup(inode);

inode->i_mode = S_IFSOCK|S_IRWXUGO;
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
\
 
 \ /
  Last update: 2005-03-22 13:15    [W:1.660 / U:0.012 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site