From af073f3a9c7f91b6fa776e7e75fd60b6825f665d Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Sun, 30 Sep 2007 00:45:08 +0100 Subject: [PATCH] --- yaml --- r: 65239 b: refs/heads/master c: ca074a33928762c65e261dd94006c1b6a47e46fa h: refs/heads/master i: 65237: 319f6ae14a05974ed6eeb7704717f2ad23be9c46 65235: 54b28c3437c93253a8a32d1c387f672e2506a8f3 65231: 690bfea25007f88570bb619162327b41ad6addab v: v3 --- [refs] | 2 +- trunk/Documentation/devices.txt | 2 - trunk/arch/arm/kernel/bios32.c | 4 +- trunk/arch/x86_64/vdso/voffset.h | 2 +- trunk/drivers/char/vt_ioctl.c | 15 ++---- trunk/drivers/media/video/ivtv/ivtv-fileops.c | 6 +-- trunk/drivers/net/mv643xx_eth.c | 2 +- trunk/drivers/net/mv643xx_eth.h | 4 +- trunk/drivers/net/wireless/Makefile | 2 +- trunk/fs/splice.c | 46 +++++------------ trunk/fs/xfs/xfs_buf_item.h | 5 ++ trunk/fs/xfs/xfs_log_recover.c | 51 +++++++++++++++++-- trunk/fs/xfs/xfs_trans_buf.c | 1 + trunk/include/asm-i386/system.h | 5 ++ trunk/include/asm-mips/fcntl.h | 1 + trunk/kernel/futex.c | 26 ++++------ trunk/kernel/futex_compat.c | 28 ++++------ trunk/kernel/sys.c | 2 - trunk/mm/hugetlb.c | 2 +- 19 files changed, 107 insertions(+), 99 deletions(-) diff --git a/[refs] b/[refs] index 65734bd3a226..56957a5c7cd2 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: cf8dc57cbac0fe089308f57c333ab763c36782ff +refs/heads/master: ca074a33928762c65e261dd94006c1b6a47e46fa diff --git a/trunk/Documentation/devices.txt b/trunk/Documentation/devices.txt index 6c46730c631a..8de132a02ba9 100644 --- a/trunk/Documentation/devices.txt +++ b/trunk/Documentation/devices.txt @@ -94,8 +94,6 @@ Your cooperation is appreciated. 9 = /dev/urandom Faster, less secure random number gen. 10 = /dev/aio Asynchronous I/O notification interface 11 = /dev/kmsg Writes to this come out as printk's - 12 = /dev/oldmem Used by crashdump kernels to access - the memory of the kernel that crashed. 1 block RAM disk 0 = /dev/ram0 First RAM disk diff --git a/trunk/arch/arm/kernel/bios32.c b/trunk/arch/arm/kernel/bios32.c index a2dd930d11ef..240c448ec31c 100644 --- a/trunk/arch/arm/kernel/bios32.c +++ b/trunk/arch/arm/kernel/bios32.c @@ -338,7 +338,7 @@ pbus_assign_bus_resources(struct pci_bus *bus, struct pci_sys_data *root) * pcibios_fixup_bus - Called after each bus is probed, * but before its children are examined. */ -void pcibios_fixup_bus(struct pci_bus *bus) +void __devinit pcibios_fixup_bus(struct pci_bus *bus) { struct pci_sys_data *root = bus->sysdata; struct pci_dev *dev; @@ -419,7 +419,7 @@ void pcibios_fixup_bus(struct pci_bus *bus) /* * Convert from Linux-centric to bus-centric addresses for bridge devices. */ -void +void __devinit pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region, struct resource *res) { diff --git a/trunk/arch/x86_64/vdso/voffset.h b/trunk/arch/x86_64/vdso/voffset.h index 4af67c79085f..5304204911f2 100644 --- a/trunk/arch/x86_64/vdso/voffset.h +++ b/trunk/arch/x86_64/vdso/voffset.h @@ -1 +1 @@ -#define VDSO_TEXT_OFFSET 0x600 +#define VDSO_TEXT_OFFSET 0x500 diff --git a/trunk/drivers/char/vt_ioctl.c b/trunk/drivers/char/vt_ioctl.c index c799b7f7bbb3..c6f6f4209739 100644 --- a/trunk/drivers/char/vt_ioctl.c +++ b/trunk/drivers/char/vt_ioctl.c @@ -770,7 +770,6 @@ int vt_ioctl(struct tty_struct *tty, struct file * file, /* * Switching-from response */ - acquire_console_sem(); if (vc->vt_newvt >= 0) { if (arg == 0) /* @@ -785,6 +784,7 @@ int vt_ioctl(struct tty_struct *tty, struct file * file, * complete the switch. */ int newvt; + acquire_console_sem(); newvt = vc->vt_newvt; vc->vt_newvt = -1; i = vc_allocate(newvt); @@ -798,6 +798,7 @@ int vt_ioctl(struct tty_struct *tty, struct file * file, * other console switches.. */ complete_change_console(vc_cons[newvt].d); + release_console_sem(); } } @@ -809,12 +810,9 @@ int vt_ioctl(struct tty_struct *tty, struct file * file, /* * If it's just an ACK, ignore it */ - if (arg != VT_ACKACQ) { - release_console_sem(); + if (arg != VT_ACKACQ) return -EINVAL; - } } - release_console_sem(); return 0; @@ -1210,18 +1208,15 @@ void change_console(struct vc_data *new_vc) /* * Send the signal as privileged - kill_pid() will * tell us if the process has gone or something else - * is awry. - * - * We need to set vt_newvt *before* sending the signal or we - * have a race. + * is awry */ - vc->vt_newvt = new_vc->vc_num; if (kill_pid(vc->vt_pid, vc->vt_mode.relsig, 1) == 0) { /* * It worked. Mark the vt to switch to and * return. The process needs to send us a * VT_RELDISP ioctl to complete the switch. */ + vc->vt_newvt = new_vc->vc_num; return; } diff --git a/trunk/drivers/media/video/ivtv/ivtv-fileops.c b/trunk/drivers/media/video/ivtv/ivtv-fileops.c index 66ea3cbc369c..0285c4a830eb 100644 --- a/trunk/drivers/media/video/ivtv/ivtv-fileops.c +++ b/trunk/drivers/media/video/ivtv/ivtv-fileops.c @@ -754,11 +754,9 @@ static void ivtv_stop_decoding(struct ivtv_open_id *id, int flags, u64 pts) ivtv_yuv_close(itv); } if (s->type == IVTV_DEC_STREAM_TYPE_YUV && itv->output_mode == OUT_YUV) - itv->output_mode = OUT_NONE; - else if (s->type == IVTV_DEC_STREAM_TYPE_YUV && itv->output_mode == OUT_UDMA_YUV) - itv->output_mode = OUT_NONE; + itv->output_mode = OUT_NONE; else if (s->type == IVTV_DEC_STREAM_TYPE_MPG && itv->output_mode == OUT_MPG) - itv->output_mode = OUT_NONE; + itv->output_mode = OUT_NONE; itv->speed = 0; clear_bit(IVTV_F_I_DEC_PAUSED, &itv->i_flags); diff --git a/trunk/drivers/net/mv643xx_eth.c b/trunk/drivers/net/mv643xx_eth.c index 34288fe038c3..456d1e1c98bd 100644 --- a/trunk/drivers/net/mv643xx_eth.c +++ b/trunk/drivers/net/mv643xx_eth.c @@ -534,7 +534,7 @@ static irqreturn_t mv643xx_eth_int_handler(int irq, void *dev_id) } /* PHY status changed */ - if (eth_int_cause_ext & (ETH_INT_CAUSE_PHY | ETH_INT_CAUSE_STATE)) { + if (eth_int_cause_ext & ETH_INT_CAUSE_PHY) { struct ethtool_cmd cmd; if (mii_link_ok(&mp->mii)) { diff --git a/trunk/drivers/net/mv643xx_eth.h b/trunk/drivers/net/mv643xx_eth.h index 565b96696aca..82f8c0cbfb64 100644 --- a/trunk/drivers/net/mv643xx_eth.h +++ b/trunk/drivers/net/mv643xx_eth.h @@ -64,9 +64,7 @@ #define ETH_INT_CAUSE_TX_ERROR (ETH_TX_QUEUES_ENABLED << 8) #define ETH_INT_CAUSE_TX (ETH_INT_CAUSE_TX_DONE | ETH_INT_CAUSE_TX_ERROR) #define ETH_INT_CAUSE_PHY 0x00010000 -#define ETH_INT_CAUSE_STATE 0x00100000 -#define ETH_INT_UNMASK_ALL_EXT (ETH_INT_CAUSE_TX | ETH_INT_CAUSE_PHY | \ - ETH_INT_CAUSE_STATE) +#define ETH_INT_UNMASK_ALL_EXT (ETH_INT_CAUSE_TX | ETH_INT_CAUSE_PHY) #define ETH_INT_MASK_ALL 0x00000000 #define ETH_INT_MASK_ALL_EXT 0x00000000 diff --git a/trunk/drivers/net/wireless/Makefile b/trunk/drivers/net/wireless/Makefile index 4eb6d9752881..ef35bc6c4a22 100644 --- a/trunk/drivers/net/wireless/Makefile +++ b/trunk/drivers/net/wireless/Makefile @@ -43,7 +43,7 @@ obj-$(CONFIG_PCMCIA_RAYCS) += ray_cs.o obj-$(CONFIG_PCMCIA_WL3501) += wl3501_cs.o obj-$(CONFIG_USB_ZD1201) += zd1201.o -obj-$(CONFIG_LIBERTAS) += libertas/ +obj-$(CONFIG_LIBERTAS_USB) += libertas/ rtl8187-objs := rtl8187_dev.o rtl8187_rtl8225.o obj-$(CONFIG_RTL8187) += rtl8187.o diff --git a/trunk/fs/splice.c b/trunk/fs/splice.c index e95a36228863..c010a72ca2d2 100644 --- a/trunk/fs/splice.c +++ b/trunk/fs/splice.c @@ -1223,33 +1223,6 @@ static long do_splice(struct file *in, loff_t __user *off_in, return -EINVAL; } -/* - * Do a copy-from-user while holding the mmap_semaphore for reading, in a - * manner safe from deadlocking with simultaneous mmap() (grabbing mmap_sem - * for writing) and page faulting on the user memory pointed to by src. - * This assumes that we will very rarely hit the partial != 0 path, or this - * will not be a win. - */ -static int copy_from_user_mmap_sem(void *dst, const void __user *src, size_t n) -{ - int partial; - - pagefault_disable(); - partial = __copy_from_user_inatomic(dst, src, n); - pagefault_enable(); - - /* - * Didn't copy everything, drop the mmap_sem and do a faulting copy - */ - if (unlikely(partial)) { - up_read(¤t->mm->mmap_sem); - partial = copy_from_user(dst, src, n); - down_read(¤t->mm->mmap_sem); - } - - return partial; -} - /* * Map an iov into an array of pages and offset/length tupples. With the * partial_page structure, we can map several non-contiguous ranges into @@ -1263,26 +1236,31 @@ static int get_iovec_page_array(const struct iovec __user *iov, { int buffers = 0, error = 0; + /* + * It's ok to take the mmap_sem for reading, even + * across a "get_user()". + */ down_read(¤t->mm->mmap_sem); while (nr_vecs) { unsigned long off, npages; - struct iovec entry; void __user *base; size_t len; int i; - error = -EFAULT; - if (copy_from_user_mmap_sem(&entry, iov, sizeof(entry))) + /* + * Get user address base and length for this iovec. + */ + error = get_user(base, &iov->iov_base); + if (unlikely(error)) + break; + error = get_user(len, &iov->iov_len); + if (unlikely(error)) break; - - base = entry.iov_base; - len = entry.iov_len; /* * Sanity check this iovec. 0 read succeeds. */ - error = 0; if (unlikely(!len)) break; error = -EFAULT; diff --git a/trunk/fs/xfs/xfs_buf_item.h b/trunk/fs/xfs/xfs_buf_item.h index d7e136143066..fa25b7dcc6c3 100644 --- a/trunk/fs/xfs/xfs_buf_item.h +++ b/trunk/fs/xfs/xfs_buf_item.h @@ -52,6 +52,11 @@ typedef struct xfs_buf_log_format_t { #define XFS_BLI_UDQUOT_BUF 0x4 #define XFS_BLI_PDQUOT_BUF 0x8 #define XFS_BLI_GDQUOT_BUF 0x10 +/* + * This flag indicates that the buffer contains newly allocated + * inodes. + */ +#define XFS_BLI_INODE_NEW_BUF 0x20 #define XFS_BLI_CHUNK 128 #define XFS_BLI_SHIFT 7 diff --git a/trunk/fs/xfs/xfs_log_recover.c b/trunk/fs/xfs/xfs_log_recover.c index 8ae6e8e5f3db..7174991f4bef 100644 --- a/trunk/fs/xfs/xfs_log_recover.c +++ b/trunk/fs/xfs/xfs_log_recover.c @@ -1874,6 +1874,7 @@ xlog_recover_do_inode_buffer( /*ARGSUSED*/ STATIC void xlog_recover_do_reg_buffer( + xfs_mount_t *mp, xlog_recover_item_t *item, xfs_buf_t *bp, xfs_buf_log_format_t *buf_f) @@ -1884,6 +1885,50 @@ xlog_recover_do_reg_buffer( unsigned int *data_map = NULL; unsigned int map_size = 0; int error; + int stale_buf = 1; + + /* + * Scan through the on-disk inode buffer and attempt to + * determine if it has been written to since it was logged. + * + * - If any of the magic numbers are incorrect then the buffer is stale + * - If any of the modes are non-zero then the buffer is not stale + * - If all of the modes are zero and at least one of the generation + * counts is non-zero then the buffer is stale + * + * If the end result is a stale buffer then the log buffer is replayed + * otherwise it is skipped. + * + * This heuristic is not perfect. It can be improved by scanning the + * entire inode chunk for evidence that any of the inode clusters have + * been updated. To fix this problem completely we will need a major + * architectural change to the logging system. + */ + if (buf_f->blf_flags & XFS_BLI_INODE_NEW_BUF) { + xfs_dinode_t *dip; + int inodes_per_buf; + int mode_count = 0; + int gen_count = 0; + + stale_buf = 0; + inodes_per_buf = XFS_BUF_COUNT(bp) >> mp->m_sb.sb_inodelog; + for (i = 0; i < inodes_per_buf; i++) { + dip = (xfs_dinode_t *)xfs_buf_offset(bp, + i * mp->m_sb.sb_inodesize); + if (be16_to_cpu(dip->di_core.di_magic) != + XFS_DINODE_MAGIC) { + stale_buf = 1; + break; + } + if (dip->di_core.di_mode) + mode_count++; + if (dip->di_core.di_gen) + gen_count++; + } + + if (!mode_count && gen_count) + stale_buf = 1; + } switch (buf_f->blf_type) { case XFS_LI_BUF: @@ -1917,7 +1962,7 @@ xlog_recover_do_reg_buffer( -1, 0, XFS_QMOPT_DOWARN, "dquot_buf_recover"); } - if (!error) + if (!error && stale_buf) memcpy(xfs_buf_offset(bp, (uint)bit << XFS_BLI_SHIFT), /* dest */ item->ri_buf[i].i_addr, /* source */ @@ -2089,7 +2134,7 @@ xlog_recover_do_dquot_buffer( if (log->l_quotaoffs_flag & type) return; - xlog_recover_do_reg_buffer(item, bp, buf_f); + xlog_recover_do_reg_buffer(mp, item, bp, buf_f); } /* @@ -2190,7 +2235,7 @@ xlog_recover_do_buffer_trans( (XFS_BLI_UDQUOT_BUF|XFS_BLI_PDQUOT_BUF|XFS_BLI_GDQUOT_BUF)) { xlog_recover_do_dquot_buffer(mp, log, item, bp, buf_f); } else { - xlog_recover_do_reg_buffer(item, bp, buf_f); + xlog_recover_do_reg_buffer(mp, item, bp, buf_f); } if (error) return XFS_ERROR(error); diff --git a/trunk/fs/xfs/xfs_trans_buf.c b/trunk/fs/xfs/xfs_trans_buf.c index 60b6b898022b..95fff6872a2f 100644 --- a/trunk/fs/xfs/xfs_trans_buf.c +++ b/trunk/fs/xfs/xfs_trans_buf.c @@ -966,6 +966,7 @@ xfs_trans_inode_alloc_buf( ASSERT(atomic_read(&bip->bli_refcount) > 0); bip->bli_flags |= XFS_BLI_INODE_ALLOC_BUF; + bip->bli_format.blf_flags |= XFS_BLI_INODE_NEW_BUF; } diff --git a/trunk/include/asm-i386/system.h b/trunk/include/asm-i386/system.h index d69ba937e092..609756c61676 100644 --- a/trunk/include/asm-i386/system.h +++ b/trunk/include/asm-i386/system.h @@ -214,6 +214,11 @@ static inline unsigned long get_limit(unsigned long segment) */ +/* + * Actually only lfence would be needed for mb() because all stores done + * by the kernel should be already ordered. But keep a full barrier for now. + */ + #define mb() alternative("lock; addl $0,0(%%esp)", "mfence", X86_FEATURE_XMM2) #define rmb() alternative("lock; addl $0,0(%%esp)", "lfence", X86_FEATURE_XMM2) diff --git a/trunk/include/asm-mips/fcntl.h b/trunk/include/asm-mips/fcntl.h index 00a50ec1c19f..2a52333a062d 100644 --- a/trunk/include/asm-mips/fcntl.h +++ b/trunk/include/asm-mips/fcntl.h @@ -13,6 +13,7 @@ #define O_SYNC 0x0010 #define O_NONBLOCK 0x0080 #define O_CREAT 0x0100 /* not fcntl */ +#define O_TRUNC 0x0200 /* not fcntl */ #define O_EXCL 0x0400 /* not fcntl */ #define O_NOCTTY 0x0800 /* not fcntl */ #define FASYNC 0x1000 /* fcntl, for BSD compatibility */ diff --git a/trunk/kernel/futex.c b/trunk/kernel/futex.c index fcc94e7b4086..e8935b195e88 100644 --- a/trunk/kernel/futex.c +++ b/trunk/kernel/futex.c @@ -1943,10 +1943,9 @@ static inline int fetch_robust_entry(struct robust_list __user **entry, void exit_robust_list(struct task_struct *curr) { struct robust_list_head __user *head = curr->robust_list; - struct robust_list __user *entry, *next_entry, *pending; - unsigned int limit = ROBUST_LIST_LIMIT, pi, next_pi, pip; + struct robust_list __user *entry, *pending; + unsigned int limit = ROBUST_LIST_LIMIT, pi, pip; unsigned long futex_offset; - int rc; /* * Fetch the list head (which was registered earlier, via @@ -1966,13 +1965,11 @@ void exit_robust_list(struct task_struct *curr) if (fetch_robust_entry(&pending, &head->list_op_pending, &pip)) return; - next_entry = NULL; /* avoid warning with gcc */ + if (pending) + handle_futex_death((void __user *)pending + futex_offset, + curr, pip); + while (entry != &head->list) { - /* - * Fetch the next entry in the list before calling - * handle_futex_death: - */ - rc = fetch_robust_entry(&next_entry, &entry->next, &next_pi); /* * A pending lock might already be on the list, so * don't process it twice: @@ -1981,10 +1978,11 @@ void exit_robust_list(struct task_struct *curr) if (handle_futex_death((void __user *)entry + futex_offset, curr, pi)) return; - if (rc) + /* + * Fetch the next entry in the list: + */ + if (fetch_robust_entry(&entry, &entry->next, &pi)) return; - entry = next_entry; - pi = next_pi; /* * Avoid excessively long or circular lists: */ @@ -1993,10 +1991,6 @@ void exit_robust_list(struct task_struct *curr) cond_resched(); } - - if (pending) - handle_futex_death((void __user *)pending + futex_offset, - curr, pip); } long do_futex(u32 __user *uaddr, int op, u32 val, ktime_t *timeout, diff --git a/trunk/kernel/futex_compat.c b/trunk/kernel/futex_compat.c index 2c2e2954b713..7e52eb051f22 100644 --- a/trunk/kernel/futex_compat.c +++ b/trunk/kernel/futex_compat.c @@ -38,11 +38,10 @@ fetch_robust_entry(compat_uptr_t *uentry, struct robust_list __user **entry, void compat_exit_robust_list(struct task_struct *curr) { struct compat_robust_list_head __user *head = curr->compat_robust_list; - struct robust_list __user *entry, *next_entry, *pending; - unsigned int limit = ROBUST_LIST_LIMIT, pi, next_pi, pip; - compat_uptr_t uentry, next_uentry, upending; + struct robust_list __user *entry, *pending; + unsigned int limit = ROBUST_LIST_LIMIT, pi, pip; + compat_uptr_t uentry, upending; compat_long_t futex_offset; - int rc; /* * Fetch the list head (which was registered earlier, via @@ -62,15 +61,10 @@ void compat_exit_robust_list(struct task_struct *curr) if (fetch_robust_entry(&upending, &pending, &head->list_op_pending, &pip)) return; + if (pending) + handle_futex_death((void __user *)pending + futex_offset, curr, pip); - next_entry = NULL; /* avoid warning with gcc */ while (entry != (struct robust_list __user *) &head->list) { - /* - * Fetch the next entry in the list before calling - * handle_futex_death: - */ - rc = fetch_robust_entry(&next_uentry, &next_entry, - (compat_uptr_t __user *)&entry->next, &next_pi); /* * A pending lock might already be on the list, so * dont process it twice: @@ -80,11 +74,12 @@ void compat_exit_robust_list(struct task_struct *curr) curr, pi)) return; - if (rc) + /* + * Fetch the next entry in the list: + */ + if (fetch_robust_entry(&uentry, &entry, + (compat_uptr_t __user *)&entry->next, &pi)) return; - uentry = next_uentry; - entry = next_entry; - pi = next_pi; /* * Avoid excessively long or circular lists: */ @@ -93,9 +88,6 @@ void compat_exit_robust_list(struct task_struct *curr) cond_resched(); } - if (pending) - handle_futex_death((void __user *)pending + futex_offset, - curr, pip); } asmlinkage long diff --git a/trunk/kernel/sys.c b/trunk/kernel/sys.c index 8ae2e636eb1b..1b33b05d346b 100644 --- a/trunk/kernel/sys.c +++ b/trunk/kernel/sys.c @@ -32,7 +32,6 @@ #include #include #include -#include #include #include @@ -879,7 +878,6 @@ void kernel_power_off(void) kernel_shutdown_prepare(SYSTEM_POWER_OFF); if (pm_power_off_prepare) pm_power_off_prepare(); - disable_nonboot_cpus(); sysdev_shutdown(); printk(KERN_EMERG "Power down.\n"); machine_power_off(); diff --git a/trunk/mm/hugetlb.c b/trunk/mm/hugetlb.c index eab8c428cc93..84c795ee2d65 100644 --- a/trunk/mm/hugetlb.c +++ b/trunk/mm/hugetlb.c @@ -42,7 +42,7 @@ static void clear_huge_page(struct page *page, unsigned long addr) might_sleep(); for (i = 0; i < (HPAGE_SIZE/PAGE_SIZE); i++) { cond_resched(); - clear_user_highpage(page + i, addr + i * PAGE_SIZE); + clear_user_highpage(page + i, addr); } }