Merge linux-3.10.67 into dev-kernel-3.10
[linux-3.10.git] / fs / pstore / ram_core.c
index 6ff9755..ecd3ad4 100644 (file)
 #include <linux/slab.h>
 #include <linux/vmalloc.h>
 #include <linux/pstore_ram.h>
+#include <linux/spinlock.h>
 #include <asm/page.h>
 
 struct persistent_ram_buffer {
-       uint32_t    sig;
-       atomic_t    start;
-       atomic_t    size;
-       uint8_t     data[0];
+       uint32_t sig;
+       size_t start;
+       size_t size;
+       uint8_t data[0];
 };
 
+static DEFINE_SPINLOCK(buffer_lock);
+
 #define PERSISTENT_RAM_SIG (0x43474244) /* DBGC */
 
 static inline size_t buffer_size(struct persistent_ram_zone *prz)
 {
-       return atomic_read(&prz->buffer->size);
+       return prz->buffer->size;
 }
 
 static inline size_t buffer_start(struct persistent_ram_zone *prz)
 {
-       return atomic_read(&prz->buffer->start);
+       return prz->buffer->start;
+}
+
+static inline int compare_and_exchange(size_t *v, int old, int new)
+{
+       size_t ret;
+
+       spin_lock(&buffer_lock);
+
+       ret = *v;
+       if (likely(ret == old))
+               *v = new;
+
+       spin_unlock(&buffer_lock);
+
+       return ret;
 }
 
 /* increase and wrap the start pointer, returning the old value */
@@ -52,11 +70,11 @@ static inline size_t buffer_start_add(struct persistent_ram_zone *prz, size_t a)
        int new;
 
        do {
-               old = atomic_read(&prz->buffer->start);
+               old = prz->buffer->start;
                new = old + a;
                while (unlikely(new > prz->buffer_size))
                        new -= prz->buffer_size;
-       } while (atomic_cmpxchg(&prz->buffer->start, old, new) != old);
+       } while (compare_and_exchange(&prz->buffer->start, old, new) != old);
 
        return old;
 }
@@ -67,15 +85,15 @@ static inline void buffer_size_add(struct persistent_ram_zone *prz, size_t a)
        size_t old;
        size_t new;
 
-       if (atomic_read(&prz->buffer->size) == prz->buffer_size)
+       if (prz->buffer->size == prz->buffer_size)
                return;
 
        do {
-               old = atomic_read(&prz->buffer->size);
+               old = prz->buffer->size;
                new = old + a;
                if (new > prz->buffer_size)
                        new = prz->buffer_size;
-       } while (atomic_cmpxchg(&prz->buffer->size, old, new) != old);
+       } while (compare_and_exchange(&prz->buffer->size, old, new) != old);
 }
 
 static void notrace persistent_ram_encode_rs8(struct persistent_ram_zone *prz,
@@ -328,8 +346,8 @@ void persistent_ram_free_old(struct persistent_ram_zone *prz)
 
 void persistent_ram_zap(struct persistent_ram_zone *prz)
 {
-       atomic_set(&prz->buffer->start, 0);
-       atomic_set(&prz->buffer->size, 0);
+       prz->buffer->start = 0;
+       prz->buffer->size = 0;
        persistent_ram_update_header_ecc(prz);
 }