Commit 6ada4e28 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge branch 'akpm' (patches from Andrew)

Merge updates from Andrew Morton:

 - a few misc things

 - a few Y2038 fixes

 - ntfs fixes

 - arch/sh tweaks

 - ocfs2 updates

 - most of MM

* emailed patches from Andrew Morton <akpm@linux-foundation.org>: (111 commits)
  mm/hmm.c: remove unused variables align_start and align_end
  fs/userfaultfd.c: remove redundant pointer uwq
  mm, vmacache: hash addresses based on pmd
  mm/list_lru: introduce list_lru_shrink_walk_irq()
  mm/list_lru.c: pass struct list_lru_node* as an argument to __list_lru_walk_one()
  mm/list_lru.c: move locking from __list_lru_walk_one() to its caller
  mm/list_lru.c: use list_lru_walk_one() in list_lru_walk_node()
  mm, swap: make CONFIG_THP_SWAP depend on CONFIG_SWAP
  mm/sparse: delete old sparse_init and enable new one
  mm/sparse: add new sparse_init_nid() and sparse_init()
  mm/sparse: move buffer init/fini to the common place
  mm/sparse: use the new sparse buffer functions in non-vmemmap
  mm/sparse: abstract sparse buffer allocations
  mm/hugetlb.c: don't zero 1GiB bootmem pages
  mm, page_alloc: double zone's batchsize
  mm/oom_kill.c: document oom_lock
  mm/hugetlb: remove gigantic page support for HIGHMEM
  mm, oom: remove sleep from under oom_lock
  kernel/dma: remove unsupported gfp_mask parameter from dma_alloc_from_contiguous()
  mm/cma: remove unsupported gfp_mask parameter from cma_alloc()
  ...
parents 9bd55392 1e926419
...@@ -2571,6 +2571,11 @@ S: Helstorfer Str. 7 ...@@ -2571,6 +2571,11 @@ S: Helstorfer Str. 7
S: D-30625 Hannover S: D-30625 Hannover
S: Germany S: Germany
N: Ron Minnich
E: rminnich@sandia.gov
E: rminnich@gmail.com
D: 9p filesystem development
N: Corey Minyard N: Corey Minyard
E: minyard@wf-rch.cirr.com E: minyard@wf-rch.cirr.com
E: minyard@mvista.com E: minyard@mvista.com
......
...@@ -65,6 +65,11 @@ workload one should: ...@@ -65,6 +65,11 @@ workload one should:
are not reclaimable, he or she can filter them out using are not reclaimable, he or she can filter them out using
``/proc/kpageflags``. ``/proc/kpageflags``.
The page-types tool in the tools/vm directory can be used to assist in this.
If the tool is run initially with the appropriate option, it will mark all the
queried pages as idle. Subsequent runs of the tool can then show which pages have
their idle flag cleared in the interim.
See :ref:`Documentation/admin-guide/mm/pagemap.rst <pagemap>` for more See :ref:`Documentation/admin-guide/mm/pagemap.rst <pagemap>` for more
information about ``/proc/pid/pagemap``, ``/proc/kpageflags``, and information about ``/proc/pid/pagemap``, ``/proc/kpageflags``, and
``/proc/kpagecgroup``. ``/proc/kpagecgroup``.
......
...@@ -44,6 +44,9 @@ There are four components to pagemap: ...@@ -44,6 +44,9 @@ There are four components to pagemap:
* ``/proc/kpagecount``. This file contains a 64-bit count of the number of * ``/proc/kpagecount``. This file contains a 64-bit count of the number of
times each page is mapped, indexed by PFN. times each page is mapped, indexed by PFN.
The page-types tool in the tools/vm directory can be used to query the
number of times a page is mapped.
* ``/proc/kpageflags``. This file contains a 64-bit set of flags for each * ``/proc/kpageflags``. This file contains a 64-bit set of flags for each
page, indexed by PFN. page, indexed by PFN.
......
...@@ -66,23 +66,39 @@ kernel 3.10. Current versions require the following update ...@@ -66,23 +66,39 @@ kernel 3.10. Current versions require the following update
The iterator interface The iterator interface
Modules implementing a virtual file with seq_file must implement a simple Modules implementing a virtual file with seq_file must implement an
iterator object that allows stepping through the data of interest. iterator object that allows stepping through the data of interest
Iterators must be able to move to a specific position - like the file they during a "session" (roughly one read() system call). If the iterator
implement - but the interpretation of that position is up to the iterator is able to move to a specific position - like the file they implement,
itself. A seq_file implementation that is formatting firewall rules, for though with freedom to map the position number to a sequence location
example, could interpret position N as the Nth rule in the chain. in whatever way is convenient - the iterator need only exist
Positioning can thus be done in whatever way makes the most sense for the transiently during a session. If the iterator cannot easily find a
generator of the data, which need not be aware of how a position translates numerical position but works well with a first/next interface, the
to an offset in the virtual file. The one obvious exception is that a iterator can be stored in the private data area and continue from one
position of zero should indicate the beginning of the file. session to the next.
A seq_file implementation that is formatting firewall rules from a
table, for example, could provide a simple iterator that interprets
position N as the Nth rule in the chain. A seq_file implementation
that presents the content of a, potentially volatile, linked list
might record a pointer into that list, providing that can be done
without risk of the current location being removed.
Positioning can thus be done in whatever way makes the most sense for
the generator of the data, which need not be aware of how a position
translates to an offset in the virtual file. The one obvious exception
is that a position of zero should indicate the beginning of the file.
The /proc/sequence iterator just uses the count of the next number it The /proc/sequence iterator just uses the count of the next number it
will output as its position. will output as its position.
Four functions must be implemented to make the iterator work. The first, Four functions must be implemented to make the iterator work. The
called start() takes a position as an argument and returns an iterator first, called start(), starts a session and takes a position as an
which will start reading at that position. For our simple sequence example, argument, returning an iterator which will start reading at that
position. The pos passed to start() will always be either zero, or
the most recent pos used in the previous session.
For our simple sequence example,
the start() function looks like: the start() function looks like:
static void *ct_seq_start(struct seq_file *s, loff_t *pos) static void *ct_seq_start(struct seq_file *s, loff_t *pos)
...@@ -101,11 +117,12 @@ implementations; in most cases the start() function should check for a ...@@ -101,11 +117,12 @@ implementations; in most cases the start() function should check for a
"past end of file" condition and return NULL if need be. "past end of file" condition and return NULL if need be.
For more complicated applications, the private field of the seq_file For more complicated applications, the private field of the seq_file
structure can be used. There is also a special value which can be returned structure can be used to hold state from session to session. There is
by the start() function called SEQ_START_TOKEN; it can be used if you wish also a special value which can be returned by the start() function
to instruct your show() function (described below) to print a header at the called SEQ_START_TOKEN; it can be used if you wish to instruct your
top of the output. SEQ_START_TOKEN should only be used if the offset is show() function (described below) to print a header at the top of the
zero, however. output. SEQ_START_TOKEN should only be used if the offset is zero,
however.
The next function to implement is called, amazingly, next(); its job is to The next function to implement is called, amazingly, next(); its job is to
move the iterator forward to the next position in the sequence. The move the iterator forward to the next position in the sequence. The
...@@ -121,9 +138,13 @@ complete. Here's the example version: ...@@ -121,9 +138,13 @@ complete. Here's the example version:
return spos; return spos;
} }
The stop() function is called when iteration is complete; its job, of The stop() function closes a session; its job, of course, is to clean
course, is to clean up. If dynamic memory is allocated for the iterator, up. If dynamic memory is allocated for the iterator, stop() is the
stop() is the place to free it. place to free it; if a lock was taken by start(), stop() must release
that lock. The value that *pos was set to by the last next() call
before stop() is remembered, and used for the first start() call of
the next session unless lseek() has been called on the file; in that
case next start() will be asked to start at position zero.
static void ct_seq_stop(struct seq_file *s, void *v) static void ct_seq_stop(struct seq_file *s, void *v)
{ {
......
...@@ -199,12 +199,13 @@ F: drivers/net/ethernet/8390/ ...@@ -199,12 +199,13 @@ F: drivers/net/ethernet/8390/
9P FILE SYSTEM 9P FILE SYSTEM
M: Eric Van Hensbergen <ericvh@gmail.com> M: Eric Van Hensbergen <ericvh@gmail.com>
M: Ron Minnich <rminnich@sandia.gov>
M: Latchesar Ionkov <lucho@ionkov.net> M: Latchesar Ionkov <lucho@ionkov.net>
M: Dominique Martinet <asmadeus@codewreck.org>
L: v9fs-developer@lists.sourceforge.net L: v9fs-developer@lists.sourceforge.net
W: http://swik.net/v9fs W: http://swik.net/v9fs
Q: http://patchwork.kernel.org/project/v9fs-devel/list/ Q: http://patchwork.kernel.org/project/v9fs-devel/list/
T: git git://git.kernel.org/pub/scm/linux/kernel/git/ericvh/v9fs.git T: git git://git.kernel.org/pub/scm/linux/kernel/git/ericvh/v9fs.git
T: git git://github.com/martinetd/linux.git
S: Maintained S: Maintained
F: Documentation/filesystems/9p.txt F: Documentation/filesystems/9p.txt
F: fs/9p/ F: fs/9p/
......
...@@ -87,7 +87,8 @@ do_page_fault(unsigned long address, unsigned long mmcsr, ...@@ -87,7 +87,8 @@ do_page_fault(unsigned long address, unsigned long mmcsr,
struct vm_area_struct * vma; struct vm_area_struct * vma;
struct mm_struct *mm = current->mm; struct mm_struct *mm = current->mm;
const struct exception_table_entry *fixup; const struct exception_table_entry *fixup;
int fault, si_code = SEGV_MAPERR; int si_code = SEGV_MAPERR;
vm_fault_t fault;
unsigned int flags = FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE; unsigned int flags = FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE;
/* As of EV6, a load into $31/$f31 is a prefetch, and never faults /* As of EV6, a load into $31/$f31 is a prefetch, and never faults
......
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
#include <linux/uaccess.h> #include <linux/uaccess.h>
#include <linux/kdebug.h> #include <linux/kdebug.h>
#include <linux/perf_event.h> #include <linux/perf_event.h>
#include <linux/mm_types.h>
#include <asm/pgalloc.h> #include <asm/pgalloc.h>
#include <asm/mmu.h> #include <asm/mmu.h>
...@@ -66,7 +67,8 @@ void do_page_fault(unsigned long address, struct pt_regs *regs) ...@@ -66,7 +67,8 @@ void do_page_fault(unsigned long address, struct pt_regs *regs)
struct task_struct *tsk = current; struct task_struct *tsk = current;
struct mm_struct *mm = tsk->mm; struct mm_struct *mm = tsk->mm;
siginfo_t info; siginfo_t info;
int fault, ret; int ret;
vm_fault_t fault;
int write = regs->ecr_cause & ECR_C_PROTV_STORE; /* ST/EX */ int write = regs->ecr_cause & ECR_C_PROTV_STORE; /* ST/EX */
unsigned int flags = FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE; unsigned int flags = FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE;
......
...@@ -594,7 +594,7 @@ static void *__alloc_from_contiguous(struct device *dev, size_t size, ...@@ -594,7 +594,7 @@ static void *__alloc_from_contiguous(struct device *dev, size_t size,
struct page *page; struct page *page;
void *ptr = NULL; void *ptr = NULL;
page = dma_alloc_from_contiguous(dev, count, order, gfp); page = dma_alloc_from_contiguous(dev, count, order, gfp & __GFP_NOWARN);
if (!page) if (!page)
return NULL; return NULL;
...@@ -1299,7 +1299,8 @@ static struct page **__iommu_alloc_buffer(struct device *dev, size_t size, ...@@ -1299,7 +1299,8 @@ static struct page **__iommu_alloc_buffer(struct device *dev, size_t size,
unsigned long order = get_order(size); unsigned long order = get_order(size);
struct page *page; struct page *page;
page = dma_alloc_from_contiguous(dev, count, order, gfp); page = dma_alloc_from_contiguous(dev, count, order,
gfp & __GFP_NOWARN);
if (!page) if (!page)
goto error; goto error;
......
...@@ -224,12 +224,12 @@ static inline bool access_error(unsigned int fsr, struct vm_area_struct *vma) ...@@ -224,12 +224,12 @@ static inline bool access_error(unsigned int fsr, struct vm_area_struct *vma)
return vma->vm_flags & mask ? false : true; return vma->vm_flags & mask ? false : true;
} }
static int __kprobes static vm_fault_t __kprobes
__do_page_fault(struct mm_struct *mm, unsigned long addr, unsigned int fsr, __do_page_fault(struct mm_struct *mm, unsigned long addr, unsigned int fsr,
unsigned int flags, struct task_struct *tsk) unsigned int flags, struct task_struct *tsk)
{ {
struct vm_area_struct *vma; struct vm_area_struct *vma;
int fault; vm_fault_t fault;
vma = find_vma(mm, addr); vma = find_vma(mm, addr);
fault = VM_FAULT_BADMAP; fault = VM_FAULT_BADMAP;
...@@ -264,7 +264,8 @@ do_page_fault(unsigned long addr, unsigned int fsr, struct pt_regs *regs) ...@@ -264,7 +264,8 @@ do_page_fault(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
{ {
struct task_struct *tsk; struct task_struct *tsk;
struct mm_struct *mm; struct mm_struct *mm;
int fault, sig, code; int sig, code;
vm_fault_t fault;
unsigned int flags = FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE; unsigned int flags = FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE;
if (notify_page_fault(regs, fsr)) if (notify_page_fault(regs, fsr))
......
...@@ -355,7 +355,7 @@ static int __init atomic_pool_init(void) ...@@ -355,7 +355,7 @@ static int __init atomic_pool_init(void)
if (dev_get_cma_area(NULL)) if (dev_get_cma_area(NULL))
page = dma_alloc_from_contiguous(NULL, nr_pages, page = dma_alloc_from_contiguous(NULL, nr_pages,
pool_size_order, GFP_KERNEL); pool_size_order, false);
else else
page = alloc_pages(GFP_DMA32, pool_size_order); page = alloc_pages(GFP_DMA32, pool_size_order);
...@@ -573,7 +573,7 @@ static void *__iommu_alloc_attrs(struct device *dev, size_t size, ...@@ -573,7 +573,7 @@ static void *__iommu_alloc_attrs(struct device *dev, size_t size,
struct page *page; struct page *page;
page = dma_alloc_from_contiguous(dev, size >> PAGE_SHIFT, page = dma_alloc_from_contiguous(dev, size >> PAGE_SHIFT,
get_order(size), gfp); get_order(size), gfp & __GFP_NOWARN);
if (!page) if (!page)
return NULL; return NULL;
......
...@@ -379,12 +379,12 @@ static void do_bad_area(unsigned long addr, unsigned int esr, struct pt_regs *re ...@@ -379,12 +379,12 @@ static void do_bad_area(unsigned long addr, unsigned int esr, struct pt_regs *re
#define VM_FAULT_BADMAP 0x010000 #define VM_FAULT_BADMAP 0x010000
#define VM_FAULT_BADACCESS 0x020000 #define VM_FAULT_BADACCESS 0x020000
static int __do_page_fault(struct mm_struct *mm, unsigned long addr, static vm_fault_t __do_page_fault(struct mm_struct *mm, unsigned long addr,
unsigned int mm_flags, unsigned long vm_flags, unsigned int mm_flags, unsigned long vm_flags,
struct task_struct *tsk) struct task_struct *tsk)
{ {
struct vm_area_struct *vma; struct vm_area_struct *vma;
int fault; vm_fault_t fault;
vma = find_vma(mm, addr); vma = find_vma(mm, addr);
fault = VM_FAULT_BADMAP; fault = VM_FAULT_BADMAP;
...@@ -427,7 +427,7 @@ static int __kprobes do_page_fault(unsigned long addr, unsigned int esr, ...@@ -427,7 +427,7 @@ static int __kprobes do_page_fault(unsigned long addr, unsigned int esr,
struct task_struct *tsk; struct task_struct *tsk;
struct mm_struct *mm; struct mm_struct *mm;
struct siginfo si; struct siginfo si;
int fault, major = 0; vm_fault_t fault, major = 0;
unsigned long vm_flags = VM_READ | VM_WRITE; unsigned long vm_flags = VM_READ | VM_WRITE;
unsigned int mm_flags = FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE; unsigned int mm_flags = FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE;
......
...@@ -52,7 +52,7 @@ void do_page_fault(unsigned long address, long cause, struct pt_regs *regs) ...@@ -52,7 +52,7 @@ void do_page_fault(unsigned long address, long cause, struct pt_regs *regs)
struct mm_struct *mm = current->mm; struct mm_struct *mm = current->mm;
int si_signo; int si_signo;
int si_code = SEGV_MAPERR; int si_code = SEGV_MAPERR;
int fault; vm_fault_t fault;
const struct exception_table_entry *fixup; const struct exception_table_entry *fixup;
unsigned int flags = FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE; unsigned int flags = FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE;
......
...@@ -86,7 +86,7 @@ ia64_do_page_fault (unsigned long address, unsigned long isr, struct pt_regs *re ...@@ -86,7 +86,7 @@ ia64_do_page_fault (unsigned long address, unsigned long isr, struct pt_regs *re
struct vm_area_struct *vma, *prev_vma; struct vm_area_struct *vma, *prev_vma;
struct mm_struct *mm = current->mm; struct mm_struct *mm = current->mm;
unsigned long mask; unsigned long mask;
int fault; vm_fault_t fault;
unsigned int flags = FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE; unsigned int flags = FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE;
mask = ((((isr >> IA64_ISR_X_BIT) & 1UL) << VM_EXEC_BIT) mask = ((((isr >> IA64_ISR_X_BIT) & 1UL) << VM_EXEC_BIT)
......
...@@ -70,7 +70,7 @@ int do_page_fault(struct pt_regs *regs, unsigned long address, ...@@ -70,7 +70,7 @@ int do_page_fault(struct pt_regs *regs, unsigned long address,
{ {
struct mm_struct *mm = current->mm; struct mm_struct *mm = current->mm;
struct vm_area_struct * vma; struct vm_area_struct * vma;
int fault; vm_fault_t fault;
unsigned int flags = FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE; unsigned int flags = FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE;
pr_debug("do page fault:\nregs->sr=%#x, regs->pc=%#lx, address=%#lx, %ld, %p\n", pr_debug("do page fault:\nregs->sr=%#x, regs->pc=%#lx, address=%#lx, %ld, %p\n",
...@@ -136,7 +136,7 @@ int do_page_fault(struct pt_regs *regs, unsigned long address, ...@@ -136,7 +136,7 @@ int do_page_fault(struct pt_regs *regs, unsigned long address,
*/ */
fault = handle_mm_fault(vma, address, flags); fault = handle_mm_fault(vma, address, flags);
pr_debug("handle_mm_fault returns %d\n", fault); pr_debug("handle_mm_fault returns %x\n", fault);
if ((fault & VM_FAULT_RETRY) && fatal_signal_pending(current)) if ((fault & VM_FAULT_RETRY) && fatal_signal_pending(current))
return 0; return 0;
......
...@@ -90,7 +90,7 @@ void do_page_fault(struct pt_regs *regs, unsigned long address, ...@@ -90,7 +90,7 @@ void do_page_fault(struct pt_regs *regs, unsigned long address,
struct mm_struct *mm = current->mm; struct mm_struct *mm = current->mm;
int code = SEGV_MAPERR; int code = SEGV_MAPERR;
int is_write = error_code & ESR_S; int is_write = error_code & ESR_S;
int fault; vm_fault_t fault;
unsigned int flags = FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE; unsigned int flags = FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE;
regs->ear = address; regs->ear = address;
......
...@@ -43,7 +43,7 @@ static void __kprobes __do_page_fault(struct pt_regs *regs, unsigned long write, ...@@ -43,7 +43,7 @@ static void __kprobes __do_page_fault(struct pt_regs *regs, unsigned long write,
struct mm_struct *mm = tsk->mm; struct mm_struct *mm = tsk->mm;
const int field = sizeof(unsigned long) * 2; const int field = sizeof(unsigned long) * 2;
int si_code; int si_code;
int fault; vm_fault_t fault;
unsigned int flags = FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE; unsigned int flags = FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE;
static DEFINE_RATELIMIT_STATE(ratelimit_state, 5 * HZ, 10); static DEFINE_RATELIMIT_STATE(ratelimit_state, 5 * HZ, 10);
......
...@@ -73,7 +73,7 @@ void do_page_fault(unsigned long entry, unsigned long addr, ...@@ -73,7 +73,7 @@ void do_page_fault(unsigned long entry, unsigned long addr,
struct mm_struct *mm; struct mm_struct *mm;
struct vm_area_struct *vma; struct vm_area_struct *vma;
int si_code; int si_code;
int fault; vm_fault_t fault;
unsigned int mask = VM_READ | VM_WRITE | VM_EXEC; unsigned int mask = VM_READ | VM_WRITE | VM_EXEC;
unsigned int flags = FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE; unsigned int flags = FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE;
......
...@@ -47,7 +47,7 @@ asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long cause, ...@@ -47,7 +47,7 @@ asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long cause,
struct task_struct *tsk = current; struct task_struct *tsk = current;
struct mm_struct *mm = tsk->mm; struct mm_struct *mm = tsk->mm;
int code = SEGV_MAPERR; int code = SEGV_MAPERR;
int fault; vm_fault_t fault;
unsigned int flags = FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE; unsigned int flags = FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE;
cause >>= 2; cause >>= 2;
......
...@@ -53,7 +53,7 @@ asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long address, ...@@ -53,7 +53,7 @@ asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long address,
struct mm_struct *mm; struct mm_struct *mm;
struct vm_area_struct *vma; struct vm_area_struct *vma;
int si_code; int si_code;
int fault; vm_fault_t fault;
unsigned int flags = FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE; unsigned int flags = FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE;
tsk = current; tsk = current;
......
...@@ -262,7 +262,7 @@ void do_page_fault(struct pt_regs *regs, unsigned long code, ...@@ -262,7 +262,7 @@ void do_page_fault(struct pt_regs *regs, unsigned long code,
struct task_struct *tsk; struct task_struct *tsk;
struct mm_struct *mm; struct mm_struct *mm;
unsigned long acc_type; unsigned long acc_type;
int fault = 0; vm_fault_t fault = 0;
unsigned int flags; unsigned int flags;
if (faulthandler_disabled()) if (faulthandler_disabled())
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment