Whamcloud - gitweb
Branch HEAD
[fs/lustre-release.git] / lustre / kernel_patches / patches / jbd-slab-race-2.6-rhel5.patch
1 kmem_cache_create: duplicate cache jbd_4k
2
3 The jbd slab cache creation/deletion is racey.  If multiple jbd based
4 filesystems are mounted concurrently, and there are no other jbd based
5 filesystems already mounted.  Then we can race creating the slab caches
6 since jbd_slab[] is not locked.  This is not commonly observed because
7 typically /root is mounted early with a jbd based filesystem making the
8 race impossible.  On our diskless systems /root does not use the jbd
9 but we do have attached storage which does, and which is mounted in
10 parallel.  Basically our setup is similiar to what may be found in a
11 NAS style appliance.
12
13 This patch wraps all modifications to jbd_slab[] in the jbd_slab_lock
14 to prevent this above race.
15
16 LLNL Bug 291
17 Signed-off-by: Brian Behlendorf <behlendorf1@llnl.gov>
18
19 Index: linux+rh+chaos/fs/jbd/journal.c
20 ===================================================================
21 --- linux+rh+chaos.orig/fs/jbd/journal.c
22 +++ linux+rh+chaos/fs/jbd/journal.c
23 @@ -1979,6 +1979,7 @@ void * __jbd_kmalloc (const char *where,
24  #define JBD_MAX_SLABS 5
25  #define JBD_SLAB_INDEX(size)  (size >> 11)
26  
27 +static DECLARE_RWSEM(jbd_slab_lock); /* protect jbd_slab[] */
28  static kmem_cache_t *jbd_slab[JBD_MAX_SLABS];
29  static const char *jbd_slab_names[JBD_MAX_SLABS] = {
30         "jbd_1k", "jbd_2k", "jbd_4k", NULL, "jbd_8k"
31 @@ -1988,24 +1989,27 @@ static void journal_destroy_jbd_slabs(vo
32  {
33         int i;
34  
35 +       down_write(&jbd_slab_lock);
36         for (i = 0; i < JBD_MAX_SLABS; i++) {
37                 if (jbd_slab[i])
38                         kmem_cache_destroy(jbd_slab[i]);
39                 jbd_slab[i] = NULL;
40         }
41 +       up_write(&jbd_slab_lock);
42  }
43  
44  static int journal_create_jbd_slab(size_t slab_size)
45  {
46 -       int i = JBD_SLAB_INDEX(slab_size);
47 +       int rc = 0, i = JBD_SLAB_INDEX(slab_size);
48  
49         BUG_ON(i >= JBD_MAX_SLABS);
50  
51         /*
52          * Check if we already have a slab created for this size
53          */
54 +       down_write(&jbd_slab_lock);
55         if (jbd_slab[i])
56 -               return 0;
57 +               goto out_lock;
58  
59         /*
60          * Create a slab and force alignment to be same as slabsize -
61 @@ -2016,27 +2020,36 @@ static int journal_create_jbd_slab(size_
62                                 slab_size, slab_size, 0, NULL, NULL);
63         if (!jbd_slab[i]) {
64                 printk(KERN_EMERG "JBD: no memory for jbd_slab cache\n");
65 -               return -ENOMEM;
66 +               rc = -ENOMEM;
67         }
68 -       return 0;
69 +out_lock:
70 +       up_write(&jbd_slab_lock);
71 +       return rc;
72  }
73  
74  void * jbd_slab_alloc(size_t size, gfp_t flags)
75  {
76 +       void *ptr;
77         int idx;
78  
79 +       down_read(&jbd_slab_lock);
80         idx = JBD_SLAB_INDEX(size);
81         BUG_ON(jbd_slab[idx] == NULL);
82 -       return kmem_cache_alloc(jbd_slab[idx], flags | __GFP_NOFAIL);
83 +       ptr = kmem_cache_alloc(jbd_slab[idx], flags | __GFP_NOFAIL);
84 +       up_read(&jbd_slab_lock);
85 +
86 +       return ptr;
87  }
88  
89  void jbd_slab_free(void *ptr,  size_t size)
90  {
91         int idx;
92  
93 +       down_read(&jbd_slab_lock);
94         idx = JBD_SLAB_INDEX(size);
95         BUG_ON(jbd_slab[idx] == NULL);
96         kmem_cache_free(jbd_slab[idx], ptr);
97 +       up_read(&jbd_slab_lock);
98  }
99  
100  /*
101