Whamcloud - gitweb
Branch b_new_cmd
authorwangdi <wangdi>
Sat, 21 Oct 2006 05:12:46 +0000 (05:12 +0000)
committerwangdi <wangdi>
Sat, 21 Oct 2006 05:12:46 +0000 (05:12 +0000)
add dynamic-locks to 2.6-fc3 series

lustre/kernel_patches/patches/dynamic-locks-2.6-fc3.patch [new file with mode: 0644]
lustre/kernel_patches/series/2.6-fc3.series

diff --git a/lustre/kernel_patches/patches/dynamic-locks-2.6-fc3.patch b/lustre/kernel_patches/patches/dynamic-locks-2.6-fc3.patch
new file mode 100644 (file)
index 0000000..426af25
--- /dev/null
@@ -0,0 +1,288 @@
+ include/linux/dynlocks.h |   33 ++++++++++
+ lib/Makefile             |    4 -
+ lib/dynlocks.c           |  152 +++++++++++++++++++++++++++++++++++++++++++++++
+ 3 files changed, 187 insertions(+), 2 deletions(-)
+
+Index: linux-2.6.10/fs/dcache.c
+===================================================================
+--- linux-2.6.10.orig/fs/dcache.c      2006-10-21 11:52:54.000000000 +0800
++++ linux-2.6.10/fs/dcache.c   2006-10-21 13:04:55.000000000 +0800
+@@ -1664,6 +1664,7 @@
+ extern void bdev_cache_init(void);
+ extern void chrdev_init(void);
++extern void dynlock_cache_init(void);
+ void __init vfs_caches_init_early(void)
+ {
+@@ -1693,6 +1694,7 @@
+       mnt_init(mempages);
+       bdev_cache_init();
+       chrdev_init();
++      dynlock_cache_init();
+ }
+ EXPORT_SYMBOL(d_alloc);
+Index: linux-2.6.10/include/linux/dynlocks.h
+===================================================================
+--- linux-2.6.10.orig/include/linux/dynlocks.h 2006-05-31 09:15:07.000000000 +0800
++++ linux-2.6.10/include/linux/dynlocks.h      2006-10-21 13:04:55.000000000 +0800
+@@ -0,0 +1,37 @@
++#ifndef _LINUX_DYNLOCKS_H
++#define _LINUX_DYNLOCKS_H
++
++#include <linux/list.h>
++#include <linux/wait.h>
++
++#define DYNLOCK_MAGIC         0xd19a10c
++#define DYNLOCK_MAGIC2                0xd1956ee
++
++struct dynlock;
++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_NONE,
++      DLT_WRITE,
++      DLT_READ
++};
++
++void dynlock_init(struct dynlock *dl);
++struct dynlock_handle *dynlock_lock(struct dynlock *dl, unsigned long value,
++                                  enum dynlock_type lt, int gfp);
++void dynlock_unlock(struct dynlock *dl, struct dynlock_handle *lock);
++
++#endif
++
+Index: linux-2.6.10/lib/Makefile
+===================================================================
+--- linux-2.6.10.orig/lib/Makefile     2004-12-25 05:33:50.000000000 +0800
++++ linux-2.6.10/lib/Makefile  2006-10-21 13:08:20.000000000 +0800
+@@ -5,7 +5,7 @@
+ lib-y := errno.o ctype.o string.o vsprintf.o cmdline.o \
+        bust_spinlocks.o rbtree.o radix-tree.o dump_stack.o \
+        kobject.o kref.o idr.o div64.o parser.o int_sqrt.o \
+-       bitmap.o extable.o kobject_uevent.o
++       bitmap.o extable.o kobject_uevent.o dynlocks.o
+ ifeq ($(CONFIG_DEBUG_KOBJECT),y)
+ CFLAGS_kobject.o += -DDEBUG
+Index: linux-2.6.10/lib/dynlocks.c
+===================================================================
+--- linux-2.6.10.orig/lib/dynlocks.c   2006-05-31 09:15:07.000000000 +0800
++++ linux-2.6.10/lib/dynlocks.c        2006-10-21 13:04:55.000000000 +0800
+@@ -0,0 +1,203 @@
++/*
++ * Dynamic Locks
++ *
++ * struct dynlock is lockspace
++ * one may request lock (exclusive or shared) for some value
++ * in that lockspace
++ *
++ */
++
++#include <linux/dynlocks.h>
++#include <linux/module.h>
++#include <linux/slab.h>
++#include <linux/sched.h>
++
++static kmem_cache_t * dynlock_cachep = NULL;
++
++struct dynlock_handle {
++      unsigned                dl_magic;
++      struct list_head        dl_list;
++      unsigned long           dl_value;       /* lock value */
++      int                     dl_refcount;    /* number of users */
++      int                     dl_readers;
++      int                     dl_writers;
++      int                     dl_pid;         /* holder of the lock */
++      wait_queue_head_t       dl_wait;
++};
++
++#define DYNLOCK_LIST_MAGIC    0x11ee91e6
++
++void __init dynlock_cache_init(void)
++{
++      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)
++              panic("Can't create dynlock cache");
++}
++
++/*
++ * 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;
++}
++
++/*
++ * 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, int gfp)
++{
++      struct dynlock_handle *nhl = NULL;
++      struct dynlock_handle *hl;
++      struct list_head *cur;
++      int num = 0;
++
++      BUG_ON(dl == NULL);
++      BUG_ON(dl->dl_magic != DYNLOCK_LIST_MAGIC);
++
++      if (lt == DLT_NONE)
++              return NULL;
++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(cur, &dl->dl_list) {
++              BUG_ON(cur->next == NULL);
++              BUG_ON(cur->prev == NULL);
++              hl = list_entry(cur, struct dynlock_handle, dl_list);
++              BUG_ON(hl->dl_magic != DYNLOCK_MAGIC);
++              if (hl->dl_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->dl_refcount++;
++                      goto found;
++              }
++              num++;
++      }
++      /* lock not found */
++      if (nhl) {
++              /* we already have allocated lock. use it */
++              hl = nhl;
++              nhl = NULL;
++              list_add(&hl->dl_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->dl_refcount = 1;
++      nhl->dl_value = value;
++      nhl->dl_readers = 0;
++      nhl->dl_writers = 0;
++      nhl->dl_magic = DYNLOCK_MAGIC;
++      init_waitqueue_head(&nhl->dl_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->dl_writers && hl->dl_pid != current->pid) ||
++                              hl->dl_readers) {
++                      spin_unlock(&dl->dl_list_lock);
++                      wait_event(hl->dl_wait,
++                              hl->dl_writers == 0 && hl->dl_readers == 0);
++                      spin_lock(&dl->dl_list_lock);
++              }
++              hl->dl_writers++;
++      } else {
++              /* shared lock: user do not want to share lock with writer */
++              while (hl->dl_writers) {
++                      spin_unlock(&dl->dl_list_lock);
++                      wait_event(hl->dl_wait, hl->dl_writers == 0);
++                      spin_lock(&dl->dl_list_lock);
++              }
++              hl->dl_readers++;
++      }
++      hl->dl_pid = current->pid;
++      spin_unlock(&dl->dl_list_lock);
++
++      return hl;
++}
++
++
++/*
++ * 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);
++      BUG_ON(hl->dl_magic != DYNLOCK_MAGIC);
++      BUG_ON(current->pid != hl->dl_pid);
++
++      spin_lock(&dl->dl_list_lock);
++      if (hl->dl_writers) {
++              BUG_ON(hl->dl_readers > 0 || hl->dl_readers < 0);
++              hl->dl_writers--;
++              if (hl->dl_writers == 0)
++                      wakeup = 1;
++      } else if (hl->dl_readers) {
++              hl->dl_readers--;
++              if (hl->dl_readers == 0)
++                      wakeup = 1;
++      } else {
++              BUG_ON(1);
++      }
++      if (wakeup) {
++              hl->dl_pid = 0;
++              wake_up(&hl->dl_wait);
++      }
++      if (--(hl->dl_refcount) == 0) {
++              hl->dl_magic = DYNLOCK_MAGIC2;
++              list_del(&hl->dl_list);
++              kmem_cache_free(dynlock_cachep, hl);
++      }
++      spin_unlock(&dl->dl_list_lock);
++}
++
++EXPORT_SYMBOL(dynlock_init);
++EXPORT_SYMBOL(dynlock_lock);
++EXPORT_SYMBOL(dynlock_unlock);
++
index 7204056..d21108e 100644 (file)
@@ -22,4 +22,4 @@ uml-exprt-clearuser.patch
 fsprivate-2.6.patch
 linux-2.6.9-ext3-sub-second-timestamp.patch 
 bitops_ext2_find_next_le_bit-2.6.patch 
-dynamic-locks-2.6.9.patch 
+dynamic-locks-2.6-fc3.patch