This is a note to let you know that I've just added the patch titled pstore: Allow prz to control need for locking to the 3.18-stable tree which can be found at: http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary The filename of the patch is: pstore-allow-prz-to-control-need-for-locking.patch and it can be found in the queue-3.18 subdirectory. If you, or anyone else, feels it should not be added to the stable tree, please let <stable@xxxxxxxxxxxxxxx> know about it. >From 663deb47880f2283809669563c5a52ac7c6aef1a Mon Sep 17 00:00:00 2001 From: Joel Fernandes <joelaf@xxxxxxxxxx> Date: Thu, 20 Oct 2016 00:34:01 -0700 Subject: pstore: Allow prz to control need for locking From: Joel Fernandes <joelaf@xxxxxxxxxx> commit 663deb47880f2283809669563c5a52ac7c6aef1a upstream. In preparation of not locking at all for certain buffers depending on if there's contention, make locking optional depending on the initialization of the prz. Signed-off-by: Joel Fernandes <joelaf@xxxxxxxxxx> [kees: moved locking flag into prz instead of via caller arguments] Signed-off-by: Kees Cook <keescook@xxxxxxxxxxxx> Signed-off-by: Greg Kroah-Hartman <gregkh@xxxxxxxxxxxxxxxxxxx> --- fs/pstore/ram.c | 5 +++-- fs/pstore/ram_core.c | 24 +++++++++++++++--------- include/linux/pstore_ram.h | 10 +++++++++- 3 files changed, 27 insertions(+), 12 deletions(-) --- a/fs/pstore/ram.c +++ b/fs/pstore/ram.c @@ -365,7 +365,7 @@ static int ramoops_init_przs(struct devi cxt->przs[i] = persistent_ram_new(*paddr, sz, 0, &cxt->ecc_info, - cxt->memtype); + cxt->memtype, 0); if (IS_ERR(cxt->przs[i])) { err = PTR_ERR(cxt->przs[i]); dev_err(dev, "failed to request mem region (0x%zx@0x%llx): %d\n", @@ -395,7 +395,8 @@ static int ramoops_init_prz(struct devic return -ENOMEM; } - *prz = persistent_ram_new(*paddr, sz, sig, &cxt->ecc_info, cxt->memtype); + *prz = persistent_ram_new(*paddr, sz, sig, &cxt->ecc_info, + cxt->memtype, 0); if (IS_ERR(*prz)) { int err = PTR_ERR(*prz); --- a/fs/pstore/ram_core.c +++ b/fs/pstore/ram_core.c @@ -85,9 +85,10 @@ static size_t buffer_start_add_locked(st { int old; int new; - unsigned long flags; + unsigned long flags = 0; - raw_spin_lock_irqsave(&prz->buffer_lock, flags); + if (!(prz->flags & PRZ_FLAG_NO_LOCK)) + raw_spin_lock_irqsave(&prz->buffer_lock, flags); old = atomic_read(&prz->buffer->start); new = old + a; @@ -95,7 +96,8 @@ static size_t buffer_start_add_locked(st new -= prz->buffer_size; atomic_set(&prz->buffer->start, new); - raw_spin_unlock_irqrestore(&prz->buffer_lock, flags); + if (!(prz->flags & PRZ_FLAG_NO_LOCK)) + raw_spin_unlock_irqrestore(&prz->buffer_lock, flags); return old; } @@ -105,9 +107,10 @@ static void buffer_size_add_locked(struc { size_t old; size_t new; - unsigned long flags; + unsigned long flags = 0; - raw_spin_lock_irqsave(&prz->buffer_lock, flags); + if (!(prz->flags & PRZ_FLAG_NO_LOCK)) + raw_spin_lock_irqsave(&prz->buffer_lock, flags); old = atomic_read(&prz->buffer->size); if (old == prz->buffer_size) @@ -119,7 +122,8 @@ static void buffer_size_add_locked(struc atomic_set(&prz->buffer->size, new); exit: - raw_spin_unlock_irqrestore(&prz->buffer_lock, flags); + if (!(prz->flags & PRZ_FLAG_NO_LOCK)) + raw_spin_unlock_irqrestore(&prz->buffer_lock, flags); } static size_t (*buffer_start_add)(struct persistent_ram_zone *, size_t) = buffer_start_add_atomic; @@ -459,7 +463,8 @@ static int persistent_ram_buffer_map(phy } static int persistent_ram_post_init(struct persistent_ram_zone *prz, u32 sig, - struct persistent_ram_ecc_info *ecc_info) + struct persistent_ram_ecc_info *ecc_info, + unsigned long flags) { int ret; @@ -488,6 +493,7 @@ static int persistent_ram_post_init(stru prz->buffer->sig = sig; persistent_ram_zap(prz); prz->buffer_lock = __RAW_SPIN_LOCK_UNLOCKED(buffer_lock); + prz->flags = flags; return 0; } @@ -512,7 +518,7 @@ void persistent_ram_free(struct persiste struct persistent_ram_zone *persistent_ram_new(phys_addr_t start, size_t size, u32 sig, struct persistent_ram_ecc_info *ecc_info, - unsigned int memtype) + unsigned int memtype, u32 flags) { struct persistent_ram_zone *prz; int ret = -ENOMEM; @@ -527,7 +533,7 @@ struct persistent_ram_zone *persistent_r if (ret) goto err; - ret = persistent_ram_post_init(prz, sig, ecc_info); + ret = persistent_ram_post_init(prz, sig, ecc_info, flags); if (ret) goto err; --- a/include/linux/pstore_ram.h +++ b/include/linux/pstore_ram.h @@ -23,6 +23,13 @@ #include <linux/types.h> #include <linux/init.h> +/* + * Choose whether access to the RAM zone requires locking or not. If a zone + * can be written to from different CPUs like with ftrace for example, then + * PRZ_FLAG_NO_LOCK is used. For all other cases, locking is required. + */ +#define PRZ_FLAG_NO_LOCK BIT(0) + struct persistent_ram_buffer; struct rs_control; @@ -39,6 +46,7 @@ struct persistent_ram_zone { void *vaddr; struct persistent_ram_buffer *buffer; size_t buffer_size; + u32 flags; raw_spinlock_t buffer_lock; /* ECC correction */ @@ -55,7 +63,7 @@ struct persistent_ram_zone { struct persistent_ram_zone *persistent_ram_new(phys_addr_t start, size_t size, u32 sig, struct persistent_ram_ecc_info *ecc_info, - unsigned int memtype); + unsigned int memtype, u32 flags); void persistent_ram_free(struct persistent_ram_zone *prz); void persistent_ram_zap(struct persistent_ram_zone *prz); Patches currently in stable-queue which might be from joelaf@xxxxxxxxxx are queue-3.18/pstore-make-spinlock-per-zone-instead-of-global.patch queue-3.18/pstore-allow-prz-to-control-need-for-locking.patch