Skip to content

Commit

Permalink
Merge branch 'akpm' (fixes from Andrew)
Browse files Browse the repository at this point in the history
Merge patches from Andrew Morton:
 "13 fixes"

* emailed patches from Andrew Morton <[email protected]>:
  mm: place page->pmd_huge_pte to right union
  MAINTAINERS: add keyboard driver to Hyper-V file list
  x86, mm: do not leak page->ptl for pmd page tables
  ipc,shm: correct error return value in shmctl (SHM_UNLOCK)
  mm, mempolicy: silence gcc warning
  block/partitions/efi.c: fix bound check
  ARM: drivers/rtc/rtc-at91rm9200.c: disable interrupts at shutdown
  mm: hugetlbfs: fix hugetlbfs optimization
  kernel: remove CONFIG_USE_GENERIC_SMP_HELPERS cleanly
  ipc,shm: fix shm_file deletion races
  mm: thp: give transparent hugepage code a separate copy_page
  checkpatch: fix "Use of uninitialized value" warnings
  configfs: fix race between dentry put and lookup
  • Loading branch information
torvalds committed Nov 22, 2013
2 parents 78dc53c + 7aa555b commit a5d6e63
Show file tree
Hide file tree
Showing 16 changed files with 227 additions and 124 deletions.
6 changes: 3 additions & 3 deletions Documentation/vm/split_page_table_lock
Original file line number Diff line number Diff line change
Expand Up @@ -63,9 +63,9 @@ levels.
PMD split lock enabling requires pgtable_pmd_page_ctor() call on PMD table
allocation and pgtable_pmd_page_dtor() on freeing.

Allocation usually happens in pmd_alloc_one(), freeing in pmd_free(), but
make sure you cover all PMD table allocation / freeing paths: i.e X86_PAE
preallocate few PMDs on pgd_alloc().
Allocation usually happens in pmd_alloc_one(), freeing in pmd_free() and
pmd_free_tlb(), but make sure you cover all PMD table allocation / freeing
paths: i.e X86_PAE preallocate few PMDs on pgd_alloc().

With everything in place you can set CONFIG_ARCH_ENABLE_SPLIT_PMD_PTLOCK.

Expand Down
1 change: 1 addition & 0 deletions MAINTAINERS
Original file line number Diff line number Diff line change
Expand Up @@ -4065,6 +4065,7 @@ F: arch/x86/include/uapi/asm/hyperv.h
F: arch/x86/kernel/cpu/mshyperv.c
F: drivers/hid/hid-hyperv.c
F: drivers/hv/
F: drivers/input/serio/hyperv-keyboard.c
F: drivers/net/hyperv/
F: drivers/scsi/storvsc_drv.c
F: drivers/video/hyperv_fb.c
Expand Down
4 changes: 3 additions & 1 deletion arch/x86/mm/pgtable.c
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ void ___pte_free_tlb(struct mmu_gather *tlb, struct page *pte)
#if PAGETABLE_LEVELS > 2
void ___pmd_free_tlb(struct mmu_gather *tlb, pmd_t *pmd)
{
struct page *page = virt_to_page(pmd);
paravirt_release_pmd(__pa(pmd) >> PAGE_SHIFT);
/*
* NOTE! For PAE, any changes to the top page-directory-pointer-table
Expand All @@ -69,7 +70,8 @@ void ___pmd_free_tlb(struct mmu_gather *tlb, pmd_t *pmd)
#ifdef CONFIG_X86_PAE
tlb->need_flush_all = 1;
#endif
tlb_remove_page(tlb, virt_to_page(pmd));
pgtable_pmd_page_dtor(page);
tlb_remove_page(tlb, page);
}

#if PAGETABLE_LEVELS > 3
Expand Down
5 changes: 3 additions & 2 deletions block/partitions/efi.c
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@
* - Code works, detects all the partitions.
*
************************************************************/
#include <linux/kernel.h>
#include <linux/crc32.h>
#include <linux/ctype.h>
#include <linux/math64.h>
Expand Down Expand Up @@ -715,8 +716,8 @@ int efi_partition(struct parsed_partitions *state)
efi_guid_unparse(&ptes[i].unique_partition_guid, info->uuid);

/* Naively convert UTF16-LE to 7 bits. */
label_max = min(sizeof(info->volname) - 1,
sizeof(ptes[i].partition_name));
label_max = min(ARRAY_SIZE(info->volname) - 1,
ARRAY_SIZE(ptes[i].partition_name));
info->volname[label_max] = 0;
while (label_count < label_max) {
u8 c = ptes[i].partition_name[label_count] & 0xff;
Expand Down
8 changes: 4 additions & 4 deletions drivers/block/null_blk.c
Original file line number Diff line number Diff line change
Expand Up @@ -223,7 +223,7 @@ static void null_softirq_done_fn(struct request *rq)
blk_end_request_all(rq, 0);
}

#if defined(CONFIG_SMP) && defined(CONFIG_USE_GENERIC_SMP_HELPERS)
#ifdef CONFIG_SMP

static void null_ipi_cmd_end_io(void *data)
{
Expand Down Expand Up @@ -260,7 +260,7 @@ static void null_cmd_end_ipi(struct nullb_cmd *cmd)
put_cpu();
}

#endif /* CONFIG_SMP && CONFIG_USE_GENERIC_SMP_HELPERS */
#endif /* CONFIG_SMP */

static inline void null_handle_cmd(struct nullb_cmd *cmd)
{
Expand All @@ -270,7 +270,7 @@ static inline void null_handle_cmd(struct nullb_cmd *cmd)
end_cmd(cmd);
break;
case NULL_IRQ_SOFTIRQ:
#if defined(CONFIG_SMP) && defined(CONFIG_USE_GENERIC_SMP_HELPERS)
#ifdef CONFIG_SMP
null_cmd_end_ipi(cmd);
#else
end_cmd(cmd);
Expand Down Expand Up @@ -571,7 +571,7 @@ static int __init null_init(void)
{
unsigned int i;

#if !defined(CONFIG_SMP) || !defined(CONFIG_USE_GENERIC_SMP_HELPERS)
#if !defined(CONFIG_SMP)
if (irqmode == NULL_IRQ_SOFTIRQ) {
pr_warn("null_blk: softirq completions not available.\n");
pr_warn("null_blk: using direct completions.\n");
Expand Down
9 changes: 9 additions & 0 deletions drivers/rtc/rtc-at91rm9200.c
Original file line number Diff line number Diff line change
Expand Up @@ -428,6 +428,14 @@ static int __exit at91_rtc_remove(struct platform_device *pdev)
return 0;
}

static void at91_rtc_shutdown(struct platform_device *pdev)
{
/* Disable all interrupts */
at91_rtc_write(AT91_RTC_IDR, AT91_RTC_ACKUPD | AT91_RTC_ALARM |
AT91_RTC_SECEV | AT91_RTC_TIMEV |
AT91_RTC_CALEV);
}

#ifdef CONFIG_PM_SLEEP

/* AT91RM9200 RTC Power management control */
Expand Down Expand Up @@ -466,6 +474,7 @@ static SIMPLE_DEV_PM_OPS(at91_rtc_pm_ops, at91_rtc_suspend, at91_rtc_resume);

static struct platform_driver at91_rtc_driver = {
.remove = __exit_p(at91_rtc_remove),
.shutdown = at91_rtc_shutdown,
.driver = {
.name = "at91_rtc",
.owner = THIS_MODULE,
Expand Down
16 changes: 14 additions & 2 deletions fs/configfs/dir.c
Original file line number Diff line number Diff line change
Expand Up @@ -56,10 +56,19 @@ static void configfs_d_iput(struct dentry * dentry,
struct configfs_dirent *sd = dentry->d_fsdata;

if (sd) {
BUG_ON(sd->s_dentry != dentry);
/* Coordinate with configfs_readdir */
spin_lock(&configfs_dirent_lock);
sd->s_dentry = NULL;
/* Coordinate with configfs_attach_attr where will increase
* sd->s_count and update sd->s_dentry to new allocated one.
* Only set sd->dentry to null when this dentry is the only
* sd owner.
* If not do so, configfs_d_iput may run just after
* configfs_attach_attr and set sd->s_dentry to null
* even it's still in use.
*/
if (atomic_read(&sd->s_count) <= 2)
sd->s_dentry = NULL;

spin_unlock(&configfs_dirent_lock);
configfs_put(sd);
}
Expand Down Expand Up @@ -416,8 +425,11 @@ static int configfs_attach_attr(struct configfs_dirent * sd, struct dentry * den
struct configfs_attribute * attr = sd->s_element;
int error;

spin_lock(&configfs_dirent_lock);
dentry->d_fsdata = configfs_get(sd);
sd->s_dentry = dentry;
spin_unlock(&configfs_dirent_lock);

error = configfs_create(dentry, (attr->ca_mode & S_IALLUGO) | S_IFREG,
configfs_init_file);
if (error) {
Expand Down
10 changes: 6 additions & 4 deletions include/linux/hugetlb.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ struct hugepage_subpool *hugepage_new_subpool(long nr_blocks);
void hugepage_put_subpool(struct hugepage_subpool *spool);

int PageHuge(struct page *page);
int PageHeadHuge(struct page *page_head);

void reset_vma_resv_huge_pages(struct vm_area_struct *vma);
int hugetlb_sysctl_handler(struct ctl_table *, int, void __user *, size_t *, loff_t *);
Expand Down Expand Up @@ -69,7 +70,6 @@ int dequeue_hwpoisoned_huge_page(struct page *page);
bool isolate_huge_page(struct page *page, struct list_head *list);
void putback_active_hugepage(struct page *page);
bool is_hugepage_active(struct page *page);
void copy_huge_page(struct page *dst, struct page *src);

#ifdef CONFIG_ARCH_WANT_HUGE_PMD_SHARE
pte_t *huge_pmd_share(struct mm_struct *mm, unsigned long addr, pud_t *pud);
Expand Down Expand Up @@ -104,6 +104,11 @@ static inline int PageHuge(struct page *page)
return 0;
}

static inline int PageHeadHuge(struct page *page_head)
{
return 0;
}

static inline void reset_vma_resv_huge_pages(struct vm_area_struct *vma)
{
}
Expand Down Expand Up @@ -140,9 +145,6 @@ static inline int dequeue_hwpoisoned_huge_page(struct page *page)
#define isolate_huge_page(p, l) false
#define putback_active_hugepage(p) do {} while (0)
#define is_hugepage_active(x) false
static inline void copy_huge_page(struct page *dst, struct page *src)
{
}

static inline unsigned long hugetlb_change_protection(struct vm_area_struct *vma,
unsigned long address, unsigned long end, pgprot_t newprot)
Expand Down
6 changes: 3 additions & 3 deletions include/linux/mm_types.h
Original file line number Diff line number Diff line change
Expand Up @@ -65,9 +65,6 @@ struct page {
* this page is only used to
* free other pages.
*/
#if defined(CONFIG_TRANSPARENT_HUGEPAGE) && USE_SPLIT_PMD_PTLOCKS
pgtable_t pmd_huge_pte; /* protected by page->ptl */
#endif
};

union {
Expand Down Expand Up @@ -135,6 +132,9 @@ struct page {

struct list_head list; /* slobs list of pages */
struct slab *slab_page; /* slab fields */
#if defined(CONFIG_TRANSPARENT_HUGEPAGE) && USE_SPLIT_PMD_PTLOCKS
pgtable_t pmd_huge_pte; /* protected by page->ptl */
#endif
};

/* Remainder is not double word aligned */
Expand Down
37 changes: 29 additions & 8 deletions ipc/shm.c
Original file line number Diff line number Diff line change
Expand Up @@ -208,15 +208,18 @@ static void shm_open(struct vm_area_struct *vma)
*/
static void shm_destroy(struct ipc_namespace *ns, struct shmid_kernel *shp)
{
struct file *shm_file;

shm_file = shp->shm_file;
shp->shm_file = NULL;
ns->shm_tot -= (shp->shm_segsz + PAGE_SIZE - 1) >> PAGE_SHIFT;
shm_rmid(ns, shp);
shm_unlock(shp);
if (!is_file_hugepages(shp->shm_file))
shmem_lock(shp->shm_file, 0, shp->mlock_user);
if (!is_file_hugepages(shm_file))
shmem_lock(shm_file, 0, shp->mlock_user);
else if (shp->mlock_user)
user_shm_unlock(file_inode(shp->shm_file)->i_size,
shp->mlock_user);
fput (shp->shm_file);
user_shm_unlock(file_inode(shm_file)->i_size, shp->mlock_user);
fput(shm_file);
ipc_rcu_putref(shp, shm_rcu_free);
}

Expand Down Expand Up @@ -974,15 +977,25 @@ SYSCALL_DEFINE3(shmctl, int, shmid, int, cmd, struct shmid_ds __user *, buf)
ipc_lock_object(&shp->shm_perm);
if (!ns_capable(ns->user_ns, CAP_IPC_LOCK)) {
kuid_t euid = current_euid();
err = -EPERM;
if (!uid_eq(euid, shp->shm_perm.uid) &&
!uid_eq(euid, shp->shm_perm.cuid))
!uid_eq(euid, shp->shm_perm.cuid)) {
err = -EPERM;
goto out_unlock0;
if (cmd == SHM_LOCK && !rlimit(RLIMIT_MEMLOCK))
}
if (cmd == SHM_LOCK && !rlimit(RLIMIT_MEMLOCK)) {
err = -EPERM;
goto out_unlock0;
}
}

shm_file = shp->shm_file;

/* check if shm_destroy() is tearing down shp */
if (shm_file == NULL) {
err = -EIDRM;
goto out_unlock0;
}

if (is_file_hugepages(shm_file))
goto out_unlock0;

Expand Down Expand Up @@ -1101,6 +1114,14 @@ long do_shmat(int shmid, char __user *shmaddr, int shmflg, ulong *raddr,
goto out_unlock;

ipc_lock_object(&shp->shm_perm);

/* check if shm_destroy() is tearing down shp */
if (shp->shm_file == NULL) {
ipc_unlock_object(&shp->shm_perm);
err = -EIDRM;
goto out_unlock;
}

path = shp->shm_file->f_path;
path_get(&path);
shp->shm_nattch++;
Expand Down
51 changes: 17 additions & 34 deletions mm/hugetlb.c
Original file line number Diff line number Diff line change
Expand Up @@ -476,40 +476,6 @@ static int vma_has_reserves(struct vm_area_struct *vma, long chg)
return 0;
}

static void copy_gigantic_page(struct page *dst, struct page *src)
{
int i;
struct hstate *h = page_hstate(src);
struct page *dst_base = dst;
struct page *src_base = src;

for (i = 0; i < pages_per_huge_page(h); ) {
cond_resched();
copy_highpage(dst, src);

i++;
dst = mem_map_next(dst, dst_base, i);
src = mem_map_next(src, src_base, i);
}
}

void copy_huge_page(struct page *dst, struct page *src)
{
int i;
struct hstate *h = page_hstate(src);

if (unlikely(pages_per_huge_page(h) > MAX_ORDER_NR_PAGES)) {
copy_gigantic_page(dst, src);
return;
}

might_sleep();
for (i = 0; i < pages_per_huge_page(h); i++) {
cond_resched();
copy_highpage(dst + i, src + i);
}
}

static void enqueue_huge_page(struct hstate *h, struct page *page)
{
int nid = page_to_nid(page);
Expand Down Expand Up @@ -736,6 +702,23 @@ int PageHuge(struct page *page)
}
EXPORT_SYMBOL_GPL(PageHuge);

/*
* PageHeadHuge() only returns true for hugetlbfs head page, but not for
* normal or transparent huge pages.
*/
int PageHeadHuge(struct page *page_head)
{
compound_page_dtor *dtor;

if (!PageHead(page_head))
return 0;

dtor = get_compound_page_dtor(page_head);

return dtor == free_huge_page;
}
EXPORT_SYMBOL_GPL(PageHeadHuge);

pgoff_t __basepage_index(struct page *page)
{
struct page *page_head = compound_head(page);
Expand Down
2 changes: 1 addition & 1 deletion mm/mempolicy.c
Original file line number Diff line number Diff line change
Expand Up @@ -2950,7 +2950,7 @@ void mpol_to_str(char *buffer, int maxlen, struct mempolicy *pol)
return;
}

p += snprintf(p, maxlen, policy_modes[mode]);
p += snprintf(p, maxlen, "%s", policy_modes[mode]);

if (flags & MPOL_MODE_FLAGS) {
p += snprintf(p, buffer + maxlen - p, "=");
Expand Down
Loading

0 comments on commit a5d6e63

Please sign in to comment.