From: deshmukh Date: Thu, 27 Aug 2009 06:47:04 +0000 (+0000) Subject: b=20298 (Merge head ldiskfs and b1_8 ldiskfs) X-Git-Tag: v1_9_251~10 X-Git-Url: https://git.whamcloud.com/?p=fs%2Flustre-release.git;a=commitdiff_plain;h=233b71769d7d64c680b7c1a0ebc6e5d806233534 b=20298 (Merge head ldiskfs and b1_8 ldiskfs) i=adilger i=girish This is related to unifying the ldiskfs branch between b1_8 and HEAD. For that adding the patches to series files which is required for HEAD. Also some other changes required in makefile and config file. --- diff --git a/ldiskfs/kernel_patches/patches/ext3-dynlocks-2.6-rhel5.patch b/ldiskfs/kernel_patches/patches/ext3-dynlocks-2.6-rhel5.patch new file mode 100644 index 0000000..85064da --- /dev/null +++ b/ldiskfs/kernel_patches/patches/ext3-dynlocks-2.6-rhel5.patch @@ -0,0 +1,33 @@ +diff -rupN linux-2.6.18-128.1.6_1/fs/ext3/Makefile linux-2.6.18-128.1.6_2/fs/ext3/Makefile +--- linux-2.6.18-128.1.6_1/fs/ext3/Makefile 2009-08-13 19:19:54.000000000 +0530 ++++ linux-2.6.18-128.1.6_2/fs/ext3/Makefile 2009-08-13 19:20:30.000000000 +0530 +@@ -5,7 +5,8 @@ + obj-$(CONFIG_EXT3_FS) += ext3.o + + ext3-y := balloc.o bitmap.o dir.o file.o fsync.o ialloc.o inode.o iopen.o \ +- ioctl.o namei.o super.o symlink.o hash.o resize.o extents.o mballoc.o ++ ioctl.o namei.o super.o symlink.o hash.o resize.o extents.o \ ++ mballoc.o dynlocks.o + + ext3-$(CONFIG_EXT3_FS_XATTR) += xattr.o xattr_user.o xattr_trusted.o + ext3-$(CONFIG_EXT3_FS_POSIX_ACL) += acl.o +diff -rupN linux-2.6.18-128.1.6_1/fs/ext3/super.c linux-2.6.18-128.1.6_2/fs/ext3/super.c +--- linux-2.6.18-128.1.6_1/fs/ext3/super.c 2009-08-13 19:19:54.000000000 +0530 ++++ linux-2.6.18-128.1.6_2/fs/ext3/super.c 2009-08-13 19:23:23.000000000 +0530 +@@ -3529,6 +3530,7 @@ static int __init init_ext3_fs(void) + err = init_inodecache(); + if (err) + goto out1; ++ dynlock_cache_init(); + err = register_filesystem(&ext3_fs_type); + if (err) + goto out; +@@ -3546,6 +3548,7 @@ out1: + static void __exit exit_ext3_fs(void) + { + unregister_filesystem(&ext3_fs_type); ++ dynlock_cache_exit(); + destroy_inodecache(); + exit_ext3_xattr(); + exit_ext3_proc(); + diff --git a/ldiskfs/kernel_patches/patches/ext3-dynlocks-common.patch b/ldiskfs/kernel_patches/patches/ext3-dynlocks-common.patch new file mode 100644 index 0000000..73b0c87 --- /dev/null +++ b/ldiskfs/kernel_patches/patches/ext3-dynlocks-common.patch @@ -0,0 +1,278 @@ +diff -rupN linux-2.6.18-128.1.6_1/fs/ext3/dynlocks.c linux-2.6.18-128.1.6_2/fs/ext3/dynlocks.c +--- linux-2.6.18-128.1.6_1/fs/ext3/dynlocks.c 1970-01-01 05:30:00.000000000 +0530 ++++ linux-2.6.18-128.1.6_2/fs/ext3/dynlocks.c 2009-08-13 20:42:59.000000000 +0530 +@@ -0,0 +1,236 @@ ++/* ++ * Dynamic Locks ++ * ++ * struct dynlock is lockspace ++ * one may request lock (exclusive or shared) for some value ++ * in that lockspace ++ * ++ */ ++ ++#include ++#include ++#include ++#include ++ ++#define DYNLOCK_HANDLE_MAGIC 0xd19a10c ++#define DYNLOCK_HANDLE_DEAD 0xd1956ee ++#define DYNLOCK_LIST_MAGIC 0x11ee91e6 ++ ++static kmem_cache_t * dynlock_cachep = NULL; ++ ++struct dynlock_handle { ++ unsigned dh_magic; ++ struct list_head dh_list; ++ unsigned long dh_value; /* lock value */ ++ int dh_refcount; /* number of users */ ++ int dh_readers; ++ int dh_writers; ++ int dh_pid; /* holder of the lock */ ++ wait_queue_head_t dh_wait; ++}; ++ ++int __init dynlock_cache_init(void) ++{ ++ int rc = 0; ++ ++ printk(KERN_INFO "init dynlocks cache\n"); ++ dynlock_cachep = kmem_cache_create("dynlock_cache", ++ sizeof(struct dynlock_handle), ++ 0, ++ SLAB_HWCACHE_ALIGN, ++ NULL, NULL); ++ if (dynlock_cachep == NULL) { ++ printk(KERN_ERR "Not able to create dynlock cache"); ++ rc = -ENOMEM; ++ } ++ return rc; ++} ++ ++void __exit dynlock_cache_exit(void) ++{ ++ printk(KERN_INFO "exit dynlocks cache\n"); ++ kmem_cache_destroy(dynlock_cachep); ++} ++ ++/* ++ * dynlock_init ++ * ++ * initialize lockspace ++ * ++ */ ++void dynlock_init(struct dynlock *dl) ++{ ++ spin_lock_init(&dl->dl_list_lock); ++ INIT_LIST_HEAD(&dl->dl_list); ++ dl->dl_magic = DYNLOCK_LIST_MAGIC; ++} ++EXPORT_SYMBOL(dynlock_init); ++ ++/* ++ * dynlock_lock ++ * ++ * acquires lock (exclusive or shared) in specified lockspace ++ * each lock in lockspace is allocated separately, so user have ++ * to specify GFP flags. ++ * routine returns pointer to lock. this pointer is intended to ++ * be passed to dynlock_unlock ++ * ++ */ ++struct dynlock_handle *dynlock_lock(struct dynlock *dl, unsigned long value, ++ enum dynlock_type lt, gfp_t gfp) ++{ ++ struct dynlock_handle *nhl = NULL; ++ struct dynlock_handle *hl; ++ ++ BUG_ON(dl == NULL); ++ BUG_ON(dl->dl_magic != DYNLOCK_LIST_MAGIC); ++ ++repeat: ++ /* find requested lock in lockspace */ ++ spin_lock(&dl->dl_list_lock); ++ BUG_ON(dl->dl_list.next == NULL); ++ BUG_ON(dl->dl_list.prev == NULL); ++ list_for_each_entry(hl, &dl->dl_list, dh_list) { ++ BUG_ON(hl->dh_list.next == NULL); ++ BUG_ON(hl->dh_list.prev == NULL); ++ BUG_ON(hl->dh_magic != DYNLOCK_HANDLE_MAGIC); ++ if (hl->dh_value == value) { ++ /* lock is found */ ++ if (nhl) { ++ /* someone else just allocated ++ * lock we didn't find and just created ++ * so, we drop our lock ++ */ ++ kmem_cache_free(dynlock_cachep, nhl); ++ nhl = NULL; ++ } ++ hl->dh_refcount++; ++ goto found; ++ } ++ } ++ /* lock not found */ ++ if (nhl) { ++ /* we already have allocated lock. use it */ ++ hl = nhl; ++ nhl = NULL; ++ list_add(&hl->dh_list, &dl->dl_list); ++ goto found; ++ } ++ spin_unlock(&dl->dl_list_lock); ++ ++ /* lock not found and we haven't allocated lock yet. allocate it */ ++ nhl = kmem_cache_alloc(dynlock_cachep, gfp); ++ if (nhl == NULL) ++ return NULL; ++ nhl->dh_refcount = 1; ++ nhl->dh_value = value; ++ nhl->dh_readers = 0; ++ nhl->dh_writers = 0; ++ nhl->dh_magic = DYNLOCK_HANDLE_MAGIC; ++ init_waitqueue_head(&nhl->dh_wait); ++ ++ /* while lock is being allocated, someone else may allocate it ++ * and put onto to list. check this situation ++ */ ++ goto repeat; ++ ++found: ++ if (lt == DLT_WRITE) { ++ /* exclusive lock: user don't want to share lock at all ++ * NOTE: one process may take the same lock several times ++ * this functionaly is useful for rename operations */ ++ while ((hl->dh_writers && hl->dh_pid != current->pid) || ++ hl->dh_readers) { ++ spin_unlock(&dl->dl_list_lock); ++ wait_event(hl->dh_wait, ++ hl->dh_writers == 0 && hl->dh_readers == 0); ++ spin_lock(&dl->dl_list_lock); ++ } ++ hl->dh_writers++; ++ } else { ++ /* shared lock: user do not want to share lock with writer */ ++ while (hl->dh_writers) { ++ spin_unlock(&dl->dl_list_lock); ++ wait_event(hl->dh_wait, hl->dh_writers == 0); ++ spin_lock(&dl->dl_list_lock); ++ } ++ hl->dh_readers++; ++ } ++ hl->dh_pid = current->pid; ++ spin_unlock(&dl->dl_list_lock); ++ ++ return hl; ++} ++EXPORT_SYMBOL(dynlock_lock); ++ ++ ++/* ++ * dynlock_unlock ++ * ++ * user have to specify lockspace (dl) and pointer to lock structure ++ * returned by dynlock_lock() ++ * ++ */ ++void dynlock_unlock(struct dynlock *dl, struct dynlock_handle *hl) ++{ ++ int wakeup = 0; ++ ++ BUG_ON(dl == NULL); ++ BUG_ON(hl == NULL); ++ BUG_ON(dl->dl_magic != DYNLOCK_LIST_MAGIC); ++ ++ if (hl->dh_magic != DYNLOCK_HANDLE_MAGIC) ++ printk(KERN_EMERG "wrong lock magic: %#x\n", hl->dh_magic); ++ ++ BUG_ON(hl->dh_magic != DYNLOCK_HANDLE_MAGIC); ++ BUG_ON(hl->dh_writers != 0 && current->pid != hl->dh_pid); ++ ++ spin_lock(&dl->dl_list_lock); ++ if (hl->dh_writers) { ++ BUG_ON(hl->dh_readers != 0); ++ hl->dh_writers--; ++ if (hl->dh_writers == 0) ++ wakeup = 1; ++ } else if (hl->dh_readers) { ++ hl->dh_readers--; ++ if (hl->dh_readers == 0) ++ wakeup = 1; ++ } else { ++ BUG(); ++ } ++ if (wakeup) { ++ hl->dh_pid = 0; ++ wake_up(&hl->dh_wait); ++ } ++ if (--(hl->dh_refcount) == 0) { ++ hl->dh_magic = DYNLOCK_HANDLE_DEAD; ++ list_del(&hl->dh_list); ++ kmem_cache_free(dynlock_cachep, hl); ++ } ++ spin_unlock(&dl->dl_list_lock); ++} ++EXPORT_SYMBOL(dynlock_unlock); ++ ++int dynlock_is_locked(struct dynlock *dl, unsigned long value) ++{ ++ struct dynlock_handle *hl; ++ int result = 0; ++ ++ /* find requested lock in lockspace */ ++ spin_lock(&dl->dl_list_lock); ++ BUG_ON(dl->dl_list.next == NULL); ++ BUG_ON(dl->dl_list.prev == NULL); ++ list_for_each_entry(hl, &dl->dl_list, dh_list) { ++ BUG_ON(hl->dh_list.next == NULL); ++ BUG_ON(hl->dh_list.prev == NULL); ++ BUG_ON(hl->dh_magic != DYNLOCK_HANDLE_MAGIC); ++ if (hl->dh_value == value && hl->dh_pid == current->pid) { ++ /* lock is found */ ++ result = 1; ++ break; ++ } ++ } ++ spin_unlock(&dl->dl_list_lock); ++ return result; ++} ++EXPORT_SYMBOL(dynlock_is_locked); +diff -rupN linux-2.6.18-128.1.6_1/include/linux/dynlocks.h linux-2.6.18-128.1.6_2/include/linux/dynlocks.h +--- linux-2.6.18-128.1.6_1/include/linux/dynlocks.h 1970-01-01 05:30:00.000000000 +0530 ++++ linux-2.6.18-128.1.6_2/include/linux/dynlocks.h 2009-08-13 20:43:18.000000000 +0530 +@@ -0,0 +1,34 @@ ++#ifndef _LINUX_DYNLOCKS_H ++#define _LINUX_DYNLOCKS_H ++ ++#include ++#include ++ ++struct dynlock_handle; ++ ++/* ++ * lock's namespace: ++ * - list of locks ++ * - lock to protect this list ++ */ ++struct dynlock { ++ unsigned dl_magic; ++ struct list_head dl_list; ++ spinlock_t dl_list_lock; ++}; ++ ++enum dynlock_type { ++ DLT_WRITE, ++ DLT_READ ++}; ++ ++int dynlock_cache_init(void); ++void dynlock_cache_exit(void); ++void dynlock_init(struct dynlock *dl); ++struct dynlock_handle *dynlock_lock(struct dynlock *dl, unsigned long value, ++ enum dynlock_type lt, gfp_t gfp); ++void dynlock_unlock(struct dynlock *dl, struct dynlock_handle *lock); ++int dynlock_is_locked(struct dynlock *dl, unsigned long value); ++ ++#endif ++ diff --git a/ldiskfs/kernel_patches/patches/ext3-extents-2.6.16-sles10.patch b/ldiskfs/kernel_patches/patches/ext3-extents-2.6.16-sles10.patch index bbccd36..5b363ea 100644 --- a/ldiskfs/kernel_patches/patches/ext3-extents-2.6.16-sles10.patch +++ b/ldiskfs/kernel_patches/patches/ext3-extents-2.6.16-sles10.patch @@ -2395,17 +2395,16 @@ Index: linux-2.6.16.54-0.2.5/fs/ext3/inode.c if (ext3_should_journal_data(inode)) ret = 3 * (bpp + indirects) + 2; else -Index: linux-2.6.16.54-0.2.5/fs/ext3/Makefile +Index: linux-2.6.18.8/fs/ext3/Makefile =================================================================== ---- linux-2.6.16.54-0.2.5.orig/fs/ext3/Makefile -+++ linux-2.6.16.54-0.2.5/fs/ext3/Makefile -@@ -5,7 +5,8 @@ +--- linux-2.6.18.8.orig/fs/ext3/Makefile 2007-07-17 09:18:11.000000000 +0200 ++++ linux-2.6.18.8/fs/ext3/Makefile 2007-07-17 11:08:11.000000000 +0200 +@@ -5,7 +5,7 @@ obj-$(CONFIG_EXT3_FS) += ext3.o ext3-y := balloc.o bitmap.o dir.o file.o fsync.o ialloc.o inode.o iopen.o \ - ioctl.o namei.o super.o symlink.o hash.o resize.o -+ ioctl.o namei.o super.o symlink.o hash.o resize.o \ -+ extents.o ++ ioctl.o namei.o super.o symlink.o hash.o resize.o extents.o ext3-$(CONFIG_EXT3_FS_XATTR) += xattr.o xattr_user.o xattr_trusted.o ext3-$(CONFIG_EXT3_FS_POSIX_ACL) += acl.o diff --git a/ldiskfs/kernel_patches/patches/ext3-hash-indexed-dir-dotdot-update.patch b/ldiskfs/kernel_patches/patches/ext3-hash-indexed-dir-dotdot-update.patch new file mode 100644 index 0000000..a817045 --- /dev/null +++ b/ldiskfs/kernel_patches/patches/ext3-hash-indexed-dir-dotdot-update.patch @@ -0,0 +1,87 @@ +Index: linux-stage/fs/ext3/namei.c +=================================================================== +--- linux-stage.orig/fs/ext3/namei.c 2009-08-10 22:31:03.000000000 +0800 ++++ linux-stage/fs/ext3/namei.c 2009-08-10 22:33:38.000000000 +0800 +@@ -1471,6 +1471,72 @@ + } + #endif + ++/* update ".." for hash-indexed directory, split the item "." if necessary */ ++static int ext3_update_dotdot(handle_t *handle, struct dentry *dentry, ++ struct inode *inode) ++{ ++ struct inode * dir = dentry->d_parent->d_inode; ++ struct buffer_head * dir_block; ++ struct ext3_dir_entry_2 * de; ++ int len, journal = 0, err = 0; ++ ++ if (IS_ERR(handle)) ++ return PTR_ERR(handle); ++ ++ if (IS_DIRSYNC(dir)) ++ handle->h_sync = 1; ++ ++ dir_block = ext3_bread(handle, dir, 0, 0, &err); ++ if (!dir_block) ++ goto out; ++ ++ de = (struct ext3_dir_entry_2 *)dir_block->b_data; ++ /* the first item must be "." */ ++ assert(de->name_len == 1 && de->name[0] == '.'); ++ len = le16_to_cpu(de->rec_len); ++ assert(len >= EXT3_DIR_REC_LEN(1)); ++ if (len > EXT3_DIR_REC_LEN(1)) { ++ BUFFER_TRACE(dir_block, "get_write_access"); ++ err = ext3_journal_get_write_access(handle, dir_block); ++ if (err) ++ goto out_journal; ++ ++ journal = 1; ++ de->rec_len = cpu_to_le16(EXT3_DIR_REC_LEN(1)); ++ } ++ ++ len -= EXT3_DIR_REC_LEN(1); ++ assert(len == 0 || len >= EXT3_DIR_REC_LEN(2)); ++ de = (struct ext3_dir_entry_2 *) ++ ((char *) de + le16_to_cpu(de->rec_len)); ++ if (!journal) { ++ BUFFER_TRACE(dir_block, "get_write_access"); ++ err = ext3_journal_get_write_access(handle, dir_block); ++ if (err) ++ goto out_journal; ++ } ++ ++ de->inode = cpu_to_le32(inode->i_ino); ++ if (len > 0) ++ de->rec_len = cpu_to_le16(len); ++ else ++ assert(le16_to_cpu(de->rec_len) >= EXT3_DIR_REC_LEN(2)); ++ de->name_len = 2; ++ strcpy (de->name, ".."); ++ ext3_set_de_type(dir->i_sb, de, S_IFDIR); ++ ++out_journal: ++ if (journal) { ++ BUFFER_TRACE(dir_block, "call ext3_journal_dirty_metadata"); ++ err = ext3_journal_dirty_metadata(handle, dir_block); ++ ext3_mark_inode_dirty(handle, dir); ++ } ++ brelse (dir_block); ++ ++out: ++ return err; ++} ++ + /* + * ext3_add_entry() + * +@@ -1502,6 +1568,9 @@ + return -EINVAL; + #ifdef CONFIG_EXT3_INDEX + if (is_dx(dir)) { ++ if (dentry->d_name.len == 2 && ++ memcmp(dentry->d_name.name, "..", 2) == 0) ++ return ext3_update_dotdot(handle, dentry, inode); + retval = ext3_dx_add_entry(handle, dentry, inode); + if (!retval || (retval != ERR_BAD_DX_DIR)) + return retval; diff --git a/ldiskfs/kernel_patches/patches/ext3-mballoc3-sles10.patch b/ldiskfs/kernel_patches/patches/ext3-mballoc3-sles10.patch index 88be686..655e4bb 100644 --- a/ldiskfs/kernel_patches/patches/ext3-mballoc3-sles10.patch +++ b/ldiskfs/kernel_patches/patches/ext3-mballoc3-sles10.patch @@ -243,16 +243,16 @@ Index: linux-2.6.16.46-0.14/fs/ext3/extents.c /* * TODO: optimization is possible here * probably we need not scaning at all, -Index: linux-2.6.16.46-0.14/fs/ext3/Makefile +Index: linux-2.6.18.8/fs/ext3/Makefile =================================================================== ---- linux-2.6.16.46-0.14.orig/fs/ext3/Makefile -+++ linux-2.6.16.46-0.14/fs/ext3/Makefile -@@ -6,7 +6,7 @@ obj-$(CONFIG_EXT3_FS) += ext3.o +--- linux-2.6.18.8.orig/fs/ext3/Makefile ++++ linux-2.6.18.8/fs/ext3/Makefile +@@ -5,7 +5,7 @@ + obj-$(CONFIG_EXT3_FS) += ext3.o ext3-y := balloc.o bitmap.o dir.o file.o fsync.o ialloc.o inode.o iopen.o \ - ioctl.o namei.o super.o symlink.o hash.o resize.o \ -- extents.o -+ extents.o mballoc.o +- ioctl.o namei.o super.o symlink.o hash.o resize.o extents.o ++ ioctl.o namei.o super.o symlink.o hash.o resize.o extents.o mballoc.o ext3-$(CONFIG_EXT3_FS_XATTR) += xattr.o xattr_user.o xattr_trusted.o ext3-$(CONFIG_EXT3_FS_POSIX_ACL) += acl.o diff --git a/ldiskfs/kernel_patches/patches/ext3-nlinks-2.6.9.patch b/ldiskfs/kernel_patches/patches/ext3-nlinks-2.6.9.patch index fb32a64..50ff2e1 100644 --- a/ldiskfs/kernel_patches/patches/ext3-nlinks-2.6.9.patch +++ b/ldiskfs/kernel_patches/patches/ext3-nlinks-2.6.9.patch @@ -30,6 +30,15 @@ Index: linux-2.6.12/fs/ext3/namei.c return -EMLINK; retry: +@@ -1782,7 +1793,7 @@ retry: + inode->i_size = EXT3_I(inode)->i_disksize = inode->i_sb->s_blocksize; + dir_block = ext3_bread (handle, inode, 0, 1, &err); + if (!dir_block) { +- inode->i_nlink--; /* is this nlink == 0? */ ++ drop_nlink(inode); /* is this nlink == 0? */ + ext3_mark_inode_dirty(handle, inode); + iput (inode); + goto out_stop; @@ -1758,7 +1764,7 @@ retry: iput (inode); goto out_stop; diff --git a/ldiskfs/kernel_patches/patches/ext3-osd-iam-exports.patch b/ldiskfs/kernel_patches/patches/ext3-osd-iam-exports.patch new file mode 100644 index 0000000..aecab61 --- /dev/null +++ b/ldiskfs/kernel_patches/patches/ext3-osd-iam-exports.patch @@ -0,0 +1,65 @@ +Index: linux-2.6.16.60-0.33_org/fs/ext3/hash.c +=================================================================== +--- linux-2.6.16.60-0.33_org/fs/ext3/hash.c 2009-07-01 18:16:50.000000000 +0530 ++++ linux-2.6.16.60-0.33_new/fs/ext3/hash.c 2009-07-01 18:26:58.000000000 +0530 +@@ -8,7 +8,7 @@ + * This file may be redistributed under the terms of the GNU Public + * License. + */ +- ++#include + #include + #include + #include +@@ -173,3 +173,4 @@ int ext3fs_dirhash(const char *name, int + hinfo->minor_hash = minor_hash; + return 0; + } ++EXPORT_SYMBOL(ext3fs_dirhash); +Index: linux-2.6.16.60-0.33_org/fs/ext3/namei.c +=================================================================== +--- linux-2.6.16.60-0.33_org/fs/ext3/namei.c 2009-07-01 18:16:50.000000000 +0530 ++++ linux-2.6.16.60-0.33_new/fs/ext3/namei.c 2009-07-01 18:24:49.000000000 +0530 +@@ -75,6 +75,7 @@ struct buffer_head *ext3_append(handle_t + + return bh; + } ++EXPORT_SYMBOL(ext3_append); + + #ifndef assert + #define assert(test) J_ASSERT(test) +Index: linux-2.6.16.60-0.33_org/fs/ext3/super.c +=================================================================== +--- linux-2.6.16.60-0.33_org/fs/ext3/super.c 2009-07-01 18:16:50.000000000 +0530 ++++ linux-2.6.16.60-0.33_new/fs/ext3/super.c 2009-07-01 18:24:27.000000000 +0530 +@@ -260,6 +260,7 @@ void __ext3_std_error (struct super_bloc + + ext3_handle_error(sb); + } ++EXPORT_SYMBOL(__ext3_std_error); + + /* + * ext3_abort is a much stronger failure handler than ext3_error. The +Index: linux-2.6.16.60-0.33_org/include/linux/ext3_fs.h +=================================================================== +--- linux-2.6.16.60-0.33_org/include/linux/ext3_fs.h 2009-07-01 18:16:50.000000000 +0530 ++++ linux-2.6.16.60-0.33_new/include/linux/ext3_fs.h 2009-07-01 18:22:09.000000000 +0530 +@@ -1055,6 +1055,8 @@ extern void ext3_abort (struct super_blo + extern void ext3_warning (struct super_block *, const char *, const char *, ...) + __attribute__ ((format (printf, 3, 4))); + extern void ext3_update_dynamic_rev (struct super_block *sb); ++extern void __ext3_std_error (struct super_block * sb, const char * function, ++ int errno); + + #define ext3_std_error(sb, errno) \ + do { \ +@@ -1076,6 +1078,8 @@ extern struct file_operations ext3_file_ + /* namei.c */ + extern struct inode_operations ext3_dir_inode_operations; + extern struct inode_operations ext3_special_inode_operations; ++extern struct buffer_head *ext3_append(handle_t *handle, struct inode *inode, ++ u32 *block, int *err); + + /* symlink.c */ + extern struct inode_operations ext3_symlink_inode_operations; + diff --git a/ldiskfs/kernel_patches/patches/ext3-osd-iop-common.patch b/ldiskfs/kernel_patches/patches/ext3-osd-iop-common.patch new file mode 100644 index 0000000..30a8184 --- /dev/null +++ b/ldiskfs/kernel_patches/patches/ext3-osd-iop-common.patch @@ -0,0 +1,227 @@ +diff -rupN linux-2.6.18-128.1.6_1/fs/ext3/namei.c linux-2.6.18-128.1.6_2/fs/ext3/namei.c +--- linux-2.6.18-128.1.6_1/fs/ext3/namei.c 2009-08-13 19:07:07.000000000 +0530 ++++ linux-2.6.18-128.1.6_2/fs/ext3/namei.c 2009-08-13 19:10:43.000000000 +0530 +@@ -24,6 +24,7 @@ + * Theodore Ts'o, 2002 + */ + ++#include + #include + #include + #include +@@ -841,7 +842,7 @@ static inline int search_dirblock(struct + * The returned buffer_head has ->b_count elevated. The caller is expected + * to brelse() it when appropriate. + */ +-static struct buffer_head * ext3_find_entry (struct dentry *dentry, ++struct buffer_head * ext3_find_entry (struct dentry *dentry, + struct ext3_dir_entry_2 ** res_dir) + { + struct super_block * sb; +@@ -953,6 +954,7 @@ cleanup_and_exit: + brelse (bh_use[ra_ptr]); + return ret; + } ++EXPORT_SYMBOL(ext3_find_entry); + + #ifdef CONFIG_EXT3_INDEX + static struct buffer_head * ext3_dx_find_entry(struct dentry *dentry, +@@ -1489,7 +1491,7 @@ static int make_indexed_dir(handle_t *ha + * may not sleep between calling this and putting something into + * the entry, as someone else might have used it while you slept. + */ +-static int ext3_add_entry (handle_t *handle, struct dentry *dentry, ++int ext3_add_entry (handle_t *handle, struct dentry *dentry, + struct inode *inode) + { + struct inode *dir = dentry->d_parent->d_inode; +@@ -1542,6 +1544,7 @@ static int ext3_add_entry (handle_t *han + de->rec_len = cpu_to_le16(blocksize); + return add_dirent_to_buf(handle, dentry, inode, de, bh); + } ++EXPORT_SYMBOL(ext3_add_entry); + + #ifdef CONFIG_EXT3_INDEX + /* +@@ -1684,10 +1687,10 @@ cleanup: + * ext3_delete_entry deletes a directory entry by merging it with the + * previous entry + */ +-static int ext3_delete_entry (handle_t *handle, +- struct inode * dir, +- struct ext3_dir_entry_2 * de_del, +- struct buffer_head * bh) ++int ext3_delete_entry (handle_t *handle, ++ struct inode * dir, ++ struct ext3_dir_entry_2 * de_del, ++ struct buffer_head * bh) + { + struct ext3_dir_entry_2 * de, * pde; + int i; +@@ -1719,6 +1722,7 @@ static int ext3_delete_entry (handle_t * + } + return -ENOENT; + } ++EXPORT_SYMBOL(ext3_delete_entry); + + /* + * ext3_mark_inode_dirty is somewhat expensive, so unlike ext2 we +@@ -1774,6 +1778,26 @@ static struct inode * ext3_new_inode_wan + return ext3_new_inode(handle, dir, mode, inum); + } + ++struct inode * ext3_create_inode(handle_t *handle, struct inode * dir, int mode) ++{ ++ struct inode *inode; ++ ++ inode = ext3_new_inode(handle, dir, mode, 0); ++ if (!IS_ERR(inode)) { ++ if (S_ISCHR(mode) || S_ISBLK(mode) || S_ISFIFO(mode)) { ++#ifdef CONFIG_LDISKFS_FS_XATTR ++ inode->i_op = &ext3_special_inode_operations; ++#endif ++ } else { ++ inode->i_op = &ext3_file_inode_operations; ++ inode->i_fop = &ext3_file_operations; ++ ext3_set_aops(inode); ++ } ++ } ++ return inode; ++} ++EXPORT_SYMBOL(ext3_create_inode); ++ + /* + * By the time this is called, we already have created + * the directory cache entry for the new file, but it +@@ -1848,42 +1872,28 @@ retry: + return err; + } + +-static int ext3_mkdir(struct inode * dir, struct dentry * dentry, int mode) ++/* Initialize @inode as a subdirectory of @dir, and add the ++ * "." and ".." entries into the first directory block. */ ++int ext3_add_dot_dotdot(handle_t *handle, struct inode * dir, ++ struct inode *inode) + { +- handle_t *handle; +- struct inode * inode; + struct buffer_head * dir_block; + struct ext3_dir_entry_2 * de; +- int err, retries = 0; +- +- if (EXT3_DIR_LINK_MAX(dir)) +- return -EMLINK; ++ int err = 0; + +-retry: +- handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS(dir->i_sb) + +- EXT3_INDEX_EXTRA_TRANS_BLOCKS + 3 + +- 2*EXT3_QUOTA_INIT_BLOCKS(dir->i_sb)); + if (IS_ERR(handle)) + return PTR_ERR(handle); + + if (IS_DIRSYNC(dir)) + handle->h_sync = 1; + +- inode = ext3_new_inode_wantedi (handle, dir, S_IFDIR | mode, dentry); +- err = PTR_ERR(inode); +- if (IS_ERR(inode)) +- goto out_stop; +- + inode->i_op = &ext3_dir_inode_operations; + inode->i_fop = &ext3_dir_operations; + inode->i_size = EXT3_I(inode)->i_disksize = inode->i_sb->s_blocksize; + dir_block = ext3_bread (handle, inode, 0, 1, &err); +- if (!dir_block) { +- drop_nlink(inode); /* is this nlink == 0? */ +- ext3_mark_inode_dirty(handle, inode); +- iput (inode); +- goto out_stop; +- } ++ if (!dir_block) ++ goto get_out; ++ + BUFFER_TRACE(dir_block, "get_write_access"); + ext3_journal_get_write_access(handle, dir_block); + de = (struct ext3_dir_entry_2 *) dir_block->b_data; +@@ -1904,6 +1914,45 @@ retry: + ext3_journal_dirty_metadata(handle, dir_block); + brelse (dir_block); + ext3_mark_inode_dirty(handle, inode); ++ ++get_out: ++ return err; ++ ++} ++EXPORT_SYMBOL(ext3_add_dot_dotdot); ++ ++static int ext3_mkdir(struct inode * dir, struct dentry * dentry, int mode) ++{ ++ handle_t *handle; ++ struct inode * inode; ++ int err, retries = 0; ++ ++ if (EXT3_DIR_LINK_MAX(dir)) ++ return -EMLINK; ++ ++retry: ++ handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS(dir->i_sb) + ++ EXT3_INDEX_EXTRA_TRANS_BLOCKS + 3 + ++ 2*EXT3_QUOTA_INIT_BLOCKS(dir->i_sb)); ++ if (IS_ERR(handle)) ++ return PTR_ERR(handle); ++ ++ if (IS_DIRSYNC(dir)) ++ handle->h_sync = 1; ++ ++ inode = ext3_new_inode_wantedi (handle, dir, S_IFDIR | mode, dentry); ++ err = PTR_ERR(inode); ++ if (IS_ERR(inode)) ++ goto out_stop; ++ ++ err = ext3_add_dot_dotdot(handle, dir, inode); ++ if (err) { ++ inode->i_nlink = 0; ++ ext3_mark_inode_dirty(handle, inode); ++ iput (inode); ++ goto out_stop; ++ } ++ + err = ext3_add_entry (handle, dentry, inode); + if (err) { + inode->i_nlink = 0; +diff -rupN linux-2.6.18-128.1.6_1/include/linux/ext3_fs.h linux-2.6.18-128.1.6_2/include/linux/ext3_fs.h +--- linux-2.6.18-128.1.6_1/include/linux/ext3_fs.h 2009-08-13 19:07:07.000000000 +0530 ++++ linux-2.6.18-128.1.6_2/include/linux/ext3_fs.h 2009-08-13 19:14:07.000000000 +0530 +@@ -1076,6 +1076,10 @@ extern int ext3_group_extend(struct supe + ext3_fsblk_t n_blocks_count); + + /* super.c */ ++extern int ext3_xattr_set_handle(handle_t *handle, struct inode *inode, ++ int name_index, const char *name, ++ const void *value, size_t value_len, ++ int flags); + extern struct proc_dir_entry *proc_root_ext3; + extern int __init init_ext3_proc(void); + extern void exit_ext3_proc(void); +@@ -1107,6 +1111,19 @@ extern struct inode_operations ext3_file + extern const struct file_operations ext3_file_operations; + + /* namei.c */ ++extern struct inode *ext3_create_inode(handle_t *handle, ++ struct inode * dir, int mode); ++extern int ext3_add_entry(handle_t *handle, struct dentry *dentry, ++ struct inode *inode); ++extern int ext3_delete_entry(handle_t *handle, ++ struct inode * dir, ++ struct ext3_dir_entry_2 * de_del, ++ struct buffer_head * bh); ++extern struct buffer_head * ext3_find_entry(struct dentry *dentry, ++ struct ext3_dir_entry_2 ++ ** res_dir); ++extern int ext3_add_dot_dotdot(handle_t *handle, struct inode *dir, ++ struct inode *inode); + extern struct inode_operations ext3_dir_inode_operations; + extern struct inode_operations ext3_special_inode_operations; + + diff --git a/ldiskfs/kernel_patches/patches/ext3-pdir-fix.patch b/ldiskfs/kernel_patches/patches/ext3-pdir-fix.patch new file mode 100644 index 0000000..471ea3c --- /dev/null +++ b/ldiskfs/kernel_patches/patches/ext3-pdir-fix.patch @@ -0,0 +1,68 @@ +diff -rupN linux-2.6.18-128.1.6_1/fs/ext3/namei.c linux-2.6.18-128.1.6_2/fs/ext3/namei.c +--- linux-2.6.18-128.1.6_1/fs/ext3/namei.c 2009-08-13 19:27:12.000000000 +0530 ++++ linux-2.6.18-128.1.6_2/fs/ext3/namei.c 2009-08-13 19:33:34.000000000 +0530 +@@ -51,19 +51,25 @@ + #define NAMEI_RA_SIZE (NAMEI_RA_CHUNKS * NAMEI_RA_BLOCKS) + #define NAMEI_RA_INDEX(c,b) (((c) * NAMEI_RA_BLOCKS) + (b)) + +-static struct buffer_head *ext3_append(handle_t *handle, ++struct buffer_head *ext3_append(handle_t *handle, + struct inode *inode, + u32 *block, int *err) + { + struct buffer_head *bh; ++ struct ext3_inode_info *ei = EXT3_I(inode); ++ ++ /* with parallel dir operations all appends ++ * have to be serialized -bzzz */ ++ down(&ei->i_append_sem); + + *block = inode->i_size >> inode->i_sb->s_blocksize_bits; + +- if ((bh = ext3_bread(handle, inode, *block, 1, err))) { ++ bh = ext3_bread(handle, inode, *block, 1, err); ++ if (bh != NULL) { + inode->i_size += inode->i_sb->s_blocksize; +- EXT3_I(inode)->i_disksize = inode->i_size; +- ext3_journal_get_write_access(handle,bh); ++ ei->i_disksize = inode->i_size; + } ++ up(&ei->i_append_sem); + return bh; + } + +diff -rupN linux-2.6.18-128.1.6_1/fs/ext3/super.c linux-2.6.18-128.1.6_2/fs/ext3/super.c +--- linux-2.6.18-128.1.6_1/fs/ext3/super.c 2009-08-13 19:27:12.000000000 +0530 ++++ linux-2.6.18-128.1.6_2/fs/ext3/super.c 2009-08-13 19:27:40.000000000 +0530 +@@ -481,6 +481,9 @@ static struct inode *ext3_alloc_inode(st + ei->i_acl = EXT3_ACL_NOT_CACHED; + ei->i_default_acl = EXT3_ACL_NOT_CACHED; + #endif ++ dynlock_init(&ei->i_htree_lock); ++ sema_init(&ei->i_append_sem, 1); ++ + ei->i_block_alloc_info = NULL; + ei->vfs_inode.i_version = 1; + +diff -rupN linux-2.6.18-128.1.6_1/include/linux/ext3_fs_i.h linux-2.6.18-128.1.6_2/include/linux/ext3_fs_i.h +--- linux-2.6.18-128.1.6_1/include/linux/ext3_fs_i.h 2009-08-13 19:27:12.000000000 +0530 ++++ linux-2.6.18-128.1.6_2/include/linux/ext3_fs_i.h 2009-08-13 19:31:22.000000000 +0530 +@@ -16,6 +16,7 @@ + #ifndef _LINUX_EXT3_FS_I + #define _LINUX_EXT3_FS_I + ++#include + #include + #include + #include +@@ -104,6 +105,10 @@ struct ext3_inode_info { + /* block reservation info */ + struct ext3_block_alloc_info *i_block_alloc_info; + ++ /* following fields for parallel directory operations -bzzz */ ++ struct dynlock i_htree_lock; ++ struct semaphore i_append_sem; ++ + __u32 i_dir_start_lookup; + #ifdef CONFIG_EXT3_FS_XATTR + /* diff --git a/ldiskfs/kernel_patches/patches/ext4-dynlocks-2.6-rhel5.patch b/ldiskfs/kernel_patches/patches/ext4-dynlocks-2.6-rhel5.patch new file mode 100644 index 0000000..2a11baa --- /dev/null +++ b/ldiskfs/kernel_patches/patches/ext4-dynlocks-2.6-rhel5.patch @@ -0,0 +1,32 @@ +diff -rupN linux-2.6.27.21-0.1_1//fs/ext4/Makefile linux-2.6.27.21-0.1_2//fs/ext4/Makefile +--- linux-2.6.27.21-0.1_1//fs/ext4/Makefile 2009-08-21 15:12:51.000000000 +0530 ++++ linux-2.6.27.21-0.1_2//fs/ext4/Makefile 2009-08-21 15:13:23.000000000 +0530 +@@ -6,7 +6,7 @@ obj-$(CONFIG_EXT4DEV_FS) += ext4dev.o + + ext4dev-y := balloc.o bitmap.o dir.o file.o fsync.o ialloc.o inode.o iopen.o \ + ioctl.o namei.o super.o symlink.o hash.o resize.o extents.o \ +- ext4_jbd2.o migrate.o mballoc.o ++ ext4_jbd2.o migrate.o mballoc.o dynlocks.o + + ext4dev-$(CONFIG_EXT4DEV_FS_XATTR) += xattr.o xattr_user.o xattr_trusted.o + ext4dev-$(CONFIG_EXT4DEV_FS_POSIX_ACL) += acl.o +diff -rupN linux-2.6.27.21-0.1_1//fs/ext4/super.c linux-2.6.27.21-0.1_2//fs/ext4/super.c +--- linux-2.6.27.21-0.1_1//fs/ext4/super.c 2009-08-21 15:12:51.000000000 +0530 ++++ linux-2.6.27.21-0.1_2//fs/ext4/super.c 2009-08-21 15:18:18.000000000 +0530 +@@ -4126,6 +4126,7 @@ static int __init init_ext4_fs(void) + err = init_inodecache(); + if (err) + goto out1; ++ dynlock_cache_init(); + err = register_filesystem(&ext4_fs_type); + if (err) + goto out; +@@ -4149,6 +4150,7 @@ static void __exit exit_ext4_fs(void) + unregister_filesystem(&ext4_fs_type); + unregister_filesystem(&ext4dev_fs_type); + destroy_inodecache(); ++ dynlock_cache_exit(); + exit_ext4_xattr(); + exit_ext4_mballoc(); + remove_proc_entry("fs/ext4", NULL); + diff --git a/ldiskfs/kernel_patches/patches/ext4-dynlocks-common-sles11.patch b/ldiskfs/kernel_patches/patches/ext4-dynlocks-common-sles11.patch new file mode 100644 index 0000000..34dc2c8 --- /dev/null +++ b/ldiskfs/kernel_patches/patches/ext4-dynlocks-common-sles11.patch @@ -0,0 +1,280 @@ +diff -rupN 2.6.27.21/fs/ext4/dynlocks.c 2.6.27.21_1//fs/ext4/dynlocks.c +--- 2.6.27.21/fs/ext4/dynlocks.c 1970-01-01 05:30:00.000000000 +0530 ++++ 2.6.27.21_1//fs/ext4/dynlocks.c 2009-08-23 10:39:59.000000000 +0530 +@@ -0,0 +1,238 @@ ++/* ++ * Dynamic Locks ++ * ++ * struct dynlock is lockspace ++ * one may request lock (exclusive or shared) for some value ++ * in that lockspace ++ * ++ */ ++ ++#include ++#include ++#include ++#include ++ ++#define DYNLOCK_HANDLE_MAGIC 0xd19a10c ++#define DYNLOCK_HANDLE_DEAD 0xd1956ee ++#define DYNLOCK_LIST_MAGIC 0x11ee91e6 ++ ++typedef struct kmem_cache kmem_cache_t; ++ ++static kmem_cache_t * dynlock_cachep = NULL; ++ ++struct dynlock_handle { ++ unsigned dh_magic; ++ struct list_head dh_list; ++ unsigned long dh_value; /* lock value */ ++ int dh_refcount; /* number of users */ ++ int dh_readers; ++ int dh_writers; ++ int dh_pid; /* holder of the lock */ ++ wait_queue_head_t dh_wait; ++}; ++ ++int __init dynlock_cache_init(void) ++{ ++ int rc = 0; ++ ++ printk(KERN_INFO "init dynlocks cache\n"); ++ dynlock_cachep = kmem_cache_create("dynlock_cache", ++ sizeof(struct dynlock_handle), ++ 0, ++ SLAB_HWCACHE_ALIGN, ++ NULL); ++ if (dynlock_cachep == NULL) { ++ printk(KERN_ERR "Not able to create dynlock cache"); ++ rc = -ENOMEM; ++ } ++ return rc; ++} ++ ++void __exit dynlock_cache_exit(void) ++{ ++ printk(KERN_INFO "exit dynlocks cache\n"); ++ kmem_cache_destroy(dynlock_cachep); ++} ++ ++/* ++ * dynlock_init ++ * ++ * initialize lockspace ++ * ++ */ ++void dynlock_init(struct dynlock *dl) ++{ ++ spin_lock_init(&dl->dl_list_lock); ++ INIT_LIST_HEAD(&dl->dl_list); ++ dl->dl_magic = DYNLOCK_LIST_MAGIC; ++} ++EXPORT_SYMBOL(dynlock_init); ++ ++/* ++ * dynlock_lock ++ * ++ * acquires lock (exclusive or shared) in specified lockspace ++ * each lock in lockspace is allocated separately, so user have ++ * to specify GFP flags. ++ * routine returns pointer to lock. this pointer is intended to ++ * be passed to dynlock_unlock ++ * ++ */ ++struct dynlock_handle *dynlock_lock(struct dynlock *dl, unsigned long value, ++ enum dynlock_type lt, gfp_t gfp) ++{ ++ struct dynlock_handle *nhl = NULL; ++ struct dynlock_handle *hl; ++ ++ BUG_ON(dl == NULL); ++ BUG_ON(dl->dl_magic != DYNLOCK_LIST_MAGIC); ++ ++repeat: ++ /* find requested lock in lockspace */ ++ spin_lock(&dl->dl_list_lock); ++ BUG_ON(dl->dl_list.next == NULL); ++ BUG_ON(dl->dl_list.prev == NULL); ++ list_for_each_entry(hl, &dl->dl_list, dh_list) { ++ BUG_ON(hl->dh_list.next == NULL); ++ BUG_ON(hl->dh_list.prev == NULL); ++ BUG_ON(hl->dh_magic != DYNLOCK_HANDLE_MAGIC); ++ if (hl->dh_value == value) { ++ /* lock is found */ ++ if (nhl) { ++ /* someone else just allocated ++ * lock we didn't find and just created ++ * so, we drop our lock ++ */ ++ kmem_cache_free(dynlock_cachep, nhl); ++ nhl = NULL; ++ } ++ hl->dh_refcount++; ++ goto found; ++ } ++ } ++ /* lock not found */ ++ if (nhl) { ++ /* we already have allocated lock. use it */ ++ hl = nhl; ++ nhl = NULL; ++ list_add(&hl->dh_list, &dl->dl_list); ++ goto found; ++ } ++ spin_unlock(&dl->dl_list_lock); ++ ++ /* lock not found and we haven't allocated lock yet. allocate it */ ++ nhl = kmem_cache_alloc(dynlock_cachep, gfp); ++ if (nhl == NULL) ++ return NULL; ++ nhl->dh_refcount = 1; ++ nhl->dh_value = value; ++ nhl->dh_readers = 0; ++ nhl->dh_writers = 0; ++ nhl->dh_magic = DYNLOCK_HANDLE_MAGIC; ++ init_waitqueue_head(&nhl->dh_wait); ++ ++ /* while lock is being allocated, someone else may allocate it ++ * and put onto to list. check this situation ++ */ ++ goto repeat; ++ ++found: ++ if (lt == DLT_WRITE) { ++ /* exclusive lock: user don't want to share lock at all ++ * NOTE: one process may take the same lock several times ++ * this functionaly is useful for rename operations */ ++ while ((hl->dh_writers && hl->dh_pid != current->pid) || ++ hl->dh_readers) { ++ spin_unlock(&dl->dl_list_lock); ++ wait_event(hl->dh_wait, ++ hl->dh_writers == 0 && hl->dh_readers == 0); ++ spin_lock(&dl->dl_list_lock); ++ } ++ hl->dh_writers++; ++ } else { ++ /* shared lock: user do not want to share lock with writer */ ++ while (hl->dh_writers) { ++ spin_unlock(&dl->dl_list_lock); ++ wait_event(hl->dh_wait, hl->dh_writers == 0); ++ spin_lock(&dl->dl_list_lock); ++ } ++ hl->dh_readers++; ++ } ++ hl->dh_pid = current->pid; ++ spin_unlock(&dl->dl_list_lock); ++ ++ return hl; ++} ++EXPORT_SYMBOL(dynlock_lock); ++ ++ ++/* ++ * dynlock_unlock ++ * ++ * user have to specify lockspace (dl) and pointer to lock structure ++ * returned by dynlock_lock() ++ * ++ */ ++void dynlock_unlock(struct dynlock *dl, struct dynlock_handle *hl) ++{ ++ int wakeup = 0; ++ ++ BUG_ON(dl == NULL); ++ BUG_ON(hl == NULL); ++ BUG_ON(dl->dl_magic != DYNLOCK_LIST_MAGIC); ++ ++ if (hl->dh_magic != DYNLOCK_HANDLE_MAGIC) ++ printk(KERN_EMERG "wrong lock magic: %#x\n", hl->dh_magic); ++ ++ BUG_ON(hl->dh_magic != DYNLOCK_HANDLE_MAGIC); ++ BUG_ON(hl->dh_writers != 0 && current->pid != hl->dh_pid); ++ ++ spin_lock(&dl->dl_list_lock); ++ if (hl->dh_writers) { ++ BUG_ON(hl->dh_readers != 0); ++ hl->dh_writers--; ++ if (hl->dh_writers == 0) ++ wakeup = 1; ++ } else if (hl->dh_readers) { ++ hl->dh_readers--; ++ if (hl->dh_readers == 0) ++ wakeup = 1; ++ } else { ++ BUG(); ++ } ++ if (wakeup) { ++ hl->dh_pid = 0; ++ wake_up(&hl->dh_wait); ++ } ++ if (--(hl->dh_refcount) == 0) { ++ hl->dh_magic = DYNLOCK_HANDLE_DEAD; ++ list_del(&hl->dh_list); ++ kmem_cache_free(dynlock_cachep, hl); ++ } ++ spin_unlock(&dl->dl_list_lock); ++} ++EXPORT_SYMBOL(dynlock_unlock); ++ ++int dynlock_is_locked(struct dynlock *dl, unsigned long value) ++{ ++ struct dynlock_handle *hl; ++ int result = 0; ++ ++ /* find requested lock in lockspace */ ++ spin_lock(&dl->dl_list_lock); ++ BUG_ON(dl->dl_list.next == NULL); ++ BUG_ON(dl->dl_list.prev == NULL); ++ list_for_each_entry(hl, &dl->dl_list, dh_list) { ++ BUG_ON(hl->dh_list.next == NULL); ++ BUG_ON(hl->dh_list.prev == NULL); ++ BUG_ON(hl->dh_magic != DYNLOCK_HANDLE_MAGIC); ++ if (hl->dh_value == value && hl->dh_pid == current->pid) { ++ /* lock is found */ ++ result = 1; ++ break; ++ } ++ } ++ spin_unlock(&dl->dl_list_lock); ++ return result; ++} ++EXPORT_SYMBOL(dynlock_is_locked); +diff -rupN 2.6.27.21/include/linux/dynlocks.h 2.6.27.21_1//include/linux/dynlocks.h +--- 2.6.27.21/include/linux/dynlocks.h 1970-01-01 05:30:00.000000000 +0530 ++++ 2.6.27.21_1//include/linux/dynlocks.h 2009-08-23 10:40:07.000000000 +0530 +@@ -0,0 +1,34 @@ ++#ifndef _LINUX_DYNLOCKS_H ++#define _LINUX_DYNLOCKS_H ++ ++#include ++#include ++ ++struct dynlock_handle; ++ ++/* ++ * lock's namespace: ++ * - list of locks ++ * - lock to protect this list ++ */ ++struct dynlock { ++ unsigned dl_magic; ++ struct list_head dl_list; ++ spinlock_t dl_list_lock; ++}; ++ ++enum dynlock_type { ++ DLT_WRITE, ++ DLT_READ ++}; ++ ++int dynlock_cache_init(void); ++void dynlock_cache_exit(void); ++void dynlock_init(struct dynlock *dl); ++struct dynlock_handle *dynlock_lock(struct dynlock *dl, unsigned long value, ++ enum dynlock_type lt, gfp_t gfp); ++void dynlock_unlock(struct dynlock *dl, struct dynlock_handle *lock); ++int dynlock_is_locked(struct dynlock *dl, unsigned long value); ++ ++#endif ++ diff --git a/ldiskfs/kernel_patches/patches/ext4-dynlocks-common.patch b/ldiskfs/kernel_patches/patches/ext4-dynlocks-common.patch new file mode 100644 index 0000000..e360662 --- /dev/null +++ b/ldiskfs/kernel_patches/patches/ext4-dynlocks-common.patch @@ -0,0 +1,278 @@ +diff -rupN linux-2.6.18-128.1.6_1/fs/ext4/dynlocks.c linux-2.6.18-128.1.6_2/fs/ext4/dynlocks.c +--- linux-2.6.18-128.1.6_1/fs/ext4/dynlocks.c 1970-01-01 05:30:00.000000000 +0530 ++++ linux-2.6.18-128.1.6_2/fs/ext4/dynlocks.c 2009-08-13 20:42:59.000000000 +0530 +@@ -0,0 +1,236 @@ ++/* ++ * Dynamic Locks ++ * ++ * struct dynlock is lockspace ++ * one may request lock (exclusive or shared) for some value ++ * in that lockspace ++ * ++ */ ++ ++#include ++#include ++#include ++#include ++ ++#define DYNLOCK_HANDLE_MAGIC 0xd19a10c ++#define DYNLOCK_HANDLE_DEAD 0xd1956ee ++#define DYNLOCK_LIST_MAGIC 0x11ee91e6 ++ ++static kmem_cache_t * dynlock_cachep = NULL; ++ ++struct dynlock_handle { ++ unsigned dh_magic; ++ struct list_head dh_list; ++ unsigned long dh_value; /* lock value */ ++ int dh_refcount; /* number of users */ ++ int dh_readers; ++ int dh_writers; ++ int dh_pid; /* holder of the lock */ ++ wait_queue_head_t dh_wait; ++}; ++ ++int __init dynlock_cache_init(void) ++{ ++ int rc = 0; ++ ++ printk(KERN_INFO "init dynlocks cache\n"); ++ dynlock_cachep = kmem_cache_create("dynlock_cache", ++ sizeof(struct dynlock_handle), ++ 0, ++ SLAB_HWCACHE_ALIGN, ++ NULL, NULL); ++ if (dynlock_cachep == NULL) { ++ printk(KERN_ERR "Not able to create dynlock cache"); ++ rc = -ENOMEM; ++ } ++ return rc; ++} ++ ++void __exit dynlock_cache_exit(void) ++{ ++ printk(KERN_INFO "exit dynlocks cache\n"); ++ kmem_cache_destroy(dynlock_cachep); ++} ++ ++/* ++ * dynlock_init ++ * ++ * initialize lockspace ++ * ++ */ ++void dynlock_init(struct dynlock *dl) ++{ ++ spin_lock_init(&dl->dl_list_lock); ++ INIT_LIST_HEAD(&dl->dl_list); ++ dl->dl_magic = DYNLOCK_LIST_MAGIC; ++} ++EXPORT_SYMBOL(dynlock_init); ++ ++/* ++ * dynlock_lock ++ * ++ * acquires lock (exclusive or shared) in specified lockspace ++ * each lock in lockspace is allocated separately, so user have ++ * to specify GFP flags. ++ * routine returns pointer to lock. this pointer is intended to ++ * be passed to dynlock_unlock ++ * ++ */ ++struct dynlock_handle *dynlock_lock(struct dynlock *dl, unsigned long value, ++ enum dynlock_type lt, gfp_t gfp) ++{ ++ struct dynlock_handle *nhl = NULL; ++ struct dynlock_handle *hl; ++ ++ BUG_ON(dl == NULL); ++ BUG_ON(dl->dl_magic != DYNLOCK_LIST_MAGIC); ++ ++repeat: ++ /* find requested lock in lockspace */ ++ spin_lock(&dl->dl_list_lock); ++ BUG_ON(dl->dl_list.next == NULL); ++ BUG_ON(dl->dl_list.prev == NULL); ++ list_for_each_entry(hl, &dl->dl_list, dh_list) { ++ BUG_ON(hl->dh_list.next == NULL); ++ BUG_ON(hl->dh_list.prev == NULL); ++ BUG_ON(hl->dh_magic != DYNLOCK_HANDLE_MAGIC); ++ if (hl->dh_value == value) { ++ /* lock is found */ ++ if (nhl) { ++ /* someone else just allocated ++ * lock we didn't find and just created ++ * so, we drop our lock ++ */ ++ kmem_cache_free(dynlock_cachep, nhl); ++ nhl = NULL; ++ } ++ hl->dh_refcount++; ++ goto found; ++ } ++ } ++ /* lock not found */ ++ if (nhl) { ++ /* we already have allocated lock. use it */ ++ hl = nhl; ++ nhl = NULL; ++ list_add(&hl->dh_list, &dl->dl_list); ++ goto found; ++ } ++ spin_unlock(&dl->dl_list_lock); ++ ++ /* lock not found and we haven't allocated lock yet. allocate it */ ++ nhl = kmem_cache_alloc(dynlock_cachep, gfp); ++ if (nhl == NULL) ++ return NULL; ++ nhl->dh_refcount = 1; ++ nhl->dh_value = value; ++ nhl->dh_readers = 0; ++ nhl->dh_writers = 0; ++ nhl->dh_magic = DYNLOCK_HANDLE_MAGIC; ++ init_waitqueue_head(&nhl->dh_wait); ++ ++ /* while lock is being allocated, someone else may allocate it ++ * and put onto to list. check this situation ++ */ ++ goto repeat; ++ ++found: ++ if (lt == DLT_WRITE) { ++ /* exclusive lock: user don't want to share lock at all ++ * NOTE: one process may take the same lock several times ++ * this functionaly is useful for rename operations */ ++ while ((hl->dh_writers && hl->dh_pid != current->pid) || ++ hl->dh_readers) { ++ spin_unlock(&dl->dl_list_lock); ++ wait_event(hl->dh_wait, ++ hl->dh_writers == 0 && hl->dh_readers == 0); ++ spin_lock(&dl->dl_list_lock); ++ } ++ hl->dh_writers++; ++ } else { ++ /* shared lock: user do not want to share lock with writer */ ++ while (hl->dh_writers) { ++ spin_unlock(&dl->dl_list_lock); ++ wait_event(hl->dh_wait, hl->dh_writers == 0); ++ spin_lock(&dl->dl_list_lock); ++ } ++ hl->dh_readers++; ++ } ++ hl->dh_pid = current->pid; ++ spin_unlock(&dl->dl_list_lock); ++ ++ return hl; ++} ++EXPORT_SYMBOL(dynlock_lock); ++ ++ ++/* ++ * dynlock_unlock ++ * ++ * user have to specify lockspace (dl) and pointer to lock structure ++ * returned by dynlock_lock() ++ * ++ */ ++void dynlock_unlock(struct dynlock *dl, struct dynlock_handle *hl) ++{ ++ int wakeup = 0; ++ ++ BUG_ON(dl == NULL); ++ BUG_ON(hl == NULL); ++ BUG_ON(dl->dl_magic != DYNLOCK_LIST_MAGIC); ++ ++ if (hl->dh_magic != DYNLOCK_HANDLE_MAGIC) ++ printk(KERN_EMERG "wrong lock magic: %#x\n", hl->dh_magic); ++ ++ BUG_ON(hl->dh_magic != DYNLOCK_HANDLE_MAGIC); ++ BUG_ON(hl->dh_writers != 0 && current->pid != hl->dh_pid); ++ ++ spin_lock(&dl->dl_list_lock); ++ if (hl->dh_writers) { ++ BUG_ON(hl->dh_readers != 0); ++ hl->dh_writers--; ++ if (hl->dh_writers == 0) ++ wakeup = 1; ++ } else if (hl->dh_readers) { ++ hl->dh_readers--; ++ if (hl->dh_readers == 0) ++ wakeup = 1; ++ } else { ++ BUG(); ++ } ++ if (wakeup) { ++ hl->dh_pid = 0; ++ wake_up(&hl->dh_wait); ++ } ++ if (--(hl->dh_refcount) == 0) { ++ hl->dh_magic = DYNLOCK_HANDLE_DEAD; ++ list_del(&hl->dh_list); ++ kmem_cache_free(dynlock_cachep, hl); ++ } ++ spin_unlock(&dl->dl_list_lock); ++} ++EXPORT_SYMBOL(dynlock_unlock); ++ ++int dynlock_is_locked(struct dynlock *dl, unsigned long value) ++{ ++ struct dynlock_handle *hl; ++ int result = 0; ++ ++ /* find requested lock in lockspace */ ++ spin_lock(&dl->dl_list_lock); ++ BUG_ON(dl->dl_list.next == NULL); ++ BUG_ON(dl->dl_list.prev == NULL); ++ list_for_each_entry(hl, &dl->dl_list, dh_list) { ++ BUG_ON(hl->dh_list.next == NULL); ++ BUG_ON(hl->dh_list.prev == NULL); ++ BUG_ON(hl->dh_magic != DYNLOCK_HANDLE_MAGIC); ++ if (hl->dh_value == value && hl->dh_pid == current->pid) { ++ /* lock is found */ ++ result = 1; ++ break; ++ } ++ } ++ spin_unlock(&dl->dl_list_lock); ++ return result; ++} ++EXPORT_SYMBOL(dynlock_is_locked); +diff -rupN linux-2.6.18-128.1.6_1/include/linux/dynlocks.h linux-2.6.18-128.1.6_2/include/linux/dynlocks.h +--- linux-2.6.18-128.1.6_1/include/linux/dynlocks.h 1970-01-01 05:30:00.000000000 +0530 ++++ linux-2.6.18-128.1.6_2/include/linux/dynlocks.h 2009-08-13 20:43:18.000000000 +0530 +@@ -0,0 +1,34 @@ ++#ifndef _LINUX_DYNLOCKS_H ++#define _LINUX_DYNLOCKS_H ++ ++#include ++#include ++ ++struct dynlock_handle; ++ ++/* ++ * lock's namespace: ++ * - list of locks ++ * - lock to protect this list ++ */ ++struct dynlock { ++ unsigned dl_magic; ++ struct list_head dl_list; ++ spinlock_t dl_list_lock; ++}; ++ ++enum dynlock_type { ++ DLT_WRITE, ++ DLT_READ ++}; ++ ++int dynlock_cache_init(void); ++void dynlock_cache_exit(void); ++void dynlock_init(struct dynlock *dl); ++struct dynlock_handle *dynlock_lock(struct dynlock *dl, unsigned long value, ++ enum dynlock_type lt, gfp_t gfp); ++void dynlock_unlock(struct dynlock *dl, struct dynlock_handle *lock); ++int dynlock_is_locked(struct dynlock *dl, unsigned long value); ++ ++#endif ++ diff --git a/ldiskfs/kernel_patches/patches/ext4-hash-indexed-dir-dotdot-update.patch b/ldiskfs/kernel_patches/patches/ext4-hash-indexed-dir-dotdot-update.patch new file mode 100644 index 0000000..d354f89 --- /dev/null +++ b/ldiskfs/kernel_patches/patches/ext4-hash-indexed-dir-dotdot-update.patch @@ -0,0 +1,87 @@ +Index: linux-stage/fs/ext4/namei.c +=================================================================== +--- linux-stage.orig/fs/ext4/namei.c 2009-08-10 22:44:33.000000000 +0800 ++++ linux-stage/fs/ext4/namei.c 2009-08-10 22:48:22.000000000 +0800 +@@ -1493,6 +1493,72 @@ + return add_dirent_to_buf(handle, dentry, inode, de, bh); + } + ++/* update ".." for hash-indexed directory, split the item "." if necessary */ ++static int ext4_update_dotdot(handle_t *handle, struct dentry *dentry, ++ struct inode *inode) ++{ ++ struct inode * dir = dentry->d_parent->d_inode; ++ struct buffer_head * dir_block; ++ struct ext4_dir_entry_2 * de; ++ int len, journal = 0, err = 0; ++ ++ if (IS_ERR(handle)) ++ return PTR_ERR(handle); ++ ++ if (IS_DIRSYNC(dir)) ++ handle->h_sync = 1; ++ ++ dir_block = ext4_bread(handle, dir, 0, 0, &err); ++ if (!dir_block) ++ goto out; ++ ++ de = (struct ext4_dir_entry_2 *)dir_block->b_data; ++ /* the first item must be "." */ ++ assert(de->name_len == 1 && de->name[0] == '.'); ++ len = le16_to_cpu(de->rec_len); ++ assert(len >= EXT4_DIR_REC_LEN(1)); ++ if (len > EXT4_DIR_REC_LEN(1)) { ++ BUFFER_TRACE(dir_block, "get_write_access"); ++ err = ext4_journal_get_write_access(handle, dir_block); ++ if (err) ++ goto out_journal; ++ ++ journal = 1; ++ de->rec_len = cpu_to_le16(EXT4_DIR_REC_LEN(1)); ++ } ++ ++ len -= EXT4_DIR_REC_LEN(1); ++ assert(len == 0 || len >= EXT4_DIR_REC_LEN(2)); ++ de = (struct ext4_dir_entry_2 *) ++ ((char *) de + le16_to_cpu(de->rec_len)); ++ if (!journal) { ++ BUFFER_TRACE(dir_block, "get_write_access"); ++ err = ext4_journal_get_write_access(handle, dir_block); ++ if (err) ++ goto out_journal; ++ } ++ ++ de->inode = cpu_to_le32(inode->i_ino); ++ if (len > 0) ++ de->rec_len = cpu_to_le16(len); ++ else ++ assert(le16_to_cpu(de->rec_len) >= EXT4_DIR_REC_LEN(2)); ++ de->name_len = 2; ++ strcpy (de->name, ".."); ++ ext4_set_de_type(dir->i_sb, de, S_IFDIR); ++ ++out_journal: ++ if (journal) { ++ BUFFER_TRACE(dir_block, "call ext4_journal_dirty_metadata"); ++ err = ext4_journal_dirty_metadata(handle, dir_block); ++ ext4_mark_inode_dirty(handle, dir); ++ } ++ brelse (dir_block); ++ ++out: ++ return err; ++} ++ + /* + * ext4_add_entry() + * +@@ -1521,6 +1587,9 @@ + if (!dentry->d_name.len) + return -EINVAL; + if (is_dx(dir)) { ++ if (dentry->d_name.len == 2 && ++ memcmp(dentry->d_name.name, "..", 2) == 0) ++ return ext4_update_dotdot(handle, dentry, inode); + retval = ext4_dx_add_entry(handle, dentry, inode); + if (!retval || (retval != ERR_BAD_DX_DIR)) + return retval; diff --git a/ldiskfs/kernel_patches/patches/ext4-osd-iam-exports.patch b/ldiskfs/kernel_patches/patches/ext4-osd-iam-exports.patch new file mode 100644 index 0000000..6b65eb0 --- /dev/null +++ b/ldiskfs/kernel_patches/patches/ext4-osd-iam-exports.patch @@ -0,0 +1,64 @@ +diff -rupN 2.6.27.21_2/fs/ext4/ext4.h 2.6.27.21_3/fs/ext4/ext4.h +--- 2.6.27.21_2/fs/ext4/ext4.h 2009-07-17 12:19:59.000000000 +0530 ++++ 2.6.27.21_3/fs/ext4/ext4.h 2009-07-17 12:38:59.000000000 +0530 +@@ -1181,6 +1181,9 @@ extern int ext4_orphan_add(handle_t *, s + extern int ext4_orphan_del(handle_t *, struct inode *); + extern int ext4_htree_fill_tree(struct file *dir_file, __u32 start_hash, + __u32 start_minor_hash, __u32 *next_hash); ++extern struct buffer_head *ext4_append(handle_t *handle, ++ struct inode *inode, ++ ext4_lblk_t *block, int *err); + + /* resize.c */ + extern int ext4_group_add(struct super_block *sb, +diff -rupN 2.6.27.21_2/fs/ext4/hash.c 2.6.27.21_3/fs/ext4/hash.c +--- 2.6.27.21_2/fs/ext4/hash.c 2009-07-17 12:12:56.000000000 +0530 ++++ 2.6.27.21_3/fs/ext4/hash.c 2009-07-17 12:40:22.000000000 +0530 +@@ -9,6 +9,7 @@ + * License. + */ + ++#include + #include + #include + #include +@@ -206,3 +207,4 @@ int ext4fs_dirhash(const char *name, int + hinfo->minor_hash = minor_hash; + return 0; + } ++EXPORT_SYMBOL(ext4fs_dirhash); +diff -rupN 2.6.27.21_2/fs/ext4/namei.c 2.6.27.21_3/fs/ext4/namei.c +--- 2.6.27.21_2/fs/ext4/namei.c 2009-07-17 12:23:51.000000000 +0530 ++++ 2.6.27.21_3/fs/ext4/namei.c 2009-07-17 12:37:59.000000000 +0530 +@@ -51,9 +51,9 @@ + #define NAMEI_RA_SIZE (NAMEI_RA_CHUNKS * NAMEI_RA_BLOCKS) + #define NAMEI_RA_INDEX(c,b) (((c) * NAMEI_RA_BLOCKS) + (b)) + +-static struct buffer_head *ext4_append(handle_t *handle, +- struct inode *inode, +- ext4_lblk_t *block, int *err) ++struct buffer_head *ext4_append(handle_t *handle, ++ struct inode *inode, ++ ext4_lblk_t *block, int *err) + { + struct buffer_head *bh; + struct ext4_inode_info *ei = EXT4_I(inode); +@@ -72,6 +72,7 @@ static struct buffer_head *ext4_append(h + up(&ei->i_append_sem); + return bh; + } ++EXPORT_SYMBOL(ext4_append); + + #ifndef assert + #define assert(test) J_ASSERT(test) +diff -rupN 2.6.27.21_2/fs/ext4/super.c 2.6.27.21_3/fs/ext4/super.c +--- 2.6.27.21_2/fs/ext4/super.c 2009-07-17 12:12:57.000000000 +0530 ++++ 2.6.27.21_3/fs/ext4/super.c 2009-07-17 12:40:52.000000000 +0530 +@@ -377,6 +377,7 @@ void __ext4_std_error(struct super_block + + ext4_handle_error(sb); + } ++EXPORT_SYMBOL(__ext4_std_error); + + /* + * ext4_abort is a much stronger failure handler than ext4_error. The diff --git a/ldiskfs/kernel_patches/patches/ext4-osd-iop-common-sles11.patch b/ldiskfs/kernel_patches/patches/ext4-osd-iop-common-sles11.patch new file mode 100644 index 0000000..7e9d654 --- /dev/null +++ b/ldiskfs/kernel_patches/patches/ext4-osd-iop-common-sles11.patch @@ -0,0 +1,237 @@ +diff -rupN linux-2.6.27.21-0.1_1//fs/ext4/ext4.h linux-2.6.27.21-0.1_2//fs/ext4/ext4.h +--- linux-2.6.27.21-0.1_1//fs/ext4/ext4.h 2009-08-24 15:32:00.000000000 +0530 ++++ linux-2.6.27.21-0.1_2//fs/ext4/ext4.h 2009-08-24 15:32:55.000000000 +0530 +@@ -1171,6 +1171,18 @@ extern int ext4_fiemap(struct inode *, s + /* migrate.c */ + extern int ext4_ext_migrate(struct inode *); + /* namei.c */ ++extern struct inode *ext4_create_inode(handle_t *handle, ++ struct inode * dir, int mode); ++extern int ext4_add_entry(handle_t *handle, struct dentry *dentry, ++ struct inode *inode); ++extern int ext4_delete_entry(handle_t *handle, struct inode * dir, ++ struct ext4_dir_entry_2 * de_del, ++ struct buffer_head * bh); ++extern struct buffer_head * ext4_find_entry (struct inode *dir, ++ const struct qstr *d_name, ++ struct ext4_dir_entry_2 ** res_dir); ++extern int ext4_add_dot_dotdot(handle_t *handle, struct inode *dir, ++ struct inode *inode); + extern int ext4_orphan_add(handle_t *, struct inode *); + extern int ext4_orphan_del(handle_t *, struct inode *); + extern int ext4_htree_fill_tree(struct file *dir_file, __u32 start_hash, +diff -rupN linux-2.6.27.21-0.1_1//fs/ext4/namei.c linux-2.6.27.21-0.1_2//fs/ext4/namei.c +--- linux-2.6.27.21-0.1_1//fs/ext4/namei.c 2009-08-24 15:32:00.000000000 +0530 ++++ linux-2.6.27.21-0.1_2//fs/ext4/namei.c 2009-08-24 15:43:56.000000000 +0530 +@@ -24,6 +24,7 @@ + * Theodore Ts'o, 2002 + */ + ++#include + #include + #include + #include +@@ -882,9 +883,9 @@ static inline int search_dirblock(struct + * The returned buffer_head has ->b_count elevated. The caller is expected + * to brelse() it when appropriate. + */ +-static struct buffer_head * ext4_find_entry (struct inode *dir, +- const struct qstr *d_name, +- struct ext4_dir_entry_2 ** res_dir) ++struct buffer_head * ext4_find_entry (struct inode *dir, ++ const struct qstr *d_name, ++ struct ext4_dir_entry_2 ** res_dir) + { + struct super_block *sb; + struct buffer_head *bh_use[NAMEI_RA_SIZE]; +@@ -991,6 +992,7 @@ cleanup_and_exit: + brelse(bh_use[ra_ptr]); + return ret; + } ++EXPORT_SYMBOL(ext4_find_entry); + + static struct buffer_head * ext4_dx_find_entry(struct inode *dir, const struct qstr *d_name, + struct ext4_dir_entry_2 **res_dir, int *err) +@@ -1511,8 +1513,8 @@ static int make_indexed_dir(handle_t *ha + * may not sleep between calling this and putting something into + * the entry, as someone else might have used it while you slept. + */ +-static int ext4_add_entry(handle_t *handle, struct dentry *dentry, +- struct inode *inode) ++int ext4_add_entry(handle_t *handle, struct dentry *dentry, ++ struct inode *inode) + { + struct inode *dir = dentry->d_parent->d_inode; + struct buffer_head *bh; +@@ -1557,6 +1559,7 @@ static int ext4_add_entry(handle_t *hand + de->rec_len = ext4_rec_len_to_disk(blocksize); + return add_dirent_to_buf(handle, dentry, inode, de, bh); + } ++EXPORT_SYMBOL(ext4_add_entry); + + /* + * Returns 0 for success, or a negative error value +@@ -1699,10 +1702,10 @@ cleanup: + * ext4_delete_entry deletes a directory entry by merging it with the + * previous entry + */ +-static int ext4_delete_entry(handle_t *handle, +- struct inode *dir, +- struct ext4_dir_entry_2 *de_del, +- struct buffer_head *bh) ++int ext4_delete_entry(handle_t *handle, ++ struct inode *dir, ++ struct ext4_dir_entry_2 *de_del, ++ struct buffer_head *bh) + { + struct ext4_dir_entry_2 *de, *pde; + int i; +@@ -1733,7 +1736,7 @@ static int ext4_delete_entry(handle_t *h + } + return -ENOENT; + } +- ++EXPORT_SYMBOL(ext4_delete_entry); + /* + * DIR_NLINK feature is set if 1) nlinks > EXT4_LINK_MAX or 2) nlinks == 2, + * since this indicates that nlinks count was previously 1. +@@ -1796,6 +1799,26 @@ static unsigned ext4_dentry_goal(struct + return inum; + } + ++struct inode * ext4_create_inode(handle_t *handle, struct inode * dir, int mode) ++{ ++ struct inode *inode; ++ ++ inode = ext4_new_inode(handle, dir, mode); ++ if (!IS_ERR(inode)) { ++ if (S_ISCHR(mode) || S_ISBLK(mode) || S_ISFIFO(mode)) { ++#ifdef CONFIG_LDISKFS_FS_XATTR ++ inode->i_op = &ext4_special_inode_operations; ++#endif ++ } else { ++ inode->i_op = &ext4_file_inode_operations; ++ inode->i_fop = &ext4_file_operations; ++ ext4_set_aops(inode); ++ } ++ } ++ return inode; ++} ++EXPORT_SYMBOL(ext4_create_inode); ++ + /* + * By the time this is called, we already have created + * the directory cache entry for the new file, but it +@@ -1872,51 +1895,43 @@ retry: + return err; + } + +-static int ext4_mkdir(struct inode *dir, struct dentry *dentry, int mode) ++/* Initialize @inode as a subdirectory of @dir, and add the ++ * "." and ".." entries into the first directory block. */ ++int ext4_add_dot_dotdot(handle_t *handle, struct inode * dir, ++ struct inode *inode) + { +- handle_t *handle; +- struct inode *inode; +- struct buffer_head *dir_block; +- struct ext4_dir_entry_2 *de; +- int err, retries = 0; +- +- if (EXT4_DIR_LINK_MAX(dir)) +- return -EMLINK; ++ struct buffer_head * dir_block; ++ struct ext4_dir_entry_2 * de; ++ int err = 0; + +-retry: +- handle = ext4_journal_start(dir, EXT4_DATA_TRANS_BLOCKS(dir->i_sb) + +- EXT4_INDEX_EXTRA_TRANS_BLOCKS + 3 + +- 2*EXT4_QUOTA_INIT_BLOCKS(dir->i_sb)); + if (IS_ERR(handle)) + return PTR_ERR(handle); + + if (IS_DIRSYNC(dir)) + handle->h_sync = 1; + +- inode = ext4_new_inode_goal(handle, dir, S_IFDIR | mode, +- ext4_dentry_goal(dir->i_sb, dentry)); +- err = PTR_ERR(inode); +- if (IS_ERR(inode)) +- goto out_stop; +- + inode->i_op = &ext4_dir_inode_operations; + inode->i_fop = &ext4_dir_operations; + inode->i_size = EXT4_I(inode)->i_disksize = inode->i_sb->s_blocksize; +- dir_block = ext4_bread(handle, inode, 0, 1, &err); +- if (!dir_block) +- goto out_clear_inode; ++ dir_block = ext4_bread (handle, inode, 0, 1, &err); ++ if (!dir_block) { ++ clear_nlink(inode); ++ ext4_mark_inode_dirty(handle, inode); ++ iput (inode); ++ goto get_out; ++ } + BUFFER_TRACE(dir_block, "get_write_access"); + ext4_journal_get_write_access(handle, dir_block); + de = (struct ext4_dir_entry_2 *) dir_block->b_data; + de->inode = cpu_to_le32(inode->i_ino); + de->name_len = 1; + de->rec_len = ext4_rec_len_to_disk(EXT4_DIR_REC_LEN(de->name_len)); +- strcpy(de->name, "."); ++ strcpy (de->name, "."); + ext4_set_de_type(dir->i_sb, de, S_IFDIR); + de = ext4_next_entry(de); + de->inode = cpu_to_le32(dir->i_ino); + de->rec_len = ext4_rec_len_to_disk(inode->i_sb->s_blocksize - +- EXT4_DIR_REC_LEN(1)); ++ EXT4_DIR_REC_LEN(1)); + de->name_len = 2; + strcpy(de->name, ".."); + ext4_set_de_type(dir->i_sb, de, S_IFDIR); +@@ -1925,9 +1940,43 @@ retry: + ext4_journal_dirty_metadata(handle, dir_block); + brelse(dir_block); + ext4_mark_inode_dirty(handle, inode); ++get_out: ++ return err; ++} ++EXPORT_SYMBOL(ext4_add_dot_dotdot); ++ ++ ++static int ext4_mkdir(struct inode *dir, struct dentry *dentry, int mode) ++{ ++ handle_t *handle; ++ struct inode *inode; ++ int err, retries = 0; ++ ++ if (EXT4_DIR_LINK_MAX(dir)) ++ return -EMLINK; ++ ++retry: ++ handle = ext4_journal_start(dir, EXT4_DATA_TRANS_BLOCKS(dir->i_sb) + ++ EXT4_INDEX_EXTRA_TRANS_BLOCKS + 3 + ++ 2*EXT4_QUOTA_INIT_BLOCKS(dir->i_sb)); ++ if (IS_ERR(handle)) ++ return PTR_ERR(handle); ++ ++ if (IS_DIRSYNC(dir)) ++ handle->h_sync = 1; ++ ++ inode = ext4_new_inode_goal(handle, dir, S_IFDIR | mode, ++ ext4_dentry_goal(dir->i_sb, dentry)); ++ err = PTR_ERR(inode); ++ if (IS_ERR(inode)) ++ goto out_stop; ++ ++ err = ext4_add_dot_dotdot(handle, dir, inode); ++ if (err) ++ goto out_stop; ++ + err = ext4_add_entry(handle, dentry, inode); + if (err) { +-out_clear_inode: + clear_nlink(inode); + ext4_mark_inode_dirty(handle, inode); + iput(inode); diff --git a/ldiskfs/kernel_patches/patches/ext4-osd-iop-common.patch b/ldiskfs/kernel_patches/patches/ext4-osd-iop-common.patch new file mode 100644 index 0000000..bc184c5 --- /dev/null +++ b/ldiskfs/kernel_patches/patches/ext4-osd-iop-common.patch @@ -0,0 +1,237 @@ +diff -rupN linux-2.6.18-128.1.6_1//fs/ext4/ext4.h linux-2.6.18-128.1.6_2//fs/ext4/ext4.h +--- linux-2.6.18-128.1.6_1//fs/ext4/ext4.h 2009-08-24 15:54:11.000000000 +0530 ++++ linux-2.6.18-128.1.6_2//fs/ext4/ext4.h 2009-08-24 15:54:52.000000000 +0530 +@@ -1144,6 +1144,18 @@ extern int ext4_fiemap(struct inode *, s + extern int ext4_ext_migrate(struct inode *, struct file *, unsigned int, + unsigned long); + /* namei.c */ ++extern struct inode *ext4_create_inode(handle_t *handle, ++ struct inode * dir, int mode); ++extern int ext4_add_entry(handle_t *handle, struct dentry *dentry, ++ struct inode *inode); ++extern int ext4_delete_entry(handle_t *handle, struct inode * dir, ++ struct ext4_dir_entry_2 * de_del, ++ struct buffer_head * bh); ++extern struct buffer_head * ext4_find_entry(struct dentry *dentry, ++ struct ext4_dir_entry_2 ++ ** res_dir); ++extern int ext4_add_dot_dotdot(handle_t *handle, struct inode *dir, ++ struct inode *inode); + extern int ext4_orphan_add(handle_t *, struct inode *); + extern int ext4_orphan_del(handle_t *, struct inode *); + extern int ext4_htree_fill_tree(struct file *dir_file, __u32 start_hash, +diff -rupN linux-2.6.18-128.1.6_1//fs/ext4/inode.c linux-2.6.18-128.1.6_2//fs/ext4/inode.c +--- linux-2.6.18-128.1.6_1//fs/ext4/inode.c 2009-08-24 15:54:11.000000000 +0530 ++++ linux-2.6.18-128.1.6_2//fs/ext4/inode.c 2009-08-24 15:54:52.000000000 +0530 +@@ -2891,6 +2891,7 @@ bad_inode: + iput(inode); + return ERR_PTR(ret); + } ++EXPORT_SYMBOL(ext4_iget); + + static int ext4_inode_blocks_set(handle_t *handle, + struct ext4_inode *raw_inode, +diff -rupN linux-2.6.18-128.1.6_1//fs/ext4/namei.c linux-2.6.18-128.1.6_2//fs/ext4/namei.c +--- linux-2.6.18-128.1.6_1//fs/ext4/namei.c 2009-08-24 15:54:11.000000000 +0530 ++++ linux-2.6.18-128.1.6_2//fs/ext4/namei.c 2009-08-24 15:55:18.000000000 +0530 +@@ -24,6 +24,7 @@ + * Theodore Ts'o, 2002 + */ + ++#include + #include + #include + #include +@@ -878,8 +879,8 @@ static inline int search_dirblock(struct + * The returned buffer_head has ->b_count elevated. The caller is expected + * to brelse() it when appropriate. + */ +-static struct buffer_head * ext4_find_entry (struct dentry *dentry, +- struct ext4_dir_entry_2 ** res_dir) ++struct buffer_head * ext4_find_entry (struct dentry *dentry, ++ struct ext4_dir_entry_2 ** res_dir) + { + struct super_block * sb; + struct buffer_head * bh_use[NAMEI_RA_SIZE]; +@@ -986,6 +987,7 @@ cleanup_and_exit: + brelse (bh_use[ra_ptr]); + return ret; + } ++EXPORT_SYMBOL(ext4_find_entry); + + static struct buffer_head * ext4_dx_find_entry(struct dentry *dentry, + struct ext4_dir_entry_2 **res_dir, int *err) +@@ -1506,8 +1508,8 @@ static int make_indexed_dir(handle_t *ha + * may not sleep between calling this and putting something into + * the entry, as someone else might have used it while you slept. + */ +-static int ext4_add_entry (handle_t *handle, struct dentry *dentry, +- struct inode *inode) ++int ext4_add_entry (handle_t *handle, struct dentry *dentry, ++ struct inode *inode) + { + struct inode *dir = dentry->d_parent->d_inode; + unsigned long offset; +@@ -1553,6 +1555,7 @@ static int ext4_add_entry (handle_t *han + de->rec_len = ext4_rec_len_to_disk(blocksize); + return add_dirent_to_buf(handle, dentry, inode, de, bh); + } ++EXPORT_SYMBOL(ext4_add_entry); + + /* + * Returns 0 for success, or a negative error value +@@ -1693,10 +1696,10 @@ cleanup: + * ext4_delete_entry deletes a directory entry by merging it with the + * previous entry + */ +-static int ext4_delete_entry (handle_t *handle, +- struct inode * dir, +- struct ext4_dir_entry_2 * de_del, +- struct buffer_head * bh) ++int ext4_delete_entry (handle_t *handle, ++ struct inode * dir, ++ struct ext4_dir_entry_2 * de_del, ++ struct buffer_head * bh) + { + struct ext4_dir_entry_2 * de, * pde; + int i; +@@ -1727,7 +1730,7 @@ static int ext4_delete_entry (handle_t * + } + return -ENOENT; + } +- ++EXPORT_SYMBOL(ext4_delete_entry); + /* + * DIR_NLINK feature is set if 1) nlinks > EXT4_LINK_MAX or 2) nlinks == 2, + * since this indicates that nlinks count was previously 1. +@@ -1790,6 +1793,26 @@ static struct inode * ext4_new_inode_wan + return ext4_new_inode(handle, dir, mode, inum); + } + ++struct inode * ext4_create_inode(handle_t *handle, struct inode * dir, int mode) ++{ ++ struct inode *inode; ++ ++ inode = ext4_new_inode(handle, dir, mode, 0); ++ if (!IS_ERR(inode)) { ++ if (S_ISCHR(mode) || S_ISBLK(mode) || S_ISFIFO(mode)) { ++#ifdef CONFIG_LDISKFS_FS_XATTR ++ inode->i_op = &ext4_special_inode_operations; ++#endif ++ } else { ++ inode->i_op = &ext4_file_inode_operations; ++ inode->i_fop = &ext4_file_operations; ++ ext4_set_aops(inode); ++ } ++ } ++ return inode; ++} ++EXPORT_SYMBOL(ext4_create_inode); ++ + /* + * By the time this is called, we already have created + * the directory cache entry for the new file, but it +@@ -1864,38 +1887,25 @@ retry: + return err; + } + +-static int ext4_mkdir(struct inode * dir, struct dentry * dentry, int mode) +-{ +- handle_t *handle; +- struct inode * inode; ++/* Initialize @inode as a subdirectory of @dir, and add the ++ * "." and ".." entries into the first directory block. */ ++int ext4_add_dot_dotdot(handle_t *handle, struct inode * dir, ++ struct inode *inode) ++ { + struct buffer_head * dir_block; + struct ext4_dir_entry_2 * de; +- int err, retries = 0; +- +- if (EXT4_DIR_LINK_MAX(dir)) +- return -EMLINK; +- +-retry: +- handle = ext4_journal_start(dir, EXT4_DATA_TRANS_BLOCKS(dir->i_sb) + +- EXT4_INDEX_EXTRA_TRANS_BLOCKS + 3 + +- 2*EXT4_QUOTA_INIT_BLOCKS(dir->i_sb)); +- if (IS_ERR(handle)) +- return PTR_ERR(handle); +- +- if (IS_DIRSYNC(dir)) +- handle->h_sync = 1; +- +- inode = ext4_new_inode_wantedi (handle, dir, S_IFDIR | mode, dentry); +- err = PTR_ERR(inode); +- if (IS_ERR(inode)) +- goto out_stop; ++ int err = 0; + + inode->i_op = &ext4_dir_inode_operations; + inode->i_fop = &ext4_dir_operations; + inode->i_size = EXT4_I(inode)->i_disksize = inode->i_sb->s_blocksize; + dir_block = ext4_bread (handle, inode, 0, 1, &err); +- if (!dir_block) +- goto out_clear_inode; ++ if (!dir_block) { ++ clear_nlink(inode); ++ ext4_mark_inode_dirty(handle, inode); ++ iput (inode); ++ goto get_out; ++ } + BUFFER_TRACE(dir_block, "get_write_access"); + ext4_journal_get_write_access(handle, dir_block); + de = (struct ext4_dir_entry_2 *) dir_block->b_data; +@@ -1907,7 +1917,7 @@ retry: + de = ext4_next_entry(de); + de->inode = cpu_to_le32(dir->i_ino); + de->rec_len = ext4_rec_len_to_disk(inode->i_sb->s_blocksize - +- EXT4_DIR_REC_LEN(1)); ++ EXT4_DIR_REC_LEN(1)); + de->name_len = 2; + strcpy (de->name, ".."); + ext4_set_de_type(dir->i_sb, de, S_IFDIR); +@@ -1916,9 +1926,41 @@ retry: + ext4_journal_dirty_metadata(handle, dir_block); + brelse (dir_block); + ext4_mark_inode_dirty(handle, inode); ++get_out: ++ return err; ++} ++EXPORT_SYMBOL(ext4_add_dot_dotdot); ++ ++static int ext4_mkdir(struct inode * dir, struct dentry * dentry, int mode) ++{ ++ handle_t *handle; ++ struct inode * inode; ++ int err, retries = 0; ++ ++ if (EXT4_DIR_LINK_MAX(dir)) ++ return -EMLINK; ++ ++retry: ++ handle = ext4_journal_start(dir, EXT4_DATA_TRANS_BLOCKS(dir->i_sb) + ++ EXT4_INDEX_EXTRA_TRANS_BLOCKS + 3 + ++ 2*EXT4_QUOTA_INIT_BLOCKS(dir->i_sb)); ++ if (IS_ERR(handle)) ++ return PTR_ERR(handle); ++ ++ if (IS_DIRSYNC(dir)) ++ handle->h_sync = 1; ++ ++ inode = ext4_new_inode_wantedi (handle, dir, S_IFDIR | mode, dentry); ++ err = PTR_ERR(inode); ++ if (IS_ERR(inode)) ++ goto out_stop; ++ ++ err = ext4_add_dot_dotdot(handle, dir, inode); ++ if (err) ++ goto out_stop; ++ + err = ext4_add_entry (handle, dentry, inode); + if (err) { +-out_clear_inode: + clear_nlink(inode); + ext4_mark_inode_dirty(handle, inode); + iput (inode); + diff --git a/ldiskfs/kernel_patches/patches/ext4-pdir-fix.patch b/ldiskfs/kernel_patches/patches/ext4-pdir-fix.patch new file mode 100644 index 0000000..b9db2ed --- /dev/null +++ b/ldiskfs/kernel_patches/patches/ext4-pdir-fix.patch @@ -0,0 +1,59 @@ +diff -rupN linux-2.6.27.21-0.1_1//fs/ext4/ext4_i.h linux-2.6.27.21-0.1_2//fs/ext4/ext4_i.h +--- linux-2.6.27.21-0.1_1//fs/ext4/ext4_i.h 2009-08-24 13:00:59.000000000 +0530 ++++ linux-2.6.27.21-0.1_2//fs/ext4/ext4_i.h 2009-08-24 13:01:25.000000000 +0530 +@@ -16,6 +16,7 @@ + #ifndef _EXT4_I + #define _EXT4_I + ++#include + #include + #include + #include +@@ -56,7 +57,9 @@ struct ext4_inode_info { + __u32 i_flags; + ext4_fsblk_t i_file_acl; + __u32 i_dtime; +- ++ /* following fields for parallel directory operations -bzzz */ ++ struct dynlock i_htree_lock; ++ struct semaphore i_append_sem; + /* + * i_block_group is the number of the block group which contains + * this file's inode. Constant across the lifetime of the inode, +diff -rupN linux-2.6.27.21-0.1_1//fs/ext4/namei.c linux-2.6.27.21-0.1_2//fs/ext4/namei.c +--- linux-2.6.27.21-0.1_1//fs/ext4/namei.c 2009-08-24 13:00:59.000000000 +0530 ++++ linux-2.6.27.21-0.1_2//fs/ext4/namei.c 2009-08-24 13:03:45.000000000 +0530 +@@ -55,6 +55,11 @@ static struct buffer_head *ext4_append(h + ext4_lblk_t *block, int *err) + { + struct buffer_head *bh; ++ struct ext4_inode_info *ei = EXT4_I(inode); ++ ++ /* with parallel dir operations all appends ++ * have to be serialized -bzzz */ ++ down(&ei->i_append_sem); + + *block = inode->i_size >> inode->i_sb->s_blocksize_bits; + +@@ -67,7 +72,9 @@ static struct buffer_head *ext4_append(h + brelse(bh); + bh = NULL; + } ++ ei->i_disksize = inode->i_size; + } ++ up(&ei->i_append_sem); + return bh; + } + +diff -rupN linux-2.6.27.21-0.1_1//fs/ext4/super.c linux-2.6.27.21-0.1_2//fs/ext4/super.c +--- linux-2.6.27.21-0.1_1//fs/ext4/super.c 2009-08-24 13:00:59.000000000 +0530 ++++ linux-2.6.27.21-0.1_2//fs/ext4/super.c 2009-08-24 13:01:25.000000000 +0530 +@@ -635,6 +635,8 @@ static struct inode *ext4_alloc_inode(st + #endif + ei->vfs_inode.i_version = 1; + ei->vfs_inode.i_data.writeback_index = 0; ++ dynlock_init(&ei->i_htree_lock); ++ sema_init(&ei->i_append_sem, 1); + memset(&ei->i_cached_extent, 0, sizeof(struct ext4_ext_cache)); + INIT_LIST_HEAD(&ei->i_prealloc_list); + spin_lock_init(&ei->i_prealloc_lock); diff --git a/ldiskfs/kernel_patches/series/ldiskfs-2.6-rhel5-ext4.series b/ldiskfs/kernel_patches/series/ldiskfs-2.6-rhel5-ext4.series index 8606846..4e89ef8 100644 --- a/ldiskfs/kernel_patches/series/ldiskfs-2.6-rhel5-ext4.series +++ b/ldiskfs/kernel_patches/series/ldiskfs-2.6-rhel5-ext4.series @@ -23,3 +23,9 @@ ext4-convert-group-lock-rhel5.patch ext4-force_over_8tb-rhel5.patch ext4_ext_search_right-fix.patch ext4-pa_lock-typo.patch +ext4-pdir-fix.patch +ext4-osd-iop-common.patch +ext4-osd-iam-exports.patch +ext4-dynlocks-common.patch +ext4-dynlocks-2.6-rhel5.patch +ext4-hash-indexed-dir-dotdot-update.patch diff --git a/ldiskfs/kernel_patches/series/ldiskfs-2.6-rhel5.series b/ldiskfs/kernel_patches/series/ldiskfs-2.6-rhel5.series index 0257bce..2c55020 100644 --- a/ldiskfs/kernel_patches/series/ldiskfs-2.6-rhel5.series +++ b/ldiskfs/kernel_patches/series/ldiskfs-2.6-rhel5.series @@ -26,4 +26,10 @@ ext3-journal-chksum-2.6.18-vanilla.patch ext3-get-raid-stripe-from-sb.patch ext3-big-endian-check-2.6-rhel5.patch alloc-policy-2.6-rhlel5.diff -ext3-force_over_8tb-rhel5.patch +ext3-force_over_8tb-rhel5.patch +ext3-pdir-fix.patch +ext3-osd-iop-common.patch +ext3-osd-iam-exports.patch +ext3-dynlocks-common.patch +ext3-dynlocks-2.6-rhel5.patch +ext3-hash-indexed-dir-dotdot-update.patch diff --git a/ldiskfs/kernel_patches/series/ldiskfs-2.6-sles10.series b/ldiskfs/kernel_patches/series/ldiskfs-2.6-sles10.series index b526868..885df46 100644 --- a/ldiskfs/kernel_patches/series/ldiskfs-2.6-sles10.series +++ b/ldiskfs/kernel_patches/series/ldiskfs-2.6-sles10.series @@ -32,3 +32,9 @@ ext3-get-raid-stripe-from-sb.patch ext3-big-endian-check-2.6-sles10.patch alloc-policy-2.6-rhlel5.diff ext3-force_over_8tb-sles10.patch +ext3-pdir-fix.patch +ext3-osd-iop-common.patch +ext3-osd-iam-exports.patch +ext3-dynlocks-common.patch +ext3-dynlocks-2.6-rhel5.patch +ext3-hash-indexed-dir-dotdot-update.patch diff --git a/ldiskfs/kernel_patches/series/ldiskfs-2.6-sles11.series b/ldiskfs/kernel_patches/series/ldiskfs-2.6-sles11.series index 2f35a0b..226eea2 100644 --- a/ldiskfs/kernel_patches/series/ldiskfs-2.6-sles11.series +++ b/ldiskfs/kernel_patches/series/ldiskfs-2.6-sles11.series @@ -26,3 +26,9 @@ ext4-force_over_8tb-sles11.patch ext4-claim_inode-free_inode-race.patch ext4_ext_search_right-fix.patch ext4-pa_lock-typo.patch +ext4-pdir-fix.patch +ext4-osd-iop-common-sles11.patch +ext4-osd-iam-exports.patch +ext4-dynlocks-common-sles11.patch +ext4-dynlocks-2.6-rhel5.patch +ext4-hash-indexed-dir-dotdot-update.patch diff --git a/ldiskfs/ldiskfs/Makefile.in b/ldiskfs/ldiskfs/Makefile.in index 7f369b2..71d312d 100644 --- a/ldiskfs/ldiskfs/Makefile.in +++ b/ldiskfs/ldiskfs/Makefile.in @@ -10,10 +10,10 @@ linux_headers := $(wildcard @LINUX@/include/linux/@BACKFS@*.h) backfs_sources := $(filter-out %.mod.c,$(wildcard @LINUX@/fs/@BACKFS@/*.c)) -ext3_new_sources := iopen.c iopen.h extents.c mballoc.c group.h fiemap.h -ext3_new_headers := ext3_extents.h +ext3_new_sources := iopen.c iopen.h extents.c mballoc.c group.h dynlocks.c fiemap.h +ext3_new_headers := ext3_extents.h -ext4_new_sources := iopen.c iopen.h fiemap.h +ext4_new_sources := iopen.c iopen.h dynlocks.c fiemap.h ext4_new_headers := new_sources := $(@BACKFS@_new_sources) diff --git a/ldiskfs/ldiskfs/autoMakefile.am b/ldiskfs/ldiskfs/autoMakefile.am index 13a9558..65d04a7 100644 --- a/ldiskfs/ldiskfs/autoMakefile.am +++ b/ldiskfs/ldiskfs/autoMakefile.am @@ -62,6 +62,11 @@ endif linux-stage/include/linux/@BACKFS@$$i \ > linux/ldiskfs$$i ; \ done + sed $(strip $(ldiskfs_sed_flags)) \ + linux-stage/include/linux/dynlocks.h \ + > linux/dynlocks.h + + @echo touch sources