Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 98388
b: refs/heads/master
c: 8dca7ff
h: refs/heads/master
v: v3
  • Loading branch information
Linus Torvalds committed Jun 23, 2008
1 parent e1f4a53 commit 4019c99
Show file tree
Hide file tree
Showing 5 changed files with 51 additions and 15 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 3e14b50dd4a3178f4f635267a2706b5d4f8c61ee
refs/heads/master: 8dca7ffe2cdbcf8a2f188c8230044c3225b70418
7 changes: 0 additions & 7 deletions trunk/drivers/char/tty_ioctl.c
Original file line number Diff line number Diff line change
Expand Up @@ -981,16 +981,9 @@ EXPORT_SYMBOL_GPL(tty_perform_flush);
int n_tty_ioctl(struct tty_struct *tty, struct file *file,
unsigned int cmd, unsigned long arg)
{
struct tty_struct *real_tty;
unsigned long flags;
int retval;

if (tty->driver->type == TTY_DRIVER_TYPE_PTY &&
tty->driver->subtype == PTY_TYPE_MASTER)
real_tty = tty->link;
else
real_tty = tty;

switch (cmd) {
case TCXONC:
retval = tty_check_change(tty);
Expand Down
2 changes: 1 addition & 1 deletion trunk/fs/select.c
Original file line number Diff line number Diff line change
Expand Up @@ -249,14 +249,14 @@ int do_select(int n, fd_set_bits *fds, s64 *timeout)
retval++;
}
}
cond_resched();
}
if (res_in)
*rinp = res_in;
if (res_out)
*routp = res_out;
if (res_ex)
*rexp = res_ex;
cond_resched();
}
wait = NULL;
if (retval || !*timeout || signal_pending(current))
Expand Down
5 changes: 2 additions & 3 deletions trunk/include/linux/tty_driver.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,7 @@
* This routine is called by the kernel to write a series of
* characters to the tty device. The characters may come from
* user space or kernel space. This routine will return the
* number of characters actually accepted for writing. This
* routine is mandatory.
* number of characters actually accepted for writing.
*
* Optional: Required for writable devices.
*
Expand Down Expand Up @@ -134,7 +133,7 @@
* This routine notifies the tty driver that it should hangup the
* tty device.
*
* Required:
* Optional:
*
* void (*break_ctl)(struct tty_stuct *tty, int state);
*
Expand Down
50 changes: 47 additions & 3 deletions trunk/mm/memory.c
Original file line number Diff line number Diff line change
Expand Up @@ -1045,6 +1045,26 @@ struct page *follow_page(struct vm_area_struct *vma, unsigned long address,
return page;
}

/* Can we do the FOLL_ANON optimization? */
static inline int use_zero_page(struct vm_area_struct *vma)
{
/*
* We don't want to optimize FOLL_ANON for make_pages_present()
* when it tries to page in a VM_LOCKED region. As to VM_SHARED,
* we want to get the page from the page tables to make sure
* that we serialize and update with any other user of that
* mapping.
*/
if (vma->vm_flags & (VM_LOCKED | VM_SHARED))
return 0;
/*
* And if we have a fault or a nopfn routine, it's not an
* anonymous region.
*/
return !vma->vm_ops ||
(!vma->vm_ops->fault && !vma->vm_ops->nopfn);
}

int get_user_pages(struct task_struct *tsk, struct mm_struct *mm,
unsigned long start, int len, int write, int force,
struct page **pages, struct vm_area_struct **vmas)
Expand Down Expand Up @@ -1119,8 +1139,7 @@ int get_user_pages(struct task_struct *tsk, struct mm_struct *mm,
foll_flags = FOLL_TOUCH;
if (pages)
foll_flags |= FOLL_GET;
if (!write && !(vma->vm_flags & VM_LOCKED) &&
(!vma->vm_ops || !vma->vm_ops->fault))
if (!write && use_zero_page(vma))
foll_flags |= FOLL_ANON;

do {
Expand Down Expand Up @@ -1766,7 +1785,6 @@ static int do_wp_page(struct mm_struct *mm, struct vm_area_struct *vma,
page_table = pte_offset_map_lock(mm, pmd, address, &ptl);
if (likely(pte_same(*page_table, orig_pte))) {
if (old_page) {
page_remove_rmap(old_page, vma);
if (!PageAnon(old_page)) {
dec_mm_counter(mm, file_rss);
inc_mm_counter(mm, anon_rss);
Expand All @@ -1788,6 +1806,32 @@ static int do_wp_page(struct mm_struct *mm, struct vm_area_struct *vma,
lru_cache_add_active(new_page);
page_add_new_anon_rmap(new_page, vma, address);

if (old_page) {
/*
* Only after switching the pte to the new page may
* we remove the mapcount here. Otherwise another
* process may come and find the rmap count decremented
* before the pte is switched to the new page, and
* "reuse" the old page writing into it while our pte
* here still points into it and can be read by other
* threads.
*
* The critical issue is to order this
* page_remove_rmap with the ptp_clear_flush above.
* Those stores are ordered by (if nothing else,)
* the barrier present in the atomic_add_negative
* in page_remove_rmap.
*
* Then the TLB flush in ptep_clear_flush ensures that
* no process can access the old page before the
* decremented mapcount is visible. And the old page
* cannot be reused until after the decremented
* mapcount is visible. So transitively, TLBs to
* old page will be flushed before it can be reused.
*/
page_remove_rmap(old_page, vma);
}

/* Free the old page.. */
new_page = old_page;
ret |= VM_FAULT_WRITE;
Expand Down

0 comments on commit 4019c99

Please sign in to comment.