From a42e8e0372bbddaf9b023069e44240ed0d24f871 Mon Sep 17 00:00:00 2001 From: Tony Luck Date: Wed, 18 Aug 2010 10:17:44 -0700 Subject: [PATCH] --- yaml --- r: 209645 b: refs/heads/master c: 145e5aa269d54e4ea53fdb5e597007bd287fbe49 h: refs/heads/master i: 209643: bbee2cc7d4f5bda7beb8a2ba6f65119ca5773091 v: v3 --- [refs] | 2 +- .../powerpc/booting-without-of.txt | 31 ++- trunk/arch/ia64/include/asm/unistd.h | 2 - trunk/arch/m68k/include/asm/ide.h | 13 +- trunk/arch/m68knommu/kernel/process.c | 10 +- trunk/arch/microblaze/kernel/prom_parse.c | 2 +- trunk/arch/microblaze/pci/pci-common.c | 5 +- trunk/arch/microblaze/pci/xilinx_pci.c | 1 - trunk/drivers/ata/sata_dwc_460ex.c | 4 +- trunk/drivers/block/xsysace.c | 1 - trunk/drivers/char/pty.c | 4 +- trunk/drivers/char/tty_io.c | 92 +++----- .../char/xilinx_hwicap/xilinx_hwicap.c | 1 - trunk/drivers/md/md.c | 44 ++-- trunk/drivers/md/raid1.c | 21 +- trunk/drivers/md/raid10.c | 17 +- trunk/drivers/md/raid5.c | 13 +- trunk/drivers/mmc/core/host.c | 2 - trunk/drivers/mtd/maps/physmap_of.c | 1 - trunk/drivers/serial/of_serial.c | 3 +- trunk/drivers/spi/coldfire_qspi.c | 1 - trunk/drivers/staging/pohmelfs/path_entry.c | 8 +- trunk/fs/buffer.c | 69 +++--- trunk/fs/cramfs/inode.c | 2 +- trunk/fs/dcache.c | 71 +++--- trunk/fs/exec.c | 4 +- trunk/fs/fat/misc.c | 4 +- trunk/fs/file_table.c | 124 +++-------- trunk/fs/fs_struct.c | 32 +-- trunk/fs/generic_acl.c | 1 - trunk/fs/hostfs/hostfs_kern.c | 4 +- trunk/fs/internal.h | 7 +- trunk/fs/jbd/checkpoint.c | 4 +- trunk/fs/jbd/commit.c | 49 ++--- trunk/fs/jbd/journal.c | 2 +- trunk/fs/jbd/revoke.c | 2 +- trunk/fs/jbd2/checkpoint.c | 4 +- trunk/fs/jbd2/commit.c | 39 ++-- trunk/fs/jbd2/journal.c | 2 +- trunk/fs/jbd2/revoke.c | 2 +- trunk/fs/mbcache.c | 30 +-- trunk/fs/namei.c | 119 +++++----- trunk/fs/namespace.c | 177 ++++++--------- trunk/fs/nilfs2/super.c | 28 +-- trunk/fs/open.c | 4 +- trunk/fs/pnode.c | 11 +- trunk/fs/reiserfs/inode.c | 1 - trunk/fs/reiserfs/journal.c | 2 +- trunk/fs/super.c | 18 -- trunk/fs/ufs/balloc.c | 24 +- trunk/fs/ufs/ialloc.c | 18 +- trunk/fs/ufs/truncate.c | 18 +- trunk/fs/ufs/util.c | 20 +- trunk/fs/ufs/util.h | 3 +- trunk/include/asm-generic/syscalls.h | 6 +- trunk/include/linux/buffer_head.h | 4 +- trunk/include/linux/fs.h | 21 +- trunk/include/linux/fs_struct.h | 14 +- trunk/include/linux/lglock.h | 172 --------------- trunk/include/linux/spi/spi.h | 3 - trunk/include/linux/tty.h | 9 - trunk/include/sound/emu10k1.h | 1 - trunk/kernel/fork.c | 10 +- trunk/kernel/trace/ring_buffer.c | 3 - trunk/kernel/trace/trace.c | 11 +- trunk/kernel/trace/trace_events.c | 207 ++++++------------ trunk/kernel/trace/trace_functions_graph.c | 10 +- trunk/lib/Kconfig.debug | 5 +- trunk/scripts/recordmcount.pl | 7 +- trunk/security/apparmor/path.c | 9 +- trunk/security/selinux/hooks.c | 9 +- trunk/sound/core/pcm_native.c | 4 - trunk/sound/pci/emu10k1/emu10k1.c | 4 - trunk/sound/pci/emu10k1/emupcm.c | 30 +-- trunk/sound/pci/emu10k1/memory.c | 4 +- trunk/sound/pci/hda/patch_conexant.c | 1 - trunk/sound/pci/hda/patch_realtek.c | 176 +++------------ trunk/sound/pci/riptide/riptide.c | 11 +- trunk/sound/soc/codecs/wm8776.c | 7 + trunk/tools/perf/Makefile | 16 +- trunk/tools/perf/util/ui/browsers/annotate.c | 3 +- 81 files changed, 670 insertions(+), 1260 deletions(-) delete mode 100644 trunk/include/linux/lglock.h diff --git a/[refs] b/[refs] index 263ed9eadd6e..8a82d8a245ce 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: d15ca3203754359cfe5d18910722d3089b204cc4 +refs/heads/master: 145e5aa269d54e4ea53fdb5e597007bd287fbe49 diff --git a/trunk/Documentation/powerpc/booting-without-of.txt b/trunk/Documentation/powerpc/booting-without-of.txt index 302db5da49b3..568fa08e82e5 100644 --- a/trunk/Documentation/powerpc/booting-without-of.txt +++ b/trunk/Documentation/powerpc/booting-without-of.txt @@ -49,13 +49,40 @@ Table of Contents f) MDIO on GPIOs g) SPI busses - VII - Specifying interrupt information for devices + VII - Marvell Discovery mv64[345]6x System Controller chips + 1) The /system-controller node + 2) Child nodes of /system-controller + a) Marvell Discovery MDIO bus + b) Marvell Discovery ethernet controller + c) Marvell Discovery PHY nodes + d) Marvell Discovery SDMA nodes + e) Marvell Discovery BRG nodes + f) Marvell Discovery CUNIT nodes + g) Marvell Discovery MPSCROUTING nodes + h) Marvell Discovery MPSCINTR nodes + i) Marvell Discovery MPSC nodes + j) Marvell Discovery Watch Dog Timer nodes + k) Marvell Discovery I2C nodes + l) Marvell Discovery PIC (Programmable Interrupt Controller) nodes + m) Marvell Discovery MPP (Multipurpose Pins) multiplexing nodes + n) Marvell Discovery GPP (General Purpose Pins) nodes + o) Marvell Discovery PCI host bridge node + p) Marvell Discovery CPU Error nodes + q) Marvell Discovery SRAM Controller nodes + r) Marvell Discovery PCI Error Handler nodes + s) Marvell Discovery Memory Controller nodes + + VIII - Specifying interrupt information for devices 1) interrupts property 2) interrupt-parent property 3) OpenPIC Interrupt Controllers 4) ISA Interrupt Controllers - VIII - Specifying device power management information (sleep property) + IX - Specifying GPIO information for devices + 1) gpios property + 2) gpio-controller nodes + + X - Specifying device power management information (sleep property) Appendix A - Sample SOC node for MPC8540 diff --git a/trunk/arch/ia64/include/asm/unistd.h b/trunk/arch/ia64/include/asm/unistd.h index 87f1bd1efc82..954d398a54b4 100644 --- a/trunk/arch/ia64/include/asm/unistd.h +++ b/trunk/arch/ia64/include/asm/unistd.h @@ -356,8 +356,6 @@ asmlinkage unsigned long sys_mmap2( int fd, long pgoff); struct pt_regs; struct sigaction; -long sys_execve(const char __user *filename, char __user * __user *argv, - char __user * __user *envp, struct pt_regs *regs); asmlinkage long sys_ia64_pipe(void); asmlinkage long sys_rt_sigaction(int sig, const struct sigaction __user *act, diff --git a/trunk/arch/m68k/include/asm/ide.h b/trunk/arch/m68k/include/asm/ide.h index 492fee8a1ab2..3958726664ba 100644 --- a/trunk/arch/m68k/include/asm/ide.h +++ b/trunk/arch/m68k/include/asm/ide.h @@ -1,4 +1,6 @@ /* + * linux/include/asm-m68k/ide.h + * * Copyright (C) 1994-1996 Linus Torvalds & authors */ @@ -32,8 +34,6 @@ #include #include -#ifdef CONFIG_MMU - /* * Get rid of defs from io.h - ide has its private and conflicting versions * Since so far no single m68k platform uses ISA/PCI I/O space for IDE, we @@ -53,14 +53,5 @@ #define __ide_mm_outsw(port, addr, n) raw_outsw((u16 *)port, addr, n) #define __ide_mm_outsl(port, addr, n) raw_outsl((u32 *)port, addr, n) -#else - -#define __ide_mm_insw(port, addr, n) io_insw((unsigned int)port, addr, n) -#define __ide_mm_insl(port, addr, n) io_insl((unsigned int)port, addr, n) -#define __ide_mm_outsw(port, addr, n) io_outsw((unsigned int)port, addr, n) -#define __ide_mm_outsl(port, addr, n) io_outsl((unsigned int)port, addr, n) - -#endif /* CONFIG_MMU */ - #endif /* __KERNEL__ */ #endif /* _M68K_IDE_H */ diff --git a/trunk/arch/m68knommu/kernel/process.c b/trunk/arch/m68knommu/kernel/process.c index 6d3390590e5b..4d090d3c0897 100644 --- a/trunk/arch/m68knommu/kernel/process.c +++ b/trunk/arch/m68knommu/kernel/process.c @@ -316,14 +316,14 @@ void dump(struct pt_regs *fp) fp->d0, fp->d1, fp->d2, fp->d3); printk(KERN_EMERG "d4: %08lx d5: %08lx a0: %08lx a1: %08lx\n", fp->d4, fp->d5, fp->a0, fp->a1); - printk(KERN_EMERG "\nUSP: %08x TRAPFRAME: %p\n", - (unsigned int) rdusp(), fp); + printk(KERN_EMERG "\nUSP: %08x TRAPFRAME: %08x\n", + (unsigned int) rdusp(), (unsigned int) fp); printk(KERN_EMERG "\nCODE:"); tp = ((unsigned char *) fp->pc) - 0x20; for (sp = (unsigned long *) tp, i = 0; (i < 0x40); i += 4) { if ((i % 0x10) == 0) - printk(KERN_EMERG "%p: ", tp + i); + printk(KERN_EMERG "%08x: ", (int) (tp + i)); printk("%08x ", (int) *sp++); } printk(KERN_EMERG "\n"); @@ -332,7 +332,7 @@ void dump(struct pt_regs *fp) tp = ((unsigned char *) fp) - 0x40; for (sp = (unsigned long *) tp, i = 0; (i < 0xc0); i += 4) { if ((i % 0x10) == 0) - printk(KERN_EMERG "%p: ", tp + i); + printk(KERN_EMERG "%08x: ", (int) (tp + i)); printk("%08x ", (int) *sp++); } printk(KERN_EMERG "\n"); @@ -341,7 +341,7 @@ void dump(struct pt_regs *fp) tp = (unsigned char *) (rdusp() - 0x10); for (sp = (unsigned long *) tp, i = 0; (i < 0x80); i += 4) { if ((i % 0x10) == 0) - printk(KERN_EMERG "%p: ", tp + i); + printk(KERN_EMERG "%08x: ", (int) (tp + i)); printk("%08x ", (int) *sp++); } printk(KERN_EMERG "\n"); diff --git a/trunk/arch/microblaze/kernel/prom_parse.c b/trunk/arch/microblaze/kernel/prom_parse.c index 99d9b61cccb5..d33ba17601fa 100644 --- a/trunk/arch/microblaze/kernel/prom_parse.c +++ b/trunk/arch/microblaze/kernel/prom_parse.c @@ -73,7 +73,7 @@ int of_irq_map_pci(struct pci_dev *pdev, struct of_irq *out_irq) /* We can only get here if we hit a P2P bridge with no node, * let's do standard swizzling and try again */ - lspec = pci_swizzle_interrupt_pin(pdev, lspec); + lspec = of_irq_pci_swizzle(PCI_SLOT(pdev->devfn), lspec); pdev = ppdev; } diff --git a/trunk/arch/microblaze/pci/pci-common.c b/trunk/arch/microblaze/pci/pci-common.c index 55ef532f32be..23be25fec4d6 100644 --- a/trunk/arch/microblaze/pci/pci-common.c +++ b/trunk/arch/microblaze/pci/pci-common.c @@ -27,11 +27,10 @@ #include #include #include -#include -#include #include #include +#include #include #include @@ -1078,7 +1077,7 @@ void __devinit pcibios_setup_bus_devices(struct pci_bus *bus) struct dev_archdata *sd = &dev->dev.archdata; /* Setup OF node pointer in archdata */ - dev->dev.of_node = pci_device_to_OF_node(dev); + sd->of_node = pci_device_to_OF_node(dev); /* Fixup NUMA node as it may not be setup yet by the generic * code and is needed by the DMA init diff --git a/trunk/arch/microblaze/pci/xilinx_pci.c b/trunk/arch/microblaze/pci/xilinx_pci.c index 0687a42a5bd4..7869a41b0f94 100644 --- a/trunk/arch/microblaze/pci/xilinx_pci.c +++ b/trunk/arch/microblaze/pci/xilinx_pci.c @@ -16,7 +16,6 @@ #include #include -#include #include #include diff --git a/trunk/drivers/ata/sata_dwc_460ex.c b/trunk/drivers/ata/sata_dwc_460ex.c index 2673a3d14806..ea24c1e51be2 100644 --- a/trunk/drivers/ata/sata_dwc_460ex.c +++ b/trunk/drivers/ata/sata_dwc_460ex.c @@ -1588,7 +1588,7 @@ static const struct ata_port_info sata_dwc_port_info[] = { }, }; -static int sata_dwc_probe(struct platform_device *ofdev, +static int sata_dwc_probe(struct of_device *ofdev, const struct of_device_id *match) { struct sata_dwc_device *hsdev; @@ -1702,7 +1702,7 @@ static int sata_dwc_probe(struct platform_device *ofdev, return err; } -static int sata_dwc_remove(struct platform_device *ofdev) +static int sata_dwc_remove(struct of_device *ofdev) { struct device *dev = &ofdev->dev; struct ata_host *host = dev_get_drvdata(dev); diff --git a/trunk/drivers/block/xsysace.c b/trunk/drivers/block/xsysace.c index 057413bb16e2..2982b3ee9465 100644 --- a/trunk/drivers/block/xsysace.c +++ b/trunk/drivers/block/xsysace.c @@ -94,7 +94,6 @@ #include #include #if defined(CONFIG_OF) -#include #include #include #endif diff --git a/trunk/drivers/char/pty.c b/trunk/drivers/char/pty.c index c350d01716bd..ad46eae1f9bb 100644 --- a/trunk/drivers/char/pty.c +++ b/trunk/drivers/char/pty.c @@ -675,8 +675,8 @@ static int ptmx_open(struct inode *inode, struct file *filp) } set_bit(TTY_PTY_LOCK, &tty->flags); /* LOCK THE SLAVE */ - - tty_add_file(tty, filp); + filp->private_data = tty; + file_move(filp, &tty->tty_files); retval = devpts_pty_new(inode, tty->link); if (retval) diff --git a/trunk/drivers/char/tty_io.c b/trunk/drivers/char/tty_io.c index 949067a0bd47..0350c42375a2 100644 --- a/trunk/drivers/char/tty_io.c +++ b/trunk/drivers/char/tty_io.c @@ -136,9 +136,6 @@ LIST_HEAD(tty_drivers); /* linked list of tty drivers */ DEFINE_MUTEX(tty_mutex); EXPORT_SYMBOL(tty_mutex); -/* Spinlock to protect the tty->tty_files list */ -DEFINE_SPINLOCK(tty_files_lock); - static ssize_t tty_read(struct file *, char __user *, size_t, loff_t *); static ssize_t tty_write(struct file *, const char __user *, size_t, loff_t *); ssize_t redirected_tty_write(struct file *, const char __user *, @@ -188,41 +185,6 @@ void free_tty_struct(struct tty_struct *tty) kfree(tty); } -static inline struct tty_struct *file_tty(struct file *file) -{ - return ((struct tty_file_private *)file->private_data)->tty; -} - -/* Associate a new file with the tty structure */ -void tty_add_file(struct tty_struct *tty, struct file *file) -{ - struct tty_file_private *priv; - - /* XXX: must implement proper error handling in callers */ - priv = kmalloc(sizeof(*priv), GFP_KERNEL|__GFP_NOFAIL); - - priv->tty = tty; - priv->file = file; - file->private_data = priv; - - spin_lock(&tty_files_lock); - list_add(&priv->list, &tty->tty_files); - spin_unlock(&tty_files_lock); -} - -/* Delete file from its tty */ -void tty_del_file(struct file *file) -{ - struct tty_file_private *priv = file->private_data; - - spin_lock(&tty_files_lock); - list_del(&priv->list); - spin_unlock(&tty_files_lock); - file->private_data = NULL; - kfree(priv); -} - - #define TTY_NUMBER(tty) ((tty)->index + (tty)->driver->name_base) /** @@ -273,11 +235,11 @@ static int check_tty_count(struct tty_struct *tty, const char *routine) struct list_head *p; int count = 0; - spin_lock(&tty_files_lock); + file_list_lock(); list_for_each(p, &tty->tty_files) { count++; } - spin_unlock(&tty_files_lock); + file_list_unlock(); if (tty->driver->type == TTY_DRIVER_TYPE_PTY && tty->driver->subtype == PTY_TYPE_SLAVE && tty->link && tty->link->count) @@ -535,7 +497,6 @@ void __tty_hangup(struct tty_struct *tty) struct file *cons_filp = NULL; struct file *filp, *f = NULL; struct task_struct *p; - struct tty_file_private *priv; int closecount = 0, n; unsigned long flags; int refs = 0; @@ -545,7 +506,7 @@ void __tty_hangup(struct tty_struct *tty) spin_lock(&redirect_lock); - if (redirect && file_tty(redirect) == tty) { + if (redirect && redirect->private_data == tty) { f = redirect; redirect = NULL; } @@ -558,10 +519,9 @@ void __tty_hangup(struct tty_struct *tty) workqueue with the lock held */ check_tty_count(tty, "tty_hangup"); - spin_lock(&tty_files_lock); + file_list_lock(); /* This breaks for file handles being sent over AF_UNIX sockets ? */ - list_for_each_entry(priv, &tty->tty_files, list) { - filp = priv->file; + list_for_each_entry(filp, &tty->tty_files, f_u.fu_list) { if (filp->f_op->write == redirected_tty_write) cons_filp = filp; if (filp->f_op->write != tty_write) @@ -570,7 +530,7 @@ void __tty_hangup(struct tty_struct *tty) __tty_fasync(-1, filp, 0); /* can't block */ filp->f_op = &hung_up_tty_fops; } - spin_unlock(&tty_files_lock); + file_list_unlock(); tty_ldisc_hangup(tty); @@ -929,10 +889,12 @@ static ssize_t tty_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) { int i; - struct inode *inode = file->f_path.dentry->d_inode; - struct tty_struct *tty = file_tty(file); + struct tty_struct *tty; + struct inode *inode; struct tty_ldisc *ld; + tty = file->private_data; + inode = file->f_path.dentry->d_inode; if (tty_paranoia_check(tty, inode, "tty_read")) return -EIO; if (!tty || (test_bit(TTY_IO_ERROR, &tty->flags))) @@ -1103,11 +1065,12 @@ void tty_write_message(struct tty_struct *tty, char *msg) static ssize_t tty_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) { + struct tty_struct *tty; struct inode *inode = file->f_path.dentry->d_inode; - struct tty_struct *tty = file_tty(file); - struct tty_ldisc *ld; ssize_t ret; + struct tty_ldisc *ld; + tty = file->private_data; if (tty_paranoia_check(tty, inode, "tty_write")) return -EIO; if (!tty || !tty->ops->write || @@ -1461,9 +1424,9 @@ static void release_one_tty(struct work_struct *work) tty_driver_kref_put(driver); module_put(driver->owner); - spin_lock(&tty_files_lock); + file_list_lock(); list_del_init(&tty->tty_files); - spin_unlock(&tty_files_lock); + file_list_unlock(); put_pid(tty->pgrp); put_pid(tty->session); @@ -1544,13 +1507,13 @@ static void release_tty(struct tty_struct *tty, int idx) int tty_release(struct inode *inode, struct file *filp) { - struct tty_struct *tty = file_tty(filp); - struct tty_struct *o_tty; + struct tty_struct *tty, *o_tty; int pty_master, tty_closing, o_tty_closing, do_sleep; int devpts; int idx; char buf[64]; + tty = filp->private_data; if (tty_paranoia_check(tty, inode, "tty_release_dev")) return 0; @@ -1708,7 +1671,8 @@ int tty_release(struct inode *inode, struct file *filp) * - do_tty_hangup no longer sees this file descriptor as * something that needs to be handled for hangups. */ - tty_del_file(filp); + file_kill(filp); + filp->private_data = NULL; /* * Perform some housekeeping before deciding whether to return. @@ -1875,8 +1839,8 @@ static int tty_open(struct inode *inode, struct file *filp) return PTR_ERR(tty); } - tty_add_file(tty, filp); - + filp->private_data = tty; + file_move(filp, &tty->tty_files); check_tty_count(tty, "tty_open"); if (tty->driver->type == TTY_DRIVER_TYPE_PTY && tty->driver->subtype == PTY_TYPE_MASTER) @@ -1952,10 +1916,11 @@ static int tty_open(struct inode *inode, struct file *filp) static unsigned int tty_poll(struct file *filp, poll_table *wait) { - struct tty_struct *tty = file_tty(filp); + struct tty_struct *tty; struct tty_ldisc *ld; int ret = 0; + tty = filp->private_data; if (tty_paranoia_check(tty, filp->f_path.dentry->d_inode, "tty_poll")) return 0; @@ -1968,10 +1933,11 @@ static unsigned int tty_poll(struct file *filp, poll_table *wait) static int __tty_fasync(int fd, struct file *filp, int on) { - struct tty_struct *tty = file_tty(filp); + struct tty_struct *tty; unsigned long flags; int retval = 0; + tty = filp->private_data; if (tty_paranoia_check(tty, filp->f_path.dentry->d_inode, "tty_fasync")) goto out; @@ -2525,13 +2491,13 @@ EXPORT_SYMBOL(tty_pair_get_pty); */ long tty_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { - struct tty_struct *tty = file_tty(file); - struct tty_struct *real_tty; + struct tty_struct *tty, *real_tty; void __user *p = (void __user *)arg; int retval; struct tty_ldisc *ld; struct inode *inode = file->f_dentry->d_inode; + tty = file->private_data; if (tty_paranoia_check(tty, inode, "tty_ioctl")) return -EINVAL; @@ -2653,7 +2619,7 @@ static long tty_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { struct inode *inode = file->f_dentry->d_inode; - struct tty_struct *tty = file_tty(file); + struct tty_struct *tty = file->private_data; struct tty_ldisc *ld; int retval = -ENOIOCTLCMD; @@ -2745,7 +2711,7 @@ void __do_SAK(struct tty_struct *tty) if (!filp) continue; if (filp->f_op->read == tty_read && - file_tty(filp) == tty) { + filp->private_data == tty) { printk(KERN_NOTICE "SAK: killed process %d" " (%s): fd#%d opened to the tty\n", task_pid_nr(p), p->comm, i); diff --git a/trunk/drivers/char/xilinx_hwicap/xilinx_hwicap.c b/trunk/drivers/char/xilinx_hwicap/xilinx_hwicap.c index b663d573aad9..0ed763cd2e77 100644 --- a/trunk/drivers/char/xilinx_hwicap/xilinx_hwicap.c +++ b/trunk/drivers/char/xilinx_hwicap/xilinx_hwicap.c @@ -94,7 +94,6 @@ #ifdef CONFIG_OF /* For open firmware. */ -#include #include #include #endif diff --git a/trunk/drivers/md/md.c b/trunk/drivers/md/md.c index c148b6302154..11567c7999a2 100644 --- a/trunk/drivers/md/md.c +++ b/trunk/drivers/md/md.c @@ -2136,6 +2136,16 @@ static void sync_sbs(mddev_t * mddev, int nospares) * with the rest of the array) */ mdk_rdev_t *rdev; + + /* First make sure individual recovery_offsets are correct */ + list_for_each_entry(rdev, &mddev->disks, same_set) { + if (rdev->raid_disk >= 0 && + mddev->delta_disks >= 0 && + !test_bit(In_sync, &rdev->flags) && + mddev->curr_resync_completed > rdev->recovery_offset) + rdev->recovery_offset = mddev->curr_resync_completed; + + } list_for_each_entry(rdev, &mddev->disks, same_set) { if (rdev->sb_events == mddev->events || (nospares && @@ -2157,27 +2167,12 @@ static void md_update_sb(mddev_t * mddev, int force_change) int sync_req; int nospares = 0; -repeat: - /* First make sure individual recovery_offsets are correct */ - list_for_each_entry(rdev, &mddev->disks, same_set) { - if (rdev->raid_disk >= 0 && - mddev->delta_disks >= 0 && - !test_bit(In_sync, &rdev->flags) && - mddev->curr_resync_completed > rdev->recovery_offset) - rdev->recovery_offset = mddev->curr_resync_completed; - - } - if (mddev->external || !mddev->persistent) { - clear_bit(MD_CHANGE_DEVS, &mddev->flags); - clear_bit(MD_CHANGE_CLEAN, &mddev->flags); - wake_up(&mddev->sb_wait); + mddev->utime = get_seconds(); + if (mddev->external) return; - } - +repeat: spin_lock_irq(&mddev->write_lock); - mddev->utime = get_seconds(); - set_bit(MD_CHANGE_PENDING, &mddev->flags); if (test_and_clear_bit(MD_CHANGE_DEVS, &mddev->flags)) force_change = 1; @@ -2226,6 +2221,19 @@ static void md_update_sb(mddev_t * mddev, int force_change) MD_BUG(); mddev->events --; } + + /* + * do not write anything to disk if using + * nonpersistent superblocks + */ + if (!mddev->persistent) { + if (!mddev->external) + clear_bit(MD_CHANGE_PENDING, &mddev->flags); + + spin_unlock_irq(&mddev->write_lock); + wake_up(&mddev->sb_wait); + return; + } sync_sbs(mddev, nospares); spin_unlock_irq(&mddev->write_lock); diff --git a/trunk/drivers/md/raid1.c b/trunk/drivers/md/raid1.c index ad83a4dcadc3..73cc74ffc26b 100644 --- a/trunk/drivers/md/raid1.c +++ b/trunk/drivers/md/raid1.c @@ -787,8 +787,8 @@ static int make_request(mddev_t *mddev, struct bio * bio) struct bio_list bl; struct page **behind_pages = NULL; const int rw = bio_data_dir(bio); - const unsigned long do_sync = (bio->bi_rw & REQ_SYNC); - unsigned long do_barriers; + const bool do_sync = (bio->bi_rw & REQ_SYNC); + bool do_barriers; mdk_rdev_t *blocked_rdev; /* @@ -1120,8 +1120,6 @@ static int raid1_spare_active(mddev_t *mddev) { int i; conf_t *conf = mddev->private; - int count = 0; - unsigned long flags; /* * Find all failed disks within the RAID1 configuration @@ -1133,16 +1131,15 @@ static int raid1_spare_active(mddev_t *mddev) if (rdev && !test_bit(Faulty, &rdev->flags) && !test_and_set_bit(In_sync, &rdev->flags)) { - count++; - sysfs_notify_dirent(rdev->sysfs_state); + unsigned long flags; + spin_lock_irqsave(&conf->device_lock, flags); + mddev->degraded--; + spin_unlock_irqrestore(&conf->device_lock, flags); } } - spin_lock_irqsave(&conf->device_lock, flags); - mddev->degraded -= count; - spin_unlock_irqrestore(&conf->device_lock, flags); print_conf(conf); - return count; + return 0; } @@ -1643,7 +1640,7 @@ static void raid1d(mddev_t *mddev) * We already have a nr_pending reference on these rdevs. */ int i; - const unsigned long do_sync = (r1_bio->master_bio->bi_rw & REQ_SYNC); + const bool do_sync = (r1_bio->master_bio->bi_rw & REQ_SYNC); clear_bit(R1BIO_BarrierRetry, &r1_bio->state); clear_bit(R1BIO_Barrier, &r1_bio->state); for (i=0; i < conf->raid_disks; i++) @@ -1699,7 +1696,7 @@ static void raid1d(mddev_t *mddev) (unsigned long long)r1_bio->sector); raid_end_bio_io(r1_bio); } else { - const unsigned long do_sync = r1_bio->master_bio->bi_rw & REQ_SYNC; + const bool do_sync = r1_bio->master_bio->bi_rw & REQ_SYNC; r1_bio->bios[r1_bio->read_disk] = mddev->ro ? IO_BLOCKED : NULL; r1_bio->read_disk = disk; diff --git a/trunk/drivers/md/raid10.c b/trunk/drivers/md/raid10.c index 84718383124d..a88aeb5198c7 100644 --- a/trunk/drivers/md/raid10.c +++ b/trunk/drivers/md/raid10.c @@ -799,7 +799,7 @@ static int make_request(mddev_t *mddev, struct bio * bio) int i; int chunk_sects = conf->chunk_mask + 1; const int rw = bio_data_dir(bio); - const unsigned long do_sync = (bio->bi_rw & REQ_SYNC); + const bool do_sync = (bio->bi_rw & REQ_SYNC); struct bio_list bl; unsigned long flags; mdk_rdev_t *blocked_rdev; @@ -1116,8 +1116,6 @@ static int raid10_spare_active(mddev_t *mddev) int i; conf_t *conf = mddev->private; mirror_info_t *tmp; - int count = 0; - unsigned long flags; /* * Find all non-in_sync disks within the RAID10 configuration @@ -1128,16 +1126,15 @@ static int raid10_spare_active(mddev_t *mddev) if (tmp->rdev && !test_bit(Faulty, &tmp->rdev->flags) && !test_and_set_bit(In_sync, &tmp->rdev->flags)) { - count++; - sysfs_notify_dirent(tmp->rdev->sysfs_state); + unsigned long flags; + spin_lock_irqsave(&conf->device_lock, flags); + mddev->degraded--; + spin_unlock_irqrestore(&conf->device_lock, flags); } } - spin_lock_irqsave(&conf->device_lock, flags); - mddev->degraded -= count; - spin_unlock_irqrestore(&conf->device_lock, flags); print_conf(conf); - return count; + return 0; } @@ -1737,7 +1734,7 @@ static void raid10d(mddev_t *mddev) raid_end_bio_io(r10_bio); bio_put(bio); } else { - const unsigned long do_sync = (r10_bio->master_bio->bi_rw & REQ_SYNC); + const bool do_sync = (r10_bio->master_bio->bi_rw & REQ_SYNC); bio_put(bio); rdev = conf->mirrors[mirror].rdev; if (printk_ratelimit()) diff --git a/trunk/drivers/md/raid5.c b/trunk/drivers/md/raid5.c index 69b0a169e43d..866d4b5a144c 100644 --- a/trunk/drivers/md/raid5.c +++ b/trunk/drivers/md/raid5.c @@ -5330,8 +5330,6 @@ static int raid5_spare_active(mddev_t *mddev) int i; raid5_conf_t *conf = mddev->private; struct disk_info *tmp; - int count = 0; - unsigned long flags; for (i = 0; i < conf->raid_disks; i++) { tmp = conf->disks + i; @@ -5339,15 +5337,14 @@ static int raid5_spare_active(mddev_t *mddev) && tmp->rdev->recovery_offset == MaxSector && !test_bit(Faulty, &tmp->rdev->flags) && !test_and_set_bit(In_sync, &tmp->rdev->flags)) { - count++; - sysfs_notify_dirent(tmp->rdev->sysfs_state); + unsigned long flags; + spin_lock_irqsave(&conf->device_lock, flags); + mddev->degraded--; + spin_unlock_irqrestore(&conf->device_lock, flags); } } - spin_lock_irqsave(&conf->device_lock, flags); - mddev->degraded -= count; - spin_unlock_irqrestore(&conf->device_lock, flags); print_raid5_conf(conf); - return count; + return 0; } static int raid5_remove_disk(mddev_t *mddev, int number) diff --git a/trunk/drivers/mmc/core/host.c b/trunk/drivers/mmc/core/host.c index d80cfdc8edd2..0efe631e50ca 100644 --- a/trunk/drivers/mmc/core/host.c +++ b/trunk/drivers/mmc/core/host.c @@ -86,9 +86,7 @@ struct mmc_host *mmc_alloc_host(int extra, struct device *dev) init_waitqueue_head(&host->wq); INIT_DELAYED_WORK(&host->detect, mmc_rescan); INIT_DELAYED_WORK_DEFERRABLE(&host->disable, mmc_host_deeper_disable); -#ifdef CONFIG_PM host->pm_notify.notifier_call = mmc_pm_notify; -#endif /* * By default, hosts do not support SGIO or large requests. diff --git a/trunk/drivers/mtd/maps/physmap_of.c b/trunk/drivers/mtd/maps/physmap_of.c index fe63f6bd663c..00af55d7afba 100644 --- a/trunk/drivers/mtd/maps/physmap_of.c +++ b/trunk/drivers/mtd/maps/physmap_of.c @@ -22,7 +22,6 @@ #include #include #include -#include #include #include diff --git a/trunk/drivers/serial/of_serial.c b/trunk/drivers/serial/of_serial.c index 2af8fd113123..659a695bdad6 100644 --- a/trunk/drivers/serial/of_serial.c +++ b/trunk/drivers/serial/of_serial.c @@ -14,10 +14,11 @@ #include #include #include -#include #include #include +#include + struct of_serial_info { int type; int line; diff --git a/trunk/drivers/spi/coldfire_qspi.c b/trunk/drivers/spi/coldfire_qspi.c index 052b3c7fa6a0..59be3efe0636 100644 --- a/trunk/drivers/spi/coldfire_qspi.c +++ b/trunk/drivers/spi/coldfire_qspi.c @@ -24,7 +24,6 @@ #include #include #include -#include #include #include #include diff --git a/trunk/drivers/staging/pohmelfs/path_entry.c b/trunk/drivers/staging/pohmelfs/path_entry.c index 8ec83d2dffb7..cdc4dd50d638 100644 --- a/trunk/drivers/staging/pohmelfs/path_entry.c +++ b/trunk/drivers/staging/pohmelfs/path_entry.c @@ -44,9 +44,9 @@ int pohmelfs_construct_path_string(struct pohmelfs_inode *pi, void *data, int le return -ENOENT; } - spin_lock(¤t->fs->lock); + read_lock(¤t->fs->lock); path.mnt = mntget(current->fs->root.mnt); - spin_unlock(¤t->fs->lock); + read_unlock(¤t->fs->lock); path.dentry = d; @@ -91,9 +91,9 @@ int pohmelfs_path_length(struct pohmelfs_inode *pi) return -ENOENT; } - spin_lock(¤t->fs->lock); + read_lock(¤t->fs->lock); root = dget(current->fs->root.dentry); - spin_unlock(¤t->fs->lock); + read_unlock(¤t->fs->lock); spin_lock(&dcache_lock); diff --git a/trunk/fs/buffer.c b/trunk/fs/buffer.c index 3e7dca279d1c..50efa339e051 100644 --- a/trunk/fs/buffer.c +++ b/trunk/fs/buffer.c @@ -770,12 +770,11 @@ static int fsync_buffers_list(spinlock_t *lock, struct list_head *list) spin_unlock(lock); /* * Ensure any pending I/O completes so that - * write_dirty_buffer() actually writes the - * current contents - it is a noop if I/O is - * still in flight on potentially older - * contents. + * ll_rw_block() actually writes the current + * contents - it is a noop if I/O is still in + * flight on potentially older contents. */ - write_dirty_buffer(bh, WRITE_SYNC_PLUG); + ll_rw_block(SWRITE_SYNC_PLUG, 1, &bh); /* * Kick off IO for the previous mapping. Note @@ -2912,6 +2911,13 @@ int submit_bh(int rw, struct buffer_head * bh) BUG_ON(buffer_delay(bh)); BUG_ON(buffer_unwritten(bh)); + /* + * Mask in barrier bit for a write (could be either a WRITE or a + * WRITE_SYNC + */ + if (buffer_ordered(bh) && (rw & WRITE)) + rw |= WRITE_BARRIER; + /* * Only clear out a write error when rewriting */ @@ -2950,21 +2956,22 @@ EXPORT_SYMBOL(submit_bh); /** * ll_rw_block: low-level access to block devices (DEPRECATED) - * @rw: whether to %READ or %WRITE or maybe %READA (readahead) + * @rw: whether to %READ or %WRITE or %SWRITE or maybe %READA (readahead) * @nr: number of &struct buffer_heads in the array * @bhs: array of pointers to &struct buffer_head * * ll_rw_block() takes an array of pointers to &struct buffer_heads, and * requests an I/O operation on them, either a %READ or a %WRITE. The third - * %READA option is described in the documentation for generic_make_request() - * which ll_rw_block() calls. + * %SWRITE is like %WRITE only we make sure that the *current* data in buffers + * are sent to disk. The fourth %READA option is described in the documentation + * for generic_make_request() which ll_rw_block() calls. * * This function drops any buffer that it cannot get a lock on (with the - * BH_Lock state bit), any buffer that appears to be clean when doing a write - * request, and any buffer that appears to be up-to-date when doing read - * request. Further it marks as clean buffers that are processed for - * writing (the buffer cache won't assume that they are actually clean - * until the buffer gets unlocked). + * BH_Lock state bit) unless SWRITE is required, any buffer that appears to be + * clean when doing a write request, and any buffer that appears to be + * up-to-date when doing read request. Further it marks as clean buffers that + * are processed for writing (the buffer cache won't assume that they are + * actually clean until the buffer gets unlocked). * * ll_rw_block sets b_end_io to simple completion handler that marks * the buffer up-to-date (if approriate), unlocks the buffer and wakes @@ -2980,13 +2987,20 @@ void ll_rw_block(int rw, int nr, struct buffer_head *bhs[]) for (i = 0; i < nr; i++) { struct buffer_head *bh = bhs[i]; - if (!trylock_buffer(bh)) + if (rw == SWRITE || rw == SWRITE_SYNC || rw == SWRITE_SYNC_PLUG) + lock_buffer(bh); + else if (!trylock_buffer(bh)) continue; - if (rw == WRITE) { + + if (rw == WRITE || rw == SWRITE || rw == SWRITE_SYNC || + rw == SWRITE_SYNC_PLUG) { if (test_clear_buffer_dirty(bh)) { bh->b_end_io = end_buffer_write_sync; get_bh(bh); - submit_bh(WRITE, bh); + if (rw == SWRITE_SYNC) + submit_bh(WRITE_SYNC, bh); + else + submit_bh(WRITE, bh); continue; } } else { @@ -3002,25 +3016,12 @@ void ll_rw_block(int rw, int nr, struct buffer_head *bhs[]) } EXPORT_SYMBOL(ll_rw_block); -void write_dirty_buffer(struct buffer_head *bh, int rw) -{ - lock_buffer(bh); - if (!test_clear_buffer_dirty(bh)) { - unlock_buffer(bh); - return; - } - bh->b_end_io = end_buffer_write_sync; - get_bh(bh); - submit_bh(rw, bh); -} -EXPORT_SYMBOL(write_dirty_buffer); - /* * For a data-integrity writeout, we need to wait upon any in-progress I/O * and then start new I/O and then wait upon it. The caller must have a ref on * the buffer_head. */ -int __sync_dirty_buffer(struct buffer_head *bh, int rw) +int sync_dirty_buffer(struct buffer_head *bh) { int ret = 0; @@ -3029,7 +3030,7 @@ int __sync_dirty_buffer(struct buffer_head *bh, int rw) if (test_clear_buffer_dirty(bh)) { get_bh(bh); bh->b_end_io = end_buffer_write_sync; - ret = submit_bh(rw, bh); + ret = submit_bh(WRITE_SYNC, bh); wait_on_buffer(bh); if (buffer_eopnotsupp(bh)) { clear_buffer_eopnotsupp(bh); @@ -3042,12 +3043,6 @@ int __sync_dirty_buffer(struct buffer_head *bh, int rw) } return ret; } -EXPORT_SYMBOL(__sync_dirty_buffer); - -int sync_dirty_buffer(struct buffer_head *bh) -{ - return __sync_dirty_buffer(bh, WRITE_SYNC); -} EXPORT_SYMBOL(sync_dirty_buffer); /* diff --git a/trunk/fs/cramfs/inode.c b/trunk/fs/cramfs/inode.c index 1e7a33028d33..a53b130b366c 100644 --- a/trunk/fs/cramfs/inode.c +++ b/trunk/fs/cramfs/inode.c @@ -80,7 +80,7 @@ static struct inode *get_cramfs_inode(struct super_block *sb, } } else { inode = iget_locked(sb, CRAMINO(cramfs_inode)); - if (inode && (inode->i_state & I_NEW)) { + if (inode) { setup_inode(inode, cramfs_inode); unlock_new_inode(inode); } diff --git a/trunk/fs/dcache.c b/trunk/fs/dcache.c index 83293be48149..4d13bf50b7b1 100644 --- a/trunk/fs/dcache.c +++ b/trunk/fs/dcache.c @@ -1332,13 +1332,31 @@ EXPORT_SYMBOL(d_add_ci); * d_lookup - search for a dentry * @parent: parent dentry * @name: qstr of name we wish to find - * Returns: dentry, or NULL * - * d_lookup searches the children of the parent dentry for the name in - * question. If the dentry is found its reference count is incremented and the - * dentry is returned. The caller must use dput to free the entry when it has - * finished using it. %NULL is returned if the dentry does not exist. + * Searches the children of the parent dentry for the name in question. If + * the dentry is found its reference count is incremented and the dentry + * is returned. The caller must use dput to free the entry when it has + * finished using it. %NULL is returned on failure. + * + * __d_lookup is dcache_lock free. The hash list is protected using RCU. + * Memory barriers are used while updating and doing lockless traversal. + * To avoid races with d_move while rename is happening, d_lock is used. + * + * Overflows in memcmp(), while d_move, are avoided by keeping the length + * and name pointer in one structure pointed by d_qstr. + * + * rcu_read_lock() and rcu_read_unlock() are used to disable preemption while + * lookup is going on. + * + * The dentry unused LRU is not updated even if lookup finds the required dentry + * in there. It is updated in places such as prune_dcache, shrink_dcache_sb, + * select_parent and __dget_locked. This laziness saves lookup from dcache_lock + * acquisition. + * + * d_lookup() is protected against the concurrent renames in some unrelated + * directory using the seqlockt_t rename_lock. */ + struct dentry * d_lookup(struct dentry * parent, struct qstr * name) { struct dentry * dentry = NULL; @@ -1354,21 +1372,6 @@ struct dentry * d_lookup(struct dentry * parent, struct qstr * name) } EXPORT_SYMBOL(d_lookup); -/* - * __d_lookup - search for a dentry (racy) - * @parent: parent dentry - * @name: qstr of name we wish to find - * Returns: dentry, or NULL - * - * __d_lookup is like d_lookup, however it may (rarely) return a - * false-negative result due to unrelated rename activity. - * - * __d_lookup is slightly faster by avoiding rename_lock read seqlock, - * however it must be used carefully, eg. with a following d_lookup in - * the case of failure. - * - * __d_lookup callers must be commented. - */ struct dentry * __d_lookup(struct dentry * parent, struct qstr * name) { unsigned int len = name->len; @@ -1379,19 +1382,6 @@ struct dentry * __d_lookup(struct dentry * parent, struct qstr * name) struct hlist_node *node; struct dentry *dentry; - /* - * The hash list is protected using RCU. - * - * Take d_lock when comparing a candidate dentry, to avoid races - * with d_move(). - * - * It is possible that concurrent renames can mess up our list - * walk here and result in missing our dentry, resulting in the - * false-negative result. d_lookup() protects against concurrent - * renames using rename_lock seqlock. - * - * See Documentation/vfs/dcache-locking.txt for more details. - */ rcu_read_lock(); hlist_for_each_entry_rcu(dentry, node, head, d_hash) { @@ -1406,8 +1396,8 @@ struct dentry * __d_lookup(struct dentry * parent, struct qstr * name) /* * Recheck the dentry after taking the lock - d_move may have - * changed things. Don't bother checking the hash because - * we're about to compare the whole name anyway. + * changed things. Don't bother checking the hash because we're + * about to compare the whole name anyway. */ if (dentry->d_parent != parent) goto next; @@ -1935,7 +1925,7 @@ static int prepend_path(const struct path *path, struct path *root, bool slash = false; int error = 0; - br_read_lock(vfsmount_lock); + spin_lock(&vfsmount_lock); while (dentry != root->dentry || vfsmnt != root->mnt) { struct dentry * parent; @@ -1964,7 +1954,7 @@ static int prepend_path(const struct path *path, struct path *root, if (!error && !slash) error = prepend(buffer, buflen, "/", 1); - br_read_unlock(vfsmount_lock); + spin_unlock(&vfsmount_lock); return error; global_root: @@ -2302,12 +2292,11 @@ int path_is_under(struct path *path1, struct path *path2) struct vfsmount *mnt = path1->mnt; struct dentry *dentry = path1->dentry; int res; - - br_read_lock(vfsmount_lock); + spin_lock(&vfsmount_lock); if (mnt != path2->mnt) { for (;;) { if (mnt->mnt_parent == mnt) { - br_read_unlock(vfsmount_lock); + spin_unlock(&vfsmount_lock); return 0; } if (mnt->mnt_parent == path2->mnt) @@ -2317,7 +2306,7 @@ int path_is_under(struct path *path1, struct path *path2) dentry = mnt->mnt_mountpoint; } res = is_subdir(dentry, path2->dentry); - br_read_unlock(vfsmount_lock); + spin_unlock(&vfsmount_lock); return res; } EXPORT_SYMBOL(path_is_under); diff --git a/trunk/fs/exec.c b/trunk/fs/exec.c index 2d9455282744..05c7d6b84df7 100644 --- a/trunk/fs/exec.c +++ b/trunk/fs/exec.c @@ -1118,7 +1118,7 @@ int check_unsafe_exec(struct linux_binprm *bprm) bprm->unsafe = tracehook_unsafe_exec(p); n_fs = 1; - spin_lock(&p->fs->lock); + write_lock(&p->fs->lock); rcu_read_lock(); for (t = next_thread(p); t != p; t = next_thread(t)) { if (t->fs == p->fs) @@ -1135,7 +1135,7 @@ int check_unsafe_exec(struct linux_binprm *bprm) res = 1; } } - spin_unlock(&p->fs->lock); + write_unlock(&p->fs->lock); return res; } diff --git a/trunk/fs/fat/misc.c b/trunk/fs/fat/misc.c index 1736f2356388..1fa23f6ffba5 100644 --- a/trunk/fs/fat/misc.c +++ b/trunk/fs/fat/misc.c @@ -250,9 +250,7 @@ int fat_sync_bhs(struct buffer_head **bhs, int nr_bhs) { int i, err = 0; - for (i = 0; i < nr_bhs; i++) - write_dirty_buffer(bhs[i], WRITE); - + ll_rw_block(SWRITE, nr_bhs, bhs); for (i = 0; i < nr_bhs; i++) { wait_on_buffer(bhs[i]); if (buffer_eopnotsupp(bhs[i])) { diff --git a/trunk/fs/file_table.c b/trunk/fs/file_table.c index a04bdd81c11c..edecd36fed9b 100644 --- a/trunk/fs/file_table.c +++ b/trunk/fs/file_table.c @@ -20,9 +20,7 @@ #include #include #include -#include #include -#include #include #include @@ -34,8 +32,8 @@ struct files_stat_struct files_stat = { .max_files = NR_FILE }; -DECLARE_LGLOCK(files_lglock); -DEFINE_LGLOCK(files_lglock); +/* public. Not pretty! */ +__cacheline_aligned_in_smp DEFINE_SPINLOCK(files_lock); /* SLAB cache for file structures */ static struct kmem_cache *filp_cachep __read_mostly; @@ -251,7 +249,7 @@ static void __fput(struct file *file) cdev_put(inode->i_cdev); fops_put(file->f_op); put_pid(file->f_owner.pid); - file_sb_list_del(file); + file_kill(file); if (file->f_mode & FMODE_WRITE) drop_file_write_access(file); file->f_path.dentry = NULL; @@ -330,107 +328,41 @@ struct file *fget_light(unsigned int fd, int *fput_needed) return file; } + void put_filp(struct file *file) { if (atomic_long_dec_and_test(&file->f_count)) { security_file_free(file); - file_sb_list_del(file); + file_kill(file); file_free(file); } } -static inline int file_list_cpu(struct file *file) -{ -#ifdef CONFIG_SMP - return file->f_sb_list_cpu; -#else - return smp_processor_id(); -#endif -} - -/* helper for file_sb_list_add to reduce ifdefs */ -static inline void __file_sb_list_add(struct file *file, struct super_block *sb) -{ - struct list_head *list; -#ifdef CONFIG_SMP - int cpu; - cpu = smp_processor_id(); - file->f_sb_list_cpu = cpu; - list = per_cpu_ptr(sb->s_files, cpu); -#else - list = &sb->s_files; -#endif - list_add(&file->f_u.fu_list, list); -} - -/** - * file_sb_list_add - add a file to the sb's file list - * @file: file to add - * @sb: sb to add it to - * - * Use this function to associate a file with the superblock of the inode it - * refers to. - */ -void file_sb_list_add(struct file *file, struct super_block *sb) +void file_move(struct file *file, struct list_head *list) { - lg_local_lock(files_lglock); - __file_sb_list_add(file, sb); - lg_local_unlock(files_lglock); + if (!list) + return; + file_list_lock(); + list_move(&file->f_u.fu_list, list); + file_list_unlock(); } -/** - * file_sb_list_del - remove a file from the sb's file list - * @file: file to remove - * @sb: sb to remove it from - * - * Use this function to remove a file from its superblock. - */ -void file_sb_list_del(struct file *file) +void file_kill(struct file *file) { if (!list_empty(&file->f_u.fu_list)) { - lg_local_lock_cpu(files_lglock, file_list_cpu(file)); + file_list_lock(); list_del_init(&file->f_u.fu_list); - lg_local_unlock_cpu(files_lglock, file_list_cpu(file)); + file_list_unlock(); } } -#ifdef CONFIG_SMP - -/* - * These macros iterate all files on all CPUs for a given superblock. - * files_lglock must be held globally. - */ -#define do_file_list_for_each_entry(__sb, __file) \ -{ \ - int i; \ - for_each_possible_cpu(i) { \ - struct list_head *list; \ - list = per_cpu_ptr((__sb)->s_files, i); \ - list_for_each_entry((__file), list, f_u.fu_list) - -#define while_file_list_for_each_entry \ - } \ -} - -#else - -#define do_file_list_for_each_entry(__sb, __file) \ -{ \ - struct list_head *list; \ - list = &(sb)->s_files; \ - list_for_each_entry((__file), list, f_u.fu_list) - -#define while_file_list_for_each_entry \ -} - -#endif - int fs_may_remount_ro(struct super_block *sb) { struct file *file; + /* Check that no files are currently opened for writing. */ - lg_global_lock(files_lglock); - do_file_list_for_each_entry(sb, file) { + file_list_lock(); + list_for_each_entry(file, &sb->s_files, f_u.fu_list) { struct inode *inode = file->f_path.dentry->d_inode; /* File with pending delete? */ @@ -440,11 +372,11 @@ int fs_may_remount_ro(struct super_block *sb) /* Writeable file? */ if (S_ISREG(inode->i_mode) && (file->f_mode & FMODE_WRITE)) goto too_bad; - } while_file_list_for_each_entry; - lg_global_unlock(files_lglock); + } + file_list_unlock(); return 1; /* Tis' cool bro. */ too_bad: - lg_global_unlock(files_lglock); + file_list_unlock(); return 0; } @@ -460,8 +392,8 @@ void mark_files_ro(struct super_block *sb) struct file *f; retry: - lg_global_lock(files_lglock); - do_file_list_for_each_entry(sb, f) { + file_list_lock(); + list_for_each_entry(f, &sb->s_files, f_u.fu_list) { struct vfsmount *mnt; if (!S_ISREG(f->f_path.dentry->d_inode->i_mode)) continue; @@ -476,13 +408,16 @@ void mark_files_ro(struct super_block *sb) continue; file_release_write(f); mnt = mntget(f->f_path.mnt); - /* This can sleep, so we can't hold the spinlock. */ - lg_global_unlock(files_lglock); + file_list_unlock(); + /* + * This can sleep, so we can't hold + * the file_list_lock() spinlock. + */ mnt_drop_write(mnt); mntput(mnt); goto retry; - } while_file_list_for_each_entry; - lg_global_unlock(files_lglock); + } + file_list_unlock(); } void __init files_init(unsigned long mempages) @@ -502,6 +437,5 @@ void __init files_init(unsigned long mempages) if (files_stat.max_files < NR_FILE) files_stat.max_files = NR_FILE; files_defer_init(); - lg_lock_init(files_lglock); percpu_counter_init(&nr_files, 0); } diff --git a/trunk/fs/fs_struct.c b/trunk/fs/fs_struct.c index ed45a9cf5f3d..1ee40eb9a2c0 100644 --- a/trunk/fs/fs_struct.c +++ b/trunk/fs/fs_struct.c @@ -13,11 +13,11 @@ void set_fs_root(struct fs_struct *fs, struct path *path) { struct path old_root; - spin_lock(&fs->lock); + write_lock(&fs->lock); old_root = fs->root; fs->root = *path; path_get(path); - spin_unlock(&fs->lock); + write_unlock(&fs->lock); if (old_root.dentry) path_put(&old_root); } @@ -30,11 +30,11 @@ void set_fs_pwd(struct fs_struct *fs, struct path *path) { struct path old_pwd; - spin_lock(&fs->lock); + write_lock(&fs->lock); old_pwd = fs->pwd; fs->pwd = *path; path_get(path); - spin_unlock(&fs->lock); + write_unlock(&fs->lock); if (old_pwd.dentry) path_put(&old_pwd); @@ -51,7 +51,7 @@ void chroot_fs_refs(struct path *old_root, struct path *new_root) task_lock(p); fs = p->fs; if (fs) { - spin_lock(&fs->lock); + write_lock(&fs->lock); if (fs->root.dentry == old_root->dentry && fs->root.mnt == old_root->mnt) { path_get(new_root); @@ -64,7 +64,7 @@ void chroot_fs_refs(struct path *old_root, struct path *new_root) fs->pwd = *new_root; count++; } - spin_unlock(&fs->lock); + write_unlock(&fs->lock); } task_unlock(p); } while_each_thread(g, p); @@ -87,10 +87,10 @@ void exit_fs(struct task_struct *tsk) if (fs) { int kill; task_lock(tsk); - spin_lock(&fs->lock); + write_lock(&fs->lock); tsk->fs = NULL; kill = !--fs->users; - spin_unlock(&fs->lock); + write_unlock(&fs->lock); task_unlock(tsk); if (kill) free_fs_struct(fs); @@ -104,7 +104,7 @@ struct fs_struct *copy_fs_struct(struct fs_struct *old) if (fs) { fs->users = 1; fs->in_exec = 0; - spin_lock_init(&fs->lock); + rwlock_init(&fs->lock); fs->umask = old->umask; get_fs_root_and_pwd(old, &fs->root, &fs->pwd); } @@ -121,10 +121,10 @@ int unshare_fs_struct(void) return -ENOMEM; task_lock(current); - spin_lock(&fs->lock); + write_lock(&fs->lock); kill = !--fs->users; current->fs = new_fs; - spin_unlock(&fs->lock); + write_unlock(&fs->lock); task_unlock(current); if (kill) @@ -143,7 +143,7 @@ EXPORT_SYMBOL(current_umask); /* to be mentioned only in INIT_TASK */ struct fs_struct init_fs = { .users = 1, - .lock = __SPIN_LOCK_UNLOCKED(init_fs.lock), + .lock = __RW_LOCK_UNLOCKED(init_fs.lock), .umask = 0022, }; @@ -156,14 +156,14 @@ void daemonize_fs_struct(void) task_lock(current); - spin_lock(&init_fs.lock); + write_lock(&init_fs.lock); init_fs.users++; - spin_unlock(&init_fs.lock); + write_unlock(&init_fs.lock); - spin_lock(&fs->lock); + write_lock(&fs->lock); current->fs = &init_fs; kill = !--fs->users; - spin_unlock(&fs->lock); + write_unlock(&fs->lock); task_unlock(current); if (kill) diff --git a/trunk/fs/generic_acl.c b/trunk/fs/generic_acl.c index 6bc9e3a5a693..99800e564157 100644 --- a/trunk/fs/generic_acl.c +++ b/trunk/fs/generic_acl.c @@ -94,7 +94,6 @@ generic_acl_set(struct dentry *dentry, const char *name, const void *value, if (error < 0) goto failed; inode->i_mode = mode; - inode->i_ctime = CURRENT_TIME; if (error == 0) { posix_acl_release(acl); acl = NULL; diff --git a/trunk/fs/hostfs/hostfs_kern.c b/trunk/fs/hostfs/hostfs_kern.c index f7dc9b5f9ef8..dd1e55535a4e 100644 --- a/trunk/fs/hostfs/hostfs_kern.c +++ b/trunk/fs/hostfs/hostfs_kern.c @@ -104,7 +104,7 @@ static char *__dentry_name(struct dentry *dentry, char *name) __putname(name); return NULL; } - strlcpy(name, root, PATH_MAX); + strncpy(name, root, PATH_MAX); if (len > p - name) { __putname(name); return NULL; @@ -876,7 +876,7 @@ static void *hostfs_follow_link(struct dentry *dentry, struct nameidata *nd) char *path = dentry_name(dentry); int err = -ENOMEM; if (path) { - err = hostfs_do_readlink(path, link, PATH_MAX); + int err = hostfs_do_readlink(path, link, PATH_MAX); if (err == PATH_MAX) err = -E2BIG; __putname(path); diff --git a/trunk/fs/internal.h b/trunk/fs/internal.h index a6910e91cee8..6b706bc60a66 100644 --- a/trunk/fs/internal.h +++ b/trunk/fs/internal.h @@ -9,8 +9,6 @@ * 2 of the License, or (at your option) any later version. */ -#include - struct super_block; struct linux_binprm; struct path; @@ -72,8 +70,7 @@ extern struct vfsmount *copy_tree(struct vfsmount *, struct dentry *, int); extern void __init mnt_init(void); -DECLARE_BRLOCK(vfsmount_lock); - +extern spinlock_t vfsmount_lock; /* * fs_struct.c @@ -83,8 +80,6 @@ extern void chroot_fs_refs(struct path *, struct path *); /* * file_table.c */ -extern void file_sb_list_add(struct file *f, struct super_block *sb); -extern void file_sb_list_del(struct file *f); extern void mark_files_ro(struct super_block *); extern struct file *get_empty_filp(void); diff --git a/trunk/fs/jbd/checkpoint.c b/trunk/fs/jbd/checkpoint.c index 05a38b9c4c0e..b0435dd0654d 100644 --- a/trunk/fs/jbd/checkpoint.c +++ b/trunk/fs/jbd/checkpoint.c @@ -254,9 +254,7 @@ __flush_batch(journal_t *journal, struct buffer_head **bhs, int *batch_count) { int i; - for (i = 0; i < *batch_count; i++) - write_dirty_buffer(bhs[i], WRITE); - + ll_rw_block(SWRITE, *batch_count, bhs); for (i = 0; i < *batch_count; i++) { struct buffer_head *bh = bhs[i]; clear_buffer_jwrite(bh); diff --git a/trunk/fs/jbd/commit.c b/trunk/fs/jbd/commit.c index 95d8c11c929e..28a9ddaa0c49 100644 --- a/trunk/fs/jbd/commit.c +++ b/trunk/fs/jbd/commit.c @@ -119,6 +119,7 @@ static int journal_write_commit_record(journal_t *journal, struct buffer_head *bh; journal_header_t *header; int ret; + int barrier_done = 0; if (is_journal_aborted(journal)) return 0; @@ -136,36 +137,34 @@ static int journal_write_commit_record(journal_t *journal, JBUFFER_TRACE(descriptor, "write commit block"); set_buffer_dirty(bh); - if (journal->j_flags & JFS_BARRIER) { - ret = __sync_dirty_buffer(bh, WRITE_SYNC | WRITE_BARRIER); - - /* - * Is it possible for another commit to fail at roughly - * the same time as this one? If so, we don't want to - * trust the barrier flag in the super, but instead want - * to remember if we sent a barrier request - */ - if (ret == -EOPNOTSUPP) { - char b[BDEVNAME_SIZE]; + set_buffer_ordered(bh); + barrier_done = 1; + } + ret = sync_dirty_buffer(bh); + if (barrier_done) + clear_buffer_ordered(bh); + /* is it possible for another commit to fail at roughly + * the same time as this one? If so, we don't want to + * trust the barrier flag in the super, but instead want + * to remember if we sent a barrier request + */ + if (ret == -EOPNOTSUPP && barrier_done) { + char b[BDEVNAME_SIZE]; - printk(KERN_WARNING - "JBD: barrier-based sync failed on %s - " - "disabling barriers\n", - bdevname(journal->j_dev, b)); - spin_lock(&journal->j_state_lock); - journal->j_flags &= ~JFS_BARRIER; - spin_unlock(&journal->j_state_lock); + printk(KERN_WARNING + "JBD: barrier-based sync failed on %s - " + "disabling barriers\n", + bdevname(journal->j_dev, b)); + spin_lock(&journal->j_state_lock); + journal->j_flags &= ~JFS_BARRIER; + spin_unlock(&journal->j_state_lock); - /* And try again, without the barrier */ - set_buffer_uptodate(bh); - set_buffer_dirty(bh); - ret = sync_dirty_buffer(bh); - } - } else { + /* And try again, without the barrier */ + set_buffer_uptodate(bh); + set_buffer_dirty(bh); ret = sync_dirty_buffer(bh); } - put_bh(bh); /* One for getblk() */ journal_put_journal_head(descriptor); diff --git a/trunk/fs/jbd/journal.c b/trunk/fs/jbd/journal.c index 2c4b1f109da9..f19ce94693d8 100644 --- a/trunk/fs/jbd/journal.c +++ b/trunk/fs/jbd/journal.c @@ -1024,7 +1024,7 @@ void journal_update_superblock(journal_t *journal, int wait) if (wait) sync_dirty_buffer(bh); else - write_dirty_buffer(bh, WRITE); + ll_rw_block(SWRITE, 1, &bh); out: /* If we have just flushed the log (by marking s_start==0), then diff --git a/trunk/fs/jbd/revoke.c b/trunk/fs/jbd/revoke.c index d29018307e2e..ad717328343a 100644 --- a/trunk/fs/jbd/revoke.c +++ b/trunk/fs/jbd/revoke.c @@ -617,7 +617,7 @@ static void flush_descriptor(journal_t *journal, set_buffer_jwrite(bh); BUFFER_TRACE(bh, "write"); set_buffer_dirty(bh); - write_dirty_buffer(bh, write_op); + ll_rw_block((write_op == WRITE) ? SWRITE : SWRITE_SYNC_PLUG, 1, &bh); } #endif diff --git a/trunk/fs/jbd2/checkpoint.c b/trunk/fs/jbd2/checkpoint.c index 5247e7ffdcb4..1c23a0f4e8a3 100644 --- a/trunk/fs/jbd2/checkpoint.c +++ b/trunk/fs/jbd2/checkpoint.c @@ -255,9 +255,7 @@ __flush_batch(journal_t *journal, int *batch_count) { int i; - for (i = 0; i < *batch_count; i++) - write_dirty_buffer(journal->j_chkpt_bhs[i], WRITE); - + ll_rw_block(SWRITE, *batch_count, journal->j_chkpt_bhs); for (i = 0; i < *batch_count; i++) { struct buffer_head *bh = journal->j_chkpt_bhs[i]; clear_buffer_jwrite(bh); diff --git a/trunk/fs/jbd2/commit.c b/trunk/fs/jbd2/commit.c index 7c068c189d80..f52e5e8049f1 100644 --- a/trunk/fs/jbd2/commit.c +++ b/trunk/fs/jbd2/commit.c @@ -101,6 +101,7 @@ static int journal_submit_commit_record(journal_t *journal, struct commit_header *tmp; struct buffer_head *bh; int ret; + int barrier_done = 0; struct timespec now = current_kernel_time(); if (is_journal_aborted(journal)) @@ -135,22 +136,30 @@ static int journal_submit_commit_record(journal_t *journal, if (journal->j_flags & JBD2_BARRIER && !JBD2_HAS_INCOMPAT_FEATURE(journal, JBD2_FEATURE_INCOMPAT_ASYNC_COMMIT)) { - ret = submit_bh(WRITE_SYNC_PLUG | WRITE_BARRIER, bh); - if (ret == -EOPNOTSUPP) { - printk(KERN_WARNING - "JBD2: Disabling barriers on %s, " - "not supported by device\n", journal->j_devname); - write_lock(&journal->j_state_lock); - journal->j_flags &= ~JBD2_BARRIER; - write_unlock(&journal->j_state_lock); + set_buffer_ordered(bh); + barrier_done = 1; + } + ret = submit_bh(WRITE_SYNC_PLUG, bh); + if (barrier_done) + clear_buffer_ordered(bh); + + /* is it possible for another commit to fail at roughly + * the same time as this one? If so, we don't want to + * trust the barrier flag in the super, but instead want + * to remember if we sent a barrier request + */ + if (ret == -EOPNOTSUPP && barrier_done) { + printk(KERN_WARNING + "JBD2: Disabling barriers on %s, " + "not supported by device\n", journal->j_devname); + write_lock(&journal->j_state_lock); + journal->j_flags &= ~JBD2_BARRIER; + write_unlock(&journal->j_state_lock); - /* And try again, without the barrier */ - lock_buffer(bh); - set_buffer_uptodate(bh); - clear_buffer_dirty(bh); - ret = submit_bh(WRITE_SYNC_PLUG, bh); - } - } else { + /* And try again, without the barrier */ + lock_buffer(bh); + set_buffer_uptodate(bh); + clear_buffer_dirty(bh); ret = submit_bh(WRITE_SYNC_PLUG, bh); } *cbh = bh; diff --git a/trunk/fs/jbd2/journal.c b/trunk/fs/jbd2/journal.c index 0e8014ea6b94..ad5866aaf0f9 100644 --- a/trunk/fs/jbd2/journal.c +++ b/trunk/fs/jbd2/journal.c @@ -1124,7 +1124,7 @@ void jbd2_journal_update_superblock(journal_t *journal, int wait) set_buffer_uptodate(bh); } } else - write_dirty_buffer(bh, WRITE); + ll_rw_block(SWRITE, 1, &bh); out: /* If we have just flushed the log (by marking s_start==0), then diff --git a/trunk/fs/jbd2/revoke.c b/trunk/fs/jbd2/revoke.c index 9ad321fd63fd..a360b06af2e3 100644 --- a/trunk/fs/jbd2/revoke.c +++ b/trunk/fs/jbd2/revoke.c @@ -625,7 +625,7 @@ static void flush_descriptor(journal_t *journal, set_buffer_jwrite(bh); BUFFER_TRACE(bh, "write"); set_buffer_dirty(bh); - write_dirty_buffer(bh, write_op); + ll_rw_block((write_op == WRITE) ? SWRITE : SWRITE_SYNC_PLUG, 1, &bh); } #endif diff --git a/trunk/fs/mbcache.c b/trunk/fs/mbcache.c index 93444747237b..cf4e6cdfd15b 100644 --- a/trunk/fs/mbcache.c +++ b/trunk/fs/mbcache.c @@ -80,7 +80,6 @@ struct mb_cache { struct list_head c_cache_list; const char *c_name; atomic_t c_entry_count; - int c_max_entries; int c_bucket_bits; struct kmem_cache *c_entry_cache; struct list_head *c_block_hash; @@ -244,12 +243,6 @@ mb_cache_create(const char *name, int bucket_bits) if (!cache->c_entry_cache) goto fail2; - /* - * Set an upper limit on the number of cache entries so that the hash - * chains won't grow too long. - */ - cache->c_max_entries = bucket_count << 4; - spin_lock(&mb_cache_spinlock); list_add(&cache->c_cache_list, &mb_cache_list); spin_unlock(&mb_cache_spinlock); @@ -340,6 +333,7 @@ mb_cache_destroy(struct mb_cache *cache) kfree(cache); } + /* * mb_cache_entry_alloc() * @@ -351,29 +345,17 @@ mb_cache_destroy(struct mb_cache *cache) struct mb_cache_entry * mb_cache_entry_alloc(struct mb_cache *cache, gfp_t gfp_flags) { - struct mb_cache_entry *ce = NULL; - - if (atomic_read(&cache->c_entry_count) >= cache->c_max_entries) { - spin_lock(&mb_cache_spinlock); - if (!list_empty(&mb_cache_lru_list)) { - ce = list_entry(mb_cache_lru_list.next, - struct mb_cache_entry, e_lru_list); - list_del_init(&ce->e_lru_list); - __mb_cache_entry_unhash(ce); - } - spin_unlock(&mb_cache_spinlock); - } - if (!ce) { - ce = kmem_cache_alloc(cache->c_entry_cache, gfp_flags); - if (!ce) - return NULL; + struct mb_cache_entry *ce; + + ce = kmem_cache_alloc(cache->c_entry_cache, gfp_flags); + if (ce) { atomic_inc(&cache->c_entry_count); INIT_LIST_HEAD(&ce->e_lru_list); INIT_LIST_HEAD(&ce->e_block_list); ce->e_cache = cache; + ce->e_used = 1 + MB_CACHE_WRITER; ce->e_queued = 0; } - ce->e_used = 1 + MB_CACHE_WRITER; return ce; } diff --git a/trunk/fs/namei.c b/trunk/fs/namei.c index 24896e833565..17ea76bf2fbe 100644 --- a/trunk/fs/namei.c +++ b/trunk/fs/namei.c @@ -595,16 +595,15 @@ int follow_up(struct path *path) { struct vfsmount *parent; struct dentry *mountpoint; - - br_read_lock(vfsmount_lock); + spin_lock(&vfsmount_lock); parent = path->mnt->mnt_parent; if (parent == path->mnt) { - br_read_unlock(vfsmount_lock); + spin_unlock(&vfsmount_lock); return 0; } mntget(parent); mountpoint = dget(path->mnt->mnt_mountpoint); - br_read_unlock(vfsmount_lock); + spin_unlock(&vfsmount_lock); dput(path->dentry); path->dentry = mountpoint; mntput(path->mnt); @@ -686,35 +685,6 @@ static __always_inline void follow_dotdot(struct nameidata *nd) follow_mount(&nd->path); } -/* - * Allocate a dentry with name and parent, and perform a parent - * directory ->lookup on it. Returns the new dentry, or ERR_PTR - * on error. parent->d_inode->i_mutex must be held. d_lookup must - * have verified that no child exists while under i_mutex. - */ -static struct dentry *d_alloc_and_lookup(struct dentry *parent, - struct qstr *name, struct nameidata *nd) -{ - struct inode *inode = parent->d_inode; - struct dentry *dentry; - struct dentry *old; - - /* Don't create child dentry for a dead directory. */ - if (unlikely(IS_DEADDIR(inode))) - return ERR_PTR(-ENOENT); - - dentry = d_alloc(parent, name); - if (unlikely(!dentry)) - return ERR_PTR(-ENOMEM); - - old = inode->i_op->lookup(inode, dentry, nd); - if (unlikely(old)) { - dput(dentry); - dentry = old; - } - return dentry; -} - /* * It's more convoluted than I'd like it to be, but... it's still fairly * small and for now I'd prefer to have fast path as straight as possible. @@ -736,15 +706,9 @@ static int do_lookup(struct nameidata *nd, struct qstr *name, return err; } - /* - * Rename seqlock is not required here because in the off chance - * of a false negative due to a concurrent rename, we're going to - * do the non-racy lookup, below. - */ dentry = __d_lookup(nd->path.dentry, name); if (!dentry) goto need_lookup; -found: if (dentry->d_op && dentry->d_op->d_revalidate) goto need_revalidate; done: @@ -760,28 +724,56 @@ static int do_lookup(struct nameidata *nd, struct qstr *name, mutex_lock(&dir->i_mutex); /* * First re-do the cached lookup just in case it was created - * while we waited for the directory semaphore, or the first - * lookup failed due to an unrelated rename. + * while we waited for the directory semaphore.. * - * This could use version numbering or similar to avoid unnecessary - * cache lookups, but then we'd have to do the first lookup in the - * non-racy way. However in the common case here, everything should - * be hot in cache, so would it be a big win? + * FIXME! This could use version numbering or similar to + * avoid unnecessary cache lookups. + * + * The "dcache_lock" is purely to protect the RCU list walker + * from concurrent renames at this point (we mustn't get false + * negatives from the RCU list walk here, unlike the optimistic + * fast walk). + * + * so doing d_lookup() (with seqlock), instead of lockfree __d_lookup */ dentry = d_lookup(parent, name); - if (likely(!dentry)) { - dentry = d_alloc_and_lookup(parent, name, nd); + if (!dentry) { + struct dentry *new; + + /* Don't create child dentry for a dead directory. */ + dentry = ERR_PTR(-ENOENT); + if (IS_DEADDIR(dir)) + goto out_unlock; + + new = d_alloc(parent, name); + dentry = ERR_PTR(-ENOMEM); + if (new) { + dentry = dir->i_op->lookup(dir, new, nd); + if (dentry) + dput(new); + else + dentry = new; + } +out_unlock: mutex_unlock(&dir->i_mutex); if (IS_ERR(dentry)) goto fail; goto done; } + /* * Uhhuh! Nasty case: the cache was re-populated while * we waited on the semaphore. Need to revalidate. */ mutex_unlock(&dir->i_mutex); - goto found; + if (dentry->d_op && dentry->d_op->d_revalidate) { + dentry = do_revalidate(dentry, nd); + if (!dentry) + dentry = ERR_PTR(-ENOENT); + } + if (IS_ERR(dentry)) + goto fail; + goto done; need_revalidate: dentry = do_revalidate(dentry, nd); @@ -1138,18 +1130,35 @@ static struct dentry *__lookup_hash(struct qstr *name, goto out; } - /* - * Don't bother with __d_lookup: callers are for creat as - * well as unlink, so a lot of the time it would cost - * a double lookup. + dentry = __d_lookup(base, name); + + /* lockess __d_lookup may fail due to concurrent d_move() + * in some unrelated directory, so try with d_lookup */ - dentry = d_lookup(base, name); + if (!dentry) + dentry = d_lookup(base, name); if (dentry && dentry->d_op && dentry->d_op->d_revalidate) dentry = do_revalidate(dentry, nd); - if (!dentry) - dentry = d_alloc_and_lookup(base, name, nd); + if (!dentry) { + struct dentry *new; + + /* Don't create child dentry for a dead directory. */ + dentry = ERR_PTR(-ENOENT); + if (IS_DEADDIR(inode)) + goto out; + + new = d_alloc(base, name); + dentry = ERR_PTR(-ENOMEM); + if (!new) + goto out; + dentry = inode->i_op->lookup(inode, new, nd); + if (!dentry) + dentry = new; + else + dput(new); + } out: return dentry; } diff --git a/trunk/fs/namespace.c b/trunk/fs/namespace.c index de402eb6eafb..2e10cb19c5b0 100644 --- a/trunk/fs/namespace.c +++ b/trunk/fs/namespace.c @@ -11,8 +11,6 @@ #include #include #include -#include -#include #include #include #include @@ -40,10 +38,12 @@ #define HASH_SHIFT ilog2(PAGE_SIZE / sizeof(struct list_head)) #define HASH_SIZE (1UL << HASH_SHIFT) +/* spinlock for vfsmount related operations, inplace of dcache_lock */ +__cacheline_aligned_in_smp DEFINE_SPINLOCK(vfsmount_lock); + static int event; static DEFINE_IDA(mnt_id_ida); static DEFINE_IDA(mnt_group_ida); -static DEFINE_SPINLOCK(mnt_id_lock); static int mnt_id_start = 0; static int mnt_group_start = 1; @@ -55,16 +55,6 @@ static struct rw_semaphore namespace_sem; struct kobject *fs_kobj; EXPORT_SYMBOL_GPL(fs_kobj); -/* - * vfsmount lock may be taken for read to prevent changes to the - * vfsmount hash, ie. during mountpoint lookups or walking back - * up the tree. - * - * It should be taken for write in all cases where the vfsmount - * tree or hash is modified or when a vfsmount structure is modified. - */ -DEFINE_BRLOCK(vfsmount_lock); - static inline unsigned long hash(struct vfsmount *mnt, struct dentry *dentry) { unsigned long tmp = ((unsigned long)mnt / L1_CACHE_BYTES); @@ -75,21 +65,18 @@ static inline unsigned long hash(struct vfsmount *mnt, struct dentry *dentry) #define MNT_WRITER_UNDERFLOW_LIMIT -(1<<16) -/* - * allocation is serialized by namespace_sem, but we need the spinlock to - * serialize with freeing. - */ +/* allocation is serialized by namespace_sem */ static int mnt_alloc_id(struct vfsmount *mnt) { int res; retry: ida_pre_get(&mnt_id_ida, GFP_KERNEL); - spin_lock(&mnt_id_lock); + spin_lock(&vfsmount_lock); res = ida_get_new_above(&mnt_id_ida, mnt_id_start, &mnt->mnt_id); if (!res) mnt_id_start = mnt->mnt_id + 1; - spin_unlock(&mnt_id_lock); + spin_unlock(&vfsmount_lock); if (res == -EAGAIN) goto retry; @@ -99,11 +86,11 @@ static int mnt_alloc_id(struct vfsmount *mnt) static void mnt_free_id(struct vfsmount *mnt) { int id = mnt->mnt_id; - spin_lock(&mnt_id_lock); + spin_lock(&vfsmount_lock); ida_remove(&mnt_id_ida, id); if (mnt_id_start > id) mnt_id_start = id; - spin_unlock(&mnt_id_lock); + spin_unlock(&vfsmount_lock); } /* @@ -361,7 +348,7 @@ static int mnt_make_readonly(struct vfsmount *mnt) { int ret = 0; - br_write_lock(vfsmount_lock); + spin_lock(&vfsmount_lock); mnt->mnt_flags |= MNT_WRITE_HOLD; /* * After storing MNT_WRITE_HOLD, we'll read the counters. This store @@ -395,15 +382,15 @@ static int mnt_make_readonly(struct vfsmount *mnt) */ smp_wmb(); mnt->mnt_flags &= ~MNT_WRITE_HOLD; - br_write_unlock(vfsmount_lock); + spin_unlock(&vfsmount_lock); return ret; } static void __mnt_unmake_readonly(struct vfsmount *mnt) { - br_write_lock(vfsmount_lock); + spin_lock(&vfsmount_lock); mnt->mnt_flags &= ~MNT_READONLY; - br_write_unlock(vfsmount_lock); + spin_unlock(&vfsmount_lock); } void simple_set_mnt(struct vfsmount *mnt, struct super_block *sb) @@ -427,7 +414,6 @@ void free_vfsmnt(struct vfsmount *mnt) /* * find the first or last mount at @dentry on vfsmount @mnt depending on * @dir. If @dir is set return the first mount else return the last mount. - * vfsmount_lock must be held for read or write. */ struct vfsmount *__lookup_mnt(struct vfsmount *mnt, struct dentry *dentry, int dir) @@ -457,11 +443,10 @@ struct vfsmount *__lookup_mnt(struct vfsmount *mnt, struct dentry *dentry, struct vfsmount *lookup_mnt(struct path *path) { struct vfsmount *child_mnt; - - br_read_lock(vfsmount_lock); + spin_lock(&vfsmount_lock); if ((child_mnt = __lookup_mnt(path->mnt, path->dentry, 1))) mntget(child_mnt); - br_read_unlock(vfsmount_lock); + spin_unlock(&vfsmount_lock); return child_mnt; } @@ -470,9 +455,6 @@ static inline int check_mnt(struct vfsmount *mnt) return mnt->mnt_ns == current->nsproxy->mnt_ns; } -/* - * vfsmount lock must be held for write - */ static void touch_mnt_namespace(struct mnt_namespace *ns) { if (ns) { @@ -481,9 +463,6 @@ static void touch_mnt_namespace(struct mnt_namespace *ns) } } -/* - * vfsmount lock must be held for write - */ static void __touch_mnt_namespace(struct mnt_namespace *ns) { if (ns && ns->event != event) { @@ -492,9 +471,6 @@ static void __touch_mnt_namespace(struct mnt_namespace *ns) } } -/* - * vfsmount lock must be held for write - */ static void detach_mnt(struct vfsmount *mnt, struct path *old_path) { old_path->dentry = mnt->mnt_mountpoint; @@ -506,9 +482,6 @@ static void detach_mnt(struct vfsmount *mnt, struct path *old_path) old_path->dentry->d_mounted--; } -/* - * vfsmount lock must be held for write - */ void mnt_set_mountpoint(struct vfsmount *mnt, struct dentry *dentry, struct vfsmount *child_mnt) { @@ -517,9 +490,6 @@ void mnt_set_mountpoint(struct vfsmount *mnt, struct dentry *dentry, dentry->d_mounted++; } -/* - * vfsmount lock must be held for write - */ static void attach_mnt(struct vfsmount *mnt, struct path *path) { mnt_set_mountpoint(path->mnt, path->dentry, mnt); @@ -529,7 +499,7 @@ static void attach_mnt(struct vfsmount *mnt, struct path *path) } /* - * vfsmount lock must be held for write + * the caller must hold vfsmount_lock */ static void commit_tree(struct vfsmount *mnt) { @@ -653,43 +623,39 @@ static inline void __mntput(struct vfsmount *mnt) void mntput_no_expire(struct vfsmount *mnt) { repeat: - if (atomic_add_unless(&mnt->mnt_count, -1, 1)) - return; - br_write_lock(vfsmount_lock); - if (!atomic_dec_and_test(&mnt->mnt_count)) { - br_write_unlock(vfsmount_lock); - return; - } - if (likely(!mnt->mnt_pinned)) { - br_write_unlock(vfsmount_lock); - __mntput(mnt); - return; + if (atomic_dec_and_lock(&mnt->mnt_count, &vfsmount_lock)) { + if (likely(!mnt->mnt_pinned)) { + spin_unlock(&vfsmount_lock); + __mntput(mnt); + return; + } + atomic_add(mnt->mnt_pinned + 1, &mnt->mnt_count); + mnt->mnt_pinned = 0; + spin_unlock(&vfsmount_lock); + acct_auto_close_mnt(mnt); + goto repeat; } - atomic_add(mnt->mnt_pinned + 1, &mnt->mnt_count); - mnt->mnt_pinned = 0; - br_write_unlock(vfsmount_lock); - acct_auto_close_mnt(mnt); - goto repeat; } + EXPORT_SYMBOL(mntput_no_expire); void mnt_pin(struct vfsmount *mnt) { - br_write_lock(vfsmount_lock); + spin_lock(&vfsmount_lock); mnt->mnt_pinned++; - br_write_unlock(vfsmount_lock); + spin_unlock(&vfsmount_lock); } EXPORT_SYMBOL(mnt_pin); void mnt_unpin(struct vfsmount *mnt) { - br_write_lock(vfsmount_lock); + spin_lock(&vfsmount_lock); if (mnt->mnt_pinned) { atomic_inc(&mnt->mnt_count); mnt->mnt_pinned--; } - br_write_unlock(vfsmount_lock); + spin_unlock(&vfsmount_lock); } EXPORT_SYMBOL(mnt_unpin); @@ -780,12 +746,12 @@ int mnt_had_events(struct proc_mounts *p) struct mnt_namespace *ns = p->ns; int res = 0; - br_read_lock(vfsmount_lock); + spin_lock(&vfsmount_lock); if (p->event != ns->event) { p->event = ns->event; res = 1; } - br_read_unlock(vfsmount_lock); + spin_unlock(&vfsmount_lock); return res; } @@ -986,12 +952,12 @@ int may_umount_tree(struct vfsmount *mnt) int minimum_refs = 0; struct vfsmount *p; - br_read_lock(vfsmount_lock); + spin_lock(&vfsmount_lock); for (p = mnt; p; p = next_mnt(p, mnt)) { actual_refs += atomic_read(&p->mnt_count); minimum_refs += 2; } - br_read_unlock(vfsmount_lock); + spin_unlock(&vfsmount_lock); if (actual_refs > minimum_refs) return 0; @@ -1018,10 +984,10 @@ int may_umount(struct vfsmount *mnt) { int ret = 1; down_read(&namespace_sem); - br_read_lock(vfsmount_lock); + spin_lock(&vfsmount_lock); if (propagate_mount_busy(mnt, 2)) ret = 0; - br_read_unlock(vfsmount_lock); + spin_unlock(&vfsmount_lock); up_read(&namespace_sem); return ret; } @@ -1037,14 +1003,13 @@ void release_mounts(struct list_head *head) if (mnt->mnt_parent != mnt) { struct dentry *dentry; struct vfsmount *m; - - br_write_lock(vfsmount_lock); + spin_lock(&vfsmount_lock); dentry = mnt->mnt_mountpoint; m = mnt->mnt_parent; mnt->mnt_mountpoint = mnt->mnt_root; mnt->mnt_parent = mnt; m->mnt_ghosts--; - br_write_unlock(vfsmount_lock); + spin_unlock(&vfsmount_lock); dput(dentry); mntput(m); } @@ -1052,10 +1017,6 @@ void release_mounts(struct list_head *head) } } -/* - * vfsmount lock must be held for write - * namespace_sem must be held for write - */ void umount_tree(struct vfsmount *mnt, int propagate, struct list_head *kill) { struct vfsmount *p; @@ -1146,7 +1107,7 @@ static int do_umount(struct vfsmount *mnt, int flags) } down_write(&namespace_sem); - br_write_lock(vfsmount_lock); + spin_lock(&vfsmount_lock); event++; if (!(flags & MNT_DETACH)) @@ -1158,7 +1119,7 @@ static int do_umount(struct vfsmount *mnt, int flags) umount_tree(mnt, 1, &umount_list); retval = 0; } - br_write_unlock(vfsmount_lock); + spin_unlock(&vfsmount_lock); up_write(&namespace_sem); release_mounts(&umount_list); return retval; @@ -1270,19 +1231,19 @@ struct vfsmount *copy_tree(struct vfsmount *mnt, struct dentry *dentry, q = clone_mnt(p, p->mnt_root, flag); if (!q) goto Enomem; - br_write_lock(vfsmount_lock); + spin_lock(&vfsmount_lock); list_add_tail(&q->mnt_list, &res->mnt_list); attach_mnt(q, &path); - br_write_unlock(vfsmount_lock); + spin_unlock(&vfsmount_lock); } } return res; Enomem: if (res) { LIST_HEAD(umount_list); - br_write_lock(vfsmount_lock); + spin_lock(&vfsmount_lock); umount_tree(res, 0, &umount_list); - br_write_unlock(vfsmount_lock); + spin_unlock(&vfsmount_lock); release_mounts(&umount_list); } return NULL; @@ -1301,9 +1262,9 @@ void drop_collected_mounts(struct vfsmount *mnt) { LIST_HEAD(umount_list); down_write(&namespace_sem); - br_write_lock(vfsmount_lock); + spin_lock(&vfsmount_lock); umount_tree(mnt, 0, &umount_list); - br_write_unlock(vfsmount_lock); + spin_unlock(&vfsmount_lock); up_write(&namespace_sem); release_mounts(&umount_list); } @@ -1431,7 +1392,7 @@ static int attach_recursive_mnt(struct vfsmount *source_mnt, if (err) goto out_cleanup_ids; - br_write_lock(vfsmount_lock); + spin_lock(&vfsmount_lock); if (IS_MNT_SHARED(dest_mnt)) { for (p = source_mnt; p; p = next_mnt(p, source_mnt)) @@ -1450,8 +1411,7 @@ static int attach_recursive_mnt(struct vfsmount *source_mnt, list_del_init(&child->mnt_hash); commit_tree(child); } - br_write_unlock(vfsmount_lock); - + spin_unlock(&vfsmount_lock); return 0; out_cleanup_ids: @@ -1506,10 +1466,10 @@ static int do_change_type(struct path *path, int flag) goto out_unlock; } - br_write_lock(vfsmount_lock); + spin_lock(&vfsmount_lock); for (m = mnt; m; m = (recurse ? next_mnt(m, mnt) : NULL)) change_mnt_propagation(m, type); - br_write_unlock(vfsmount_lock); + spin_unlock(&vfsmount_lock); out_unlock: up_write(&namespace_sem); @@ -1553,10 +1513,9 @@ static int do_loopback(struct path *path, char *old_name, err = graft_tree(mnt, path); if (err) { LIST_HEAD(umount_list); - - br_write_lock(vfsmount_lock); + spin_lock(&vfsmount_lock); umount_tree(mnt, 0, &umount_list); - br_write_unlock(vfsmount_lock); + spin_unlock(&vfsmount_lock); release_mounts(&umount_list); } @@ -1609,16 +1568,16 @@ static int do_remount(struct path *path, int flags, int mnt_flags, else err = do_remount_sb(sb, flags, data, 0); if (!err) { - br_write_lock(vfsmount_lock); + spin_lock(&vfsmount_lock); mnt_flags |= path->mnt->mnt_flags & MNT_PROPAGATION_MASK; path->mnt->mnt_flags = mnt_flags; - br_write_unlock(vfsmount_lock); + spin_unlock(&vfsmount_lock); } up_write(&sb->s_umount); if (!err) { - br_write_lock(vfsmount_lock); + spin_lock(&vfsmount_lock); touch_mnt_namespace(path->mnt->mnt_ns); - br_write_unlock(vfsmount_lock); + spin_unlock(&vfsmount_lock); } return err; } @@ -1795,7 +1754,7 @@ void mark_mounts_for_expiry(struct list_head *mounts) return; down_write(&namespace_sem); - br_write_lock(vfsmount_lock); + spin_lock(&vfsmount_lock); /* extract from the expiration list every vfsmount that matches the * following criteria: @@ -1814,7 +1773,7 @@ void mark_mounts_for_expiry(struct list_head *mounts) touch_mnt_namespace(mnt->mnt_ns); umount_tree(mnt, 1, &umounts); } - br_write_unlock(vfsmount_lock); + spin_unlock(&vfsmount_lock); up_write(&namespace_sem); release_mounts(&umounts); @@ -1871,8 +1830,6 @@ static int select_submounts(struct vfsmount *parent, struct list_head *graveyard /* * process a list of expirable mountpoints with the intent of discarding any * submounts of a specific parent mountpoint - * - * vfsmount_lock must be held for write */ static void shrink_submounts(struct vfsmount *mnt, struct list_head *umounts) { @@ -2091,9 +2048,9 @@ static struct mnt_namespace *dup_mnt_ns(struct mnt_namespace *mnt_ns, kfree(new_ns); return ERR_PTR(-ENOMEM); } - br_write_lock(vfsmount_lock); + spin_lock(&vfsmount_lock); list_add_tail(&new_ns->list, &new_ns->root->mnt_list); - br_write_unlock(vfsmount_lock); + spin_unlock(&vfsmount_lock); /* * Second pass: switch the tsk->fs->* elements and mark new vfsmounts @@ -2287,7 +2244,7 @@ SYSCALL_DEFINE2(pivot_root, const char __user *, new_root, goto out2; /* not attached */ /* make sure we can reach put_old from new_root */ tmp = old.mnt; - br_write_lock(vfsmount_lock); + spin_lock(&vfsmount_lock); if (tmp != new.mnt) { for (;;) { if (tmp->mnt_parent == tmp) @@ -2307,7 +2264,7 @@ SYSCALL_DEFINE2(pivot_root, const char __user *, new_root, /* mount new_root on / */ attach_mnt(new.mnt, &root_parent); touch_mnt_namespace(current->nsproxy->mnt_ns); - br_write_unlock(vfsmount_lock); + spin_unlock(&vfsmount_lock); chroot_fs_refs(&root, &new); error = 0; path_put(&root_parent); @@ -2322,7 +2279,7 @@ SYSCALL_DEFINE2(pivot_root, const char __user *, new_root, out0: return error; out3: - br_write_unlock(vfsmount_lock); + spin_unlock(&vfsmount_lock); goto out2; } @@ -2369,8 +2326,6 @@ void __init mnt_init(void) for (u = 0; u < HASH_SIZE; u++) INIT_LIST_HEAD(&mount_hashtable[u]); - br_lock_init(vfsmount_lock); - err = sysfs_init(); if (err) printk(KERN_WARNING "%s: sysfs_init error: %d\n", @@ -2389,9 +2344,9 @@ void put_mnt_ns(struct mnt_namespace *ns) if (!atomic_dec_and_test(&ns->count)) return; down_write(&namespace_sem); - br_write_lock(vfsmount_lock); + spin_lock(&vfsmount_lock); umount_tree(ns->root, 0, &umount_list); - br_write_unlock(vfsmount_lock); + spin_unlock(&vfsmount_lock); up_write(&namespace_sem); release_mounts(&umount_list); kfree(ns); diff --git a/trunk/fs/nilfs2/super.c b/trunk/fs/nilfs2/super.c index 922263393c76..bee60c04109a 100644 --- a/trunk/fs/nilfs2/super.c +++ b/trunk/fs/nilfs2/super.c @@ -175,24 +175,24 @@ static int nilfs_sync_super(struct nilfs_sb_info *sbi, int flag) { struct the_nilfs *nilfs = sbi->s_nilfs; int err; + int barrier_done = 0; + if (nilfs_test_opt(sbi, BARRIER)) { + set_buffer_ordered(nilfs->ns_sbh[0]); + barrier_done = 1; + } retry: set_buffer_dirty(nilfs->ns_sbh[0]); - - if (nilfs_test_opt(sbi, BARRIER)) { - err = __sync_dirty_buffer(nilfs->ns_sbh[0], - WRITE_SYNC | WRITE_BARRIER); - if (err == -EOPNOTSUPP) { - nilfs_warning(sbi->s_super, __func__, - "barrier-based sync failed. " - "disabling barriers\n"); - nilfs_clear_opt(sbi, BARRIER); - goto retry; - } - } else { - err = sync_dirty_buffer(nilfs->ns_sbh[0]); + err = sync_dirty_buffer(nilfs->ns_sbh[0]); + if (err == -EOPNOTSUPP && barrier_done) { + nilfs_warning(sbi->s_super, __func__, + "barrier-based sync failed. " + "disabling barriers\n"); + nilfs_clear_opt(sbi, BARRIER); + barrier_done = 0; + clear_buffer_ordered(nilfs->ns_sbh[0]); + goto retry; } - if (unlikely(err)) { printk(KERN_ERR "NILFS: unable to write superblock (err=%d)\n", err); diff --git a/trunk/fs/open.c b/trunk/fs/open.c index d74e1983e8dc..630715f9f73d 100644 --- a/trunk/fs/open.c +++ b/trunk/fs/open.c @@ -675,7 +675,7 @@ static struct file *__dentry_open(struct dentry *dentry, struct vfsmount *mnt, f->f_path.mnt = mnt; f->f_pos = 0; f->f_op = fops_get(inode->i_fop); - file_sb_list_add(f, inode->i_sb); + file_move(f, &inode->i_sb->s_files); error = security_dentry_open(f, cred); if (error) @@ -721,7 +721,7 @@ static struct file *__dentry_open(struct dentry *dentry, struct vfsmount *mnt, mnt_drop_write(mnt); } } - file_sb_list_del(f); + file_kill(f); f->f_path.dentry = NULL; f->f_path.mnt = NULL; cleanup_file: diff --git a/trunk/fs/pnode.c b/trunk/fs/pnode.c index 8066b8dd748f..5cc564a83149 100644 --- a/trunk/fs/pnode.c +++ b/trunk/fs/pnode.c @@ -126,9 +126,6 @@ static int do_make_slave(struct vfsmount *mnt) return 0; } -/* - * vfsmount lock must be held for write - */ void change_mnt_propagation(struct vfsmount *mnt, int type) { if (type == MS_SHARED) { @@ -273,12 +270,12 @@ int propagate_mnt(struct vfsmount *dest_mnt, struct dentry *dest_dentry, prev_src_mnt = child; } out: - br_write_lock(vfsmount_lock); + spin_lock(&vfsmount_lock); while (!list_empty(&tmp_list)) { child = list_first_entry(&tmp_list, struct vfsmount, mnt_hash); umount_tree(child, 0, &umount_list); } - br_write_unlock(vfsmount_lock); + spin_unlock(&vfsmount_lock); release_mounts(&umount_list); return ret; } @@ -299,8 +296,6 @@ static inline int do_refcount_check(struct vfsmount *mnt, int count) * other mounts its parent propagates to. * Check if any of these mounts that **do not have submounts** * have more references than 'refcnt'. If so return busy. - * - * vfsmount lock must be held for read or write */ int propagate_mount_busy(struct vfsmount *mnt, int refcnt) { @@ -358,8 +353,6 @@ static void __propagate_umount(struct vfsmount *mnt) * collect all mounts that receive propagation from the mount in @list, * and return these additional mounts in the same list. * @list: the list of mounts to be unmounted. - * - * vfsmount lock must be held for write */ int propagate_umount(struct list_head *list) { diff --git a/trunk/fs/reiserfs/inode.c b/trunk/fs/reiserfs/inode.c index caa758377d66..ae35413dcbe1 100644 --- a/trunk/fs/reiserfs/inode.c +++ b/trunk/fs/reiserfs/inode.c @@ -83,7 +83,6 @@ void reiserfs_evict_inode(struct inode *inode) dquot_drop(inode); inode->i_blocks = 0; reiserfs_write_unlock_once(inode->i_sb, depth); - return; no_delete: end_writeback(inode); diff --git a/trunk/fs/reiserfs/journal.c b/trunk/fs/reiserfs/journal.c index 812e2c05aa29..1ec952b1f036 100644 --- a/trunk/fs/reiserfs/journal.c +++ b/trunk/fs/reiserfs/journal.c @@ -2311,7 +2311,7 @@ static int journal_read_transaction(struct super_block *sb, /* flush out the real blocks */ for (i = 0; i < get_desc_trans_len(desc); i++) { set_buffer_dirty(real_blocks[i]); - write_dirty_buffer(real_blocks[i], WRITE); + ll_rw_block(SWRITE, 1, real_blocks + i); } for (i = 0; i < get_desc_trans_len(desc); i++) { wait_on_buffer(real_blocks[i]); diff --git a/trunk/fs/super.c b/trunk/fs/super.c index 8819e3a7ff20..9674ab2c8718 100644 --- a/trunk/fs/super.c +++ b/trunk/fs/super.c @@ -54,22 +54,7 @@ static struct super_block *alloc_super(struct file_system_type *type) s = NULL; goto out; } -#ifdef CONFIG_SMP - s->s_files = alloc_percpu(struct list_head); - if (!s->s_files) { - security_sb_free(s); - kfree(s); - s = NULL; - goto out; - } else { - int i; - - for_each_possible_cpu(i) - INIT_LIST_HEAD(per_cpu_ptr(s->s_files, i)); - } -#else INIT_LIST_HEAD(&s->s_files); -#endif INIT_LIST_HEAD(&s->s_instances); INIT_HLIST_HEAD(&s->s_anon); INIT_LIST_HEAD(&s->s_inodes); @@ -123,9 +108,6 @@ static struct super_block *alloc_super(struct file_system_type *type) */ static inline void destroy_super(struct super_block *s) { -#ifdef CONFIG_SMP - free_percpu(s->s_files); -#endif security_sb_free(s); kfree(s->s_subtype); kfree(s->s_options); diff --git a/trunk/fs/ufs/balloc.c b/trunk/fs/ufs/balloc.c index 46f7a807bbc1..048484fb10d2 100644 --- a/trunk/fs/ufs/balloc.c +++ b/trunk/fs/ufs/balloc.c @@ -114,8 +114,10 @@ void ufs_free_fragments(struct inode *inode, u64 fragment, unsigned count) ubh_mark_buffer_dirty (USPI_UBH(uspi)); ubh_mark_buffer_dirty (UCPI_UBH(ucpi)); - if (sb->s_flags & MS_SYNCHRONOUS) - ubh_sync_block(UCPI_UBH(ucpi)); + if (sb->s_flags & MS_SYNCHRONOUS) { + ubh_ll_rw_block(SWRITE, UCPI_UBH(ucpi)); + ubh_wait_on_buffer (UCPI_UBH(ucpi)); + } sb->s_dirt = 1; unlock_super (sb); @@ -205,8 +207,10 @@ void ufs_free_blocks(struct inode *inode, u64 fragment, unsigned count) ubh_mark_buffer_dirty (USPI_UBH(uspi)); ubh_mark_buffer_dirty (UCPI_UBH(ucpi)); - if (sb->s_flags & MS_SYNCHRONOUS) - ubh_sync_block(UCPI_UBH(ucpi)); + if (sb->s_flags & MS_SYNCHRONOUS) { + ubh_ll_rw_block(SWRITE, UCPI_UBH(ucpi)); + ubh_wait_on_buffer (UCPI_UBH(ucpi)); + } if (overflow) { fragment += count; @@ -554,8 +558,10 @@ static u64 ufs_add_fragments(struct inode *inode, u64 fragment, ubh_mark_buffer_dirty (USPI_UBH(uspi)); ubh_mark_buffer_dirty (UCPI_UBH(ucpi)); - if (sb->s_flags & MS_SYNCHRONOUS) - ubh_sync_block(UCPI_UBH(ucpi)); + if (sb->s_flags & MS_SYNCHRONOUS) { + ubh_ll_rw_block(SWRITE, UCPI_UBH(ucpi)); + ubh_wait_on_buffer (UCPI_UBH(ucpi)); + } sb->s_dirt = 1; UFSD("EXIT, fragment %llu\n", (unsigned long long)fragment); @@ -674,8 +680,10 @@ static u64 ufs_alloc_fragments(struct inode *inode, unsigned cgno, succed: ubh_mark_buffer_dirty (USPI_UBH(uspi)); ubh_mark_buffer_dirty (UCPI_UBH(ucpi)); - if (sb->s_flags & MS_SYNCHRONOUS) - ubh_sync_block(UCPI_UBH(ucpi)); + if (sb->s_flags & MS_SYNCHRONOUS) { + ubh_ll_rw_block(SWRITE, UCPI_UBH(ucpi)); + ubh_wait_on_buffer (UCPI_UBH(ucpi)); + } sb->s_dirt = 1; result += cgno * uspi->s_fpg; diff --git a/trunk/fs/ufs/ialloc.c b/trunk/fs/ufs/ialloc.c index 2eabf04af3de..428017e018fe 100644 --- a/trunk/fs/ufs/ialloc.c +++ b/trunk/fs/ufs/ialloc.c @@ -113,8 +113,10 @@ void ufs_free_inode (struct inode * inode) ubh_mark_buffer_dirty (USPI_UBH(uspi)); ubh_mark_buffer_dirty (UCPI_UBH(ucpi)); - if (sb->s_flags & MS_SYNCHRONOUS) - ubh_sync_block(UCPI_UBH(ucpi)); + if (sb->s_flags & MS_SYNCHRONOUS) { + ubh_ll_rw_block(SWRITE, UCPI_UBH(ucpi)); + ubh_wait_on_buffer (UCPI_UBH(ucpi)); + } sb->s_dirt = 1; unlock_super (sb); @@ -154,8 +156,10 @@ static void ufs2_init_inodes_chunk(struct super_block *sb, fs32_add(sb, &ucg->cg_u.cg_u2.cg_initediblk, uspi->s_inopb); ubh_mark_buffer_dirty(UCPI_UBH(ucpi)); - if (sb->s_flags & MS_SYNCHRONOUS) - ubh_sync_block(UCPI_UBH(ucpi)); + if (sb->s_flags & MS_SYNCHRONOUS) { + ubh_ll_rw_block(SWRITE, UCPI_UBH(ucpi)); + ubh_wait_on_buffer(UCPI_UBH(ucpi)); + } UFSD("EXIT\n"); } @@ -286,8 +290,10 @@ struct inode * ufs_new_inode(struct inode * dir, int mode) } ubh_mark_buffer_dirty (USPI_UBH(uspi)); ubh_mark_buffer_dirty (UCPI_UBH(ucpi)); - if (sb->s_flags & MS_SYNCHRONOUS) - ubh_sync_block(UCPI_UBH(ucpi)); + if (sb->s_flags & MS_SYNCHRONOUS) { + ubh_ll_rw_block(SWRITE, UCPI_UBH(ucpi)); + ubh_wait_on_buffer (UCPI_UBH(ucpi)); + } sb->s_dirt = 1; inode->i_ino = cg * uspi->s_ipg + bit; diff --git a/trunk/fs/ufs/truncate.c b/trunk/fs/ufs/truncate.c index a58f9155fc9a..34d5cb135320 100644 --- a/trunk/fs/ufs/truncate.c +++ b/trunk/fs/ufs/truncate.c @@ -243,8 +243,10 @@ static int ufs_trunc_indirect(struct inode *inode, u64 offset, void *p) ubh_bforget(ind_ubh); ind_ubh = NULL; } - if (IS_SYNC(inode) && ind_ubh && ubh_buffer_dirty(ind_ubh)) - ubh_sync_block(ind_ubh); + if (IS_SYNC(inode) && ind_ubh && ubh_buffer_dirty(ind_ubh)) { + ubh_ll_rw_block(SWRITE, ind_ubh); + ubh_wait_on_buffer (ind_ubh); + } ubh_brelse (ind_ubh); UFSD("EXIT: ino %lu\n", inode->i_ino); @@ -305,8 +307,10 @@ static int ufs_trunc_dindirect(struct inode *inode, u64 offset, void *p) ubh_bforget(dind_bh); dind_bh = NULL; } - if (IS_SYNC(inode) && dind_bh && ubh_buffer_dirty(dind_bh)) - ubh_sync_block(dind_bh); + if (IS_SYNC(inode) && dind_bh && ubh_buffer_dirty(dind_bh)) { + ubh_ll_rw_block(SWRITE, dind_bh); + ubh_wait_on_buffer (dind_bh); + } ubh_brelse (dind_bh); UFSD("EXIT: ino %lu\n", inode->i_ino); @@ -363,8 +367,10 @@ static int ufs_trunc_tindirect(struct inode *inode) ubh_bforget(tind_bh); tind_bh = NULL; } - if (IS_SYNC(inode) && tind_bh && ubh_buffer_dirty(tind_bh)) - ubh_sync_block(tind_bh); + if (IS_SYNC(inode) && tind_bh && ubh_buffer_dirty(tind_bh)) { + ubh_ll_rw_block(SWRITE, tind_bh); + ubh_wait_on_buffer (tind_bh); + } ubh_brelse (tind_bh); UFSD("EXIT: ino %lu\n", inode->i_ino); diff --git a/trunk/fs/ufs/util.c b/trunk/fs/ufs/util.c index d2c36d53fe66..85a7fc9e4a4e 100644 --- a/trunk/fs/ufs/util.c +++ b/trunk/fs/ufs/util.c @@ -113,17 +113,21 @@ void ubh_mark_buffer_uptodate (struct ufs_buffer_head * ubh, int flag) } } -void ubh_sync_block(struct ufs_buffer_head *ubh) +void ubh_ll_rw_block(int rw, struct ufs_buffer_head *ubh) { - if (ubh) { - unsigned i; + if (!ubh) + return; - for (i = 0; i < ubh->count; i++) - write_dirty_buffer(ubh->bh[i], WRITE); + ll_rw_block(rw, ubh->count, ubh->bh); +} - for (i = 0; i < ubh->count; i++) - wait_on_buffer(ubh->bh[i]); - } +void ubh_wait_on_buffer (struct ufs_buffer_head * ubh) +{ + unsigned i; + if (!ubh) + return; + for ( i = 0; i < ubh->count; i++ ) + wait_on_buffer (ubh->bh[i]); } void ubh_bforget (struct ufs_buffer_head * ubh) diff --git a/trunk/fs/ufs/util.h b/trunk/fs/ufs/util.h index 9f8775ce381c..0466036912f1 100644 --- a/trunk/fs/ufs/util.h +++ b/trunk/fs/ufs/util.h @@ -269,7 +269,8 @@ extern void ubh_brelse (struct ufs_buffer_head *); extern void ubh_brelse_uspi (struct ufs_sb_private_info *); extern void ubh_mark_buffer_dirty (struct ufs_buffer_head *); extern void ubh_mark_buffer_uptodate (struct ufs_buffer_head *, int); -extern void ubh_sync_block(struct ufs_buffer_head *); +extern void ubh_ll_rw_block(int, struct ufs_buffer_head *); +extern void ubh_wait_on_buffer (struct ufs_buffer_head *); extern void ubh_bforget (struct ufs_buffer_head *); extern int ubh_buffer_dirty (struct ufs_buffer_head *); #define ubh_ubhcpymem(mem,ubh,size) _ubh_ubhcpymem_(uspi,mem,ubh,size) diff --git a/trunk/include/asm-generic/syscalls.h b/trunk/include/asm-generic/syscalls.h index d89dec864d42..df84e3b04555 100644 --- a/trunk/include/asm-generic/syscalls.h +++ b/trunk/include/asm-generic/syscalls.h @@ -23,10 +23,8 @@ asmlinkage long sys_vfork(struct pt_regs *regs); #endif #ifndef sys_execve -asmlinkage long sys_execve(const char __user *filename, - const char __user *const __user *argv, - const char __user *const __user *envp, - struct pt_regs *regs); +asmlinkage long sys_execve(char __user *filename, char __user * __user *argv, + char __user * __user *envp, struct pt_regs *regs); #endif #ifndef sys_mmap2 diff --git a/trunk/include/linux/buffer_head.h b/trunk/include/linux/buffer_head.h index ec94c12f21da..43e649a72529 100644 --- a/trunk/include/linux/buffer_head.h +++ b/trunk/include/linux/buffer_head.h @@ -32,6 +32,7 @@ enum bh_state_bits { BH_Delay, /* Buffer is not yet allocated on disk */ BH_Boundary, /* Block is followed by a discontiguity */ BH_Write_EIO, /* I/O error on write */ + BH_Ordered, /* ordered write */ BH_Eopnotsupp, /* operation not supported (barrier) */ BH_Unwritten, /* Buffer is allocated on disk but not written */ BH_Quiet, /* Buffer Error Prinks to be quiet */ @@ -124,6 +125,7 @@ BUFFER_FNS(Async_Write, async_write) BUFFER_FNS(Delay, delay) BUFFER_FNS(Boundary, boundary) BUFFER_FNS(Write_EIO, write_io_error) +BUFFER_FNS(Ordered, ordered) BUFFER_FNS(Eopnotsupp, eopnotsupp) BUFFER_FNS(Unwritten, unwritten) @@ -181,8 +183,6 @@ void unlock_buffer(struct buffer_head *bh); void __lock_buffer(struct buffer_head *bh); void ll_rw_block(int, int, struct buffer_head * bh[]); int sync_dirty_buffer(struct buffer_head *bh); -int __sync_dirty_buffer(struct buffer_head *bh, int rw); -void write_dirty_buffer(struct buffer_head *bh, int rw); int submit_bh(int, struct buffer_head *); void write_boundary_block(struct block_device *bdev, sector_t bblock, unsigned blocksize); diff --git a/trunk/include/linux/fs.h b/trunk/include/linux/fs.h index 76041b614758..9a96b4d83fc1 100644 --- a/trunk/include/linux/fs.h +++ b/trunk/include/linux/fs.h @@ -125,6 +125,9 @@ struct inodes_stat_t { * block layer could (in theory) choose to ignore this * request if it runs into resource problems. * WRITE A normal async write. Device will be plugged. + * SWRITE Like WRITE, but a special case for ll_rw_block() that + * tells it to lock the buffer first. Normally a buffer + * must be locked before doing IO. * WRITE_SYNC_PLUG Synchronous write. Identical to WRITE, but passes down * the hint that someone will be waiting on this IO * shortly. The device must still be unplugged explicitly, @@ -135,6 +138,9 @@ struct inodes_stat_t { * immediately after submission. The write equivalent * of READ_SYNC. * WRITE_ODIRECT_PLUG Special case write for O_DIRECT only. + * SWRITE_SYNC + * SWRITE_SYNC_PLUG Like WRITE_SYNC/WRITE_SYNC_PLUG, but locks the buffer. + * See SWRITE. * WRITE_BARRIER Like WRITE_SYNC, but tells the block layer that all * previously submitted writes must be safely on storage * before this one is started. Also guarantees that when @@ -149,6 +155,7 @@ struct inodes_stat_t { #define READ 0 #define WRITE RW_MASK #define READA RWA_MASK +#define SWRITE (WRITE | READA) #define READ_SYNC (READ | REQ_SYNC | REQ_UNPLUG) #define READ_META (READ | REQ_META) @@ -158,6 +165,8 @@ struct inodes_stat_t { #define WRITE_META (WRITE | REQ_META) #define WRITE_BARRIER (WRITE | REQ_SYNC | REQ_NOIDLE | REQ_UNPLUG | \ REQ_HARDBARRIER) +#define SWRITE_SYNC_PLUG (SWRITE | REQ_SYNC | REQ_NOIDLE) +#define SWRITE_SYNC (SWRITE | REQ_SYNC | REQ_NOIDLE | REQ_UNPLUG) /* * These aren't really reads or writes, they pass down information about @@ -920,9 +929,6 @@ struct file { #define f_vfsmnt f_path.mnt const struct file_operations *f_op; spinlock_t f_lock; /* f_ep_links, f_flags, no IRQ */ -#ifdef CONFIG_SMP - int f_sb_list_cpu; -#endif atomic_long_t f_count; unsigned int f_flags; fmode_t f_mode; @@ -947,6 +953,9 @@ struct file { unsigned long f_mnt_write_state; #endif }; +extern spinlock_t files_lock; +#define file_list_lock() spin_lock(&files_lock); +#define file_list_unlock() spin_unlock(&files_lock); #define get_file(x) atomic_long_inc(&(x)->f_count) #define fput_atomic(x) atomic_long_add_unless(&(x)->f_count, -1, 1) @@ -1337,11 +1346,7 @@ struct super_block { struct list_head s_inodes; /* all inodes */ struct hlist_head s_anon; /* anonymous dentries for (nfs) exporting */ -#ifdef CONFIG_SMP - struct list_head __percpu *s_files; -#else struct list_head s_files; -#endif /* s_dentry_lru and s_nr_dentry_unused are protected by dcache_lock */ struct list_head s_dentry_lru; /* unused dentry lru */ int s_nr_dentry_unused; /* # of dentry on lru */ @@ -2192,6 +2197,8 @@ static inline void insert_inode_hash(struct inode *inode) { __insert_inode_hash(inode, inode->i_ino); } +extern void file_move(struct file *f, struct list_head *list); +extern void file_kill(struct file *f); #ifdef CONFIG_BLOCK extern void submit_bio(int, struct bio *); extern int bdev_read_only(struct block_device *); diff --git a/trunk/include/linux/fs_struct.h b/trunk/include/linux/fs_struct.h index a42b5bf02f8b..eca3d5202138 100644 --- a/trunk/include/linux/fs_struct.h +++ b/trunk/include/linux/fs_struct.h @@ -5,7 +5,7 @@ struct fs_struct { int users; - spinlock_t lock; + rwlock_t lock; int umask; int in_exec; struct path root, pwd; @@ -23,29 +23,29 @@ extern int unshare_fs_struct(void); static inline void get_fs_root(struct fs_struct *fs, struct path *root) { - spin_lock(&fs->lock); + read_lock(&fs->lock); *root = fs->root; path_get(root); - spin_unlock(&fs->lock); + read_unlock(&fs->lock); } static inline void get_fs_pwd(struct fs_struct *fs, struct path *pwd) { - spin_lock(&fs->lock); + read_lock(&fs->lock); *pwd = fs->pwd; path_get(pwd); - spin_unlock(&fs->lock); + read_unlock(&fs->lock); } static inline void get_fs_root_and_pwd(struct fs_struct *fs, struct path *root, struct path *pwd) { - spin_lock(&fs->lock); + read_lock(&fs->lock); *root = fs->root; path_get(root); *pwd = fs->pwd; path_get(pwd); - spin_unlock(&fs->lock); + read_unlock(&fs->lock); } #endif /* _LINUX_FS_STRUCT_H */ diff --git a/trunk/include/linux/lglock.h b/trunk/include/linux/lglock.h deleted file mode 100644 index b288cb713b90..000000000000 --- a/trunk/include/linux/lglock.h +++ /dev/null @@ -1,172 +0,0 @@ -/* - * Specialised local-global spinlock. Can only be declared as global variables - * to avoid overhead and keep things simple (and we don't want to start using - * these inside dynamically allocated structures). - * - * "local/global locks" (lglocks) can be used to: - * - * - Provide fast exclusive access to per-CPU data, with exclusive access to - * another CPU's data allowed but possibly subject to contention, and to - * provide very slow exclusive access to all per-CPU data. - * - Or to provide very fast and scalable read serialisation, and to provide - * very slow exclusive serialisation of data (not necessarily per-CPU data). - * - * Brlocks are also implemented as a short-hand notation for the latter use - * case. - * - * Copyright 2009, 2010, Nick Piggin, Novell Inc. - */ -#ifndef __LINUX_LGLOCK_H -#define __LINUX_LGLOCK_H - -#include -#include -#include - -/* can make br locks by using local lock for read side, global lock for write */ -#define br_lock_init(name) name##_lock_init() -#define br_read_lock(name) name##_local_lock() -#define br_read_unlock(name) name##_local_unlock() -#define br_write_lock(name) name##_global_lock_online() -#define br_write_unlock(name) name##_global_unlock_online() - -#define DECLARE_BRLOCK(name) DECLARE_LGLOCK(name) -#define DEFINE_BRLOCK(name) DEFINE_LGLOCK(name) - - -#define lg_lock_init(name) name##_lock_init() -#define lg_local_lock(name) name##_local_lock() -#define lg_local_unlock(name) name##_local_unlock() -#define lg_local_lock_cpu(name, cpu) name##_local_lock_cpu(cpu) -#define lg_local_unlock_cpu(name, cpu) name##_local_unlock_cpu(cpu) -#define lg_global_lock(name) name##_global_lock() -#define lg_global_unlock(name) name##_global_unlock() -#define lg_global_lock_online(name) name##_global_lock_online() -#define lg_global_unlock_online(name) name##_global_unlock_online() - -#ifdef CONFIG_DEBUG_LOCK_ALLOC -#define LOCKDEP_INIT_MAP lockdep_init_map - -#define DEFINE_LGLOCK_LOCKDEP(name) \ - struct lock_class_key name##_lock_key; \ - struct lockdep_map name##_lock_dep_map; \ - EXPORT_SYMBOL(name##_lock_dep_map) - -#else -#define LOCKDEP_INIT_MAP(a, b, c, d) - -#define DEFINE_LGLOCK_LOCKDEP(name) -#endif - - -#define DECLARE_LGLOCK(name) \ - extern void name##_lock_init(void); \ - extern void name##_local_lock(void); \ - extern void name##_local_unlock(void); \ - extern void name##_local_lock_cpu(int cpu); \ - extern void name##_local_unlock_cpu(int cpu); \ - extern void name##_global_lock(void); \ - extern void name##_global_unlock(void); \ - extern void name##_global_lock_online(void); \ - extern void name##_global_unlock_online(void); \ - -#define DEFINE_LGLOCK(name) \ - \ - DEFINE_PER_CPU(arch_spinlock_t, name##_lock); \ - DEFINE_LGLOCK_LOCKDEP(name); \ - \ - void name##_lock_init(void) { \ - int i; \ - LOCKDEP_INIT_MAP(&name##_lock_dep_map, #name, &name##_lock_key, 0); \ - for_each_possible_cpu(i) { \ - arch_spinlock_t *lock; \ - lock = &per_cpu(name##_lock, i); \ - *lock = (arch_spinlock_t)__ARCH_SPIN_LOCK_UNLOCKED; \ - } \ - } \ - EXPORT_SYMBOL(name##_lock_init); \ - \ - void name##_local_lock(void) { \ - arch_spinlock_t *lock; \ - preempt_disable(); \ - rwlock_acquire_read(&name##_lock_dep_map, 0, 0, _THIS_IP_); \ - lock = &__get_cpu_var(name##_lock); \ - arch_spin_lock(lock); \ - } \ - EXPORT_SYMBOL(name##_local_lock); \ - \ - void name##_local_unlock(void) { \ - arch_spinlock_t *lock; \ - rwlock_release(&name##_lock_dep_map, 1, _THIS_IP_); \ - lock = &__get_cpu_var(name##_lock); \ - arch_spin_unlock(lock); \ - preempt_enable(); \ - } \ - EXPORT_SYMBOL(name##_local_unlock); \ - \ - void name##_local_lock_cpu(int cpu) { \ - arch_spinlock_t *lock; \ - preempt_disable(); \ - rwlock_acquire_read(&name##_lock_dep_map, 0, 0, _THIS_IP_); \ - lock = &per_cpu(name##_lock, cpu); \ - arch_spin_lock(lock); \ - } \ - EXPORT_SYMBOL(name##_local_lock_cpu); \ - \ - void name##_local_unlock_cpu(int cpu) { \ - arch_spinlock_t *lock; \ - rwlock_release(&name##_lock_dep_map, 1, _THIS_IP_); \ - lock = &per_cpu(name##_lock, cpu); \ - arch_spin_unlock(lock); \ - preempt_enable(); \ - } \ - EXPORT_SYMBOL(name##_local_unlock_cpu); \ - \ - void name##_global_lock_online(void) { \ - int i; \ - preempt_disable(); \ - rwlock_acquire(&name##_lock_dep_map, 0, 0, _RET_IP_); \ - for_each_online_cpu(i) { \ - arch_spinlock_t *lock; \ - lock = &per_cpu(name##_lock, i); \ - arch_spin_lock(lock); \ - } \ - } \ - EXPORT_SYMBOL(name##_global_lock_online); \ - \ - void name##_global_unlock_online(void) { \ - int i; \ - rwlock_release(&name##_lock_dep_map, 1, _RET_IP_); \ - for_each_online_cpu(i) { \ - arch_spinlock_t *lock; \ - lock = &per_cpu(name##_lock, i); \ - arch_spin_unlock(lock); \ - } \ - preempt_enable(); \ - } \ - EXPORT_SYMBOL(name##_global_unlock_online); \ - \ - void name##_global_lock(void) { \ - int i; \ - preempt_disable(); \ - rwlock_acquire(&name##_lock_dep_map, 0, 0, _RET_IP_); \ - for_each_online_cpu(i) { \ - arch_spinlock_t *lock; \ - lock = &per_cpu(name##_lock, i); \ - arch_spin_lock(lock); \ - } \ - } \ - EXPORT_SYMBOL(name##_global_lock); \ - \ - void name##_global_unlock(void) { \ - int i; \ - rwlock_release(&name##_lock_dep_map, 1, _RET_IP_); \ - for_each_online_cpu(i) { \ - arch_spinlock_t *lock; \ - lock = &per_cpu(name##_lock, i); \ - arch_spin_unlock(lock); \ - } \ - preempt_enable(); \ - } \ - EXPORT_SYMBOL(name##_global_unlock); -#endif diff --git a/trunk/include/linux/spi/spi.h b/trunk/include/linux/spi/spi.h index 92e52a1e6af3..ae0a5286f558 100644 --- a/trunk/include/linux/spi/spi.h +++ b/trunk/include/linux/spi/spi.h @@ -213,9 +213,6 @@ static inline void spi_unregister_driver(struct spi_driver *sdrv) * @dma_alignment: SPI controller constraint on DMA buffers alignment. * @mode_bits: flags understood by this controller driver * @flags: other constraints relevant to this driver - * @bus_lock_spinlock: spinlock for SPI bus locking - * @bus_lock_mutex: mutex for SPI bus locking - * @bus_lock_flag: indicates that the SPI bus is locked for exclusive use * @setup: updates the device mode and clocking records used by a * device's SPI controller; protocol code may call this. This * must fail if an unrecognized or unsupported mode is requested. diff --git a/trunk/include/linux/tty.h b/trunk/include/linux/tty.h index 67d64e6efe7a..1437da3ddc62 100644 --- a/trunk/include/linux/tty.h +++ b/trunk/include/linux/tty.h @@ -329,13 +329,6 @@ struct tty_struct { struct tty_port *port; }; -/* Each of a tty's open files has private_data pointing to tty_file_private */ -struct tty_file_private { - struct tty_struct *tty; - struct file *file; - struct list_head list; -}; - /* tty magic number */ #define TTY_MAGIC 0x5401 @@ -465,7 +458,6 @@ extern void proc_clear_tty(struct task_struct *p); extern struct tty_struct *get_current_tty(void); extern void tty_default_fops(struct file_operations *fops); extern struct tty_struct *alloc_tty_struct(void); -extern void tty_add_file(struct tty_struct *tty, struct file *file); extern void free_tty_struct(struct tty_struct *tty); extern void initialize_tty_struct(struct tty_struct *tty, struct tty_driver *driver, int idx); @@ -478,7 +470,6 @@ extern struct tty_struct *tty_pair_get_tty(struct tty_struct *tty); extern struct tty_struct *tty_pair_get_pty(struct tty_struct *tty); extern struct mutex tty_mutex; -extern spinlock_t tty_files_lock; extern void tty_write_unlock(struct tty_struct *tty); extern int tty_write_lock(struct tty_struct *tty, int ndelay); diff --git a/trunk/include/sound/emu10k1.h b/trunk/include/sound/emu10k1.h index 7dc97d12253c..6a664c3f7c1e 100644 --- a/trunk/include/sound/emu10k1.h +++ b/trunk/include/sound/emu10k1.h @@ -1707,7 +1707,6 @@ struct snd_emu10k1 { unsigned int card_type; /* EMU10K1_CARD_* */ unsigned int ecard_ctrl; /* ecard control bits */ unsigned long dma_mask; /* PCI DMA mask */ - unsigned int delay_pcm_irq; /* in samples */ int max_cache_pages; /* max memory size / PAGE_SIZE */ struct snd_dma_buffer silent_page; /* silent page */ struct snd_dma_buffer ptb_pages; /* page table pages */ diff --git a/trunk/kernel/fork.c b/trunk/kernel/fork.c index 856eac3ec52e..98b450876f93 100644 --- a/trunk/kernel/fork.c +++ b/trunk/kernel/fork.c @@ -752,13 +752,13 @@ static int copy_fs(unsigned long clone_flags, struct task_struct *tsk) struct fs_struct *fs = current->fs; if (clone_flags & CLONE_FS) { /* tsk->fs is already what we want */ - spin_lock(&fs->lock); + write_lock(&fs->lock); if (fs->in_exec) { - spin_unlock(&fs->lock); + write_unlock(&fs->lock); return -EAGAIN; } fs->users++; - spin_unlock(&fs->lock); + write_unlock(&fs->lock); return 0; } tsk->fs = copy_fs_struct(fs); @@ -1676,13 +1676,13 @@ SYSCALL_DEFINE1(unshare, unsigned long, unshare_flags) if (new_fs) { fs = current->fs; - spin_lock(&fs->lock); + write_lock(&fs->lock); current->fs = new_fs; if (--fs->users) new_fs = NULL; else new_fs = fs; - spin_unlock(&fs->lock); + write_unlock(&fs->lock); } if (new_mm) { diff --git a/trunk/kernel/trace/ring_buffer.c b/trunk/kernel/trace/ring_buffer.c index 19cccc3c3028..3632ce87674f 100644 --- a/trunk/kernel/trace/ring_buffer.c +++ b/trunk/kernel/trace/ring_buffer.c @@ -3846,9 +3846,6 @@ int ring_buffer_read_page(struct ring_buffer *buffer, rpos = reader->read; pos += size; - if (rpos >= commit) - break; - event = rb_reader_event(cpu_buffer); size = rb_event_length(event); } while (len > size); diff --git a/trunk/kernel/trace/trace.c b/trunk/kernel/trace/trace.c index 9ec59f541156..ba14a22be4cc 100644 --- a/trunk/kernel/trace/trace.c +++ b/trunk/kernel/trace/trace.c @@ -3463,7 +3463,6 @@ tracing_mark_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *fpos) { char *buf; - size_t written; if (tracing_disabled) return -EINVAL; @@ -3485,15 +3484,11 @@ tracing_mark_write(struct file *filp, const char __user *ubuf, } else buf[cnt] = '\0'; - written = mark_printk("%s", buf); + cnt = mark_printk("%s", buf); kfree(buf); - *fpos += written; - - /* don't tell userspace we wrote more - it might confuse them */ - if (written > cnt) - written = cnt; + *fpos += cnt; - return written; + return cnt; } static int tracing_clock_show(struct seq_file *m, void *v) diff --git a/trunk/kernel/trace/trace_events.c b/trunk/kernel/trace/trace_events.c index 4c758f146328..09b4fa6e4d3b 100644 --- a/trunk/kernel/trace/trace_events.c +++ b/trunk/kernel/trace/trace_events.c @@ -598,165 +598,88 @@ system_enable_write(struct file *filp, const char __user *ubuf, size_t cnt, return ret; } -enum { - FORMAT_HEADER = 1, - FORMAT_PRINTFMT = 2, -}; - -static void *f_next(struct seq_file *m, void *v, loff_t *pos) +static void print_event_fields(struct trace_seq *s, struct list_head *head) { - struct ftrace_event_call *call = m->private; struct ftrace_event_field *field; - struct list_head *head; - - (*pos)++; - - switch ((unsigned long)v) { - case FORMAT_HEADER: - head = &ftrace_common_fields; - - if (unlikely(list_empty(head))) - return NULL; - - field = list_entry(head->prev, struct ftrace_event_field, link); - return field; - - case FORMAT_PRINTFMT: - /* all done */ - return NULL; - } - head = trace_get_fields(call); + list_for_each_entry_reverse(field, head, link) { + /* + * Smartly shows the array type(except dynamic array). + * Normal: + * field:TYPE VAR + * If TYPE := TYPE[LEN], it is shown: + * field:TYPE VAR[LEN] + */ + const char *array_descriptor = strchr(field->type, '['); - /* - * To separate common fields from event fields, the - * LSB is set on the first event field. Clear it in case. - */ - v = (void *)((unsigned long)v & ~1L); + if (!strncmp(field->type, "__data_loc", 10)) + array_descriptor = NULL; - field = v; - /* - * If this is a common field, and at the end of the list, then - * continue with main list. - */ - if (field->link.prev == &ftrace_common_fields) { - if (unlikely(list_empty(head))) - return NULL; - field = list_entry(head->prev, struct ftrace_event_field, link); - /* Set the LSB to notify f_show to print an extra newline */ - field = (struct ftrace_event_field *) - ((unsigned long)field | 1); - return field; + if (!array_descriptor) { + trace_seq_printf(s, "\tfield:%s %s;\toffset:%u;" + "\tsize:%u;\tsigned:%d;\n", + field->type, field->name, field->offset, + field->size, !!field->is_signed); + } else { + trace_seq_printf(s, "\tfield:%.*s %s%s;\toffset:%u;" + "\tsize:%u;\tsigned:%d;\n", + (int)(array_descriptor - field->type), + field->type, field->name, + array_descriptor, field->offset, + field->size, !!field->is_signed); + } } - - /* If we are done tell f_show to print the format */ - if (field->link.prev == head) - return (void *)FORMAT_PRINTFMT; - - field = list_entry(field->link.prev, struct ftrace_event_field, link); - - return field; -} - -static void *f_start(struct seq_file *m, loff_t *pos) -{ - loff_t l = 0; - void *p; - - /* Start by showing the header */ - if (!*pos) - return (void *)FORMAT_HEADER; - - p = (void *)FORMAT_HEADER; - do { - p = f_next(m, p, &l); - } while (p && l < *pos); - - return p; } -static int f_show(struct seq_file *m, void *v) +static ssize_t +event_format_read(struct file *filp, char __user *ubuf, size_t cnt, + loff_t *ppos) { - struct ftrace_event_call *call = m->private; - struct ftrace_event_field *field; - const char *array_descriptor; - - switch ((unsigned long)v) { - case FORMAT_HEADER: - seq_printf(m, "name: %s\n", call->name); - seq_printf(m, "ID: %d\n", call->event.type); - seq_printf(m, "format:\n"); - return 0; + struct ftrace_event_call *call = filp->private_data; + struct list_head *head; + struct trace_seq *s; + char *buf; + int r; - case FORMAT_PRINTFMT: - seq_printf(m, "\nprint fmt: %s\n", - call->print_fmt); + if (*ppos) return 0; - } - - /* - * To separate common fields from event fields, the - * LSB is set on the first event field. Clear it and - * print a newline if it is set. - */ - if ((unsigned long)v & 1) { - seq_putc(m, '\n'); - v = (void *)((unsigned long)v & ~1L); - } - - field = v; - - /* - * Smartly shows the array type(except dynamic array). - * Normal: - * field:TYPE VAR - * If TYPE := TYPE[LEN], it is shown: - * field:TYPE VAR[LEN] - */ - array_descriptor = strchr(field->type, '['); - if (!strncmp(field->type, "__data_loc", 10)) - array_descriptor = NULL; + s = kmalloc(sizeof(*s), GFP_KERNEL); + if (!s) + return -ENOMEM; - if (!array_descriptor) - seq_printf(m, "\tfield:%s %s;\toffset:%u;\tsize:%u;\tsigned:%d;\n", - field->type, field->name, field->offset, - field->size, !!field->is_signed); - else - seq_printf(m, "\tfield:%.*s %s%s;\toffset:%u;\tsize:%u;\tsigned:%d;\n", - (int)(array_descriptor - field->type), - field->type, field->name, - array_descriptor, field->offset, - field->size, !!field->is_signed); + trace_seq_init(s); - return 0; -} + trace_seq_printf(s, "name: %s\n", call->name); + trace_seq_printf(s, "ID: %d\n", call->event.type); + trace_seq_printf(s, "format:\n"); -static void f_stop(struct seq_file *m, void *p) -{ -} + /* print common fields */ + print_event_fields(s, &ftrace_common_fields); -static const struct seq_operations trace_format_seq_ops = { - .start = f_start, - .next = f_next, - .stop = f_stop, - .show = f_show, -}; + trace_seq_putc(s, '\n'); -static int trace_format_open(struct inode *inode, struct file *file) -{ - struct ftrace_event_call *call = inode->i_private; - struct seq_file *m; - int ret; + /* print event specific fields */ + head = trace_get_fields(call); + print_event_fields(s, head); - ret = seq_open(file, &trace_format_seq_ops); - if (ret < 0) - return ret; + r = trace_seq_printf(s, "\nprint fmt: %s\n", call->print_fmt); - m = file->private_data; - m->private = call; + if (!r) { + /* + * ug! The format output is bigger than a PAGE!! + */ + buf = "FORMAT TOO BIG\n"; + r = simple_read_from_buffer(ubuf, cnt, ppos, + buf, strlen(buf)); + goto out; + } - return 0; + r = simple_read_from_buffer(ubuf, cnt, ppos, + s->buffer, s->len); + out: + kfree(s); + return r; } static ssize_t @@ -954,10 +877,8 @@ static const struct file_operations ftrace_enable_fops = { }; static const struct file_operations ftrace_event_format_fops = { - .open = trace_format_open, - .read = seq_read, - .llseek = seq_lseek, - .release = seq_release, + .open = tracing_open_generic, + .read = event_format_read, }; static const struct file_operations ftrace_event_id_fops = { diff --git a/trunk/kernel/trace/trace_functions_graph.c b/trunk/kernel/trace/trace_functions_graph.c index 6f233698518e..6bff23625781 100644 --- a/trunk/kernel/trace/trace_functions_graph.c +++ b/trunk/kernel/trace/trace_functions_graph.c @@ -507,15 +507,7 @@ get_return_for_leaf(struct trace_iterator *iter, * if the output fails. */ data->ent = *curr; - /* - * If the next event is not a return type, then - * we only care about what type it is. Otherwise we can - * safely copy the entire event. - */ - if (next->ent.type == TRACE_GRAPH_RET) - data->ret = *next; - else - data->ret.ent.type = next->ent.type; + data->ret = *next; } } diff --git a/trunk/lib/Kconfig.debug b/trunk/lib/Kconfig.debug index 1b4afd2e6ca0..9e06b7f5ecf1 100644 --- a/trunk/lib/Kconfig.debug +++ b/trunk/lib/Kconfig.debug @@ -994,16 +994,13 @@ config FAULT_INJECTION_STACKTRACE_FILTER config LATENCYTOP bool "Latency measuring infrastructure" - depends on HAVE_LATENCYTOP_SUPPORT - depends on DEBUG_KERNEL - depends on STACKTRACE_SUPPORT - depends on PROC_FS select FRAME_POINTER if !MIPS && !PPC && !S390 && !MICROBLAZE select KALLSYMS select KALLSYMS_ALL select STACKTRACE select SCHEDSTATS select SCHED_DEBUG + depends on HAVE_LATENCYTOP_SUPPORT help Enable this option if you want to use the LatencyTOP tool to find out which userspace is blocking on what kernel operations. diff --git a/trunk/scripts/recordmcount.pl b/trunk/scripts/recordmcount.pl index e67f05486087..0171060b5fd6 100755 --- a/trunk/scripts/recordmcount.pl +++ b/trunk/scripts/recordmcount.pl @@ -159,7 +159,6 @@ my $function_regex; # Find the name of a function # (return offset and func name) my $mcount_regex; # Find the call site to mcount (return offset) -my $mcount_adjust; # Address adjustment to mcount offset my $alignment; # The .align value to use for $mcount_section my $section_type; # Section header plus possible alignment command my $can_use_local = 0; # If we can use local function references @@ -214,7 +213,6 @@ sub check_objcopy $function_regex = "^([0-9a-fA-F]+)\\s+<(.*?)>:"; $mcount_regex = "^\\s*([0-9a-fA-F]+):.*\\smcount\$"; $section_type = '@progbits'; -$mcount_adjust = 0; $type = ".long"; if ($arch eq "x86_64") { @@ -353,9 +351,6 @@ sub check_objcopy } elsif ($arch eq "microblaze") { # Microblaze calls '_mcount' instead of plain 'mcount'. $mcount_regex = "^\\s*([0-9a-fA-F]+):.*\\s_mcount\$"; -} elsif ($arch eq "blackfin") { - $mcount_regex = "^\\s*([0-9a-fA-F]+):.*\\s__mcount\$"; - $mcount_adjust = -4; } else { die "Arch $arch is not supported with CONFIG_FTRACE_MCOUNT_RECORD"; } @@ -516,7 +511,7 @@ sub update_funcs } # is this a call site to mcount? If so, record it to print later if ($text_found && /$mcount_regex/) { - push(@offsets, (hex $1) + $mcount_adjust); + push(@offsets, hex $1); } } diff --git a/trunk/security/apparmor/path.c b/trunk/security/apparmor/path.c index 19358dc14605..96bab9469d48 100644 --- a/trunk/security/apparmor/path.c +++ b/trunk/security/apparmor/path.c @@ -62,14 +62,19 @@ static int d_namespace_path(struct path *path, char *buf, int buflen, int deleted, connected; int error = 0; - /* Get the root we want to resolve too, released below */ + /* Get the root we want to resolve too */ if (flags & PATH_CHROOT_REL) { /* resolve paths relative to chroot */ - get_fs_root(current->fs, &root); + read_lock(¤t->fs->lock); + root = current->fs->root; + /* released below */ + path_get(&root); + read_unlock(¤t->fs->lock); } else { /* resolve paths relative to namespace */ root.mnt = current->nsproxy->mnt_ns->root; root.dentry = root.mnt->mnt_root; + /* released below */ path_get(&root); } diff --git a/trunk/security/selinux/hooks.c b/trunk/security/selinux/hooks.c index 4796ddd4e721..42043f96e54f 100644 --- a/trunk/security/selinux/hooks.c +++ b/trunk/security/selinux/hooks.c @@ -2170,9 +2170,8 @@ static inline void flush_unauthorized_files(const struct cred *cred, tty = get_current_tty(); if (tty) { - spin_lock(&tty_files_lock); + file_list_lock(); if (!list_empty(&tty->tty_files)) { - struct tty_file_private *file_priv; struct inode *inode; /* Revalidate access to controlling tty. @@ -2180,16 +2179,14 @@ static inline void flush_unauthorized_files(const struct cred *cred, than using file_has_perm, as this particular open file may belong to another process and we are only interested in the inode-based check here. */ - file_priv = list_first_entry(&tty->tty_files, - struct tty_file_private, list); - file = file_priv->file; + file = list_first_entry(&tty->tty_files, struct file, f_u.fu_list); inode = file->f_path.dentry->d_inode; if (inode_has_perm(cred, inode, FILE__READ | FILE__WRITE, NULL)) { drop_tty = 1; } } - spin_unlock(&tty_files_lock); + file_list_unlock(); tty_kref_put(tty); } /* Reset controlling tty. */ diff --git a/trunk/sound/core/pcm_native.c b/trunk/sound/core/pcm_native.c index 134fc6c2e08d..a3b2a6479246 100644 --- a/trunk/sound/core/pcm_native.c +++ b/trunk/sound/core/pcm_native.c @@ -978,10 +978,6 @@ static int snd_pcm_do_pause(struct snd_pcm_substream *substream, int push) { if (substream->runtime->trigger_master != substream) return 0; - /* some drivers might use hw_ptr to recover from the pause - - update the hw_ptr now */ - if (push) - snd_pcm_update_hw_ptr(substream); /* The jiffies check in snd_pcm_update_hw_ptr*() is done by * a delta betwen the current jiffies, this gives a large enough * delta, effectively to skip the check once. diff --git a/trunk/sound/pci/emu10k1/emu10k1.c b/trunk/sound/pci/emu10k1/emu10k1.c index aff8387c45cf..4203782d7cb7 100644 --- a/trunk/sound/pci/emu10k1/emu10k1.c +++ b/trunk/sound/pci/emu10k1/emu10k1.c @@ -52,7 +52,6 @@ static int max_synth_voices[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 64}; static int max_buffer_size[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 128}; static int enable_ir[SNDRV_CARDS]; static uint subsystem[SNDRV_CARDS]; /* Force card subsystem model */ -static uint delay_pcm_irq[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 2}; module_param_array(index, int, NULL, 0444); MODULE_PARM_DESC(index, "Index value for the EMU10K1 soundcard."); @@ -74,8 +73,6 @@ module_param_array(enable_ir, bool, NULL, 0444); MODULE_PARM_DESC(enable_ir, "Enable IR."); module_param_array(subsystem, uint, NULL, 0444); MODULE_PARM_DESC(subsystem, "Force card subsystem model."); -module_param_array(delay_pcm_irq, uint, NULL, 0444); -MODULE_PARM_DESC(delay_pcm_irq, "Delay PCM interrupt by specified number of samples (default 0)."); /* * Class 0401: 1102:0008 (rev 00) Subsystem: 1102:1001 -> Audigy2 Value Model:SB0400 */ @@ -130,7 +127,6 @@ static int __devinit snd_card_emu10k1_probe(struct pci_dev *pci, &emu)) < 0) goto error; card->private_data = emu; - emu->delay_pcm_irq = delay_pcm_irq[dev] & 0x1f; if ((err = snd_emu10k1_pcm(emu, 0, NULL)) < 0) goto error; if ((err = snd_emu10k1_pcm_mic(emu, 1, NULL)) < 0) diff --git a/trunk/sound/pci/emu10k1/emupcm.c b/trunk/sound/pci/emu10k1/emupcm.c index 622bace148e3..55b83ef73c63 100644 --- a/trunk/sound/pci/emu10k1/emupcm.c +++ b/trunk/sound/pci/emu10k1/emupcm.c @@ -332,7 +332,7 @@ static void snd_emu10k1_pcm_init_voice(struct snd_emu10k1 *emu, evoice->epcm->ccca_start_addr = start_addr + ccis; if (extra) { start_addr += ccis; - end_addr += ccis + emu->delay_pcm_irq; + end_addr += ccis; } if (stereo && !extra) { snd_emu10k1_ptr_write(emu, CPF, voice, CPF_STEREO_MASK); @@ -360,9 +360,7 @@ static void snd_emu10k1_pcm_init_voice(struct snd_emu10k1 *emu, /* Assumption that PT is already 0 so no harm overwriting */ snd_emu10k1_ptr_write(emu, PTRX, voice, (send_amount[0] << 8) | send_amount[1]); snd_emu10k1_ptr_write(emu, DSL, voice, end_addr | (send_amount[3] << 24)); - snd_emu10k1_ptr_write(emu, PSST, voice, - (start_addr + (extra ? emu->delay_pcm_irq : 0)) | - (send_amount[2] << 24)); + snd_emu10k1_ptr_write(emu, PSST, voice, start_addr | (send_amount[2] << 24)); if (emu->card_capabilities->emu_model) pitch_target = PITCH_48000; /* Disable interpolators on emu1010 card */ else @@ -734,23 +732,6 @@ static void snd_emu10k1_playback_stop_voice(struct snd_emu10k1 *emu, struct snd_ snd_emu10k1_ptr_write(emu, IP, voice, 0); } -static inline void snd_emu10k1_playback_mangle_extra(struct snd_emu10k1 *emu, - struct snd_emu10k1_pcm *epcm, - struct snd_pcm_substream *substream, - struct snd_pcm_runtime *runtime) -{ - unsigned int ptr, period_pos; - - /* try to sychronize the current position for the interrupt - source voice */ - period_pos = runtime->status->hw_ptr - runtime->hw_ptr_interrupt; - period_pos %= runtime->period_size; - ptr = snd_emu10k1_ptr_read(emu, CCCA, epcm->extra->number); - ptr &= ~0x00ffffff; - ptr |= epcm->ccca_start_addr + period_pos; - snd_emu10k1_ptr_write(emu, CCCA, epcm->extra->number, ptr); -} - static int snd_emu10k1_playback_trigger(struct snd_pcm_substream *substream, int cmd) { @@ -772,8 +753,6 @@ static int snd_emu10k1_playback_trigger(struct snd_pcm_substream *substream, /* follow thru */ case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: case SNDRV_PCM_TRIGGER_RESUME: - if (cmd == SNDRV_PCM_TRIGGER_PAUSE_RELEASE) - snd_emu10k1_playback_mangle_extra(emu, epcm, substream, runtime); mix = &emu->pcm_mixer[substream->number]; snd_emu10k1_playback_prepare_voice(emu, epcm->voices[0], 1, 0, mix); snd_emu10k1_playback_prepare_voice(emu, epcm->voices[1], 0, 0, mix); @@ -890,9 +869,8 @@ static snd_pcm_uframes_t snd_emu10k1_playback_pointer(struct snd_pcm_substream * #endif /* printk(KERN_DEBUG - "ptr = 0x%lx, buffer_size = 0x%lx, period_size = 0x%lx\n", - (long)ptr, (long)runtime->buffer_size, - (long)runtime->period_size); + "ptr = 0x%x, buffer_size = 0x%x, period_size = 0x%x\n", + ptr, runtime->buffer_size, runtime->period_size); */ return ptr; } diff --git a/trunk/sound/pci/emu10k1/memory.c b/trunk/sound/pci/emu10k1/memory.c index 957a311514c8..ffb1ddb8dc28 100644 --- a/trunk/sound/pci/emu10k1/memory.c +++ b/trunk/sound/pci/emu10k1/memory.c @@ -310,10 +310,8 @@ snd_emu10k1_alloc_pages(struct snd_emu10k1 *emu, struct snd_pcm_substream *subst if (snd_BUG_ON(!hdr)) return NULL; - idx = runtime->period_size >= runtime->buffer_size ? - (emu->delay_pcm_irq * 2) : 0; mutex_lock(&hdr->block_mutex); - blk = search_empty(emu, runtime->dma_bytes + idx); + blk = search_empty(emu, runtime->dma_bytes); if (blk == NULL) { mutex_unlock(&hdr->block_mutex); return NULL; diff --git a/trunk/sound/pci/hda/patch_conexant.c b/trunk/sound/pci/hda/patch_conexant.c index c424952a734e..31b5d9eeba68 100644 --- a/trunk/sound/pci/hda/patch_conexant.c +++ b/trunk/sound/pci/hda/patch_conexant.c @@ -3049,7 +3049,6 @@ static struct snd_pci_quirk cxt5066_cfg_tbl[] = { SND_PCI_QUIRK(0x1028, 0x02f5, "Dell", CXT5066_DELL_LAPTOP), SND_PCI_QUIRK(0x152d, 0x0833, "OLPC XO-1.5", CXT5066_OLPC_XO_1_5), - SND_PCI_QUIRK(0x1028, 0x02d8, "Dell Vostro", CXT5066_DELL_VOSTO), SND_PCI_QUIRK(0x1028, 0x0402, "Dell Vostro", CXT5066_DELL_VOSTO), SND_PCI_QUIRK(0x1028, 0x0408, "Dell Inspiron One 19T", CXT5066_IDEAPAD), SND_PCI_QUIRK(0x1179, 0xff50, "Toshiba Satellite P500-PSPGSC-01800T", CXT5066_OLPC_XO_1_5), diff --git a/trunk/sound/pci/hda/patch_realtek.c b/trunk/sound/pci/hda/patch_realtek.c index a4dd04524e43..2cd1ae809e46 100644 --- a/trunk/sound/pci/hda/patch_realtek.c +++ b/trunk/sound/pci/hda/patch_realtek.c @@ -19030,7 +19030,6 @@ static int patch_alc888(struct hda_codec *codec) /* * ALC680 support */ -#define ALC680_DIGIN_NID ALC880_DIGIN_NID #define ALC680_DIGOUT_NID ALC880_DIGOUT_NID #define alc680_modes alc260_modes @@ -19045,93 +19044,23 @@ static hda_nid_t alc680_adc_nids[3] = { 0x07, 0x08, 0x09 }; -/* - * Analog capture ADC cgange - */ -static int alc680_capture_pcm_prepare(struct hda_pcm_stream *hinfo, - struct hda_codec *codec, - unsigned int stream_tag, - unsigned int format, - struct snd_pcm_substream *substream) -{ - struct alc_spec *spec = codec->spec; - struct auto_pin_cfg *cfg = &spec->autocfg; - unsigned int pre_mic, pre_line; - - pre_mic = snd_hda_jack_detect(codec, cfg->input_pins[AUTO_PIN_MIC]); - pre_line = snd_hda_jack_detect(codec, cfg->input_pins[AUTO_PIN_LINE]); - - spec->cur_adc_stream_tag = stream_tag; - spec->cur_adc_format = format; - - if (pre_mic || pre_line) { - if (pre_mic) - snd_hda_codec_setup_stream(codec, 0x08, stream_tag, 0, - format); - else - snd_hda_codec_setup_stream(codec, 0x09, stream_tag, 0, - format); - } else - snd_hda_codec_setup_stream(codec, 0x07, stream_tag, 0, format); - return 0; -} - -static int alc680_capture_pcm_cleanup(struct hda_pcm_stream *hinfo, - struct hda_codec *codec, - struct snd_pcm_substream *substream) -{ - snd_hda_codec_cleanup_stream(codec, 0x07); - snd_hda_codec_cleanup_stream(codec, 0x08); - snd_hda_codec_cleanup_stream(codec, 0x09); - return 0; -} - -static struct hda_pcm_stream alc680_pcm_analog_auto_capture = { - .substreams = 1, /* can be overridden */ - .channels_min = 2, - .channels_max = 2, - /* NID is set in alc_build_pcms */ - .ops = { - .prepare = alc680_capture_pcm_prepare, - .cleanup = alc680_capture_pcm_cleanup - }, -}; - static struct snd_kcontrol_new alc680_base_mixer[] = { /* output mixer control */ HDA_CODEC_VOLUME("Front Playback Volume", 0x2, 0x0, HDA_OUTPUT), HDA_CODEC_MUTE("Front Playback Switch", 0x14, 0x0, HDA_OUTPUT), HDA_CODEC_VOLUME("Headphone Playback Volume", 0x4, 0x0, HDA_OUTPUT), HDA_CODEC_MUTE("Headphone Playback Switch", 0x16, 0x0, HDA_OUTPUT), - HDA_CODEC_VOLUME("Int Mic Boost", 0x12, 0, HDA_INPUT), HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT), - HDA_CODEC_VOLUME("Line In Boost", 0x19, 0, HDA_INPUT), { } }; -static struct hda_bind_ctls alc680_bind_cap_vol = { - .ops = &snd_hda_bind_vol, - .values = { - HDA_COMPOSE_AMP_VAL(0x07, 3, 0, HDA_INPUT), - HDA_COMPOSE_AMP_VAL(0x08, 3, 0, HDA_INPUT), - HDA_COMPOSE_AMP_VAL(0x09, 3, 0, HDA_INPUT), - 0 - }, -}; - -static struct hda_bind_ctls alc680_bind_cap_switch = { - .ops = &snd_hda_bind_sw, - .values = { - HDA_COMPOSE_AMP_VAL(0x07, 3, 0, HDA_INPUT), - HDA_COMPOSE_AMP_VAL(0x08, 3, 0, HDA_INPUT), - HDA_COMPOSE_AMP_VAL(0x09, 3, 0, HDA_INPUT), - 0 - }, -}; - -static struct snd_kcontrol_new alc680_master_capture_mixer[] = { - HDA_BIND_VOL("Capture Volume", &alc680_bind_cap_vol), - HDA_BIND_SW("Capture Switch", &alc680_bind_cap_switch), +static struct snd_kcontrol_new alc680_capture_mixer[] = { + HDA_CODEC_VOLUME("Capture Volume", 0x07, 0x0, HDA_INPUT), + HDA_CODEC_MUTE("Capture Switch", 0x07, 0x0, HDA_INPUT), + HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x08, 0x0, HDA_INPUT), + HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x08, 0x0, HDA_INPUT), + HDA_CODEC_VOLUME_IDX("Capture Volume", 2, 0x09, 0x0, HDA_INPUT), + HDA_CODEC_MUTE_IDX("Capture Switch", 2, 0x09, 0x0, HDA_INPUT), { } /* end */ }; @@ -19139,73 +19068,25 @@ static struct snd_kcontrol_new alc680_master_capture_mixer[] = { * generic initialization of ADC, input mixers and output mixers */ static struct hda_verb alc680_init_verbs[] = { - {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, - {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, - {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, + /* Unmute DAC0-1 and set vol = 0 */ + {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, + {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, + {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, - {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, - {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, - {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, - {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, - {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, - {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, + {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40}, + {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40}, + {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0}, + {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24}, + {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20}, {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, - - {0x16, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN}, - {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_MIC_EVENT | AC_USRSP_EN}, - { } }; -/* toggle speaker-output according to the hp-jack state */ -static void alc680_base_setup(struct hda_codec *codec) -{ - struct alc_spec *spec = codec->spec; - - spec->autocfg.hp_pins[0] = 0x16; - spec->autocfg.speaker_pins[0] = 0x14; - spec->autocfg.speaker_pins[1] = 0x15; - spec->autocfg.input_pins[AUTO_PIN_MIC] = 0x18; - spec->autocfg.input_pins[AUTO_PIN_LINE] = 0x19; -} - -static void alc680_rec_autoswitch(struct hda_codec *codec) -{ - struct alc_spec *spec = codec->spec; - struct auto_pin_cfg *cfg = &spec->autocfg; - unsigned int present; - hda_nid_t new_adc; - - present = snd_hda_jack_detect(codec, cfg->input_pins[AUTO_PIN_MIC]); - - new_adc = present ? 0x8 : 0x7; - __snd_hda_codec_cleanup_stream(codec, !present ? 0x8 : 0x7, 1); - snd_hda_codec_setup_stream(codec, new_adc, - spec->cur_adc_stream_tag, 0, - spec->cur_adc_format); - -} - -static void alc680_unsol_event(struct hda_codec *codec, - unsigned int res) -{ - if ((res >> 26) == ALC880_HP_EVENT) - alc_automute_amp(codec); - if ((res >> 26) == ALC880_MIC_EVENT) - alc680_rec_autoswitch(codec); -} - -static void alc680_inithook(struct hda_codec *codec) -{ - alc_automute_amp(codec); - alc680_rec_autoswitch(codec); -} - /* create input playback/capture controls for the given pin */ static int alc680_new_analog_output(struct alc_spec *spec, hda_nid_t nid, const char *ctlname, int idx) @@ -19316,7 +19197,13 @@ static void alc680_auto_init_hp_out(struct hda_codec *codec) #define alc680_pcm_analog_capture alc880_pcm_analog_capture #define alc680_pcm_analog_alt_capture alc880_pcm_analog_alt_capture #define alc680_pcm_digital_playback alc880_pcm_digital_playback -#define alc680_pcm_digital_capture alc880_pcm_digital_capture + +static struct hda_input_mux alc680_capture_source = { + .num_items = 1, + .items = { + { "Mic", 0x0 }, + }, +}; /* * BIOS auto configuration @@ -19331,7 +19218,6 @@ static int alc680_parse_auto_config(struct hda_codec *codec) alc680_ignore); if (err < 0) return err; - if (!spec->autocfg.line_outs) { if (spec->autocfg.dig_outs || spec->autocfg.dig_in_pin) { spec->multiout.max_channels = 2; @@ -19353,6 +19239,8 @@ static int alc680_parse_auto_config(struct hda_codec *codec) add_mixer(spec, spec->kctls.list); add_verb(spec, alc680_init_verbs); + spec->num_mux_defs = 1; + spec->input_mux = &alc680_capture_source; err = alc_auto_add_mic_boost(codec); if (err < 0) @@ -19391,17 +19279,17 @@ static struct snd_pci_quirk alc680_cfg_tbl[] = { static struct alc_config_preset alc680_presets[] = { [ALC680_BASE] = { .mixers = { alc680_base_mixer }, - .cap_mixer = alc680_master_capture_mixer, + .cap_mixer = alc680_capture_mixer, .init_verbs = { alc680_init_verbs }, .num_dacs = ARRAY_SIZE(alc680_dac_nids), .dac_nids = alc680_dac_nids, + .num_adc_nids = ARRAY_SIZE(alc680_adc_nids), + .adc_nids = alc680_adc_nids, + .hp_nid = 0x04, .dig_out_nid = ALC680_DIGOUT_NID, .num_channel_mode = ARRAY_SIZE(alc680_modes), .channel_mode = alc680_modes, - .unsol_event = alc680_unsol_event, - .setup = alc680_base_setup, - .init_hook = alc680_inithook, - + .input_mux = &alc680_capture_source, }, }; @@ -19445,9 +19333,9 @@ static int patch_alc680(struct hda_codec *codec) setup_preset(codec, &alc680_presets[board_config]); spec->stream_analog_playback = &alc680_pcm_analog_playback; - spec->stream_analog_capture = &alc680_pcm_analog_auto_capture; + spec->stream_analog_capture = &alc680_pcm_analog_capture; + spec->stream_analog_alt_capture = &alc680_pcm_analog_alt_capture; spec->stream_digital_playback = &alc680_pcm_digital_playback; - spec->stream_digital_capture = &alc680_pcm_digital_capture; if (!spec->adc_nids) { spec->adc_nids = alc680_adc_nids; diff --git a/trunk/sound/pci/riptide/riptide.c b/trunk/sound/pci/riptide/riptide.c index ad5202efd7a9..f64fb7d988cb 100644 --- a/trunk/sound/pci/riptide/riptide.c +++ b/trunk/sound/pci/riptide/riptide.c @@ -1224,14 +1224,15 @@ static int try_to_load_firmware(struct cmdif *cif, struct snd_riptide *chip) firmware.firmware.ASIC, firmware.firmware.CODEC, firmware.firmware.AUXDSP, firmware.firmware.PROG); - if (!chip) - return 1; - for (i = 0; i < FIRMWARE_VERSIONS; i++) { if (!memcmp(&firmware_versions[i], &firmware, sizeof(firmware))) - return 1; /* OK */ - + break; } + if (i >= FIRMWARE_VERSIONS) + return 0; /* no match */ + + if (!chip) + return 1; /* OK */ snd_printdd("Writing Firmware\n"); if (!chip->fw_entry) { diff --git a/trunk/sound/soc/codecs/wm8776.c b/trunk/sound/soc/codecs/wm8776.c index f8154e661524..4e212ed62ea6 100644 --- a/trunk/sound/soc/codecs/wm8776.c +++ b/trunk/sound/soc/codecs/wm8776.c @@ -178,6 +178,13 @@ static int wm8776_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) case SND_SOC_DAIFMT_LEFT_J: iface |= 0x0001; break; + /* FIXME: CHECK A/B */ + case SND_SOC_DAIFMT_DSP_A: + iface |= 0x0003; + break; + case SND_SOC_DAIFMT_DSP_B: + iface |= 0x0007; + break; default: return -EINVAL; } diff --git a/trunk/tools/perf/Makefile b/trunk/tools/perf/Makefile index dcb9700b88d2..41abb90df50d 100644 --- a/trunk/tools/perf/Makefile +++ b/trunk/tools/perf/Makefile @@ -157,6 +157,10 @@ all:: # # Define NO_DWARF if you do not want debug-info analysis feature at all. +$(shell sh -c 'mkdir -p $(OUTPUT)scripts/{perl,python}/Perf-Trace-Util/' 2> /dev/null) +$(shell sh -c 'mkdir -p $(OUTPUT)util/{ui/browsers,scripting-engines}/' 2> /dev/null) +$(shell sh -c 'mkdir $(OUTPUT)bench' 2> /dev/null) + $(OUTPUT)PERF-VERSION-FILE: .FORCE-PERF-VERSION-FILE @$(SHELL_PATH) util/PERF-VERSION-GEN $(OUTPUT) -include $(OUTPUT)PERF-VERSION-FILE @@ -182,6 +186,8 @@ ifeq ($(ARCH),x86_64) ARCH := x86 endif +$(shell sh -c 'mkdir -p $(OUTPUT)arch/$(ARCH)/util/' 2> /dev/null) + # CFLAGS and LDFLAGS are for the users to override from the command line. # @@ -262,7 +268,6 @@ export prefix bindir sharedir sysconfdir CC = $(CROSS_COMPILE)gcc AR = $(CROSS_COMPILE)ar RM = rm -f -MKDIR = mkdir TAR = tar FIND = find INSTALL = install @@ -833,7 +838,6 @@ ifndef V QUIET_CC = @echo ' ' CC $@; QUIET_AR = @echo ' ' AR $@; QUIET_LINK = @echo ' ' LINK $@; - QUIET_MKDIR = @echo ' ' MKDIR $@; QUIET_BUILT_IN = @echo ' ' BUILTIN $@; QUIET_GEN = @echo ' ' GEN $@; QUIET_SUBDIR0 = +@subdir= @@ -1008,14 +1012,6 @@ $(LIB_OBJS) $(BUILTIN_OBJS): $(LIB_H) $(patsubst perf-%$X,%.o,$(PROGRAMS)): $(LIB_H) $(wildcard */*.h) builtin-revert.o wt-status.o: wt-status.h -# we compile into subdirectories. if the target directory is not the source directory, they might not exists. So -# we depend the various files onto their directories. -DIRECTORY_DEPS = $(LIB_OBJS) $(BUILTIN_OBJS) $(OUTPUT)PERF-VERSION-FILE $(OUTPUT)common-cmds.h -$(DIRECTORY_DEPS): $(sort $(dir $(DIRECTORY_DEPS))) -# In the second step, we make a rule to actually create these directories -$(sort $(dir $(DIRECTORY_DEPS))): - $(QUIET_MKDIR)$(MKDIR) -p $@ 2>/dev/null - $(LIB_FILE): $(LIB_OBJS) $(QUIET_AR)$(RM) $@ && $(AR) rcs $@ $(LIB_OBJS) diff --git a/trunk/tools/perf/util/ui/browsers/annotate.c b/trunk/tools/perf/util/ui/browsers/annotate.c index a90273e63f4f..55ff792459ac 100644 --- a/trunk/tools/perf/util/ui/browsers/annotate.c +++ b/trunk/tools/perf/util/ui/browsers/annotate.c @@ -146,7 +146,6 @@ static int annotate_browser__run(struct annotate_browser *self, return -1; newtFormAddHotKey(self->b.form, NEWT_KEY_LEFT); - newtFormAddHotKey(self->b.form, NEWT_KEY_RIGHT); nd = self->curr_hot; if (nd) { @@ -179,7 +178,7 @@ static int annotate_browser__run(struct annotate_browser *self, } out: ui_browser__hide(&self->b); - return es->u.key; + return 0; } int hist_entry__tui_annotate(struct hist_entry *self)