Merge branch 'perfcounters/urgent' into perfcounters/core
Conflicts: kernel/perf_counter.c Merge reason: update to latest upstream (-rc6) and resolve the conflict with urgent fixes. Signed-off-by: Ingo Molnar <mingo@elte.hu>
This commit is contained in:
commit
be750231ce
|
@ -139,6 +139,7 @@ Code Seq# Include File Comments
|
||||||
'm' all linux/synclink.h conflict!
|
'm' all linux/synclink.h conflict!
|
||||||
'm' 00-1F net/irda/irmod.h conflict!
|
'm' 00-1F net/irda/irmod.h conflict!
|
||||||
'n' 00-7F linux/ncp_fs.h
|
'n' 00-7F linux/ncp_fs.h
|
||||||
|
'n' 80-8F linux/nilfs2_fs.h NILFS2
|
||||||
'n' E0-FF video/matrox.h matroxfb
|
'n' E0-FF video/matrox.h matroxfb
|
||||||
'o' 00-1F fs/ocfs2/ocfs2_fs.h OCFS2
|
'o' 00-1F fs/ocfs2/ocfs2_fs.h OCFS2
|
||||||
'o' 00-03 include/mtd/ubi-user.h conflict! (OCFS2 and UBI overlaps)
|
'o' 00-03 include/mtd/ubi-user.h conflict! (OCFS2 and UBI overlaps)
|
||||||
|
|
|
@ -1116,6 +1116,10 @@ and is between 256 and 4096 characters. It is defined in the file
|
||||||
Combinations also work, so libata.dma=3 enables DMA
|
Combinations also work, so libata.dma=3 enables DMA
|
||||||
for disks and CDROMs, but not CFs.
|
for disks and CDROMs, but not CFs.
|
||||||
|
|
||||||
|
libata.ignore_hpa= [LIBATA] Ignore HPA limit
|
||||||
|
libata.ignore_hpa=0 keep BIOS limits (default)
|
||||||
|
libata.ignore_hpa=1 ignore limits, using full disk
|
||||||
|
|
||||||
libata.noacpi [LIBATA] Disables use of ACPI in libata suspend/resume
|
libata.noacpi [LIBATA] Disables use of ACPI in libata suspend/resume
|
||||||
when set.
|
when set.
|
||||||
Format: <int>
|
Format: <int>
|
||||||
|
|
|
@ -30,9 +30,9 @@ State
|
||||||
The validator tracks lock-class usage history into 4n + 1 separate state bits:
|
The validator tracks lock-class usage history into 4n + 1 separate state bits:
|
||||||
|
|
||||||
- 'ever held in STATE context'
|
- 'ever held in STATE context'
|
||||||
- 'ever head as readlock in STATE context'
|
- 'ever held as readlock in STATE context'
|
||||||
- 'ever head with STATE enabled'
|
- 'ever held with STATE enabled'
|
||||||
- 'ever head as readlock with STATE enabled'
|
- 'ever held as readlock with STATE enabled'
|
||||||
|
|
||||||
Where STATE can be either one of (kernel/lockdep_states.h)
|
Where STATE can be either one of (kernel/lockdep_states.h)
|
||||||
- hardirq
|
- hardirq
|
||||||
|
|
2
Makefile
2
Makefile
|
@ -1,7 +1,7 @@
|
||||||
VERSION = 2
|
VERSION = 2
|
||||||
PATCHLEVEL = 6
|
PATCHLEVEL = 6
|
||||||
SUBLEVEL = 31
|
SUBLEVEL = 31
|
||||||
EXTRAVERSION = -rc5
|
EXTRAVERSION = -rc6
|
||||||
NAME = Man-Eating Seals of Antiquity
|
NAME = Man-Eating Seals of Antiquity
|
||||||
|
|
||||||
# *DOCUMENTATION*
|
# *DOCUMENTATION*
|
||||||
|
|
|
@ -41,11 +41,6 @@ $(error Sorry, you need a newer version of the assember, one that is built from
|
||||||
ftp://ftp.hpl.hp.com/pub/linux-ia64/gas-030124.tar.gz)
|
ftp://ftp.hpl.hp.com/pub/linux-ia64/gas-030124.tar.gz)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifeq ($(call cc-version),0304)
|
|
||||||
cflags-$(CONFIG_ITANIUM) += -mtune=merced
|
|
||||||
cflags-$(CONFIG_MCKINLEY) += -mtune=mckinley
|
|
||||||
endif
|
|
||||||
|
|
||||||
KBUILD_CFLAGS += $(cflags-y)
|
KBUILD_CFLAGS += $(cflags-y)
|
||||||
head-y := arch/ia64/kernel/head.o arch/ia64/kernel/init_task.o
|
head-y := arch/ia64/kernel/head.o arch/ia64/kernel/init_task.o
|
||||||
|
|
||||||
|
|
|
@ -286,7 +286,7 @@ __test_and_clear_bit(int nr, volatile void * addr)
|
||||||
{
|
{
|
||||||
__u32 *p = (__u32 *) addr + (nr >> 5);
|
__u32 *p = (__u32 *) addr + (nr >> 5);
|
||||||
__u32 m = 1 << (nr & 31);
|
__u32 m = 1 << (nr & 31);
|
||||||
int oldbitset = *p & m;
|
int oldbitset = (*p & m) != 0;
|
||||||
|
|
||||||
*p &= ~m;
|
*p &= ~m;
|
||||||
return oldbitset;
|
return oldbitset;
|
||||||
|
|
|
@ -155,7 +155,6 @@
|
||||||
#include <linux/bitops.h>
|
#include <linux/bitops.h>
|
||||||
#include <asm/cacheflush.h>
|
#include <asm/cacheflush.h>
|
||||||
#include <asm/mmu_context.h>
|
#include <asm/mmu_context.h>
|
||||||
#include <asm/processor.h>
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Next come the mappings that determine how mmap() protection bits
|
* Next come the mappings that determine how mmap() protection bits
|
||||||
|
|
|
@ -21,6 +21,7 @@ EXPORT_SYMBOL(csum_ipv6_magic);
|
||||||
|
|
||||||
#include <asm/page.h>
|
#include <asm/page.h>
|
||||||
EXPORT_SYMBOL(clear_page);
|
EXPORT_SYMBOL(clear_page);
|
||||||
|
EXPORT_SYMBOL(copy_page);
|
||||||
|
|
||||||
#ifdef CONFIG_VIRTUAL_MEM_MAP
|
#ifdef CONFIG_VIRTUAL_MEM_MAP
|
||||||
#include <linux/bootmem.h>
|
#include <linux/bootmem.h>
|
||||||
|
@ -60,9 +61,6 @@ EXPORT_SYMBOL(__udivdi3);
|
||||||
EXPORT_SYMBOL(__moddi3);
|
EXPORT_SYMBOL(__moddi3);
|
||||||
EXPORT_SYMBOL(__umoddi3);
|
EXPORT_SYMBOL(__umoddi3);
|
||||||
|
|
||||||
#include <asm/page.h>
|
|
||||||
EXPORT_SYMBOL(copy_page);
|
|
||||||
|
|
||||||
#if defined(CONFIG_MD_RAID456) || defined(CONFIG_MD_RAID456_MODULE)
|
#if defined(CONFIG_MD_RAID456) || defined(CONFIG_MD_RAID456_MODULE)
|
||||||
extern void xor_ia64_2(void);
|
extern void xor_ia64_2(void);
|
||||||
extern void xor_ia64_3(void);
|
extern void xor_ia64_3(void);
|
||||||
|
|
|
@ -1072,6 +1072,10 @@ iosapic_init (unsigned long phys_addr, unsigned int gsi_base)
|
||||||
}
|
}
|
||||||
|
|
||||||
addr = ioremap(phys_addr, 0);
|
addr = ioremap(phys_addr, 0);
|
||||||
|
if (addr == NULL) {
|
||||||
|
spin_unlock_irqrestore(&iosapic_lock, flags);
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
ver = iosapic_version(addr);
|
ver = iosapic_version(addr);
|
||||||
if ((err = iosapic_check_gsi_range(gsi_base, ver))) {
|
if ((err = iosapic_check_gsi_range(gsi_base, ver))) {
|
||||||
iounmap(addr);
|
iounmap(addr);
|
||||||
|
|
|
@ -69,11 +69,6 @@ iommu_dma_init(void)
|
||||||
|
|
||||||
int iommu_dma_supported(struct device *dev, u64 mask)
|
int iommu_dma_supported(struct device *dev, u64 mask)
|
||||||
{
|
{
|
||||||
struct dma_map_ops *ops = platform_dma_get_ops(dev);
|
|
||||||
|
|
||||||
if (ops->dma_supported)
|
|
||||||
return ops->dma_supported(dev, mask);
|
|
||||||
|
|
||||||
/* Copied from i386. Doesn't make much sense, because it will
|
/* Copied from i386. Doesn't make much sense, because it will
|
||||||
only work for pci_alloc_coherent.
|
only work for pci_alloc_coherent.
|
||||||
The caller just has to use GFP_DMA in this case. */
|
The caller just has to use GFP_DMA in this case. */
|
||||||
|
|
|
@ -372,6 +372,10 @@ static int __cpuinit cache_add_dev(struct sys_device * sys_dev)
|
||||||
retval = kobject_init_and_add(&all_cpu_cache_info[cpu].kobj,
|
retval = kobject_init_and_add(&all_cpu_cache_info[cpu].kobj,
|
||||||
&cache_ktype_percpu_entry, &sys_dev->kobj,
|
&cache_ktype_percpu_entry, &sys_dev->kobj,
|
||||||
"%s", "cache");
|
"%s", "cache");
|
||||||
|
if (unlikely(retval < 0)) {
|
||||||
|
cpu_cache_sysfs_exit(cpu);
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
for (i = 0; i < all_cpu_cache_info[cpu].num_cache_leaves; i++) {
|
for (i = 0; i < all_cpu_cache_info[cpu].num_cache_leaves; i++) {
|
||||||
this_object = LEAF_KOBJECT_PTR(cpu,i);
|
this_object = LEAF_KOBJECT_PTR(cpu,i);
|
||||||
|
@ -385,7 +389,7 @@ static int __cpuinit cache_add_dev(struct sys_device * sys_dev)
|
||||||
}
|
}
|
||||||
kobject_put(&all_cpu_cache_info[cpu].kobj);
|
kobject_put(&all_cpu_cache_info[cpu].kobj);
|
||||||
cpu_cache_sysfs_exit(cpu);
|
cpu_cache_sysfs_exit(cpu);
|
||||||
break;
|
return retval;
|
||||||
}
|
}
|
||||||
kobject_uevent(&(this_object->kobj), KOBJ_ADD);
|
kobject_uevent(&(this_object->kobj), KOBJ_ADD);
|
||||||
}
|
}
|
||||||
|
|
|
@ -247,7 +247,8 @@ void emulate_io_inst(struct kvm_vcpu *vcpu, u64 padr, u64 ma)
|
||||||
vcpu_get_fpreg(vcpu, inst.M9.f2, &v);
|
vcpu_get_fpreg(vcpu, inst.M9.f2, &v);
|
||||||
/* Write high word. FIXME: this is a kludge! */
|
/* Write high word. FIXME: this is a kludge! */
|
||||||
v.u.bits[1] &= 0x3ffff;
|
v.u.bits[1] &= 0x3ffff;
|
||||||
mmio_access(vcpu, padr + 8, &v.u.bits[1], 8, ma, IOREQ_WRITE);
|
mmio_access(vcpu, padr + 8, (u64 *)&v.u.bits[1], 8,
|
||||||
|
ma, IOREQ_WRITE);
|
||||||
data = v.u.bits[0];
|
data = v.u.bits[0];
|
||||||
size = 3;
|
size = 3;
|
||||||
} else if (inst.M10.major == 7 && inst.M10.x6 == 0x3B) {
|
} else if (inst.M10.major == 7 && inst.M10.x6 == 0x3B) {
|
||||||
|
@ -265,7 +266,8 @@ void emulate_io_inst(struct kvm_vcpu *vcpu, u64 padr, u64 ma)
|
||||||
|
|
||||||
/* Write high word.FIXME: this is a kludge! */
|
/* Write high word.FIXME: this is a kludge! */
|
||||||
v.u.bits[1] &= 0x3ffff;
|
v.u.bits[1] &= 0x3ffff;
|
||||||
mmio_access(vcpu, padr + 8, &v.u.bits[1], 8, ma, IOREQ_WRITE);
|
mmio_access(vcpu, padr + 8, (u64 *)&v.u.bits[1],
|
||||||
|
8, ma, IOREQ_WRITE);
|
||||||
data = v.u.bits[0];
|
data = v.u.bits[0];
|
||||||
size = 3;
|
size = 3;
|
||||||
} else if (inst.M10.major == 7 && inst.M10.x6 == 0x31) {
|
} else if (inst.M10.major == 7 && inst.M10.x6 == 0x31) {
|
||||||
|
|
|
@ -461,7 +461,7 @@ void setreg(unsigned long regnum, unsigned long val,
|
||||||
u64 vcpu_get_gr(struct kvm_vcpu *vcpu, unsigned long reg)
|
u64 vcpu_get_gr(struct kvm_vcpu *vcpu, unsigned long reg)
|
||||||
{
|
{
|
||||||
struct kvm_pt_regs *regs = vcpu_regs(vcpu);
|
struct kvm_pt_regs *regs = vcpu_regs(vcpu);
|
||||||
u64 val;
|
unsigned long val;
|
||||||
|
|
||||||
if (!reg)
|
if (!reg)
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -469,7 +469,7 @@ u64 vcpu_get_gr(struct kvm_vcpu *vcpu, unsigned long reg)
|
||||||
return val;
|
return val;
|
||||||
}
|
}
|
||||||
|
|
||||||
void vcpu_set_gr(struct kvm_vcpu *vcpu, u64 reg, u64 value, int nat)
|
void vcpu_set_gr(struct kvm_vcpu *vcpu, unsigned long reg, u64 value, int nat)
|
||||||
{
|
{
|
||||||
struct kvm_pt_regs *regs = vcpu_regs(vcpu);
|
struct kvm_pt_regs *regs = vcpu_regs(vcpu);
|
||||||
long sof = (regs->cr_ifs) & 0x7f;
|
long sof = (regs->cr_ifs) & 0x7f;
|
||||||
|
@ -1072,7 +1072,7 @@ void kvm_ttag(struct kvm_vcpu *vcpu, INST64 inst)
|
||||||
vcpu_set_gr(vcpu, inst.M46.r1, tag, 0);
|
vcpu_set_gr(vcpu, inst.M46.r1, tag, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
int vcpu_tpa(struct kvm_vcpu *vcpu, u64 vadr, u64 *padr)
|
int vcpu_tpa(struct kvm_vcpu *vcpu, u64 vadr, unsigned long *padr)
|
||||||
{
|
{
|
||||||
struct thash_data *data;
|
struct thash_data *data;
|
||||||
union ia64_isr visr, pt_isr;
|
union ia64_isr visr, pt_isr;
|
||||||
|
|
|
@ -686,14 +686,15 @@ static inline int highest_inservice_irq(struct kvm_vcpu *vcpu)
|
||||||
return highest_bits((int *)&(VMX(vcpu, insvc[0])));
|
return highest_bits((int *)&(VMX(vcpu, insvc[0])));
|
||||||
}
|
}
|
||||||
|
|
||||||
extern void vcpu_get_fpreg(struct kvm_vcpu *vcpu, u64 reg,
|
extern void vcpu_get_fpreg(struct kvm_vcpu *vcpu, unsigned long reg,
|
||||||
struct ia64_fpreg *val);
|
struct ia64_fpreg *val);
|
||||||
extern void vcpu_set_fpreg(struct kvm_vcpu *vcpu, u64 reg,
|
extern void vcpu_set_fpreg(struct kvm_vcpu *vcpu, unsigned long reg,
|
||||||
struct ia64_fpreg *val);
|
struct ia64_fpreg *val);
|
||||||
extern u64 vcpu_get_gr(struct kvm_vcpu *vcpu, u64 reg);
|
extern u64 vcpu_get_gr(struct kvm_vcpu *vcpu, unsigned long reg);
|
||||||
extern void vcpu_set_gr(struct kvm_vcpu *vcpu, u64 reg, u64 val, int nat);
|
extern void vcpu_set_gr(struct kvm_vcpu *vcpu, unsigned long reg,
|
||||||
extern u64 vcpu_get_psr(struct kvm_vcpu *vcpu);
|
u64 val, int nat);
|
||||||
extern void vcpu_set_psr(struct kvm_vcpu *vcpu, u64 val);
|
extern unsigned long vcpu_get_psr(struct kvm_vcpu *vcpu);
|
||||||
|
extern void vcpu_set_psr(struct kvm_vcpu *vcpu, unsigned long val);
|
||||||
extern u64 vcpu_thash(struct kvm_vcpu *vcpu, u64 vadr);
|
extern u64 vcpu_thash(struct kvm_vcpu *vcpu, u64 vadr);
|
||||||
extern void vcpu_bsw0(struct kvm_vcpu *vcpu);
|
extern void vcpu_bsw0(struct kvm_vcpu *vcpu);
|
||||||
extern void thash_vhpt_insert(struct kvm_vcpu *v, u64 pte,
|
extern void thash_vhpt_insert(struct kvm_vcpu *v, u64 pte,
|
||||||
|
|
|
@ -59,7 +59,6 @@ void pcibios_penalize_isa_irq(int irq);
|
||||||
#include <linux/slab.h>
|
#include <linux/slab.h>
|
||||||
#include <asm/scatterlist.h>
|
#include <asm/scatterlist.h>
|
||||||
#include <linux/string.h>
|
#include <linux/string.h>
|
||||||
#include <linux/mm.h>
|
|
||||||
#include <asm/io.h>
|
#include <asm/io.h>
|
||||||
|
|
||||||
struct pci_dev;
|
struct pci_dev;
|
||||||
|
|
|
@ -34,7 +34,7 @@
|
||||||
#define KVM_COALESCED_MMIO_PAGE_OFFSET 1
|
#define KVM_COALESCED_MMIO_PAGE_OFFSET 1
|
||||||
|
|
||||||
/* We don't currently support large pages. */
|
/* We don't currently support large pages. */
|
||||||
#define KVM_PAGES_PER_HPAGE (1<<31)
|
#define KVM_PAGES_PER_HPAGE (1UL << 31)
|
||||||
|
|
||||||
struct kvm;
|
struct kvm;
|
||||||
struct kvm_run;
|
struct kvm_run;
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
|
|
||||||
#include <linux/device.h>
|
#include <linux/device.h>
|
||||||
#include <linux/dma-mapping.h>
|
#include <linux/dma-mapping.h>
|
||||||
|
#include <linux/lmb.h>
|
||||||
#include <asm/bug.h>
|
#include <asm/bug.h>
|
||||||
#include <asm/abs_addr.h>
|
#include <asm/abs_addr.h>
|
||||||
|
|
||||||
|
@ -90,11 +91,10 @@ static void dma_direct_unmap_sg(struct device *dev, struct scatterlist *sg,
|
||||||
static int dma_direct_dma_supported(struct device *dev, u64 mask)
|
static int dma_direct_dma_supported(struct device *dev, u64 mask)
|
||||||
{
|
{
|
||||||
#ifdef CONFIG_PPC64
|
#ifdef CONFIG_PPC64
|
||||||
/* Could be improved to check for memory though it better be
|
/* Could be improved so platforms can set the limit in case
|
||||||
* done via some global so platforms can set the limit in case
|
|
||||||
* they have limited DMA windows
|
* they have limited DMA windows
|
||||||
*/
|
*/
|
||||||
return mask >= DMA_BIT_MASK(32);
|
return mask >= (lmb_end_of_DRAM() - 1);
|
||||||
#else
|
#else
|
||||||
return 1;
|
return 1;
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -386,7 +386,7 @@ no_timer:
|
||||||
}
|
}
|
||||||
__unset_cpu_idle(vcpu);
|
__unset_cpu_idle(vcpu);
|
||||||
__set_current_state(TASK_RUNNING);
|
__set_current_state(TASK_RUNNING);
|
||||||
remove_wait_queue(&vcpu->wq, &wait);
|
remove_wait_queue(&vcpu->arch.local_int.wq, &wait);
|
||||||
spin_unlock_bh(&vcpu->arch.local_int.lock);
|
spin_unlock_bh(&vcpu->arch.local_int.lock);
|
||||||
spin_unlock(&vcpu->arch.local_int.float_int->lock);
|
spin_unlock(&vcpu->arch.local_int.float_int->lock);
|
||||||
hrtimer_try_to_cancel(&vcpu->arch.ckc_timer);
|
hrtimer_try_to_cancel(&vcpu->arch.ckc_timer);
|
||||||
|
|
|
@ -547,7 +547,7 @@ static int __init ap325rxa_devices_setup(void)
|
||||||
return platform_add_devices(ap325rxa_devices,
|
return platform_add_devices(ap325rxa_devices,
|
||||||
ARRAY_SIZE(ap325rxa_devices));
|
ARRAY_SIZE(ap325rxa_devices));
|
||||||
}
|
}
|
||||||
device_initcall(ap325rxa_devices_setup);
|
arch_initcall(ap325rxa_devices_setup);
|
||||||
|
|
||||||
/* Return the board specific boot mode pin configuration */
|
/* Return the board specific boot mode pin configuration */
|
||||||
static int ap325rxa_mode_pins(void)
|
static int ap325rxa_mode_pins(void)
|
||||||
|
|
|
@ -608,7 +608,7 @@ static int __init migor_devices_setup(void)
|
||||||
|
|
||||||
return platform_add_devices(migor_devices, ARRAY_SIZE(migor_devices));
|
return platform_add_devices(migor_devices, ARRAY_SIZE(migor_devices));
|
||||||
}
|
}
|
||||||
__initcall(migor_devices_setup);
|
arch_initcall(migor_devices_setup);
|
||||||
|
|
||||||
/* Return the board specific boot mode pin configuration */
|
/* Return the board specific boot mode pin configuration */
|
||||||
static int migor_mode_pins(void)
|
static int migor_mode_pins(void)
|
||||||
|
|
|
@ -187,7 +187,7 @@ static int __init sh7619_devices_setup(void)
|
||||||
return platform_add_devices(sh7619_devices,
|
return platform_add_devices(sh7619_devices,
|
||||||
ARRAY_SIZE(sh7619_devices));
|
ARRAY_SIZE(sh7619_devices));
|
||||||
}
|
}
|
||||||
__initcall(sh7619_devices_setup);
|
arch_initcall(sh7619_devices_setup);
|
||||||
|
|
||||||
void __init plat_irq_setup(void)
|
void __init plat_irq_setup(void)
|
||||||
{
|
{
|
||||||
|
|
|
@ -238,7 +238,7 @@ static int __init mxg_devices_setup(void)
|
||||||
return platform_add_devices(mxg_devices,
|
return platform_add_devices(mxg_devices,
|
||||||
ARRAY_SIZE(mxg_devices));
|
ARRAY_SIZE(mxg_devices));
|
||||||
}
|
}
|
||||||
__initcall(mxg_devices_setup);
|
arch_initcall(mxg_devices_setup);
|
||||||
|
|
||||||
void __init plat_irq_setup(void)
|
void __init plat_irq_setup(void)
|
||||||
{
|
{
|
||||||
|
|
|
@ -357,7 +357,7 @@ static int __init sh7201_devices_setup(void)
|
||||||
return platform_add_devices(sh7201_devices,
|
return platform_add_devices(sh7201_devices,
|
||||||
ARRAY_SIZE(sh7201_devices));
|
ARRAY_SIZE(sh7201_devices));
|
||||||
}
|
}
|
||||||
__initcall(sh7201_devices_setup);
|
arch_initcall(sh7201_devices_setup);
|
||||||
|
|
||||||
void __init plat_irq_setup(void)
|
void __init plat_irq_setup(void)
|
||||||
{
|
{
|
||||||
|
|
|
@ -367,7 +367,7 @@ static int __init sh7203_devices_setup(void)
|
||||||
return platform_add_devices(sh7203_devices,
|
return platform_add_devices(sh7203_devices,
|
||||||
ARRAY_SIZE(sh7203_devices));
|
ARRAY_SIZE(sh7203_devices));
|
||||||
}
|
}
|
||||||
__initcall(sh7203_devices_setup);
|
arch_initcall(sh7203_devices_setup);
|
||||||
|
|
||||||
void __init plat_irq_setup(void)
|
void __init plat_irq_setup(void)
|
||||||
{
|
{
|
||||||
|
|
|
@ -338,7 +338,7 @@ static int __init sh7206_devices_setup(void)
|
||||||
return platform_add_devices(sh7206_devices,
|
return platform_add_devices(sh7206_devices,
|
||||||
ARRAY_SIZE(sh7206_devices));
|
ARRAY_SIZE(sh7206_devices));
|
||||||
}
|
}
|
||||||
__initcall(sh7206_devices_setup);
|
arch_initcall(sh7206_devices_setup);
|
||||||
|
|
||||||
void __init plat_irq_setup(void)
|
void __init plat_irq_setup(void)
|
||||||
{
|
{
|
||||||
|
|
|
@ -222,7 +222,7 @@ static int __init sh7705_devices_setup(void)
|
||||||
return platform_add_devices(sh7705_devices,
|
return platform_add_devices(sh7705_devices,
|
||||||
ARRAY_SIZE(sh7705_devices));
|
ARRAY_SIZE(sh7705_devices));
|
||||||
}
|
}
|
||||||
__initcall(sh7705_devices_setup);
|
arch_initcall(sh7705_devices_setup);
|
||||||
|
|
||||||
static struct platform_device *sh7705_early_devices[] __initdata = {
|
static struct platform_device *sh7705_early_devices[] __initdata = {
|
||||||
&tmu0_device,
|
&tmu0_device,
|
||||||
|
|
|
@ -250,7 +250,7 @@ static int __init sh770x_devices_setup(void)
|
||||||
return platform_add_devices(sh770x_devices,
|
return platform_add_devices(sh770x_devices,
|
||||||
ARRAY_SIZE(sh770x_devices));
|
ARRAY_SIZE(sh770x_devices));
|
||||||
}
|
}
|
||||||
__initcall(sh770x_devices_setup);
|
arch_initcall(sh770x_devices_setup);
|
||||||
|
|
||||||
static struct platform_device *sh770x_early_devices[] __initdata = {
|
static struct platform_device *sh770x_early_devices[] __initdata = {
|
||||||
&tmu0_device,
|
&tmu0_device,
|
||||||
|
|
|
@ -226,7 +226,7 @@ static int __init sh7710_devices_setup(void)
|
||||||
return platform_add_devices(sh7710_devices,
|
return platform_add_devices(sh7710_devices,
|
||||||
ARRAY_SIZE(sh7710_devices));
|
ARRAY_SIZE(sh7710_devices));
|
||||||
}
|
}
|
||||||
__initcall(sh7710_devices_setup);
|
arch_initcall(sh7710_devices_setup);
|
||||||
|
|
||||||
static struct platform_device *sh7710_early_devices[] __initdata = {
|
static struct platform_device *sh7710_early_devices[] __initdata = {
|
||||||
&tmu0_device,
|
&tmu0_device,
|
||||||
|
|
|
@ -388,7 +388,7 @@ static int __init sh7720_devices_setup(void)
|
||||||
return platform_add_devices(sh7720_devices,
|
return platform_add_devices(sh7720_devices,
|
||||||
ARRAY_SIZE(sh7720_devices));
|
ARRAY_SIZE(sh7720_devices));
|
||||||
}
|
}
|
||||||
__initcall(sh7720_devices_setup);
|
arch_initcall(sh7720_devices_setup);
|
||||||
|
|
||||||
static struct platform_device *sh7720_early_devices[] __initdata = {
|
static struct platform_device *sh7720_early_devices[] __initdata = {
|
||||||
&cmt0_device,
|
&cmt0_device,
|
||||||
|
|
|
@ -138,7 +138,7 @@ static int __init sh4202_devices_setup(void)
|
||||||
return platform_add_devices(sh4202_devices,
|
return platform_add_devices(sh4202_devices,
|
||||||
ARRAY_SIZE(sh4202_devices));
|
ARRAY_SIZE(sh4202_devices));
|
||||||
}
|
}
|
||||||
__initcall(sh4202_devices_setup);
|
arch_initcall(sh4202_devices_setup);
|
||||||
|
|
||||||
static struct platform_device *sh4202_early_devices[] __initdata = {
|
static struct platform_device *sh4202_early_devices[] __initdata = {
|
||||||
&tmu0_device,
|
&tmu0_device,
|
||||||
|
|
|
@ -239,7 +239,7 @@ static int __init sh7750_devices_setup(void)
|
||||||
return platform_add_devices(sh7750_devices,
|
return platform_add_devices(sh7750_devices,
|
||||||
ARRAY_SIZE(sh7750_devices));
|
ARRAY_SIZE(sh7750_devices));
|
||||||
}
|
}
|
||||||
__initcall(sh7750_devices_setup);
|
arch_initcall(sh7750_devices_setup);
|
||||||
|
|
||||||
static struct platform_device *sh7750_early_devices[] __initdata = {
|
static struct platform_device *sh7750_early_devices[] __initdata = {
|
||||||
&tmu0_device,
|
&tmu0_device,
|
||||||
|
|
|
@ -265,7 +265,7 @@ static int __init sh7760_devices_setup(void)
|
||||||
return platform_add_devices(sh7760_devices,
|
return platform_add_devices(sh7760_devices,
|
||||||
ARRAY_SIZE(sh7760_devices));
|
ARRAY_SIZE(sh7760_devices));
|
||||||
}
|
}
|
||||||
__initcall(sh7760_devices_setup);
|
arch_initcall(sh7760_devices_setup);
|
||||||
|
|
||||||
static struct platform_device *sh7760_early_devices[] __initdata = {
|
static struct platform_device *sh7760_early_devices[] __initdata = {
|
||||||
&tmu0_device,
|
&tmu0_device,
|
||||||
|
|
|
@ -325,7 +325,7 @@ static int __init sh7343_devices_setup(void)
|
||||||
return platform_add_devices(sh7343_devices,
|
return platform_add_devices(sh7343_devices,
|
||||||
ARRAY_SIZE(sh7343_devices));
|
ARRAY_SIZE(sh7343_devices));
|
||||||
}
|
}
|
||||||
__initcall(sh7343_devices_setup);
|
arch_initcall(sh7343_devices_setup);
|
||||||
|
|
||||||
static struct platform_device *sh7343_early_devices[] __initdata = {
|
static struct platform_device *sh7343_early_devices[] __initdata = {
|
||||||
&cmt_device,
|
&cmt_device,
|
||||||
|
|
|
@ -318,7 +318,7 @@ static int __init sh7366_devices_setup(void)
|
||||||
return platform_add_devices(sh7366_devices,
|
return platform_add_devices(sh7366_devices,
|
||||||
ARRAY_SIZE(sh7366_devices));
|
ARRAY_SIZE(sh7366_devices));
|
||||||
}
|
}
|
||||||
__initcall(sh7366_devices_setup);
|
arch_initcall(sh7366_devices_setup);
|
||||||
|
|
||||||
static struct platform_device *sh7366_early_devices[] __initdata = {
|
static struct platform_device *sh7366_early_devices[] __initdata = {
|
||||||
&cmt_device,
|
&cmt_device,
|
||||||
|
|
|
@ -359,7 +359,7 @@ static int __init sh7722_devices_setup(void)
|
||||||
return platform_add_devices(sh7722_devices,
|
return platform_add_devices(sh7722_devices,
|
||||||
ARRAY_SIZE(sh7722_devices));
|
ARRAY_SIZE(sh7722_devices));
|
||||||
}
|
}
|
||||||
__initcall(sh7722_devices_setup);
|
arch_initcall(sh7722_devices_setup);
|
||||||
|
|
||||||
static struct platform_device *sh7722_early_devices[] __initdata = {
|
static struct platform_device *sh7722_early_devices[] __initdata = {
|
||||||
&cmt_device,
|
&cmt_device,
|
||||||
|
|
|
@ -473,7 +473,7 @@ static int __init sh7723_devices_setup(void)
|
||||||
return platform_add_devices(sh7723_devices,
|
return platform_add_devices(sh7723_devices,
|
||||||
ARRAY_SIZE(sh7723_devices));
|
ARRAY_SIZE(sh7723_devices));
|
||||||
}
|
}
|
||||||
__initcall(sh7723_devices_setup);
|
arch_initcall(sh7723_devices_setup);
|
||||||
|
|
||||||
static struct platform_device *sh7723_early_devices[] __initdata = {
|
static struct platform_device *sh7723_early_devices[] __initdata = {
|
||||||
&cmt_device,
|
&cmt_device,
|
||||||
|
|
|
@ -508,7 +508,7 @@ static int __init sh7724_devices_setup(void)
|
||||||
return platform_add_devices(sh7724_devices,
|
return platform_add_devices(sh7724_devices,
|
||||||
ARRAY_SIZE(sh7724_devices));
|
ARRAY_SIZE(sh7724_devices));
|
||||||
}
|
}
|
||||||
device_initcall(sh7724_devices_setup);
|
arch_initcall(sh7724_devices_setup);
|
||||||
|
|
||||||
static struct platform_device *sh7724_early_devices[] __initdata = {
|
static struct platform_device *sh7724_early_devices[] __initdata = {
|
||||||
&cmt_device,
|
&cmt_device,
|
||||||
|
|
|
@ -314,7 +314,7 @@ static int __init sh7763_devices_setup(void)
|
||||||
return platform_add_devices(sh7763_devices,
|
return platform_add_devices(sh7763_devices,
|
||||||
ARRAY_SIZE(sh7763_devices));
|
ARRAY_SIZE(sh7763_devices));
|
||||||
}
|
}
|
||||||
__initcall(sh7763_devices_setup);
|
arch_initcall(sh7763_devices_setup);
|
||||||
|
|
||||||
static struct platform_device *sh7763_early_devices[] __initdata = {
|
static struct platform_device *sh7763_early_devices[] __initdata = {
|
||||||
&tmu0_device,
|
&tmu0_device,
|
||||||
|
|
|
@ -368,7 +368,7 @@ static int __init sh7770_devices_setup(void)
|
||||||
return platform_add_devices(sh7770_devices,
|
return platform_add_devices(sh7770_devices,
|
||||||
ARRAY_SIZE(sh7770_devices));
|
ARRAY_SIZE(sh7770_devices));
|
||||||
}
|
}
|
||||||
__initcall(sh7770_devices_setup);
|
arch_initcall(sh7770_devices_setup);
|
||||||
|
|
||||||
static struct platform_device *sh7770_early_devices[] __initdata = {
|
static struct platform_device *sh7770_early_devices[] __initdata = {
|
||||||
&tmu0_device,
|
&tmu0_device,
|
||||||
|
|
|
@ -256,7 +256,7 @@ static int __init sh7780_devices_setup(void)
|
||||||
return platform_add_devices(sh7780_devices,
|
return platform_add_devices(sh7780_devices,
|
||||||
ARRAY_SIZE(sh7780_devices));
|
ARRAY_SIZE(sh7780_devices));
|
||||||
}
|
}
|
||||||
__initcall(sh7780_devices_setup);
|
arch_initcall(sh7780_devices_setup);
|
||||||
|
|
||||||
static struct platform_device *sh7780_early_devices[] __initdata = {
|
static struct platform_device *sh7780_early_devices[] __initdata = {
|
||||||
&tmu0_device,
|
&tmu0_device,
|
||||||
|
|
|
@ -263,7 +263,7 @@ static int __init sh7785_devices_setup(void)
|
||||||
return platform_add_devices(sh7785_devices,
|
return platform_add_devices(sh7785_devices,
|
||||||
ARRAY_SIZE(sh7785_devices));
|
ARRAY_SIZE(sh7785_devices));
|
||||||
}
|
}
|
||||||
__initcall(sh7785_devices_setup);
|
arch_initcall(sh7785_devices_setup);
|
||||||
|
|
||||||
static struct platform_device *sh7785_early_devices[] __initdata = {
|
static struct platform_device *sh7785_early_devices[] __initdata = {
|
||||||
&tmu0_device,
|
&tmu0_device,
|
||||||
|
|
|
@ -547,7 +547,7 @@ static int __init sh7786_devices_setup(void)
|
||||||
return platform_add_devices(sh7786_devices,
|
return platform_add_devices(sh7786_devices,
|
||||||
ARRAY_SIZE(sh7786_devices));
|
ARRAY_SIZE(sh7786_devices));
|
||||||
}
|
}
|
||||||
device_initcall(sh7786_devices_setup);
|
arch_initcall(sh7786_devices_setup);
|
||||||
|
|
||||||
void __init plat_early_device_setup(void)
|
void __init plat_early_device_setup(void)
|
||||||
{
|
{
|
||||||
|
|
|
@ -256,7 +256,7 @@ static int __init shx3_devices_setup(void)
|
||||||
return platform_add_devices(shx3_devices,
|
return platform_add_devices(shx3_devices,
|
||||||
ARRAY_SIZE(shx3_devices));
|
ARRAY_SIZE(shx3_devices));
|
||||||
}
|
}
|
||||||
__initcall(shx3_devices_setup);
|
arch_initcall(shx3_devices_setup);
|
||||||
|
|
||||||
void __init plat_early_device_setup(void)
|
void __init plat_early_device_setup(void)
|
||||||
{
|
{
|
||||||
|
|
|
@ -186,7 +186,7 @@ static int __init sh5_devices_setup(void)
|
||||||
return platform_add_devices(sh5_devices,
|
return platform_add_devices(sh5_devices,
|
||||||
ARRAY_SIZE(sh5_devices));
|
ARRAY_SIZE(sh5_devices));
|
||||||
}
|
}
|
||||||
__initcall(sh5_devices_setup);
|
arch_initcall(sh5_devices_setup);
|
||||||
|
|
||||||
void __init plat_early_device_setup(void)
|
void __init plat_early_device_setup(void)
|
||||||
{
|
{
|
||||||
|
|
|
@ -24,6 +24,7 @@ config X86
|
||||||
select HAVE_UNSTABLE_SCHED_CLOCK
|
select HAVE_UNSTABLE_SCHED_CLOCK
|
||||||
select HAVE_IDE
|
select HAVE_IDE
|
||||||
select HAVE_OPROFILE
|
select HAVE_OPROFILE
|
||||||
|
select HAVE_PERF_COUNTERS if (!M386 && !M486)
|
||||||
select HAVE_IOREMAP_PROT
|
select HAVE_IOREMAP_PROT
|
||||||
select HAVE_KPROBES
|
select HAVE_KPROBES
|
||||||
select ARCH_WANT_OPTIONAL_GPIOLIB
|
select ARCH_WANT_OPTIONAL_GPIOLIB
|
||||||
|
@ -742,7 +743,6 @@ config X86_UP_IOAPIC
|
||||||
config X86_LOCAL_APIC
|
config X86_LOCAL_APIC
|
||||||
def_bool y
|
def_bool y
|
||||||
depends on X86_64 || SMP || X86_32_NON_STANDARD || X86_UP_APIC
|
depends on X86_64 || SMP || X86_32_NON_STANDARD || X86_UP_APIC
|
||||||
select HAVE_PERF_COUNTERS if (!M386 && !M486)
|
|
||||||
|
|
||||||
config X86_IO_APIC
|
config X86_IO_APIC
|
||||||
def_bool y
|
def_bool y
|
||||||
|
|
|
@ -17,11 +17,13 @@ static int x2apic_acpi_madt_oem_check(char *oem_id, char *oem_table_id)
|
||||||
return x2apic_enabled();
|
return x2apic_enabled();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Start with all IRQs pointing to boot CPU. IRQ balancing will shift them. */
|
/*
|
||||||
|
* need to use more than cpu 0, because we need more vectors when
|
||||||
|
* MSI-X are used.
|
||||||
|
*/
|
||||||
static const struct cpumask *x2apic_target_cpus(void)
|
static const struct cpumask *x2apic_target_cpus(void)
|
||||||
{
|
{
|
||||||
return cpumask_of(0);
|
return cpu_online_mask;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -27,11 +27,13 @@ static int x2apic_acpi_madt_oem_check(char *oem_id, char *oem_table_id)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Start with all IRQs pointing to boot CPU. IRQ balancing will shift them. */
|
/*
|
||||||
|
* need to use more than cpu 0, because we need more vectors when
|
||||||
|
* MSI-X are used.
|
||||||
|
*/
|
||||||
static const struct cpumask *x2apic_target_cpus(void)
|
static const struct cpumask *x2apic_target_cpus(void)
|
||||||
{
|
{
|
||||||
return cpumask_of(0);
|
return cpu_online_mask;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void x2apic_vector_allocation_domain(int cpu, struct cpumask *retmask)
|
static void x2apic_vector_allocation_domain(int cpu, struct cpumask *retmask)
|
||||||
|
|
|
@ -400,6 +400,13 @@ static void __cpuinit init_amd(struct cpuinfo_x86 *c)
|
||||||
level = cpuid_eax(1);
|
level = cpuid_eax(1);
|
||||||
if((level >= 0x0f48 && level < 0x0f50) || level >= 0x0f58)
|
if((level >= 0x0f48 && level < 0x0f50) || level >= 0x0f58)
|
||||||
set_cpu_cap(c, X86_FEATURE_REP_GOOD);
|
set_cpu_cap(c, X86_FEATURE_REP_GOOD);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Some BIOSes incorrectly force this feature, but only K8
|
||||||
|
* revision D (model = 0x14) and later actually support it.
|
||||||
|
*/
|
||||||
|
if (c->x86_model < 0x14)
|
||||||
|
clear_cpu_cap(c, X86_FEATURE_LAHF_LM);
|
||||||
}
|
}
|
||||||
if (c->x86 == 0x10 || c->x86 == 0x11)
|
if (c->x86 == 0x10 || c->x86 == 0x11)
|
||||||
set_cpu_cap(c, X86_FEATURE_REP_GOOD);
|
set_cpu_cap(c, X86_FEATURE_REP_GOOD);
|
||||||
|
|
|
@ -59,7 +59,30 @@ void __init setup_cpu_local_masks(void)
|
||||||
alloc_bootmem_cpumask_var(&cpu_sibling_setup_mask);
|
alloc_bootmem_cpumask_var(&cpu_sibling_setup_mask);
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct cpu_dev *this_cpu __cpuinitdata;
|
static void __cpuinit default_init(struct cpuinfo_x86 *c)
|
||||||
|
{
|
||||||
|
#ifdef CONFIG_X86_64
|
||||||
|
display_cacheinfo(c);
|
||||||
|
#else
|
||||||
|
/* Not much we can do here... */
|
||||||
|
/* Check if at least it has cpuid */
|
||||||
|
if (c->cpuid_level == -1) {
|
||||||
|
/* No cpuid. It must be an ancient CPU */
|
||||||
|
if (c->x86 == 4)
|
||||||
|
strcpy(c->x86_model_id, "486");
|
||||||
|
else if (c->x86 == 3)
|
||||||
|
strcpy(c->x86_model_id, "386");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct cpu_dev __cpuinitconst default_cpu = {
|
||||||
|
.c_init = default_init,
|
||||||
|
.c_vendor = "Unknown",
|
||||||
|
.c_x86_vendor = X86_VENDOR_UNKNOWN,
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct cpu_dev *this_cpu __cpuinitdata = &default_cpu;
|
||||||
|
|
||||||
DEFINE_PER_CPU_PAGE_ALIGNED(struct gdt_page, gdt_page) = { .gdt = {
|
DEFINE_PER_CPU_PAGE_ALIGNED(struct gdt_page, gdt_page) = { .gdt = {
|
||||||
#ifdef CONFIG_X86_64
|
#ifdef CONFIG_X86_64
|
||||||
|
@ -332,29 +355,6 @@ void switch_to_new_gdt(int cpu)
|
||||||
|
|
||||||
static const struct cpu_dev *__cpuinitdata cpu_devs[X86_VENDOR_NUM] = {};
|
static const struct cpu_dev *__cpuinitdata cpu_devs[X86_VENDOR_NUM] = {};
|
||||||
|
|
||||||
static void __cpuinit default_init(struct cpuinfo_x86 *c)
|
|
||||||
{
|
|
||||||
#ifdef CONFIG_X86_64
|
|
||||||
display_cacheinfo(c);
|
|
||||||
#else
|
|
||||||
/* Not much we can do here... */
|
|
||||||
/* Check if at least it has cpuid */
|
|
||||||
if (c->cpuid_level == -1) {
|
|
||||||
/* No cpuid. It must be an ancient CPU */
|
|
||||||
if (c->x86 == 4)
|
|
||||||
strcpy(c->x86_model_id, "486");
|
|
||||||
else if (c->x86 == 3)
|
|
||||||
strcpy(c->x86_model_id, "386");
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
static const struct cpu_dev __cpuinitconst default_cpu = {
|
|
||||||
.c_init = default_init,
|
|
||||||
.c_vendor = "Unknown",
|
|
||||||
.c_x86_vendor = X86_VENDOR_UNKNOWN,
|
|
||||||
};
|
|
||||||
|
|
||||||
static void __cpuinit get_model_name(struct cpuinfo_x86 *c)
|
static void __cpuinit get_model_name(struct cpuinfo_x86 *c)
|
||||||
{
|
{
|
||||||
unsigned int *v;
|
unsigned int *v;
|
||||||
|
|
|
@ -36,6 +36,7 @@
|
||||||
|
|
||||||
static DEFINE_PER_CPU(__u64, next_check) = INITIAL_JIFFIES;
|
static DEFINE_PER_CPU(__u64, next_check) = INITIAL_JIFFIES;
|
||||||
static DEFINE_PER_CPU(unsigned long, thermal_throttle_count);
|
static DEFINE_PER_CPU(unsigned long, thermal_throttle_count);
|
||||||
|
static DEFINE_PER_CPU(bool, thermal_throttle_active);
|
||||||
|
|
||||||
static atomic_t therm_throt_en = ATOMIC_INIT(0);
|
static atomic_t therm_throt_en = ATOMIC_INIT(0);
|
||||||
|
|
||||||
|
@ -96,24 +97,27 @@ static int therm_throt_process(int curr)
|
||||||
{
|
{
|
||||||
unsigned int cpu = smp_processor_id();
|
unsigned int cpu = smp_processor_id();
|
||||||
__u64 tmp_jiffs = get_jiffies_64();
|
__u64 tmp_jiffs = get_jiffies_64();
|
||||||
|
bool was_throttled = __get_cpu_var(thermal_throttle_active);
|
||||||
|
bool is_throttled = __get_cpu_var(thermal_throttle_active) = curr;
|
||||||
|
|
||||||
if (curr)
|
if (is_throttled)
|
||||||
__get_cpu_var(thermal_throttle_count)++;
|
__get_cpu_var(thermal_throttle_count)++;
|
||||||
|
|
||||||
if (time_before64(tmp_jiffs, __get_cpu_var(next_check)))
|
if (!(was_throttled ^ is_throttled) &&
|
||||||
|
time_before64(tmp_jiffs, __get_cpu_var(next_check)))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
__get_cpu_var(next_check) = tmp_jiffs + CHECK_INTERVAL;
|
__get_cpu_var(next_check) = tmp_jiffs + CHECK_INTERVAL;
|
||||||
|
|
||||||
/* if we just entered the thermal event */
|
/* if we just entered the thermal event */
|
||||||
if (curr) {
|
if (is_throttled) {
|
||||||
printk(KERN_CRIT "CPU%d: Temperature above threshold, "
|
printk(KERN_CRIT "CPU%d: Temperature above threshold, "
|
||||||
"cpu clock throttled (total events = %lu)\n", cpu,
|
"cpu clock throttled (total events = %lu)\n",
|
||||||
__get_cpu_var(thermal_throttle_count));
|
cpu, __get_cpu_var(thermal_throttle_count));
|
||||||
|
|
||||||
add_taint(TAINT_MACHINE_CHECK);
|
add_taint(TAINT_MACHINE_CHECK);
|
||||||
} else {
|
} else if (was_throttled) {
|
||||||
printk(KERN_CRIT "CPU%d: Temperature/speed normal\n", cpu);
|
printk(KERN_INFO "CPU%d: Temperature/speed normal\n", cpu);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
|
|
|
@ -97,6 +97,7 @@ struct x86_pmu {
|
||||||
int num_counters_fixed;
|
int num_counters_fixed;
|
||||||
int counter_bits;
|
int counter_bits;
|
||||||
u64 counter_mask;
|
u64 counter_mask;
|
||||||
|
int apic;
|
||||||
u64 max_period;
|
u64 max_period;
|
||||||
u64 intel_ctrl;
|
u64 intel_ctrl;
|
||||||
void (*enable_bts)(u64 config);
|
void (*enable_bts)(u64 config);
|
||||||
|
@ -116,8 +117,8 @@ static const u64 p6_perfmon_event_map[] =
|
||||||
{
|
{
|
||||||
[PERF_COUNT_HW_CPU_CYCLES] = 0x0079,
|
[PERF_COUNT_HW_CPU_CYCLES] = 0x0079,
|
||||||
[PERF_COUNT_HW_INSTRUCTIONS] = 0x00c0,
|
[PERF_COUNT_HW_INSTRUCTIONS] = 0x00c0,
|
||||||
[PERF_COUNT_HW_CACHE_REFERENCES] = 0x0000,
|
[PERF_COUNT_HW_CACHE_REFERENCES] = 0x0f2e,
|
||||||
[PERF_COUNT_HW_CACHE_MISSES] = 0x0000,
|
[PERF_COUNT_HW_CACHE_MISSES] = 0x012e,
|
||||||
[PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = 0x00c4,
|
[PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = 0x00c4,
|
||||||
[PERF_COUNT_HW_BRANCH_MISSES] = 0x00c5,
|
[PERF_COUNT_HW_BRANCH_MISSES] = 0x00c5,
|
||||||
[PERF_COUNT_HW_BUS_CYCLES] = 0x0062,
|
[PERF_COUNT_HW_BUS_CYCLES] = 0x0062,
|
||||||
|
@ -660,6 +661,7 @@ static DEFINE_MUTEX(pmc_reserve_mutex);
|
||||||
|
|
||||||
static bool reserve_pmc_hardware(void)
|
static bool reserve_pmc_hardware(void)
|
||||||
{
|
{
|
||||||
|
#ifdef CONFIG_X86_LOCAL_APIC
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
if (nmi_watchdog == NMI_LOCAL_APIC)
|
if (nmi_watchdog == NMI_LOCAL_APIC)
|
||||||
|
@ -674,9 +676,11 @@ static bool reserve_pmc_hardware(void)
|
||||||
if (!reserve_evntsel_nmi(x86_pmu.eventsel + i))
|
if (!reserve_evntsel_nmi(x86_pmu.eventsel + i))
|
||||||
goto eventsel_fail;
|
goto eventsel_fail;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
#ifdef CONFIG_X86_LOCAL_APIC
|
||||||
eventsel_fail:
|
eventsel_fail:
|
||||||
for (i--; i >= 0; i--)
|
for (i--; i >= 0; i--)
|
||||||
release_evntsel_nmi(x86_pmu.eventsel + i);
|
release_evntsel_nmi(x86_pmu.eventsel + i);
|
||||||
|
@ -691,10 +695,12 @@ perfctr_fail:
|
||||||
enable_lapic_nmi_watchdog();
|
enable_lapic_nmi_watchdog();
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static void release_pmc_hardware(void)
|
static void release_pmc_hardware(void)
|
||||||
{
|
{
|
||||||
|
#ifdef CONFIG_X86_LOCAL_APIC
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
for (i = 0; i < x86_pmu.num_counters; i++) {
|
for (i = 0; i < x86_pmu.num_counters; i++) {
|
||||||
|
@ -704,6 +710,7 @@ static void release_pmc_hardware(void)
|
||||||
|
|
||||||
if (nmi_watchdog == NMI_LOCAL_APIC)
|
if (nmi_watchdog == NMI_LOCAL_APIC)
|
||||||
enable_lapic_nmi_watchdog();
|
enable_lapic_nmi_watchdog();
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline bool bts_available(void)
|
static inline bool bts_available(void)
|
||||||
|
@ -934,6 +941,15 @@ static int __hw_perf_counter_init(struct perf_counter *counter)
|
||||||
hwc->sample_period = x86_pmu.max_period;
|
hwc->sample_period = x86_pmu.max_period;
|
||||||
hwc->last_period = hwc->sample_period;
|
hwc->last_period = hwc->sample_period;
|
||||||
atomic64_set(&hwc->period_left, hwc->sample_period);
|
atomic64_set(&hwc->period_left, hwc->sample_period);
|
||||||
|
} else {
|
||||||
|
/*
|
||||||
|
* If we have a PMU initialized but no APIC
|
||||||
|
* interrupts, we cannot sample hardware
|
||||||
|
* counters (user-space has to fall back and
|
||||||
|
* sample via a hrtimer based software counter):
|
||||||
|
*/
|
||||||
|
if (!x86_pmu.apic)
|
||||||
|
return -EOPNOTSUPP;
|
||||||
}
|
}
|
||||||
|
|
||||||
counter->destroy = hw_perf_counter_destroy;
|
counter->destroy = hw_perf_counter_destroy;
|
||||||
|
@ -1755,18 +1771,22 @@ void smp_perf_pending_interrupt(struct pt_regs *regs)
|
||||||
|
|
||||||
void set_perf_counter_pending(void)
|
void set_perf_counter_pending(void)
|
||||||
{
|
{
|
||||||
|
#ifdef CONFIG_X86_LOCAL_APIC
|
||||||
apic->send_IPI_self(LOCAL_PENDING_VECTOR);
|
apic->send_IPI_self(LOCAL_PENDING_VECTOR);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void perf_counters_lapic_init(void)
|
void perf_counters_lapic_init(void)
|
||||||
{
|
{
|
||||||
if (!x86_pmu_initialized())
|
#ifdef CONFIG_X86_LOCAL_APIC
|
||||||
|
if (!x86_pmu.apic || !x86_pmu_initialized())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Always use NMI for PMU
|
* Always use NMI for PMU
|
||||||
*/
|
*/
|
||||||
apic_write(APIC_LVTPC, APIC_DM_NMI);
|
apic_write(APIC_LVTPC, APIC_DM_NMI);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static int __kprobes
|
static int __kprobes
|
||||||
|
@ -1790,7 +1810,9 @@ perf_counter_nmi_handler(struct notifier_block *self,
|
||||||
|
|
||||||
regs = args->regs;
|
regs = args->regs;
|
||||||
|
|
||||||
|
#ifdef CONFIG_X86_LOCAL_APIC
|
||||||
apic_write(APIC_LVTPC, APIC_DM_NMI);
|
apic_write(APIC_LVTPC, APIC_DM_NMI);
|
||||||
|
#endif
|
||||||
/*
|
/*
|
||||||
* Can't rely on the handled return value to say it was our NMI, two
|
* Can't rely on the handled return value to say it was our NMI, two
|
||||||
* counters could trigger 'simultaneously' raising two back-to-back NMIs.
|
* counters could trigger 'simultaneously' raising two back-to-back NMIs.
|
||||||
|
@ -1821,6 +1843,7 @@ static struct x86_pmu p6_pmu = {
|
||||||
.event_map = p6_pmu_event_map,
|
.event_map = p6_pmu_event_map,
|
||||||
.raw_event = p6_pmu_raw_event,
|
.raw_event = p6_pmu_raw_event,
|
||||||
.max_events = ARRAY_SIZE(p6_perfmon_event_map),
|
.max_events = ARRAY_SIZE(p6_perfmon_event_map),
|
||||||
|
.apic = 1,
|
||||||
.max_period = (1ULL << 31) - 1,
|
.max_period = (1ULL << 31) - 1,
|
||||||
.version = 0,
|
.version = 0,
|
||||||
.num_counters = 2,
|
.num_counters = 2,
|
||||||
|
@ -1847,6 +1870,7 @@ static struct x86_pmu intel_pmu = {
|
||||||
.event_map = intel_pmu_event_map,
|
.event_map = intel_pmu_event_map,
|
||||||
.raw_event = intel_pmu_raw_event,
|
.raw_event = intel_pmu_raw_event,
|
||||||
.max_events = ARRAY_SIZE(intel_perfmon_event_map),
|
.max_events = ARRAY_SIZE(intel_perfmon_event_map),
|
||||||
|
.apic = 1,
|
||||||
/*
|
/*
|
||||||
* Intel PMCs cannot be accessed sanely above 32 bit width,
|
* Intel PMCs cannot be accessed sanely above 32 bit width,
|
||||||
* so we install an artificial 1<<31 period regardless of
|
* so we install an artificial 1<<31 period regardless of
|
||||||
|
@ -1872,6 +1896,7 @@ static struct x86_pmu amd_pmu = {
|
||||||
.num_counters = 4,
|
.num_counters = 4,
|
||||||
.counter_bits = 48,
|
.counter_bits = 48,
|
||||||
.counter_mask = (1ULL << 48) - 1,
|
.counter_mask = (1ULL << 48) - 1,
|
||||||
|
.apic = 1,
|
||||||
/* use highest bit to detect overflow */
|
/* use highest bit to detect overflow */
|
||||||
.max_period = (1ULL << 47) - 1,
|
.max_period = (1ULL << 47) - 1,
|
||||||
};
|
};
|
||||||
|
@ -1897,12 +1922,13 @@ static int p6_pmu_init(void)
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!cpu_has_apic) {
|
x86_pmu = p6_pmu;
|
||||||
pr_info("no Local APIC, try rebooting with lapic");
|
|
||||||
return -ENODEV;
|
|
||||||
}
|
|
||||||
|
|
||||||
x86_pmu = p6_pmu;
|
if (!cpu_has_apic) {
|
||||||
|
pr_info("no APIC, boot with the \"lapic\" boot parameter to force-enable it.\n");
|
||||||
|
pr_info("no hardware sampling interrupt available.\n");
|
||||||
|
x86_pmu.apic = 0;
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -354,7 +354,7 @@ void __init efi_init(void)
|
||||||
*/
|
*/
|
||||||
c16 = tmp = early_ioremap(efi.systab->fw_vendor, 2);
|
c16 = tmp = early_ioremap(efi.systab->fw_vendor, 2);
|
||||||
if (c16) {
|
if (c16) {
|
||||||
for (i = 0; i < sizeof(vendor) && *c16; ++i)
|
for (i = 0; i < sizeof(vendor) - 1 && *c16; ++i)
|
||||||
vendor[i] = *c16++;
|
vendor[i] = *c16++;
|
||||||
vendor[i] = '\0';
|
vendor[i] = '\0';
|
||||||
} else
|
} else
|
||||||
|
|
|
@ -405,7 +405,7 @@ EXPORT_SYMBOL(machine_real_restart);
|
||||||
#endif /* CONFIG_X86_32 */
|
#endif /* CONFIG_X86_32 */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Apple MacBook5,2 (2009 MacBook) needs reboot=p
|
* Some Apple MacBook and MacBookPro's needs reboot=p to be able to reboot
|
||||||
*/
|
*/
|
||||||
static int __init set_pci_reboot(const struct dmi_system_id *d)
|
static int __init set_pci_reboot(const struct dmi_system_id *d)
|
||||||
{
|
{
|
||||||
|
@ -418,12 +418,20 @@ static int __init set_pci_reboot(const struct dmi_system_id *d)
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct dmi_system_id __initdata pci_reboot_dmi_table[] = {
|
static struct dmi_system_id __initdata pci_reboot_dmi_table[] = {
|
||||||
{ /* Handle problems with rebooting on Apple MacBook5,2 */
|
{ /* Handle problems with rebooting on Apple MacBook5 */
|
||||||
.callback = set_pci_reboot,
|
.callback = set_pci_reboot,
|
||||||
.ident = "Apple MacBook",
|
.ident = "Apple MacBook5",
|
||||||
.matches = {
|
.matches = {
|
||||||
DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
|
DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
|
||||||
DMI_MATCH(DMI_PRODUCT_NAME, "MacBook5,2"),
|
DMI_MATCH(DMI_PRODUCT_NAME, "MacBook5"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{ /* Handle problems with rebooting on Apple MacBookPro5 */
|
||||||
|
.callback = set_pci_reboot,
|
||||||
|
.ident = "Apple MacBookPro5",
|
||||||
|
.matches = {
|
||||||
|
DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
|
||||||
|
DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro5"),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{ }
|
{ }
|
||||||
|
|
|
@ -275,15 +275,20 @@ static unsigned long pit_calibrate_tsc(u32 latch, unsigned long ms, int loopmin)
|
||||||
* use the TSC value at the transitions to calculate a pretty
|
* use the TSC value at the transitions to calculate a pretty
|
||||||
* good value for the TSC frequencty.
|
* good value for the TSC frequencty.
|
||||||
*/
|
*/
|
||||||
|
static inline int pit_verify_msb(unsigned char val)
|
||||||
|
{
|
||||||
|
/* Ignore LSB */
|
||||||
|
inb(0x42);
|
||||||
|
return inb(0x42) == val;
|
||||||
|
}
|
||||||
|
|
||||||
static inline int pit_expect_msb(unsigned char val, u64 *tscp, unsigned long *deltap)
|
static inline int pit_expect_msb(unsigned char val, u64 *tscp, unsigned long *deltap)
|
||||||
{
|
{
|
||||||
int count;
|
int count;
|
||||||
u64 tsc = 0;
|
u64 tsc = 0;
|
||||||
|
|
||||||
for (count = 0; count < 50000; count++) {
|
for (count = 0; count < 50000; count++) {
|
||||||
/* Ignore LSB */
|
if (!pit_verify_msb(val))
|
||||||
inb(0x42);
|
|
||||||
if (inb(0x42) != val)
|
|
||||||
break;
|
break;
|
||||||
tsc = get_cycles();
|
tsc = get_cycles();
|
||||||
}
|
}
|
||||||
|
@ -336,8 +341,7 @@ static unsigned long quick_pit_calibrate(void)
|
||||||
* to do that is to just read back the 16-bit counter
|
* to do that is to just read back the 16-bit counter
|
||||||
* once from the PIT.
|
* once from the PIT.
|
||||||
*/
|
*/
|
||||||
inb(0x42);
|
pit_verify_msb(0);
|
||||||
inb(0x42);
|
|
||||||
|
|
||||||
if (pit_expect_msb(0xff, &tsc, &d1)) {
|
if (pit_expect_msb(0xff, &tsc, &d1)) {
|
||||||
for (i = 1; i <= MAX_QUICK_PIT_ITERATIONS; i++) {
|
for (i = 1; i <= MAX_QUICK_PIT_ITERATIONS; i++) {
|
||||||
|
@ -348,8 +352,19 @@ static unsigned long quick_pit_calibrate(void)
|
||||||
* Iterate until the error is less than 500 ppm
|
* Iterate until the error is less than 500 ppm
|
||||||
*/
|
*/
|
||||||
delta -= tsc;
|
delta -= tsc;
|
||||||
if (d1+d2 < delta >> 11)
|
if (d1+d2 >= delta >> 11)
|
||||||
goto success;
|
continue;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check the PIT one more time to verify that
|
||||||
|
* all TSC reads were stable wrt the PIT.
|
||||||
|
*
|
||||||
|
* This also guarantees serialization of the
|
||||||
|
* last cycle read ('d2') in pit_expect_msb.
|
||||||
|
*/
|
||||||
|
if (!pit_verify_msb(0xfe - i))
|
||||||
|
break;
|
||||||
|
goto success;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
printk("Fast TSC calibration failed\n");
|
printk("Fast TSC calibration failed\n");
|
||||||
|
|
|
@ -441,7 +441,7 @@ vmi_startup_ipi_hook(int phys_apicid, unsigned long start_eip,
|
||||||
ap.ds = __USER_DS;
|
ap.ds = __USER_DS;
|
||||||
ap.es = __USER_DS;
|
ap.es = __USER_DS;
|
||||||
ap.fs = __KERNEL_PERCPU;
|
ap.fs = __KERNEL_PERCPU;
|
||||||
ap.gs = 0;
|
ap.gs = __KERNEL_STACK_CANARY;
|
||||||
|
|
||||||
ap.eflags = 0;
|
ap.eflags = 0;
|
||||||
|
|
||||||
|
|
|
@ -104,6 +104,9 @@ static s64 __kpit_elapsed(struct kvm *kvm)
|
||||||
ktime_t remaining;
|
ktime_t remaining;
|
||||||
struct kvm_kpit_state *ps = &kvm->arch.vpit->pit_state;
|
struct kvm_kpit_state *ps = &kvm->arch.vpit->pit_state;
|
||||||
|
|
||||||
|
if (!ps->pit_timer.period)
|
||||||
|
return 0;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The Counter does not stop when it reaches zero. In
|
* The Counter does not stop when it reaches zero. In
|
||||||
* Modes 0, 1, 4, and 5 the Counter ``wraps around'' to
|
* Modes 0, 1, 4, and 5 the Counter ``wraps around'' to
|
||||||
|
|
|
@ -489,16 +489,20 @@ static unsigned long *gfn_to_rmap(struct kvm *kvm, gfn_t gfn, int lpage)
|
||||||
*
|
*
|
||||||
* If rmapp bit zero is one, (then rmap & ~1) points to a struct kvm_rmap_desc
|
* If rmapp bit zero is one, (then rmap & ~1) points to a struct kvm_rmap_desc
|
||||||
* containing more mappings.
|
* containing more mappings.
|
||||||
|
*
|
||||||
|
* Returns the number of rmap entries before the spte was added or zero if
|
||||||
|
* the spte was not added.
|
||||||
|
*
|
||||||
*/
|
*/
|
||||||
static void rmap_add(struct kvm_vcpu *vcpu, u64 *spte, gfn_t gfn, int lpage)
|
static int rmap_add(struct kvm_vcpu *vcpu, u64 *spte, gfn_t gfn, int lpage)
|
||||||
{
|
{
|
||||||
struct kvm_mmu_page *sp;
|
struct kvm_mmu_page *sp;
|
||||||
struct kvm_rmap_desc *desc;
|
struct kvm_rmap_desc *desc;
|
||||||
unsigned long *rmapp;
|
unsigned long *rmapp;
|
||||||
int i;
|
int i, count = 0;
|
||||||
|
|
||||||
if (!is_rmap_pte(*spte))
|
if (!is_rmap_pte(*spte))
|
||||||
return;
|
return count;
|
||||||
gfn = unalias_gfn(vcpu->kvm, gfn);
|
gfn = unalias_gfn(vcpu->kvm, gfn);
|
||||||
sp = page_header(__pa(spte));
|
sp = page_header(__pa(spte));
|
||||||
sp->gfns[spte - sp->spt] = gfn;
|
sp->gfns[spte - sp->spt] = gfn;
|
||||||
|
@ -515,8 +519,10 @@ static void rmap_add(struct kvm_vcpu *vcpu, u64 *spte, gfn_t gfn, int lpage)
|
||||||
} else {
|
} else {
|
||||||
rmap_printk("rmap_add: %p %llx many->many\n", spte, *spte);
|
rmap_printk("rmap_add: %p %llx many->many\n", spte, *spte);
|
||||||
desc = (struct kvm_rmap_desc *)(*rmapp & ~1ul);
|
desc = (struct kvm_rmap_desc *)(*rmapp & ~1ul);
|
||||||
while (desc->shadow_ptes[RMAP_EXT-1] && desc->more)
|
while (desc->shadow_ptes[RMAP_EXT-1] && desc->more) {
|
||||||
desc = desc->more;
|
desc = desc->more;
|
||||||
|
count += RMAP_EXT;
|
||||||
|
}
|
||||||
if (desc->shadow_ptes[RMAP_EXT-1]) {
|
if (desc->shadow_ptes[RMAP_EXT-1]) {
|
||||||
desc->more = mmu_alloc_rmap_desc(vcpu);
|
desc->more = mmu_alloc_rmap_desc(vcpu);
|
||||||
desc = desc->more;
|
desc = desc->more;
|
||||||
|
@ -525,6 +531,7 @@ static void rmap_add(struct kvm_vcpu *vcpu, u64 *spte, gfn_t gfn, int lpage)
|
||||||
;
|
;
|
||||||
desc->shadow_ptes[i] = spte;
|
desc->shadow_ptes[i] = spte;
|
||||||
}
|
}
|
||||||
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void rmap_desc_remove_entry(unsigned long *rmapp,
|
static void rmap_desc_remove_entry(unsigned long *rmapp,
|
||||||
|
@ -754,6 +761,19 @@ static int kvm_age_rmapp(struct kvm *kvm, unsigned long *rmapp)
|
||||||
return young;
|
return young;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define RMAP_RECYCLE_THRESHOLD 1000
|
||||||
|
|
||||||
|
static void rmap_recycle(struct kvm_vcpu *vcpu, gfn_t gfn, int lpage)
|
||||||
|
{
|
||||||
|
unsigned long *rmapp;
|
||||||
|
|
||||||
|
gfn = unalias_gfn(vcpu->kvm, gfn);
|
||||||
|
rmapp = gfn_to_rmap(vcpu->kvm, gfn, lpage);
|
||||||
|
|
||||||
|
kvm_unmap_rmapp(vcpu->kvm, rmapp);
|
||||||
|
kvm_flush_remote_tlbs(vcpu->kvm);
|
||||||
|
}
|
||||||
|
|
||||||
int kvm_age_hva(struct kvm *kvm, unsigned long hva)
|
int kvm_age_hva(struct kvm *kvm, unsigned long hva)
|
||||||
{
|
{
|
||||||
return kvm_handle_hva(kvm, hva, kvm_age_rmapp);
|
return kvm_handle_hva(kvm, hva, kvm_age_rmapp);
|
||||||
|
@ -1407,24 +1427,25 @@ static int kvm_mmu_zap_page(struct kvm *kvm, struct kvm_mmu_page *sp)
|
||||||
*/
|
*/
|
||||||
void kvm_mmu_change_mmu_pages(struct kvm *kvm, unsigned int kvm_nr_mmu_pages)
|
void kvm_mmu_change_mmu_pages(struct kvm *kvm, unsigned int kvm_nr_mmu_pages)
|
||||||
{
|
{
|
||||||
|
int used_pages;
|
||||||
|
|
||||||
|
used_pages = kvm->arch.n_alloc_mmu_pages - kvm->arch.n_free_mmu_pages;
|
||||||
|
used_pages = max(0, used_pages);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If we set the number of mmu pages to be smaller be than the
|
* If we set the number of mmu pages to be smaller be than the
|
||||||
* number of actived pages , we must to free some mmu pages before we
|
* number of actived pages , we must to free some mmu pages before we
|
||||||
* change the value
|
* change the value
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if ((kvm->arch.n_alloc_mmu_pages - kvm->arch.n_free_mmu_pages) >
|
if (used_pages > kvm_nr_mmu_pages) {
|
||||||
kvm_nr_mmu_pages) {
|
while (used_pages > kvm_nr_mmu_pages) {
|
||||||
int n_used_mmu_pages = kvm->arch.n_alloc_mmu_pages
|
|
||||||
- kvm->arch.n_free_mmu_pages;
|
|
||||||
|
|
||||||
while (n_used_mmu_pages > kvm_nr_mmu_pages) {
|
|
||||||
struct kvm_mmu_page *page;
|
struct kvm_mmu_page *page;
|
||||||
|
|
||||||
page = container_of(kvm->arch.active_mmu_pages.prev,
|
page = container_of(kvm->arch.active_mmu_pages.prev,
|
||||||
struct kvm_mmu_page, link);
|
struct kvm_mmu_page, link);
|
||||||
kvm_mmu_zap_page(kvm, page);
|
kvm_mmu_zap_page(kvm, page);
|
||||||
n_used_mmu_pages--;
|
used_pages--;
|
||||||
}
|
}
|
||||||
kvm->arch.n_free_mmu_pages = 0;
|
kvm->arch.n_free_mmu_pages = 0;
|
||||||
}
|
}
|
||||||
|
@ -1740,6 +1761,7 @@ static void mmu_set_spte(struct kvm_vcpu *vcpu, u64 *shadow_pte,
|
||||||
{
|
{
|
||||||
int was_rmapped = 0;
|
int was_rmapped = 0;
|
||||||
int was_writeble = is_writeble_pte(*shadow_pte);
|
int was_writeble = is_writeble_pte(*shadow_pte);
|
||||||
|
int rmap_count;
|
||||||
|
|
||||||
pgprintk("%s: spte %llx access %x write_fault %d"
|
pgprintk("%s: spte %llx access %x write_fault %d"
|
||||||
" user_fault %d gfn %lx\n",
|
" user_fault %d gfn %lx\n",
|
||||||
|
@ -1781,9 +1803,11 @@ static void mmu_set_spte(struct kvm_vcpu *vcpu, u64 *shadow_pte,
|
||||||
|
|
||||||
page_header_update_slot(vcpu->kvm, shadow_pte, gfn);
|
page_header_update_slot(vcpu->kvm, shadow_pte, gfn);
|
||||||
if (!was_rmapped) {
|
if (!was_rmapped) {
|
||||||
rmap_add(vcpu, shadow_pte, gfn, largepage);
|
rmap_count = rmap_add(vcpu, shadow_pte, gfn, largepage);
|
||||||
if (!is_rmap_pte(*shadow_pte))
|
if (!is_rmap_pte(*shadow_pte))
|
||||||
kvm_release_pfn_clean(pfn);
|
kvm_release_pfn_clean(pfn);
|
||||||
|
if (rmap_count > RMAP_RECYCLE_THRESHOLD)
|
||||||
|
rmap_recycle(vcpu, gfn, largepage);
|
||||||
} else {
|
} else {
|
||||||
if (was_writeble)
|
if (was_writeble)
|
||||||
kvm_release_pfn_dirty(pfn);
|
kvm_release_pfn_dirty(pfn);
|
||||||
|
|
|
@ -711,6 +711,7 @@ static void svm_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
|
||||||
svm->vmcb->control.tsc_offset += delta;
|
svm->vmcb->control.tsc_offset += delta;
|
||||||
vcpu->cpu = cpu;
|
vcpu->cpu = cpu;
|
||||||
kvm_migrate_timers(vcpu);
|
kvm_migrate_timers(vcpu);
|
||||||
|
svm->asid_generation = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < NR_HOST_SAVE_USER_MSRS; i++)
|
for (i = 0; i < NR_HOST_SAVE_USER_MSRS; i++)
|
||||||
|
@ -1031,7 +1032,6 @@ static void new_asid(struct vcpu_svm *svm, struct svm_cpu_data *svm_data)
|
||||||
svm->vmcb->control.tlb_ctl = TLB_CONTROL_FLUSH_ALL_ASID;
|
svm->vmcb->control.tlb_ctl = TLB_CONTROL_FLUSH_ALL_ASID;
|
||||||
}
|
}
|
||||||
|
|
||||||
svm->vcpu.cpu = svm_data->cpu;
|
|
||||||
svm->asid_generation = svm_data->asid_generation;
|
svm->asid_generation = svm_data->asid_generation;
|
||||||
svm->vmcb->control.asid = svm_data->next_asid++;
|
svm->vmcb->control.asid = svm_data->next_asid++;
|
||||||
}
|
}
|
||||||
|
@ -2300,8 +2300,8 @@ static void pre_svm_run(struct vcpu_svm *svm)
|
||||||
struct svm_cpu_data *svm_data = per_cpu(svm_data, cpu);
|
struct svm_cpu_data *svm_data = per_cpu(svm_data, cpu);
|
||||||
|
|
||||||
svm->vmcb->control.tlb_ctl = TLB_CONTROL_DO_NOTHING;
|
svm->vmcb->control.tlb_ctl = TLB_CONTROL_DO_NOTHING;
|
||||||
if (svm->vcpu.cpu != cpu ||
|
/* FIXME: handle wraparound of asid_generation */
|
||||||
svm->asid_generation != svm_data->asid_generation)
|
if (svm->asid_generation != svm_data->asid_generation)
|
||||||
new_asid(svm, svm_data);
|
new_asid(svm, svm_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3157,8 +3157,8 @@ static void handle_invalid_guest_state(struct kvm_vcpu *vcpu,
|
||||||
struct vcpu_vmx *vmx = to_vmx(vcpu);
|
struct vcpu_vmx *vmx = to_vmx(vcpu);
|
||||||
enum emulation_result err = EMULATE_DONE;
|
enum emulation_result err = EMULATE_DONE;
|
||||||
|
|
||||||
preempt_enable();
|
|
||||||
local_irq_enable();
|
local_irq_enable();
|
||||||
|
preempt_enable();
|
||||||
|
|
||||||
while (!guest_state_valid(vcpu)) {
|
while (!guest_state_valid(vcpu)) {
|
||||||
err = emulate_instruction(vcpu, kvm_run, 0, 0, 0);
|
err = emulate_instruction(vcpu, kvm_run, 0, 0, 0);
|
||||||
|
@ -3168,7 +3168,7 @@ static void handle_invalid_guest_state(struct kvm_vcpu *vcpu,
|
||||||
|
|
||||||
if (err != EMULATE_DONE) {
|
if (err != EMULATE_DONE) {
|
||||||
kvm_report_emulation_failure(vcpu, "emulation failure");
|
kvm_report_emulation_failure(vcpu, "emulation failure");
|
||||||
return;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (signal_pending(current))
|
if (signal_pending(current))
|
||||||
|
@ -3177,8 +3177,8 @@ static void handle_invalid_guest_state(struct kvm_vcpu *vcpu,
|
||||||
schedule();
|
schedule();
|
||||||
}
|
}
|
||||||
|
|
||||||
local_irq_disable();
|
|
||||||
preempt_disable();
|
preempt_disable();
|
||||||
|
local_irq_disable();
|
||||||
|
|
||||||
vmx->invalid_state_emulation_result = err;
|
vmx->invalid_state_emulation_result = err;
|
||||||
}
|
}
|
||||||
|
|
|
@ -704,11 +704,48 @@ static bool msr_mtrr_valid(unsigned msr)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool valid_pat_type(unsigned t)
|
||||||
|
{
|
||||||
|
return t < 8 && (1 << t) & 0xf3; /* 0, 1, 4, 5, 6, 7 */
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool valid_mtrr_type(unsigned t)
|
||||||
|
{
|
||||||
|
return t < 8 && (1 << t) & 0x73; /* 0, 1, 4, 5, 6 */
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool mtrr_valid(struct kvm_vcpu *vcpu, u32 msr, u64 data)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (!msr_mtrr_valid(msr))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (msr == MSR_IA32_CR_PAT) {
|
||||||
|
for (i = 0; i < 8; i++)
|
||||||
|
if (!valid_pat_type((data >> (i * 8)) & 0xff))
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
} else if (msr == MSR_MTRRdefType) {
|
||||||
|
if (data & ~0xcff)
|
||||||
|
return false;
|
||||||
|
return valid_mtrr_type(data & 0xff);
|
||||||
|
} else if (msr >= MSR_MTRRfix64K_00000 && msr <= MSR_MTRRfix4K_F8000) {
|
||||||
|
for (i = 0; i < 8 ; i++)
|
||||||
|
if (!valid_mtrr_type((data >> (i * 8)) & 0xff))
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* variable MTRRs */
|
||||||
|
return valid_mtrr_type(data & 0xff);
|
||||||
|
}
|
||||||
|
|
||||||
static int set_msr_mtrr(struct kvm_vcpu *vcpu, u32 msr, u64 data)
|
static int set_msr_mtrr(struct kvm_vcpu *vcpu, u32 msr, u64 data)
|
||||||
{
|
{
|
||||||
u64 *p = (u64 *)&vcpu->arch.mtrr_state.fixed_ranges;
|
u64 *p = (u64 *)&vcpu->arch.mtrr_state.fixed_ranges;
|
||||||
|
|
||||||
if (!msr_mtrr_valid(msr))
|
if (!mtrr_valid(vcpu, msr, data))
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
if (msr == MSR_MTRRdefType) {
|
if (msr == MSR_MTRRdefType) {
|
||||||
|
@ -1079,14 +1116,13 @@ long kvm_arch_dev_ioctl(struct file *filp,
|
||||||
if (copy_to_user(user_msr_list, &msr_list, sizeof msr_list))
|
if (copy_to_user(user_msr_list, &msr_list, sizeof msr_list))
|
||||||
goto out;
|
goto out;
|
||||||
r = -E2BIG;
|
r = -E2BIG;
|
||||||
if (n < num_msrs_to_save)
|
if (n < msr_list.nmsrs)
|
||||||
goto out;
|
goto out;
|
||||||
r = -EFAULT;
|
r = -EFAULT;
|
||||||
if (copy_to_user(user_msr_list->indices, &msrs_to_save,
|
if (copy_to_user(user_msr_list->indices, &msrs_to_save,
|
||||||
num_msrs_to_save * sizeof(u32)))
|
num_msrs_to_save * sizeof(u32)))
|
||||||
goto out;
|
goto out;
|
||||||
if (copy_to_user(user_msr_list->indices
|
if (copy_to_user(user_msr_list->indices + num_msrs_to_save,
|
||||||
+ num_msrs_to_save * sizeof(u32),
|
|
||||||
&emulated_msrs,
|
&emulated_msrs,
|
||||||
ARRAY_SIZE(emulated_msrs) * sizeof(u32)))
|
ARRAY_SIZE(emulated_msrs) * sizeof(u32)))
|
||||||
goto out;
|
goto out;
|
||||||
|
|
|
@ -219,6 +219,8 @@ enum {
|
||||||
AHCI_HFLAG_SECT255 = (1 << 8), /* max 255 sectors */
|
AHCI_HFLAG_SECT255 = (1 << 8), /* max 255 sectors */
|
||||||
AHCI_HFLAG_YES_NCQ = (1 << 9), /* force NCQ cap on */
|
AHCI_HFLAG_YES_NCQ = (1 << 9), /* force NCQ cap on */
|
||||||
AHCI_HFLAG_NO_SUSPEND = (1 << 10), /* don't suspend */
|
AHCI_HFLAG_NO_SUSPEND = (1 << 10), /* don't suspend */
|
||||||
|
AHCI_HFLAG_SRST_TOUT_IS_OFFLINE = (1 << 11), /* treat SRST timeout as
|
||||||
|
link offline */
|
||||||
|
|
||||||
/* ap->flags bits */
|
/* ap->flags bits */
|
||||||
|
|
||||||
|
@ -1663,6 +1665,7 @@ static int ahci_do_softreset(struct ata_link *link, unsigned int *class,
|
||||||
int (*check_ready)(struct ata_link *link))
|
int (*check_ready)(struct ata_link *link))
|
||||||
{
|
{
|
||||||
struct ata_port *ap = link->ap;
|
struct ata_port *ap = link->ap;
|
||||||
|
struct ahci_host_priv *hpriv = ap->host->private_data;
|
||||||
const char *reason = NULL;
|
const char *reason = NULL;
|
||||||
unsigned long now, msecs;
|
unsigned long now, msecs;
|
||||||
struct ata_taskfile tf;
|
struct ata_taskfile tf;
|
||||||
|
@ -1701,12 +1704,21 @@ static int ahci_do_softreset(struct ata_link *link, unsigned int *class,
|
||||||
|
|
||||||
/* wait for link to become ready */
|
/* wait for link to become ready */
|
||||||
rc = ata_wait_after_reset(link, deadline, check_ready);
|
rc = ata_wait_after_reset(link, deadline, check_ready);
|
||||||
/* link occupied, -ENODEV too is an error */
|
if (rc == -EBUSY && hpriv->flags & AHCI_HFLAG_SRST_TOUT_IS_OFFLINE) {
|
||||||
if (rc) {
|
/*
|
||||||
|
* Workaround for cases where link online status can't
|
||||||
|
* be trusted. Treat device readiness timeout as link
|
||||||
|
* offline.
|
||||||
|
*/
|
||||||
|
ata_link_printk(link, KERN_INFO,
|
||||||
|
"device not ready, treating as offline\n");
|
||||||
|
*class = ATA_DEV_NONE;
|
||||||
|
} else if (rc) {
|
||||||
|
/* link occupied, -ENODEV too is an error */
|
||||||
reason = "device not ready";
|
reason = "device not ready";
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
} else
|
||||||
*class = ahci_dev_classify(ap);
|
*class = ahci_dev_classify(ap);
|
||||||
|
|
||||||
DPRINTK("EXIT, class=%u\n", *class);
|
DPRINTK("EXIT, class=%u\n", *class);
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -1773,7 +1785,8 @@ static int ahci_sb600_softreset(struct ata_link *link, unsigned int *class,
|
||||||
irq_sts = readl(port_mmio + PORT_IRQ_STAT);
|
irq_sts = readl(port_mmio + PORT_IRQ_STAT);
|
||||||
if (irq_sts & PORT_IRQ_BAD_PMP) {
|
if (irq_sts & PORT_IRQ_BAD_PMP) {
|
||||||
ata_link_printk(link, KERN_WARNING,
|
ata_link_printk(link, KERN_WARNING,
|
||||||
"failed due to HW bug, retry pmp=0\n");
|
"applying SB600 PMP SRST workaround "
|
||||||
|
"and retrying\n");
|
||||||
rc = ahci_do_softreset(link, class, 0, deadline,
|
rc = ahci_do_softreset(link, class, 0, deadline,
|
||||||
ahci_check_ready);
|
ahci_check_ready);
|
||||||
}
|
}
|
||||||
|
@ -2726,6 +2739,56 @@ static bool ahci_broken_suspend(struct pci_dev *pdev)
|
||||||
return !ver || strcmp(ver, dmi->driver_data) < 0;
|
return !ver || strcmp(ver, dmi->driver_data) < 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool ahci_broken_online(struct pci_dev *pdev)
|
||||||
|
{
|
||||||
|
#define ENCODE_BUSDEVFN(bus, slot, func) \
|
||||||
|
(void *)(unsigned long)(((bus) << 8) | PCI_DEVFN((slot), (func)))
|
||||||
|
static const struct dmi_system_id sysids[] = {
|
||||||
|
/*
|
||||||
|
* There are several gigabyte boards which use
|
||||||
|
* SIMG5723s configured as hardware RAID. Certain
|
||||||
|
* 5723 firmware revisions shipped there keep the link
|
||||||
|
* online but fail to answer properly to SRST or
|
||||||
|
* IDENTIFY when no device is attached downstream
|
||||||
|
* causing libata to retry quite a few times leading
|
||||||
|
* to excessive detection delay.
|
||||||
|
*
|
||||||
|
* As these firmwares respond to the second reset try
|
||||||
|
* with invalid device signature, considering unknown
|
||||||
|
* sig as offline works around the problem acceptably.
|
||||||
|
*/
|
||||||
|
{
|
||||||
|
.ident = "EP45-DQ6",
|
||||||
|
.matches = {
|
||||||
|
DMI_MATCH(DMI_BOARD_VENDOR,
|
||||||
|
"Gigabyte Technology Co., Ltd."),
|
||||||
|
DMI_MATCH(DMI_BOARD_NAME, "EP45-DQ6"),
|
||||||
|
},
|
||||||
|
.driver_data = ENCODE_BUSDEVFN(0x0a, 0x00, 0),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.ident = "EP45-DS5",
|
||||||
|
.matches = {
|
||||||
|
DMI_MATCH(DMI_BOARD_VENDOR,
|
||||||
|
"Gigabyte Technology Co., Ltd."),
|
||||||
|
DMI_MATCH(DMI_BOARD_NAME, "EP45-DS5"),
|
||||||
|
},
|
||||||
|
.driver_data = ENCODE_BUSDEVFN(0x03, 0x00, 0),
|
||||||
|
},
|
||||||
|
{ } /* terminate list */
|
||||||
|
};
|
||||||
|
#undef ENCODE_BUSDEVFN
|
||||||
|
const struct dmi_system_id *dmi = dmi_first_match(sysids);
|
||||||
|
unsigned int val;
|
||||||
|
|
||||||
|
if (!dmi)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
val = (unsigned long)dmi->driver_data;
|
||||||
|
|
||||||
|
return pdev->bus->number == (val >> 8) && pdev->devfn == (val & 0xff);
|
||||||
|
}
|
||||||
|
|
||||||
static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
|
static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
|
||||||
{
|
{
|
||||||
static int printed_version;
|
static int printed_version;
|
||||||
|
@ -2841,6 +2904,12 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
|
||||||
"BIOS update required for suspend/resume\n");
|
"BIOS update required for suspend/resume\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (ahci_broken_online(pdev)) {
|
||||||
|
hpriv->flags |= AHCI_HFLAG_SRST_TOUT_IS_OFFLINE;
|
||||||
|
dev_info(&pdev->dev,
|
||||||
|
"online status unreliable, applying workaround\n");
|
||||||
|
}
|
||||||
|
|
||||||
/* CAP.NP sometimes indicate the index of the last enabled
|
/* CAP.NP sometimes indicate the index of the last enabled
|
||||||
* port, at other times, that of the last possible port, so
|
* port, at other times, that of the last possible port, so
|
||||||
* determining the maximum port number requires looking at
|
* determining the maximum port number requires looking at
|
||||||
|
|
|
@ -4302,6 +4302,9 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = {
|
||||||
{ "WDC WD2500JD-00HBB0", "WD-WMAL71490727", ATA_HORKAGE_BROKEN_HPA },
|
{ "WDC WD2500JD-00HBB0", "WD-WMAL71490727", ATA_HORKAGE_BROKEN_HPA },
|
||||||
{ "MAXTOR 6L080L4", "A93.0500", ATA_HORKAGE_BROKEN_HPA },
|
{ "MAXTOR 6L080L4", "A93.0500", ATA_HORKAGE_BROKEN_HPA },
|
||||||
|
|
||||||
|
/* this one allows HPA unlocking but fails IOs on the area */
|
||||||
|
{ "OCZ-VERTEX", "1.30", ATA_HORKAGE_BROKEN_HPA },
|
||||||
|
|
||||||
/* Devices which report 1 sector over size HPA */
|
/* Devices which report 1 sector over size HPA */
|
||||||
{ "ST340823A", NULL, ATA_HORKAGE_HPA_SIZE, },
|
{ "ST340823A", NULL, ATA_HORKAGE_HPA_SIZE, },
|
||||||
{ "ST320413A", NULL, ATA_HORKAGE_HPA_SIZE, },
|
{ "ST320413A", NULL, ATA_HORKAGE_HPA_SIZE, },
|
||||||
|
|
|
@ -250,7 +250,7 @@ static int __devinit pata_at91_probe(struct platform_device *pdev)
|
||||||
ata_port_desc(ap, "no IRQ, using PIO polling");
|
ata_port_desc(ap, "no IRQ, using PIO polling");
|
||||||
}
|
}
|
||||||
|
|
||||||
info = kzalloc(sizeof(*info), GFP_KERNEL);
|
info = devm_kzalloc(dev, sizeof(*info), GFP_KERNEL);
|
||||||
|
|
||||||
if (!info) {
|
if (!info) {
|
||||||
dev_err(dev, "failed to allocate memory for private data\n");
|
dev_err(dev, "failed to allocate memory for private data\n");
|
||||||
|
@ -275,7 +275,7 @@ static int __devinit pata_at91_probe(struct platform_device *pdev)
|
||||||
if (!info->ide_addr) {
|
if (!info->ide_addr) {
|
||||||
dev_err(dev, "failed to map IO base\n");
|
dev_err(dev, "failed to map IO base\n");
|
||||||
ret = -ENOMEM;
|
ret = -ENOMEM;
|
||||||
goto err_ide_ioremap;
|
goto err_put;
|
||||||
}
|
}
|
||||||
|
|
||||||
info->alt_addr = devm_ioremap(dev,
|
info->alt_addr = devm_ioremap(dev,
|
||||||
|
@ -284,7 +284,7 @@ static int __devinit pata_at91_probe(struct platform_device *pdev)
|
||||||
if (!info->alt_addr) {
|
if (!info->alt_addr) {
|
||||||
dev_err(dev, "failed to map CTL base\n");
|
dev_err(dev, "failed to map CTL base\n");
|
||||||
ret = -ENOMEM;
|
ret = -ENOMEM;
|
||||||
goto err_alt_ioremap;
|
goto err_put;
|
||||||
}
|
}
|
||||||
|
|
||||||
ap->ioaddr.cmd_addr = info->ide_addr;
|
ap->ioaddr.cmd_addr = info->ide_addr;
|
||||||
|
@ -303,13 +303,8 @@ static int __devinit pata_at91_probe(struct platform_device *pdev)
|
||||||
irq ? ata_sff_interrupt : NULL,
|
irq ? ata_sff_interrupt : NULL,
|
||||||
irq_flags, &pata_at91_sht);
|
irq_flags, &pata_at91_sht);
|
||||||
|
|
||||||
err_alt_ioremap:
|
err_put:
|
||||||
devm_iounmap(dev, info->ide_addr);
|
|
||||||
|
|
||||||
err_ide_ioremap:
|
|
||||||
clk_put(info->mck);
|
clk_put(info->mck);
|
||||||
kfree(info);
|
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -317,7 +312,6 @@ static int __devexit pata_at91_remove(struct platform_device *pdev)
|
||||||
{
|
{
|
||||||
struct ata_host *host = dev_get_drvdata(&pdev->dev);
|
struct ata_host *host = dev_get_drvdata(&pdev->dev);
|
||||||
struct at91_ide_info *info;
|
struct at91_ide_info *info;
|
||||||
struct device *dev = &pdev->dev;
|
|
||||||
|
|
||||||
if (!host)
|
if (!host)
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -328,11 +322,8 @@ static int __devexit pata_at91_remove(struct platform_device *pdev)
|
||||||
if (!info)
|
if (!info)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
devm_iounmap(dev, info->ide_addr);
|
|
||||||
devm_iounmap(dev, info->alt_addr);
|
|
||||||
clk_put(info->mck);
|
clk_put(info->mck);
|
||||||
|
|
||||||
kfree(info);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
/*
|
/*
|
||||||
* pata_atiixp.c - ATI PATA for new ATA layer
|
* pata_atiixp.c - ATI PATA for new ATA layer
|
||||||
* (C) 2005 Red Hat Inc
|
* (C) 2005 Red Hat Inc
|
||||||
|
* (C) 2009 Bartlomiej Zolnierkiewicz
|
||||||
*
|
*
|
||||||
* Based on
|
* Based on
|
||||||
*
|
*
|
||||||
|
@ -61,20 +62,19 @@ static void atiixp_set_pio_timing(struct ata_port *ap, struct ata_device *adev,
|
||||||
|
|
||||||
struct pci_dev *pdev = to_pci_dev(ap->host->dev);
|
struct pci_dev *pdev = to_pci_dev(ap->host->dev);
|
||||||
int dn = 2 * ap->port_no + adev->devno;
|
int dn = 2 * ap->port_no + adev->devno;
|
||||||
|
|
||||||
/* Check this is correct - the order is odd in both drivers */
|
|
||||||
int timing_shift = (16 * ap->port_no) + 8 * (adev->devno ^ 1);
|
int timing_shift = (16 * ap->port_no) + 8 * (adev->devno ^ 1);
|
||||||
u16 pio_mode_data, pio_timing_data;
|
u32 pio_timing_data;
|
||||||
|
u16 pio_mode_data;
|
||||||
|
|
||||||
pci_read_config_word(pdev, ATIIXP_IDE_PIO_MODE, &pio_mode_data);
|
pci_read_config_word(pdev, ATIIXP_IDE_PIO_MODE, &pio_mode_data);
|
||||||
pio_mode_data &= ~(0x7 << (4 * dn));
|
pio_mode_data &= ~(0x7 << (4 * dn));
|
||||||
pio_mode_data |= pio << (4 * dn);
|
pio_mode_data |= pio << (4 * dn);
|
||||||
pci_write_config_word(pdev, ATIIXP_IDE_PIO_MODE, pio_mode_data);
|
pci_write_config_word(pdev, ATIIXP_IDE_PIO_MODE, pio_mode_data);
|
||||||
|
|
||||||
pci_read_config_word(pdev, ATIIXP_IDE_PIO_TIMING, &pio_timing_data);
|
pci_read_config_dword(pdev, ATIIXP_IDE_PIO_TIMING, &pio_timing_data);
|
||||||
pio_timing_data &= ~(0xFF << timing_shift);
|
pio_timing_data &= ~(0xFF << timing_shift);
|
||||||
pio_timing_data |= (pio_timings[pio] << timing_shift);
|
pio_timing_data |= (pio_timings[pio] << timing_shift);
|
||||||
pci_write_config_word(pdev, ATIIXP_IDE_PIO_TIMING, pio_timing_data);
|
pci_write_config_dword(pdev, ATIIXP_IDE_PIO_TIMING, pio_timing_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -119,16 +119,17 @@ static void atiixp_set_dmamode(struct ata_port *ap, struct ata_device *adev)
|
||||||
udma_mode_data |= dma << (4 * dn);
|
udma_mode_data |= dma << (4 * dn);
|
||||||
pci_write_config_word(pdev, ATIIXP_IDE_UDMA_MODE, udma_mode_data);
|
pci_write_config_word(pdev, ATIIXP_IDE_UDMA_MODE, udma_mode_data);
|
||||||
} else {
|
} else {
|
||||||
u16 mwdma_timing_data;
|
|
||||||
/* Check this is correct - the order is odd in both drivers */
|
|
||||||
int timing_shift = (16 * ap->port_no) + 8 * (adev->devno ^ 1);
|
int timing_shift = (16 * ap->port_no) + 8 * (adev->devno ^ 1);
|
||||||
|
u32 mwdma_timing_data;
|
||||||
|
|
||||||
dma -= XFER_MW_DMA_0;
|
dma -= XFER_MW_DMA_0;
|
||||||
|
|
||||||
pci_read_config_word(pdev, ATIIXP_IDE_MWDMA_TIMING, &mwdma_timing_data);
|
pci_read_config_dword(pdev, ATIIXP_IDE_MWDMA_TIMING,
|
||||||
|
&mwdma_timing_data);
|
||||||
mwdma_timing_data &= ~(0xFF << timing_shift);
|
mwdma_timing_data &= ~(0xFF << timing_shift);
|
||||||
mwdma_timing_data |= (mwdma_timings[dma] << timing_shift);
|
mwdma_timing_data |= (mwdma_timings[dma] << timing_shift);
|
||||||
pci_write_config_word(pdev, ATIIXP_IDE_MWDMA_TIMING, mwdma_timing_data);
|
pci_write_config_dword(pdev, ATIIXP_IDE_MWDMA_TIMING,
|
||||||
|
mwdma_timing_data);
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
* We must now look at the PIO mode situation. We may need to
|
* We must now look at the PIO mode situation. We may need to
|
||||||
|
|
|
@ -602,6 +602,7 @@ MODULE_VERSION(DRV_VERSION);
|
||||||
|
|
||||||
static int adma_enabled;
|
static int adma_enabled;
|
||||||
static int swncq_enabled = 1;
|
static int swncq_enabled = 1;
|
||||||
|
static int msi_enabled;
|
||||||
|
|
||||||
static void nv_adma_register_mode(struct ata_port *ap)
|
static void nv_adma_register_mode(struct ata_port *ap)
|
||||||
{
|
{
|
||||||
|
@ -2459,6 +2460,11 @@ static int nv_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
|
||||||
} else if (type == SWNCQ)
|
} else if (type == SWNCQ)
|
||||||
nv_swncq_host_init(host);
|
nv_swncq_host_init(host);
|
||||||
|
|
||||||
|
if (msi_enabled) {
|
||||||
|
dev_printk(KERN_NOTICE, &pdev->dev, "Using MSI\n");
|
||||||
|
pci_enable_msi(pdev);
|
||||||
|
}
|
||||||
|
|
||||||
pci_set_master(pdev);
|
pci_set_master(pdev);
|
||||||
return ata_host_activate(host, pdev->irq, ipriv->irq_handler,
|
return ata_host_activate(host, pdev->irq, ipriv->irq_handler,
|
||||||
IRQF_SHARED, ipriv->sht);
|
IRQF_SHARED, ipriv->sht);
|
||||||
|
@ -2558,4 +2564,6 @@ module_param_named(adma, adma_enabled, bool, 0444);
|
||||||
MODULE_PARM_DESC(adma, "Enable use of ADMA (Default: false)");
|
MODULE_PARM_DESC(adma, "Enable use of ADMA (Default: false)");
|
||||||
module_param_named(swncq, swncq_enabled, bool, 0444);
|
module_param_named(swncq, swncq_enabled, bool, 0444);
|
||||||
MODULE_PARM_DESC(swncq, "Enable use of SWNCQ (Default: true)");
|
MODULE_PARM_DESC(swncq, "Enable use of SWNCQ (Default: true)");
|
||||||
|
module_param_named(msi, msi_enabled, bool, 0444);
|
||||||
|
MODULE_PARM_DESC(msi, "Enable use of MSI (Default: false)");
|
||||||
|
|
||||||
|
|
|
@ -483,9 +483,6 @@ int platform_driver_register(struct platform_driver *drv)
|
||||||
drv->driver.remove = platform_drv_remove;
|
drv->driver.remove = platform_drv_remove;
|
||||||
if (drv->shutdown)
|
if (drv->shutdown)
|
||||||
drv->driver.shutdown = platform_drv_shutdown;
|
drv->driver.shutdown = platform_drv_shutdown;
|
||||||
if (drv->suspend || drv->resume)
|
|
||||||
pr_warning("Platform driver '%s' needs updating - please use "
|
|
||||||
"dev_pm_ops\n", drv->driver.name);
|
|
||||||
|
|
||||||
return driver_register(&drv->driver);
|
return driver_register(&drv->driver);
|
||||||
}
|
}
|
||||||
|
|
|
@ -144,6 +144,8 @@ static int pty_write(struct tty_struct *tty, const unsigned char *buf,
|
||||||
|
|
||||||
static int pty_write_room(struct tty_struct *tty)
|
static int pty_write_room(struct tty_struct *tty)
|
||||||
{
|
{
|
||||||
|
if (tty->stopped)
|
||||||
|
return 0;
|
||||||
return pty_space(tty->link);
|
return pty_space(tty->link);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -566,7 +566,7 @@ int drm_wait_vblank(struct drm_device *dev, void *data,
|
||||||
|
|
||||||
ret = drm_vblank_get(dev, crtc);
|
ret = drm_vblank_get(dev, crtc);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
DRM_ERROR("failed to acquire vblank counter, %d\n", ret);
|
DRM_DEBUG("failed to acquire vblank counter, %d\n", ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
seq = drm_vblank_count(dev, crtc);
|
seq = drm_vblank_count(dev, crtc);
|
||||||
|
|
|
@ -566,6 +566,8 @@ void drm_mode_connector_list_update(struct drm_connector *connector)
|
||||||
found_it = 1;
|
found_it = 1;
|
||||||
/* if equal delete the probed mode */
|
/* if equal delete the probed mode */
|
||||||
mode->status = pmode->status;
|
mode->status = pmode->status;
|
||||||
|
/* Merge type bits together */
|
||||||
|
mode->type |= pmode->type;
|
||||||
list_del(&pmode->head);
|
list_del(&pmode->head);
|
||||||
drm_mode_destroy(connector->dev, pmode);
|
drm_mode_destroy(connector->dev, pmode);
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -190,7 +190,7 @@ u32 i915_get_vblank_counter(struct drm_device *dev, int pipe)
|
||||||
low_frame = pipe ? PIPEBFRAMEPIXEL : PIPEAFRAMEPIXEL;
|
low_frame = pipe ? PIPEBFRAMEPIXEL : PIPEAFRAMEPIXEL;
|
||||||
|
|
||||||
if (!i915_pipe_enabled(dev, pipe)) {
|
if (!i915_pipe_enabled(dev, pipe)) {
|
||||||
DRM_ERROR("trying to get vblank count for disabled pipe %d\n", pipe);
|
DRM_DEBUG("trying to get vblank count for disabled pipe %d\n", pipe);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -219,7 +219,7 @@ u32 gm45_get_vblank_counter(struct drm_device *dev, int pipe)
|
||||||
int reg = pipe ? PIPEB_FRMCOUNT_GM45 : PIPEA_FRMCOUNT_GM45;
|
int reg = pipe ? PIPEB_FRMCOUNT_GM45 : PIPEA_FRMCOUNT_GM45;
|
||||||
|
|
||||||
if (!i915_pipe_enabled(dev, pipe)) {
|
if (!i915_pipe_enabled(dev, pipe)) {
|
||||||
DRM_ERROR("trying to get vblank count for disabled pipe %d\n", pipe);
|
DRM_DEBUG("trying to get vblank count for disabled pipe %d\n", pipe);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -359,6 +359,7 @@ static mddev_t * mddev_find(dev_t unit)
|
||||||
else
|
else
|
||||||
new->md_minor = MINOR(unit) >> MdpMinorShift;
|
new->md_minor = MINOR(unit) >> MdpMinorShift;
|
||||||
|
|
||||||
|
mutex_init(&new->open_mutex);
|
||||||
mutex_init(&new->reconfig_mutex);
|
mutex_init(&new->reconfig_mutex);
|
||||||
INIT_LIST_HEAD(&new->disks);
|
INIT_LIST_HEAD(&new->disks);
|
||||||
INIT_LIST_HEAD(&new->all_mddevs);
|
INIT_LIST_HEAD(&new->all_mddevs);
|
||||||
|
@ -1974,17 +1975,14 @@ repeat:
|
||||||
/* otherwise we have to go forward and ... */
|
/* otherwise we have to go forward and ... */
|
||||||
mddev->events ++;
|
mddev->events ++;
|
||||||
if (!mddev->in_sync || mddev->recovery_cp != MaxSector) { /* not clean */
|
if (!mddev->in_sync || mddev->recovery_cp != MaxSector) { /* not clean */
|
||||||
/* .. if the array isn't clean, insist on an odd 'events' */
|
/* .. if the array isn't clean, an 'even' event must also go
|
||||||
if ((mddev->events&1)==0) {
|
* to spares. */
|
||||||
mddev->events++;
|
if ((mddev->events&1)==0)
|
||||||
nospares = 0;
|
nospares = 0;
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
/* otherwise insist on an even 'events' (for clean states) */
|
/* otherwise an 'odd' event must go to spares */
|
||||||
if ((mddev->events&1)) {
|
if ((mddev->events&1))
|
||||||
mddev->events++;
|
|
||||||
nospares = 0;
|
nospares = 0;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3601,6 +3599,7 @@ max_sync_store(mddev_t *mddev, const char *buf, size_t len)
|
||||||
if (max < mddev->resync_min)
|
if (max < mddev->resync_min)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
if (max < mddev->resync_max &&
|
if (max < mddev->resync_max &&
|
||||||
|
mddev->ro == 0 &&
|
||||||
test_bit(MD_RECOVERY_RUNNING, &mddev->recovery))
|
test_bit(MD_RECOVERY_RUNNING, &mddev->recovery))
|
||||||
return -EBUSY;
|
return -EBUSY;
|
||||||
|
|
||||||
|
@ -4304,12 +4303,11 @@ static int do_md_stop(mddev_t * mddev, int mode, int is_open)
|
||||||
struct gendisk *disk = mddev->gendisk;
|
struct gendisk *disk = mddev->gendisk;
|
||||||
mdk_rdev_t *rdev;
|
mdk_rdev_t *rdev;
|
||||||
|
|
||||||
|
mutex_lock(&mddev->open_mutex);
|
||||||
if (atomic_read(&mddev->openers) > is_open) {
|
if (atomic_read(&mddev->openers) > is_open) {
|
||||||
printk("md: %s still in use.\n",mdname(mddev));
|
printk("md: %s still in use.\n",mdname(mddev));
|
||||||
return -EBUSY;
|
err = -EBUSY;
|
||||||
}
|
} else if (mddev->pers) {
|
||||||
|
|
||||||
if (mddev->pers) {
|
|
||||||
|
|
||||||
if (mddev->sync_thread) {
|
if (mddev->sync_thread) {
|
||||||
set_bit(MD_RECOVERY_FROZEN, &mddev->recovery);
|
set_bit(MD_RECOVERY_FROZEN, &mddev->recovery);
|
||||||
|
@ -4367,7 +4365,10 @@ static int do_md_stop(mddev_t * mddev, int mode, int is_open)
|
||||||
set_disk_ro(disk, 1);
|
set_disk_ro(disk, 1);
|
||||||
clear_bit(MD_RECOVERY_FROZEN, &mddev->recovery);
|
clear_bit(MD_RECOVERY_FROZEN, &mddev->recovery);
|
||||||
}
|
}
|
||||||
|
out:
|
||||||
|
mutex_unlock(&mddev->open_mutex);
|
||||||
|
if (err)
|
||||||
|
return err;
|
||||||
/*
|
/*
|
||||||
* Free resources if final stop
|
* Free resources if final stop
|
||||||
*/
|
*/
|
||||||
|
@ -4433,7 +4434,6 @@ static int do_md_stop(mddev_t * mddev, int mode, int is_open)
|
||||||
blk_integrity_unregister(disk);
|
blk_integrity_unregister(disk);
|
||||||
md_new_event(mddev);
|
md_new_event(mddev);
|
||||||
sysfs_notify_dirent(mddev->sysfs_state);
|
sysfs_notify_dirent(mddev->sysfs_state);
|
||||||
out:
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5518,12 +5518,12 @@ static int md_open(struct block_device *bdev, fmode_t mode)
|
||||||
}
|
}
|
||||||
BUG_ON(mddev != bdev->bd_disk->private_data);
|
BUG_ON(mddev != bdev->bd_disk->private_data);
|
||||||
|
|
||||||
if ((err = mutex_lock_interruptible_nested(&mddev->reconfig_mutex, 1)))
|
if ((err = mutex_lock_interruptible(&mddev->open_mutex)))
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
err = 0;
|
err = 0;
|
||||||
atomic_inc(&mddev->openers);
|
atomic_inc(&mddev->openers);
|
||||||
mddev_unlock(mddev);
|
mutex_unlock(&mddev->open_mutex);
|
||||||
|
|
||||||
check_disk_change(bdev);
|
check_disk_change(bdev);
|
||||||
out:
|
out:
|
||||||
|
|
|
@ -223,6 +223,16 @@ struct mddev_s
|
||||||
* so we don't loop trying */
|
* so we don't loop trying */
|
||||||
|
|
||||||
int in_sync; /* know to not need resync */
|
int in_sync; /* know to not need resync */
|
||||||
|
/* 'open_mutex' avoids races between 'md_open' and 'do_md_stop', so
|
||||||
|
* that we are never stopping an array while it is open.
|
||||||
|
* 'reconfig_mutex' protects all other reconfiguration.
|
||||||
|
* These locks are separate due to conflicting interactions
|
||||||
|
* with bdev->bd_mutex.
|
||||||
|
* Lock ordering is:
|
||||||
|
* reconfig_mutex -> bd_mutex : e.g. do_md_run -> revalidate_disk
|
||||||
|
* bd_mutex -> open_mutex: e.g. __blkdev_get -> md_open
|
||||||
|
*/
|
||||||
|
struct mutex open_mutex;
|
||||||
struct mutex reconfig_mutex;
|
struct mutex reconfig_mutex;
|
||||||
atomic_t active; /* general refcount */
|
atomic_t active; /* general refcount */
|
||||||
atomic_t openers; /* number of active opens */
|
atomic_t openers; /* number of active opens */
|
||||||
|
|
|
@ -3785,7 +3785,7 @@ static sector_t reshape_request(mddev_t *mddev, sector_t sector_nr, int *skipped
|
||||||
conf->reshape_progress < raid5_size(mddev, 0, 0)) {
|
conf->reshape_progress < raid5_size(mddev, 0, 0)) {
|
||||||
sector_nr = raid5_size(mddev, 0, 0)
|
sector_nr = raid5_size(mddev, 0, 0)
|
||||||
- conf->reshape_progress;
|
- conf->reshape_progress;
|
||||||
} else if (mddev->delta_disks > 0 &&
|
} else if (mddev->delta_disks >= 0 &&
|
||||||
conf->reshape_progress > 0)
|
conf->reshape_progress > 0)
|
||||||
sector_nr = conf->reshape_progress;
|
sector_nr = conf->reshape_progress;
|
||||||
sector_div(sector_nr, new_data_disks);
|
sector_div(sector_nr, new_data_disks);
|
||||||
|
@ -4509,7 +4509,26 @@ static int run(mddev_t *mddev)
|
||||||
(old_disks-max_degraded));
|
(old_disks-max_degraded));
|
||||||
/* here_old is the first stripe that we might need to read
|
/* here_old is the first stripe that we might need to read
|
||||||
* from */
|
* from */
|
||||||
if (here_new >= here_old) {
|
if (mddev->delta_disks == 0) {
|
||||||
|
/* We cannot be sure it is safe to start an in-place
|
||||||
|
* reshape. It is only safe if user-space if monitoring
|
||||||
|
* and taking constant backups.
|
||||||
|
* mdadm always starts a situation like this in
|
||||||
|
* readonly mode so it can take control before
|
||||||
|
* allowing any writes. So just check for that.
|
||||||
|
*/
|
||||||
|
if ((here_new * mddev->new_chunk_sectors !=
|
||||||
|
here_old * mddev->chunk_sectors) ||
|
||||||
|
mddev->ro == 0) {
|
||||||
|
printk(KERN_ERR "raid5: in-place reshape must be started"
|
||||||
|
" in read-only mode - aborting\n");
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
} else if (mddev->delta_disks < 0
|
||||||
|
? (here_new * mddev->new_chunk_sectors <=
|
||||||
|
here_old * mddev->chunk_sectors)
|
||||||
|
: (here_new * mddev->new_chunk_sectors >=
|
||||||
|
here_old * mddev->chunk_sectors)) {
|
||||||
/* Reading from the same stripe as writing to - bad */
|
/* Reading from the same stripe as writing to - bad */
|
||||||
printk(KERN_ERR "raid5: reshape_position too early for "
|
printk(KERN_ERR "raid5: reshape_position too early for "
|
||||||
"auto-recovery - aborting.\n");
|
"auto-recovery - aborting.\n");
|
||||||
|
@ -5078,8 +5097,15 @@ static void raid5_finish_reshape(mddev_t *mddev)
|
||||||
mddev->degraded--;
|
mddev->degraded--;
|
||||||
for (d = conf->raid_disks ;
|
for (d = conf->raid_disks ;
|
||||||
d < conf->raid_disks - mddev->delta_disks;
|
d < conf->raid_disks - mddev->delta_disks;
|
||||||
d++)
|
d++) {
|
||||||
raid5_remove_disk(mddev, d);
|
mdk_rdev_t *rdev = conf->disks[d].rdev;
|
||||||
|
if (rdev && raid5_remove_disk(mddev, d) == 0) {
|
||||||
|
char nm[20];
|
||||||
|
sprintf(nm, "rd%d", rdev->raid_disk);
|
||||||
|
sysfs_remove_link(&mddev->kobj, nm);
|
||||||
|
rdev->raid_disk = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
mddev->layout = conf->algorithm;
|
mddev->layout = conf->algorithm;
|
||||||
mddev->chunk_sectors = conf->chunk_sectors;
|
mddev->chunk_sectors = conf->chunk_sectors;
|
||||||
|
|
|
@ -1254,6 +1254,7 @@ out_free:
|
||||||
if (!ubi->volumes[i])
|
if (!ubi->volumes[i])
|
||||||
continue;
|
continue;
|
||||||
kfree(ubi->volumes[i]->eba_tbl);
|
kfree(ubi->volumes[i]->eba_tbl);
|
||||||
|
ubi->volumes[i]->eba_tbl = NULL;
|
||||||
}
|
}
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
|
@ -781,11 +781,22 @@ static int process_eb(struct ubi_device *ubi, struct ubi_scan_info *si,
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Make sure that all PEBs have the same image sequence number.
|
||||||
|
* This allows us to detect situations when users flash UBI
|
||||||
|
* images incorrectly, so that the flash has the new UBI image
|
||||||
|
* and leftovers from the old one. This feature was added
|
||||||
|
* relatively recently, and the sequence number was always
|
||||||
|
* zero, because old UBI implementations always set it to zero.
|
||||||
|
* For this reasons, we do not panic if some PEBs have zero
|
||||||
|
* sequence number, while other PEBs have non-zero sequence
|
||||||
|
* number.
|
||||||
|
*/
|
||||||
image_seq = be32_to_cpu(ech->image_seq);
|
image_seq = be32_to_cpu(ech->image_seq);
|
||||||
if (!si->image_seq_set) {
|
if (!si->image_seq_set) {
|
||||||
ubi->image_seq = image_seq;
|
ubi->image_seq = image_seq;
|
||||||
si->image_seq_set = 1;
|
si->image_seq_set = 1;
|
||||||
} else if (ubi->image_seq != image_seq) {
|
} else if (ubi->image_seq && ubi->image_seq != image_seq) {
|
||||||
ubi_err("bad image sequence number %d in PEB %d, "
|
ubi_err("bad image sequence number %d in PEB %d, "
|
||||||
"expected %d", image_seq, pnum, ubi->image_seq);
|
"expected %d", image_seq, pnum, ubi->image_seq);
|
||||||
ubi_dbg_dump_ec_hdr(ech);
|
ubi_dbg_dump_ec_hdr(ech);
|
||||||
|
|
|
@ -90,11 +90,10 @@ static struct hotplug_slot_ops sn_hotplug_slot_ops = {
|
||||||
|
|
||||||
static DEFINE_MUTEX(sn_hotplug_mutex);
|
static DEFINE_MUTEX(sn_hotplug_mutex);
|
||||||
|
|
||||||
static ssize_t path_show (struct hotplug_slot *bss_hotplug_slot,
|
static ssize_t path_show(struct pci_slot *pci_slot, char *buf)
|
||||||
char *buf)
|
|
||||||
{
|
{
|
||||||
int retval = -ENOENT;
|
int retval = -ENOENT;
|
||||||
struct slot *slot = bss_hotplug_slot->private;
|
struct slot *slot = pci_slot->hotplug->private;
|
||||||
|
|
||||||
if (!slot)
|
if (!slot)
|
||||||
return retval;
|
return retval;
|
||||||
|
@ -103,7 +102,7 @@ static ssize_t path_show (struct hotplug_slot *bss_hotplug_slot,
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct hotplug_slot_attribute sn_slot_path_attr = __ATTR_RO(path);
|
static struct pci_slot_attribute sn_slot_path_attr = __ATTR_RO(path);
|
||||||
|
|
||||||
static int sn_pci_slot_valid(struct pci_bus *pci_bus, int device)
|
static int sn_pci_slot_valid(struct pci_bus *pci_bus, int device)
|
||||||
{
|
{
|
||||||
|
|
|
@ -255,7 +255,7 @@ static void nfs_direct_read_release(void *calldata)
|
||||||
|
|
||||||
if (put_dreq(dreq))
|
if (put_dreq(dreq))
|
||||||
nfs_direct_complete(dreq);
|
nfs_direct_complete(dreq);
|
||||||
nfs_readdata_release(calldata);
|
nfs_readdata_free(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct rpc_call_ops nfs_read_direct_ops = {
|
static const struct rpc_call_ops nfs_read_direct_ops = {
|
||||||
|
@ -314,14 +314,14 @@ static ssize_t nfs_direct_read_schedule_segment(struct nfs_direct_req *dreq,
|
||||||
data->npages, 1, 0, data->pagevec, NULL);
|
data->npages, 1, 0, data->pagevec, NULL);
|
||||||
up_read(¤t->mm->mmap_sem);
|
up_read(¤t->mm->mmap_sem);
|
||||||
if (result < 0) {
|
if (result < 0) {
|
||||||
nfs_readdata_release(data);
|
nfs_readdata_free(data);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if ((unsigned)result < data->npages) {
|
if ((unsigned)result < data->npages) {
|
||||||
bytes = result * PAGE_SIZE;
|
bytes = result * PAGE_SIZE;
|
||||||
if (bytes <= pgbase) {
|
if (bytes <= pgbase) {
|
||||||
nfs_direct_release_pages(data->pagevec, result);
|
nfs_direct_release_pages(data->pagevec, result);
|
||||||
nfs_readdata_release(data);
|
nfs_readdata_free(data);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
bytes -= pgbase;
|
bytes -= pgbase;
|
||||||
|
@ -334,7 +334,7 @@ static ssize_t nfs_direct_read_schedule_segment(struct nfs_direct_req *dreq,
|
||||||
data->inode = inode;
|
data->inode = inode;
|
||||||
data->cred = msg.rpc_cred;
|
data->cred = msg.rpc_cred;
|
||||||
data->args.fh = NFS_FH(inode);
|
data->args.fh = NFS_FH(inode);
|
||||||
data->args.context = get_nfs_open_context(ctx);
|
data->args.context = ctx;
|
||||||
data->args.offset = pos;
|
data->args.offset = pos;
|
||||||
data->args.pgbase = pgbase;
|
data->args.pgbase = pgbase;
|
||||||
data->args.pages = data->pagevec;
|
data->args.pages = data->pagevec;
|
||||||
|
@ -441,7 +441,7 @@ static void nfs_direct_free_writedata(struct nfs_direct_req *dreq)
|
||||||
struct nfs_write_data *data = list_entry(dreq->rewrite_list.next, struct nfs_write_data, pages);
|
struct nfs_write_data *data = list_entry(dreq->rewrite_list.next, struct nfs_write_data, pages);
|
||||||
list_del(&data->pages);
|
list_del(&data->pages);
|
||||||
nfs_direct_release_pages(data->pagevec, data->npages);
|
nfs_direct_release_pages(data->pagevec, data->npages);
|
||||||
nfs_writedata_release(data);
|
nfs_writedata_free(data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -534,7 +534,7 @@ static void nfs_direct_commit_release(void *calldata)
|
||||||
|
|
||||||
dprintk("NFS: %5u commit returned %d\n", data->task.tk_pid, status);
|
dprintk("NFS: %5u commit returned %d\n", data->task.tk_pid, status);
|
||||||
nfs_direct_write_complete(dreq, data->inode);
|
nfs_direct_write_complete(dreq, data->inode);
|
||||||
nfs_commitdata_release(calldata);
|
nfs_commit_free(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct rpc_call_ops nfs_commit_direct_ops = {
|
static const struct rpc_call_ops nfs_commit_direct_ops = {
|
||||||
|
@ -570,7 +570,7 @@ static void nfs_direct_commit_schedule(struct nfs_direct_req *dreq)
|
||||||
data->args.fh = NFS_FH(data->inode);
|
data->args.fh = NFS_FH(data->inode);
|
||||||
data->args.offset = 0;
|
data->args.offset = 0;
|
||||||
data->args.count = 0;
|
data->args.count = 0;
|
||||||
data->args.context = get_nfs_open_context(dreq->ctx);
|
data->args.context = dreq->ctx;
|
||||||
data->res.count = 0;
|
data->res.count = 0;
|
||||||
data->res.fattr = &data->fattr;
|
data->res.fattr = &data->fattr;
|
||||||
data->res.verf = &data->verf;
|
data->res.verf = &data->verf;
|
||||||
|
@ -734,14 +734,14 @@ static ssize_t nfs_direct_write_schedule_segment(struct nfs_direct_req *dreq,
|
||||||
data->npages, 0, 0, data->pagevec, NULL);
|
data->npages, 0, 0, data->pagevec, NULL);
|
||||||
up_read(¤t->mm->mmap_sem);
|
up_read(¤t->mm->mmap_sem);
|
||||||
if (result < 0) {
|
if (result < 0) {
|
||||||
nfs_writedata_release(data);
|
nfs_writedata_free(data);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if ((unsigned)result < data->npages) {
|
if ((unsigned)result < data->npages) {
|
||||||
bytes = result * PAGE_SIZE;
|
bytes = result * PAGE_SIZE;
|
||||||
if (bytes <= pgbase) {
|
if (bytes <= pgbase) {
|
||||||
nfs_direct_release_pages(data->pagevec, result);
|
nfs_direct_release_pages(data->pagevec, result);
|
||||||
nfs_writedata_release(data);
|
nfs_writedata_free(data);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
bytes -= pgbase;
|
bytes -= pgbase;
|
||||||
|
@ -756,7 +756,7 @@ static ssize_t nfs_direct_write_schedule_segment(struct nfs_direct_req *dreq,
|
||||||
data->inode = inode;
|
data->inode = inode;
|
||||||
data->cred = msg.rpc_cred;
|
data->cred = msg.rpc_cred;
|
||||||
data->args.fh = NFS_FH(inode);
|
data->args.fh = NFS_FH(inode);
|
||||||
data->args.context = get_nfs_open_context(ctx);
|
data->args.context = ctx;
|
||||||
data->args.offset = pos;
|
data->args.offset = pos;
|
||||||
data->args.pgbase = pgbase;
|
data->args.pgbase = pgbase;
|
||||||
data->args.pages = data->pagevec;
|
data->args.pages = data->pagevec;
|
||||||
|
|
|
@ -60,17 +60,15 @@ struct nfs_read_data *nfs_readdata_alloc(unsigned int pagecount)
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void nfs_readdata_free(struct nfs_read_data *p)
|
void nfs_readdata_free(struct nfs_read_data *p)
|
||||||
{
|
{
|
||||||
if (p && (p->pagevec != &p->page_array[0]))
|
if (p && (p->pagevec != &p->page_array[0]))
|
||||||
kfree(p->pagevec);
|
kfree(p->pagevec);
|
||||||
mempool_free(p, nfs_rdata_mempool);
|
mempool_free(p, nfs_rdata_mempool);
|
||||||
}
|
}
|
||||||
|
|
||||||
void nfs_readdata_release(void *data)
|
static void nfs_readdata_release(struct nfs_read_data *rdata)
|
||||||
{
|
{
|
||||||
struct nfs_read_data *rdata = data;
|
|
||||||
|
|
||||||
put_nfs_open_context(rdata->args.context);
|
put_nfs_open_context(rdata->args.context);
|
||||||
nfs_readdata_free(rdata);
|
nfs_readdata_free(rdata);
|
||||||
}
|
}
|
||||||
|
|
|
@ -87,17 +87,15 @@ struct nfs_write_data *nfs_writedata_alloc(unsigned int pagecount)
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void nfs_writedata_free(struct nfs_write_data *p)
|
void nfs_writedata_free(struct nfs_write_data *p)
|
||||||
{
|
{
|
||||||
if (p && (p->pagevec != &p->page_array[0]))
|
if (p && (p->pagevec != &p->page_array[0]))
|
||||||
kfree(p->pagevec);
|
kfree(p->pagevec);
|
||||||
mempool_free(p, nfs_wdata_mempool);
|
mempool_free(p, nfs_wdata_mempool);
|
||||||
}
|
}
|
||||||
|
|
||||||
void nfs_writedata_release(void *data)
|
static void nfs_writedata_release(struct nfs_write_data *wdata)
|
||||||
{
|
{
|
||||||
struct nfs_write_data *wdata = data;
|
|
||||||
|
|
||||||
put_nfs_open_context(wdata->args.context);
|
put_nfs_open_context(wdata->args.context);
|
||||||
nfs_writedata_free(wdata);
|
nfs_writedata_free(wdata);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1914,7 +1914,8 @@ static void ocfs2_adjust_adjacent_records(struct ocfs2_extent_rec *left_rec,
|
||||||
* immediately to their right.
|
* immediately to their right.
|
||||||
*/
|
*/
|
||||||
left_clusters = le32_to_cpu(right_child_el->l_recs[0].e_cpos);
|
left_clusters = le32_to_cpu(right_child_el->l_recs[0].e_cpos);
|
||||||
if (ocfs2_is_empty_extent(&right_child_el->l_recs[0])) {
|
if (!ocfs2_rec_clusters(right_child_el, &right_child_el->l_recs[0])) {
|
||||||
|
BUG_ON(right_child_el->l_tree_depth);
|
||||||
BUG_ON(le16_to_cpu(right_child_el->l_next_free_rec) <= 1);
|
BUG_ON(le16_to_cpu(right_child_el->l_next_free_rec) <= 1);
|
||||||
left_clusters = le32_to_cpu(right_child_el->l_recs[1].e_cpos);
|
left_clusters = le32_to_cpu(right_child_el->l_recs[1].e_cpos);
|
||||||
}
|
}
|
||||||
|
@ -2476,15 +2477,37 @@ out_ret_path:
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ocfs2_update_edge_lengths(struct inode *inode, handle_t *handle,
|
static int ocfs2_update_edge_lengths(struct inode *inode, handle_t *handle,
|
||||||
struct ocfs2_path *path)
|
int subtree_index, struct ocfs2_path *path)
|
||||||
{
|
{
|
||||||
int i, idx;
|
int i, idx, ret;
|
||||||
struct ocfs2_extent_rec *rec;
|
struct ocfs2_extent_rec *rec;
|
||||||
struct ocfs2_extent_list *el;
|
struct ocfs2_extent_list *el;
|
||||||
struct ocfs2_extent_block *eb;
|
struct ocfs2_extent_block *eb;
|
||||||
u32 range;
|
u32 range;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* In normal tree rotation process, we will never touch the
|
||||||
|
* tree branch above subtree_index and ocfs2_extend_rotate_transaction
|
||||||
|
* doesn't reserve the credits for them either.
|
||||||
|
*
|
||||||
|
* But we do have a special case here which will update the rightmost
|
||||||
|
* records for all the bh in the path.
|
||||||
|
* So we have to allocate extra credits and access them.
|
||||||
|
*/
|
||||||
|
ret = ocfs2_extend_trans(handle,
|
||||||
|
handle->h_buffer_credits + subtree_index);
|
||||||
|
if (ret) {
|
||||||
|
mlog_errno(ret);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = ocfs2_journal_access_path(inode, handle, path);
|
||||||
|
if (ret) {
|
||||||
|
mlog_errno(ret);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
/* Path should always be rightmost. */
|
/* Path should always be rightmost. */
|
||||||
eb = (struct ocfs2_extent_block *)path_leaf_bh(path)->b_data;
|
eb = (struct ocfs2_extent_block *)path_leaf_bh(path)->b_data;
|
||||||
BUG_ON(eb->h_next_leaf_blk != 0ULL);
|
BUG_ON(eb->h_next_leaf_blk != 0ULL);
|
||||||
|
@ -2505,6 +2528,8 @@ static void ocfs2_update_edge_lengths(struct inode *inode, handle_t *handle,
|
||||||
|
|
||||||
ocfs2_journal_dirty(handle, path->p_node[i].bh);
|
ocfs2_journal_dirty(handle, path->p_node[i].bh);
|
||||||
}
|
}
|
||||||
|
out:
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ocfs2_unlink_path(struct inode *inode, handle_t *handle,
|
static void ocfs2_unlink_path(struct inode *inode, handle_t *handle,
|
||||||
|
@ -2717,7 +2742,12 @@ static int ocfs2_rotate_subtree_left(struct inode *inode, handle_t *handle,
|
||||||
if (del_right_subtree) {
|
if (del_right_subtree) {
|
||||||
ocfs2_unlink_subtree(inode, handle, left_path, right_path,
|
ocfs2_unlink_subtree(inode, handle, left_path, right_path,
|
||||||
subtree_index, dealloc);
|
subtree_index, dealloc);
|
||||||
ocfs2_update_edge_lengths(inode, handle, left_path);
|
ret = ocfs2_update_edge_lengths(inode, handle, subtree_index,
|
||||||
|
left_path);
|
||||||
|
if (ret) {
|
||||||
|
mlog_errno(ret);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
eb = (struct ocfs2_extent_block *)path_leaf_bh(left_path)->b_data;
|
eb = (struct ocfs2_extent_block *)path_leaf_bh(left_path)->b_data;
|
||||||
ocfs2_et_set_last_eb_blk(et, le64_to_cpu(eb->h_blkno));
|
ocfs2_et_set_last_eb_blk(et, le64_to_cpu(eb->h_blkno));
|
||||||
|
@ -3034,7 +3064,12 @@ static int ocfs2_remove_rightmost_path(struct inode *inode, handle_t *handle,
|
||||||
|
|
||||||
ocfs2_unlink_subtree(inode, handle, left_path, path,
|
ocfs2_unlink_subtree(inode, handle, left_path, path,
|
||||||
subtree_index, dealloc);
|
subtree_index, dealloc);
|
||||||
ocfs2_update_edge_lengths(inode, handle, left_path);
|
ret = ocfs2_update_edge_lengths(inode, handle, subtree_index,
|
||||||
|
left_path);
|
||||||
|
if (ret) {
|
||||||
|
mlog_errno(ret);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
eb = (struct ocfs2_extent_block *)path_leaf_bh(left_path)->b_data;
|
eb = (struct ocfs2_extent_block *)path_leaf_bh(left_path)->b_data;
|
||||||
ocfs2_et_set_last_eb_blk(et, le64_to_cpu(eb->h_blkno));
|
ocfs2_et_set_last_eb_blk(et, le64_to_cpu(eb->h_blkno));
|
||||||
|
|
|
@ -193,6 +193,7 @@ static int ocfs2_get_block(struct inode *inode, sector_t iblock,
|
||||||
(unsigned long long)OCFS2_I(inode)->ip_blkno);
|
(unsigned long long)OCFS2_I(inode)->ip_blkno);
|
||||||
mlog(ML_ERROR, "Size %llu, clusters %u\n", (unsigned long long)i_size_read(inode), OCFS2_I(inode)->ip_clusters);
|
mlog(ML_ERROR, "Size %llu, clusters %u\n", (unsigned long long)i_size_read(inode), OCFS2_I(inode)->ip_clusters);
|
||||||
dump_stack();
|
dump_stack();
|
||||||
|
goto bail;
|
||||||
}
|
}
|
||||||
|
|
||||||
past_eof = ocfs2_blocks_for_bytes(inode->i_sb, i_size_read(inode));
|
past_eof = ocfs2_blocks_for_bytes(inode->i_sb, i_size_read(inode));
|
||||||
|
@ -894,18 +895,17 @@ struct ocfs2_write_cluster_desc {
|
||||||
*/
|
*/
|
||||||
unsigned c_new;
|
unsigned c_new;
|
||||||
unsigned c_unwritten;
|
unsigned c_unwritten;
|
||||||
|
unsigned c_needs_zero;
|
||||||
};
|
};
|
||||||
|
|
||||||
static inline int ocfs2_should_zero_cluster(struct ocfs2_write_cluster_desc *d)
|
|
||||||
{
|
|
||||||
return d->c_new || d->c_unwritten;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct ocfs2_write_ctxt {
|
struct ocfs2_write_ctxt {
|
||||||
/* Logical cluster position / len of write */
|
/* Logical cluster position / len of write */
|
||||||
u32 w_cpos;
|
u32 w_cpos;
|
||||||
u32 w_clen;
|
u32 w_clen;
|
||||||
|
|
||||||
|
/* First cluster allocated in a nonsparse extend */
|
||||||
|
u32 w_first_new_cpos;
|
||||||
|
|
||||||
struct ocfs2_write_cluster_desc w_desc[OCFS2_MAX_CLUSTERS_PER_PAGE];
|
struct ocfs2_write_cluster_desc w_desc[OCFS2_MAX_CLUSTERS_PER_PAGE];
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -983,6 +983,7 @@ static int ocfs2_alloc_write_ctxt(struct ocfs2_write_ctxt **wcp,
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
wc->w_cpos = pos >> osb->s_clustersize_bits;
|
wc->w_cpos = pos >> osb->s_clustersize_bits;
|
||||||
|
wc->w_first_new_cpos = UINT_MAX;
|
||||||
cend = (pos + len - 1) >> osb->s_clustersize_bits;
|
cend = (pos + len - 1) >> osb->s_clustersize_bits;
|
||||||
wc->w_clen = cend - wc->w_cpos + 1;
|
wc->w_clen = cend - wc->w_cpos + 1;
|
||||||
get_bh(di_bh);
|
get_bh(di_bh);
|
||||||
|
@ -1217,20 +1218,18 @@ out:
|
||||||
*/
|
*/
|
||||||
static int ocfs2_write_cluster(struct address_space *mapping,
|
static int ocfs2_write_cluster(struct address_space *mapping,
|
||||||
u32 phys, unsigned int unwritten,
|
u32 phys, unsigned int unwritten,
|
||||||
|
unsigned int should_zero,
|
||||||
struct ocfs2_alloc_context *data_ac,
|
struct ocfs2_alloc_context *data_ac,
|
||||||
struct ocfs2_alloc_context *meta_ac,
|
struct ocfs2_alloc_context *meta_ac,
|
||||||
struct ocfs2_write_ctxt *wc, u32 cpos,
|
struct ocfs2_write_ctxt *wc, u32 cpos,
|
||||||
loff_t user_pos, unsigned user_len)
|
loff_t user_pos, unsigned user_len)
|
||||||
{
|
{
|
||||||
int ret, i, new, should_zero = 0;
|
int ret, i, new;
|
||||||
u64 v_blkno, p_blkno;
|
u64 v_blkno, p_blkno;
|
||||||
struct inode *inode = mapping->host;
|
struct inode *inode = mapping->host;
|
||||||
struct ocfs2_extent_tree et;
|
struct ocfs2_extent_tree et;
|
||||||
|
|
||||||
new = phys == 0 ? 1 : 0;
|
new = phys == 0 ? 1 : 0;
|
||||||
if (new || unwritten)
|
|
||||||
should_zero = 1;
|
|
||||||
|
|
||||||
if (new) {
|
if (new) {
|
||||||
u32 tmp_pos;
|
u32 tmp_pos;
|
||||||
|
|
||||||
|
@ -1301,7 +1300,7 @@ static int ocfs2_write_cluster(struct address_space *mapping,
|
||||||
if (tmpret) {
|
if (tmpret) {
|
||||||
mlog_errno(tmpret);
|
mlog_errno(tmpret);
|
||||||
if (ret == 0)
|
if (ret == 0)
|
||||||
tmpret = ret;
|
ret = tmpret;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1341,7 +1340,9 @@ static int ocfs2_write_cluster_by_desc(struct address_space *mapping,
|
||||||
local_len = osb->s_clustersize - cluster_off;
|
local_len = osb->s_clustersize - cluster_off;
|
||||||
|
|
||||||
ret = ocfs2_write_cluster(mapping, desc->c_phys,
|
ret = ocfs2_write_cluster(mapping, desc->c_phys,
|
||||||
desc->c_unwritten, data_ac, meta_ac,
|
desc->c_unwritten,
|
||||||
|
desc->c_needs_zero,
|
||||||
|
data_ac, meta_ac,
|
||||||
wc, desc->c_cpos, pos, local_len);
|
wc, desc->c_cpos, pos, local_len);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
mlog_errno(ret);
|
mlog_errno(ret);
|
||||||
|
@ -1391,14 +1392,14 @@ static void ocfs2_set_target_boundaries(struct ocfs2_super *osb,
|
||||||
* newly allocated cluster.
|
* newly allocated cluster.
|
||||||
*/
|
*/
|
||||||
desc = &wc->w_desc[0];
|
desc = &wc->w_desc[0];
|
||||||
if (ocfs2_should_zero_cluster(desc))
|
if (desc->c_needs_zero)
|
||||||
ocfs2_figure_cluster_boundaries(osb,
|
ocfs2_figure_cluster_boundaries(osb,
|
||||||
desc->c_cpos,
|
desc->c_cpos,
|
||||||
&wc->w_target_from,
|
&wc->w_target_from,
|
||||||
NULL);
|
NULL);
|
||||||
|
|
||||||
desc = &wc->w_desc[wc->w_clen - 1];
|
desc = &wc->w_desc[wc->w_clen - 1];
|
||||||
if (ocfs2_should_zero_cluster(desc))
|
if (desc->c_needs_zero)
|
||||||
ocfs2_figure_cluster_boundaries(osb,
|
ocfs2_figure_cluster_boundaries(osb,
|
||||||
desc->c_cpos,
|
desc->c_cpos,
|
||||||
NULL,
|
NULL,
|
||||||
|
@ -1466,13 +1467,28 @@ static int ocfs2_populate_write_desc(struct inode *inode,
|
||||||
phys++;
|
phys++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If w_first_new_cpos is < UINT_MAX, we have a non-sparse
|
||||||
|
* file that got extended. w_first_new_cpos tells us
|
||||||
|
* where the newly allocated clusters are so we can
|
||||||
|
* zero them.
|
||||||
|
*/
|
||||||
|
if (desc->c_cpos >= wc->w_first_new_cpos) {
|
||||||
|
BUG_ON(phys == 0);
|
||||||
|
desc->c_needs_zero = 1;
|
||||||
|
}
|
||||||
|
|
||||||
desc->c_phys = phys;
|
desc->c_phys = phys;
|
||||||
if (phys == 0) {
|
if (phys == 0) {
|
||||||
desc->c_new = 1;
|
desc->c_new = 1;
|
||||||
|
desc->c_needs_zero = 1;
|
||||||
*clusters_to_alloc = *clusters_to_alloc + 1;
|
*clusters_to_alloc = *clusters_to_alloc + 1;
|
||||||
}
|
}
|
||||||
if (ext_flags & OCFS2_EXT_UNWRITTEN)
|
|
||||||
|
if (ext_flags & OCFS2_EXT_UNWRITTEN) {
|
||||||
desc->c_unwritten = 1;
|
desc->c_unwritten = 1;
|
||||||
|
desc->c_needs_zero = 1;
|
||||||
|
}
|
||||||
|
|
||||||
num_clusters--;
|
num_clusters--;
|
||||||
}
|
}
|
||||||
|
@ -1632,10 +1648,13 @@ static int ocfs2_expand_nonsparse_inode(struct inode *inode, loff_t pos,
|
||||||
if (newsize <= i_size_read(inode))
|
if (newsize <= i_size_read(inode))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
ret = ocfs2_extend_no_holes(inode, newsize, newsize - len);
|
ret = ocfs2_extend_no_holes(inode, newsize, pos);
|
||||||
if (ret)
|
if (ret)
|
||||||
mlog_errno(ret);
|
mlog_errno(ret);
|
||||||
|
|
||||||
|
wc->w_first_new_cpos =
|
||||||
|
ocfs2_clusters_for_bytes(inode->i_sb, i_size_read(inode));
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1644,7 +1663,7 @@ int ocfs2_write_begin_nolock(struct address_space *mapping,
|
||||||
struct page **pagep, void **fsdata,
|
struct page **pagep, void **fsdata,
|
||||||
struct buffer_head *di_bh, struct page *mmap_page)
|
struct buffer_head *di_bh, struct page *mmap_page)
|
||||||
{
|
{
|
||||||
int ret, credits = OCFS2_INODE_UPDATE_CREDITS;
|
int ret, cluster_of_pages, credits = OCFS2_INODE_UPDATE_CREDITS;
|
||||||
unsigned int clusters_to_alloc, extents_to_split;
|
unsigned int clusters_to_alloc, extents_to_split;
|
||||||
struct ocfs2_write_ctxt *wc;
|
struct ocfs2_write_ctxt *wc;
|
||||||
struct inode *inode = mapping->host;
|
struct inode *inode = mapping->host;
|
||||||
|
@ -1722,8 +1741,19 @@ int ocfs2_write_begin_nolock(struct address_space *mapping,
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ocfs2_set_target_boundaries(osb, wc, pos, len,
|
/*
|
||||||
clusters_to_alloc + extents_to_split);
|
* We have to zero sparse allocated clusters, unwritten extent clusters,
|
||||||
|
* and non-sparse clusters we just extended. For non-sparse writes,
|
||||||
|
* we know zeros will only be needed in the first and/or last cluster.
|
||||||
|
*/
|
||||||
|
if (clusters_to_alloc || extents_to_split ||
|
||||||
|
wc->w_desc[0].c_needs_zero ||
|
||||||
|
wc->w_desc[wc->w_clen - 1].c_needs_zero)
|
||||||
|
cluster_of_pages = 1;
|
||||||
|
else
|
||||||
|
cluster_of_pages = 0;
|
||||||
|
|
||||||
|
ocfs2_set_target_boundaries(osb, wc, pos, len, cluster_of_pages);
|
||||||
|
|
||||||
handle = ocfs2_start_trans(osb, credits);
|
handle = ocfs2_start_trans(osb, credits);
|
||||||
if (IS_ERR(handle)) {
|
if (IS_ERR(handle)) {
|
||||||
|
@ -1756,8 +1786,7 @@ int ocfs2_write_begin_nolock(struct address_space *mapping,
|
||||||
* extent.
|
* extent.
|
||||||
*/
|
*/
|
||||||
ret = ocfs2_grab_pages_for_write(mapping, wc, wc->w_cpos, pos,
|
ret = ocfs2_grab_pages_for_write(mapping, wc, wc->w_cpos, pos,
|
||||||
clusters_to_alloc + extents_to_split,
|
cluster_of_pages, mmap_page);
|
||||||
mmap_page);
|
|
||||||
if (ret) {
|
if (ret) {
|
||||||
mlog_errno(ret);
|
mlog_errno(ret);
|
||||||
goto out_quota;
|
goto out_quota;
|
||||||
|
|
|
@ -310,22 +310,19 @@ out_attach:
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static DEFINE_SPINLOCK(dentry_list_lock);
|
DEFINE_SPINLOCK(dentry_list_lock);
|
||||||
|
|
||||||
/* We limit the number of dentry locks to drop in one go. We have
|
/* We limit the number of dentry locks to drop in one go. We have
|
||||||
* this limit so that we don't starve other users of ocfs2_wq. */
|
* this limit so that we don't starve other users of ocfs2_wq. */
|
||||||
#define DL_INODE_DROP_COUNT 64
|
#define DL_INODE_DROP_COUNT 64
|
||||||
|
|
||||||
/* Drop inode references from dentry locks */
|
/* Drop inode references from dentry locks */
|
||||||
void ocfs2_drop_dl_inodes(struct work_struct *work)
|
static void __ocfs2_drop_dl_inodes(struct ocfs2_super *osb, int drop_count)
|
||||||
{
|
{
|
||||||
struct ocfs2_super *osb = container_of(work, struct ocfs2_super,
|
|
||||||
dentry_lock_work);
|
|
||||||
struct ocfs2_dentry_lock *dl;
|
struct ocfs2_dentry_lock *dl;
|
||||||
int drop_count = DL_INODE_DROP_COUNT;
|
|
||||||
|
|
||||||
spin_lock(&dentry_list_lock);
|
spin_lock(&dentry_list_lock);
|
||||||
while (osb->dentry_lock_list && drop_count--) {
|
while (osb->dentry_lock_list && (drop_count < 0 || drop_count--)) {
|
||||||
dl = osb->dentry_lock_list;
|
dl = osb->dentry_lock_list;
|
||||||
osb->dentry_lock_list = dl->dl_next;
|
osb->dentry_lock_list = dl->dl_next;
|
||||||
spin_unlock(&dentry_list_lock);
|
spin_unlock(&dentry_list_lock);
|
||||||
|
@ -333,11 +330,32 @@ void ocfs2_drop_dl_inodes(struct work_struct *work)
|
||||||
kfree(dl);
|
kfree(dl);
|
||||||
spin_lock(&dentry_list_lock);
|
spin_lock(&dentry_list_lock);
|
||||||
}
|
}
|
||||||
if (osb->dentry_lock_list)
|
spin_unlock(&dentry_list_lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ocfs2_drop_dl_inodes(struct work_struct *work)
|
||||||
|
{
|
||||||
|
struct ocfs2_super *osb = container_of(work, struct ocfs2_super,
|
||||||
|
dentry_lock_work);
|
||||||
|
|
||||||
|
__ocfs2_drop_dl_inodes(osb, DL_INODE_DROP_COUNT);
|
||||||
|
/*
|
||||||
|
* Don't queue dropping if umount is in progress. We flush the
|
||||||
|
* list in ocfs2_dismount_volume
|
||||||
|
*/
|
||||||
|
spin_lock(&dentry_list_lock);
|
||||||
|
if (osb->dentry_lock_list &&
|
||||||
|
!ocfs2_test_osb_flag(osb, OCFS2_OSB_DROP_DENTRY_LOCK_IMMED))
|
||||||
queue_work(ocfs2_wq, &osb->dentry_lock_work);
|
queue_work(ocfs2_wq, &osb->dentry_lock_work);
|
||||||
spin_unlock(&dentry_list_lock);
|
spin_unlock(&dentry_list_lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Flush the whole work queue */
|
||||||
|
void ocfs2_drop_all_dl_inodes(struct ocfs2_super *osb)
|
||||||
|
{
|
||||||
|
__ocfs2_drop_dl_inodes(osb, -1);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ocfs2_dentry_iput() and friends.
|
* ocfs2_dentry_iput() and friends.
|
||||||
*
|
*
|
||||||
|
@ -368,7 +386,8 @@ static void ocfs2_drop_dentry_lock(struct ocfs2_super *osb,
|
||||||
/* We leave dropping of inode reference to ocfs2_wq as that can
|
/* We leave dropping of inode reference to ocfs2_wq as that can
|
||||||
* possibly lead to inode deletion which gets tricky */
|
* possibly lead to inode deletion which gets tricky */
|
||||||
spin_lock(&dentry_list_lock);
|
spin_lock(&dentry_list_lock);
|
||||||
if (!osb->dentry_lock_list)
|
if (!osb->dentry_lock_list &&
|
||||||
|
!ocfs2_test_osb_flag(osb, OCFS2_OSB_DROP_DENTRY_LOCK_IMMED))
|
||||||
queue_work(ocfs2_wq, &osb->dentry_lock_work);
|
queue_work(ocfs2_wq, &osb->dentry_lock_work);
|
||||||
dl->dl_next = osb->dentry_lock_list;
|
dl->dl_next = osb->dentry_lock_list;
|
||||||
osb->dentry_lock_list = dl;
|
osb->dentry_lock_list = dl;
|
||||||
|
|
|
@ -49,10 +49,13 @@ struct ocfs2_dentry_lock {
|
||||||
int ocfs2_dentry_attach_lock(struct dentry *dentry, struct inode *inode,
|
int ocfs2_dentry_attach_lock(struct dentry *dentry, struct inode *inode,
|
||||||
u64 parent_blkno);
|
u64 parent_blkno);
|
||||||
|
|
||||||
|
extern spinlock_t dentry_list_lock;
|
||||||
|
|
||||||
void ocfs2_dentry_lock_put(struct ocfs2_super *osb,
|
void ocfs2_dentry_lock_put(struct ocfs2_super *osb,
|
||||||
struct ocfs2_dentry_lock *dl);
|
struct ocfs2_dentry_lock *dl);
|
||||||
|
|
||||||
void ocfs2_drop_dl_inodes(struct work_struct *work);
|
void ocfs2_drop_dl_inodes(struct work_struct *work);
|
||||||
|
void ocfs2_drop_all_dl_inodes(struct ocfs2_super *osb);
|
||||||
|
|
||||||
struct dentry *ocfs2_find_local_alias(struct inode *inode, u64 parent_blkno,
|
struct dentry *ocfs2_find_local_alias(struct inode *inode, u64 parent_blkno,
|
||||||
int skip_unhashed);
|
int skip_unhashed);
|
||||||
|
|
|
@ -103,7 +103,6 @@ static void __dlm_queue_ast(struct dlm_ctxt *dlm, struct dlm_lock *lock)
|
||||||
lock->ast_pending, lock->ml.type);
|
lock->ast_pending, lock->ml.type);
|
||||||
BUG();
|
BUG();
|
||||||
}
|
}
|
||||||
BUG_ON(!list_empty(&lock->ast_list));
|
|
||||||
if (lock->ast_pending)
|
if (lock->ast_pending)
|
||||||
mlog(0, "lock has an ast getting flushed right now\n");
|
mlog(0, "lock has an ast getting flushed right now\n");
|
||||||
|
|
||||||
|
|
|
@ -1118,7 +1118,7 @@ static int dlm_send_mig_lockres_msg(struct dlm_ctxt *dlm,
|
||||||
|
|
||||||
mlog(0, "%s:%.*s: sending mig lockres (%s) to %u\n",
|
mlog(0, "%s:%.*s: sending mig lockres (%s) to %u\n",
|
||||||
dlm->name, res->lockname.len, res->lockname.name,
|
dlm->name, res->lockname.len, res->lockname.name,
|
||||||
orig_flags & DLM_MRES_MIGRATION ? "migrate" : "recovery",
|
orig_flags & DLM_MRES_MIGRATION ? "migration" : "recovery",
|
||||||
send_to);
|
send_to);
|
||||||
|
|
||||||
/* send it */
|
/* send it */
|
||||||
|
|
|
@ -1851,6 +1851,7 @@ relock:
|
||||||
if (ret)
|
if (ret)
|
||||||
goto out_dio;
|
goto out_dio;
|
||||||
|
|
||||||
|
count = ocount;
|
||||||
ret = generic_write_checks(file, ppos, &count,
|
ret = generic_write_checks(file, ppos, &count,
|
||||||
S_ISBLK(inode->i_mode));
|
S_ISBLK(inode->i_mode));
|
||||||
if (ret)
|
if (ret)
|
||||||
|
@ -1918,8 +1919,10 @@ out_sems:
|
||||||
|
|
||||||
mutex_unlock(&inode->i_mutex);
|
mutex_unlock(&inode->i_mutex);
|
||||||
|
|
||||||
|
if (written)
|
||||||
|
ret = written;
|
||||||
mlog_exit(ret);
|
mlog_exit(ret);
|
||||||
return written ? written : ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ocfs2_splice_to_file(struct pipe_inode_info *pipe,
|
static int ocfs2_splice_to_file(struct pipe_inode_info *pipe,
|
||||||
|
|
|
@ -1954,10 +1954,16 @@ void ocfs2_orphan_scan_init(struct ocfs2_super *osb)
|
||||||
os->os_osb = osb;
|
os->os_osb = osb;
|
||||||
os->os_count = 0;
|
os->os_count = 0;
|
||||||
os->os_seqno = 0;
|
os->os_seqno = 0;
|
||||||
os->os_scantime = CURRENT_TIME;
|
|
||||||
mutex_init(&os->os_lock);
|
mutex_init(&os->os_lock);
|
||||||
INIT_DELAYED_WORK(&os->os_orphan_scan_work, ocfs2_orphan_scan_work);
|
INIT_DELAYED_WORK(&os->os_orphan_scan_work, ocfs2_orphan_scan_work);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ocfs2_orphan_scan_start(struct ocfs2_super *osb)
|
||||||
|
{
|
||||||
|
struct ocfs2_orphan_scan *os;
|
||||||
|
|
||||||
|
os = &osb->osb_orphan_scan;
|
||||||
|
os->os_scantime = CURRENT_TIME;
|
||||||
if (ocfs2_is_hard_readonly(osb) || ocfs2_mount_local(osb))
|
if (ocfs2_is_hard_readonly(osb) || ocfs2_mount_local(osb))
|
||||||
atomic_set(&os->os_state, ORPHAN_SCAN_INACTIVE);
|
atomic_set(&os->os_state, ORPHAN_SCAN_INACTIVE);
|
||||||
else {
|
else {
|
||||||
|
|
|
@ -145,6 +145,7 @@ static inline void ocfs2_inode_set_new(struct ocfs2_super *osb,
|
||||||
|
|
||||||
/* Exported only for the journal struct init code in super.c. Do not call. */
|
/* Exported only for the journal struct init code in super.c. Do not call. */
|
||||||
void ocfs2_orphan_scan_init(struct ocfs2_super *osb);
|
void ocfs2_orphan_scan_init(struct ocfs2_super *osb);
|
||||||
|
void ocfs2_orphan_scan_start(struct ocfs2_super *osb);
|
||||||
void ocfs2_orphan_scan_stop(struct ocfs2_super *osb);
|
void ocfs2_orphan_scan_stop(struct ocfs2_super *osb);
|
||||||
void ocfs2_orphan_scan_exit(struct ocfs2_super *osb);
|
void ocfs2_orphan_scan_exit(struct ocfs2_super *osb);
|
||||||
|
|
||||||
|
@ -329,20 +330,27 @@ int ocfs2_journal_dirty(handle_t *handle,
|
||||||
/* extended attribute block update */
|
/* extended attribute block update */
|
||||||
#define OCFS2_XATTR_BLOCK_UPDATE_CREDITS 1
|
#define OCFS2_XATTR_BLOCK_UPDATE_CREDITS 1
|
||||||
|
|
||||||
/* global quotafile inode update, data block */
|
/* Update of a single quota block */
|
||||||
#define OCFS2_QINFO_WRITE_CREDITS (OCFS2_INODE_UPDATE_CREDITS + 1)
|
#define OCFS2_QUOTA_BLOCK_UPDATE_CREDITS 1
|
||||||
|
|
||||||
|
/* global quotafile inode update, data block */
|
||||||
|
#define OCFS2_QINFO_WRITE_CREDITS (OCFS2_INODE_UPDATE_CREDITS + \
|
||||||
|
OCFS2_QUOTA_BLOCK_UPDATE_CREDITS)
|
||||||
|
|
||||||
|
#define OCFS2_LOCAL_QINFO_WRITE_CREDITS OCFS2_QUOTA_BLOCK_UPDATE_CREDITS
|
||||||
/*
|
/*
|
||||||
* The two writes below can accidentally see global info dirty due
|
* The two writes below can accidentally see global info dirty due
|
||||||
* to set_info() quotactl so make them prepared for the writes.
|
* to set_info() quotactl so make them prepared for the writes.
|
||||||
*/
|
*/
|
||||||
/* quota data block, global info */
|
/* quota data block, global info */
|
||||||
/* Write to local quota file */
|
/* Write to local quota file */
|
||||||
#define OCFS2_QWRITE_CREDITS (OCFS2_QINFO_WRITE_CREDITS + 1)
|
#define OCFS2_QWRITE_CREDITS (OCFS2_QINFO_WRITE_CREDITS + \
|
||||||
|
OCFS2_QUOTA_BLOCK_UPDATE_CREDITS)
|
||||||
|
|
||||||
/* global quota data block, local quota data block, global quota inode,
|
/* global quota data block, local quota data block, global quota inode,
|
||||||
* global quota info */
|
* global quota info */
|
||||||
#define OCFS2_QSYNC_CREDITS (OCFS2_INODE_UPDATE_CREDITS + 3)
|
#define OCFS2_QSYNC_CREDITS (OCFS2_QINFO_WRITE_CREDITS + \
|
||||||
|
2 * OCFS2_QUOTA_BLOCK_UPDATE_CREDITS)
|
||||||
|
|
||||||
static inline int ocfs2_quota_trans_credits(struct super_block *sb)
|
static inline int ocfs2_quota_trans_credits(struct super_block *sb)
|
||||||
{
|
{
|
||||||
|
@ -355,11 +363,6 @@ static inline int ocfs2_quota_trans_credits(struct super_block *sb)
|
||||||
return credits;
|
return credits;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Number of credits needed for removing quota structure from file */
|
|
||||||
int ocfs2_calc_qdel_credits(struct super_block *sb, int type);
|
|
||||||
/* Number of credits needed for initialization of new quota structure */
|
|
||||||
int ocfs2_calc_qinit_credits(struct super_block *sb, int type);
|
|
||||||
|
|
||||||
/* group extend. inode update and last group update. */
|
/* group extend. inode update and last group update. */
|
||||||
#define OCFS2_GROUP_EXTEND_CREDITS (OCFS2_INODE_UPDATE_CREDITS + 1)
|
#define OCFS2_GROUP_EXTEND_CREDITS (OCFS2_INODE_UPDATE_CREDITS + 1)
|
||||||
|
|
||||||
|
|
|
@ -224,10 +224,12 @@ enum ocfs2_mount_options
|
||||||
OCFS2_MOUNT_GRPQUOTA = 1 << 10, /* We support group quotas */
|
OCFS2_MOUNT_GRPQUOTA = 1 << 10, /* We support group quotas */
|
||||||
};
|
};
|
||||||
|
|
||||||
#define OCFS2_OSB_SOFT_RO 0x0001
|
#define OCFS2_OSB_SOFT_RO 0x0001
|
||||||
#define OCFS2_OSB_HARD_RO 0x0002
|
#define OCFS2_OSB_HARD_RO 0x0002
|
||||||
#define OCFS2_OSB_ERROR_FS 0x0004
|
#define OCFS2_OSB_ERROR_FS 0x0004
|
||||||
#define OCFS2_DEFAULT_ATIME_QUANTUM 60
|
#define OCFS2_OSB_DROP_DENTRY_LOCK_IMMED 0x0008
|
||||||
|
|
||||||
|
#define OCFS2_DEFAULT_ATIME_QUANTUM 60
|
||||||
|
|
||||||
struct ocfs2_journal;
|
struct ocfs2_journal;
|
||||||
struct ocfs2_slot_info;
|
struct ocfs2_slot_info;
|
||||||
|
@ -490,6 +492,18 @@ static inline void ocfs2_set_osb_flag(struct ocfs2_super *osb,
|
||||||
spin_unlock(&osb->osb_lock);
|
spin_unlock(&osb->osb_lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static inline unsigned long ocfs2_test_osb_flag(struct ocfs2_super *osb,
|
||||||
|
unsigned long flag)
|
||||||
|
{
|
||||||
|
unsigned long ret;
|
||||||
|
|
||||||
|
spin_lock(&osb->osb_lock);
|
||||||
|
ret = osb->osb_flags & flag;
|
||||||
|
spin_unlock(&osb->osb_lock);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
static inline void ocfs2_set_ro_flag(struct ocfs2_super *osb,
|
static inline void ocfs2_set_ro_flag(struct ocfs2_super *osb,
|
||||||
int hard)
|
int hard)
|
||||||
{
|
{
|
||||||
|
|
|
@ -50,7 +50,6 @@ struct ocfs2_mem_dqinfo {
|
||||||
unsigned int dqi_chunks; /* Number of chunks in local quota file */
|
unsigned int dqi_chunks; /* Number of chunks in local quota file */
|
||||||
unsigned int dqi_blocks; /* Number of blocks allocated for local quota file */
|
unsigned int dqi_blocks; /* Number of blocks allocated for local quota file */
|
||||||
unsigned int dqi_syncms; /* How often should we sync with other nodes */
|
unsigned int dqi_syncms; /* How often should we sync with other nodes */
|
||||||
unsigned int dqi_syncjiff; /* Precomputed dqi_syncms in jiffies */
|
|
||||||
struct list_head dqi_chunk; /* List of chunks */
|
struct list_head dqi_chunk; /* List of chunks */
|
||||||
struct inode *dqi_gqinode; /* Global quota file inode */
|
struct inode *dqi_gqinode; /* Global quota file inode */
|
||||||
struct ocfs2_lock_res dqi_gqlock; /* Lock protecting quota information structure */
|
struct ocfs2_lock_res dqi_gqlock; /* Lock protecting quota information structure */
|
||||||
|
|
|
@ -69,6 +69,7 @@ static void ocfs2_global_mem2diskdqb(void *dp, struct dquot *dquot)
|
||||||
d->dqb_curspace = cpu_to_le64(m->dqb_curspace);
|
d->dqb_curspace = cpu_to_le64(m->dqb_curspace);
|
||||||
d->dqb_btime = cpu_to_le64(m->dqb_btime);
|
d->dqb_btime = cpu_to_le64(m->dqb_btime);
|
||||||
d->dqb_itime = cpu_to_le64(m->dqb_itime);
|
d->dqb_itime = cpu_to_le64(m->dqb_itime);
|
||||||
|
d->dqb_pad1 = d->dqb_pad2 = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ocfs2_global_is_id(void *dp, struct dquot *dquot)
|
static int ocfs2_global_is_id(void *dp, struct dquot *dquot)
|
||||||
|
@ -211,14 +212,13 @@ ssize_t ocfs2_quota_write(struct super_block *sb, int type,
|
||||||
|
|
||||||
mutex_lock_nested(&gqinode->i_mutex, I_MUTEX_QUOTA);
|
mutex_lock_nested(&gqinode->i_mutex, I_MUTEX_QUOTA);
|
||||||
if (gqinode->i_size < off + len) {
|
if (gqinode->i_size < off + len) {
|
||||||
down_write(&OCFS2_I(gqinode)->ip_alloc_sem);
|
loff_t rounded_end =
|
||||||
err = ocfs2_extend_no_holes(gqinode, off + len, off);
|
ocfs2_align_bytes_to_blocks(sb, off + len);
|
||||||
up_write(&OCFS2_I(gqinode)->ip_alloc_sem);
|
|
||||||
if (err < 0)
|
/* Space is already allocated in ocfs2_global_read_dquot() */
|
||||||
goto out;
|
|
||||||
err = ocfs2_simple_size_update(gqinode,
|
err = ocfs2_simple_size_update(gqinode,
|
||||||
oinfo->dqi_gqi_bh,
|
oinfo->dqi_gqi_bh,
|
||||||
off + len);
|
rounded_end);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
goto out;
|
goto out;
|
||||||
new = 1;
|
new = 1;
|
||||||
|
@ -234,7 +234,7 @@ ssize_t ocfs2_quota_write(struct super_block *sb, int type,
|
||||||
}
|
}
|
||||||
if (err) {
|
if (err) {
|
||||||
mlog_errno(err);
|
mlog_errno(err);
|
||||||
return err;
|
goto out;
|
||||||
}
|
}
|
||||||
lock_buffer(bh);
|
lock_buffer(bh);
|
||||||
if (new)
|
if (new)
|
||||||
|
@ -342,7 +342,6 @@ int ocfs2_global_read_info(struct super_block *sb, int type)
|
||||||
info->dqi_bgrace = le32_to_cpu(dinfo.dqi_bgrace);
|
info->dqi_bgrace = le32_to_cpu(dinfo.dqi_bgrace);
|
||||||
info->dqi_igrace = le32_to_cpu(dinfo.dqi_igrace);
|
info->dqi_igrace = le32_to_cpu(dinfo.dqi_igrace);
|
||||||
oinfo->dqi_syncms = le32_to_cpu(dinfo.dqi_syncms);
|
oinfo->dqi_syncms = le32_to_cpu(dinfo.dqi_syncms);
|
||||||
oinfo->dqi_syncjiff = msecs_to_jiffies(oinfo->dqi_syncms);
|
|
||||||
oinfo->dqi_gi.dqi_blocks = le32_to_cpu(dinfo.dqi_blocks);
|
oinfo->dqi_gi.dqi_blocks = le32_to_cpu(dinfo.dqi_blocks);
|
||||||
oinfo->dqi_gi.dqi_free_blk = le32_to_cpu(dinfo.dqi_free_blk);
|
oinfo->dqi_gi.dqi_free_blk = le32_to_cpu(dinfo.dqi_free_blk);
|
||||||
oinfo->dqi_gi.dqi_free_entry = le32_to_cpu(dinfo.dqi_free_entry);
|
oinfo->dqi_gi.dqi_free_entry = le32_to_cpu(dinfo.dqi_free_entry);
|
||||||
|
@ -352,7 +351,7 @@ int ocfs2_global_read_info(struct super_block *sb, int type)
|
||||||
oinfo->dqi_gi.dqi_qtree_depth = qtree_depth(&oinfo->dqi_gi);
|
oinfo->dqi_gi.dqi_qtree_depth = qtree_depth(&oinfo->dqi_gi);
|
||||||
INIT_DELAYED_WORK(&oinfo->dqi_sync_work, qsync_work_fn);
|
INIT_DELAYED_WORK(&oinfo->dqi_sync_work, qsync_work_fn);
|
||||||
queue_delayed_work(ocfs2_quota_wq, &oinfo->dqi_sync_work,
|
queue_delayed_work(ocfs2_quota_wq, &oinfo->dqi_sync_work,
|
||||||
oinfo->dqi_syncjiff);
|
msecs_to_jiffies(oinfo->dqi_syncms));
|
||||||
|
|
||||||
out_err:
|
out_err:
|
||||||
mlog_exit(status);
|
mlog_exit(status);
|
||||||
|
@ -402,13 +401,36 @@ int ocfs2_global_write_info(struct super_block *sb, int type)
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int ocfs2_global_qinit_alloc(struct super_block *sb, int type)
|
||||||
|
{
|
||||||
|
struct ocfs2_mem_dqinfo *oinfo = sb_dqinfo(sb, type)->dqi_priv;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We may need to allocate tree blocks and a leaf block but not the
|
||||||
|
* root block
|
||||||
|
*/
|
||||||
|
return oinfo->dqi_gi.dqi_qtree_depth;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ocfs2_calc_global_qinit_credits(struct super_block *sb, int type)
|
||||||
|
{
|
||||||
|
/* We modify all the allocated blocks, tree root, and info block */
|
||||||
|
return (ocfs2_global_qinit_alloc(sb, type) + 2) *
|
||||||
|
OCFS2_QUOTA_BLOCK_UPDATE_CREDITS;
|
||||||
|
}
|
||||||
|
|
||||||
/* Read in information from global quota file and acquire a reference to it.
|
/* Read in information from global quota file and acquire a reference to it.
|
||||||
* dquot_acquire() has already started the transaction and locked quota file */
|
* dquot_acquire() has already started the transaction and locked quota file */
|
||||||
int ocfs2_global_read_dquot(struct dquot *dquot)
|
int ocfs2_global_read_dquot(struct dquot *dquot)
|
||||||
{
|
{
|
||||||
int err, err2, ex = 0;
|
int err, err2, ex = 0;
|
||||||
struct ocfs2_mem_dqinfo *info =
|
struct super_block *sb = dquot->dq_sb;
|
||||||
sb_dqinfo(dquot->dq_sb, dquot->dq_type)->dqi_priv;
|
int type = dquot->dq_type;
|
||||||
|
struct ocfs2_mem_dqinfo *info = sb_dqinfo(sb, type)->dqi_priv;
|
||||||
|
struct ocfs2_super *osb = OCFS2_SB(sb);
|
||||||
|
struct inode *gqinode = info->dqi_gqinode;
|
||||||
|
int need_alloc = ocfs2_global_qinit_alloc(sb, type);
|
||||||
|
handle_t *handle = NULL;
|
||||||
|
|
||||||
err = ocfs2_qinfo_lock(info, 0);
|
err = ocfs2_qinfo_lock(info, 0);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
|
@ -419,14 +441,33 @@ int ocfs2_global_read_dquot(struct dquot *dquot)
|
||||||
OCFS2_DQUOT(dquot)->dq_use_count++;
|
OCFS2_DQUOT(dquot)->dq_use_count++;
|
||||||
OCFS2_DQUOT(dquot)->dq_origspace = dquot->dq_dqb.dqb_curspace;
|
OCFS2_DQUOT(dquot)->dq_origspace = dquot->dq_dqb.dqb_curspace;
|
||||||
OCFS2_DQUOT(dquot)->dq_originodes = dquot->dq_dqb.dqb_curinodes;
|
OCFS2_DQUOT(dquot)->dq_originodes = dquot->dq_dqb.dqb_curinodes;
|
||||||
|
ocfs2_qinfo_unlock(info, 0);
|
||||||
|
|
||||||
if (!dquot->dq_off) { /* No real quota entry? */
|
if (!dquot->dq_off) { /* No real quota entry? */
|
||||||
/* Upgrade to exclusive lock for allocation */
|
|
||||||
ocfs2_qinfo_unlock(info, 0);
|
|
||||||
err = ocfs2_qinfo_lock(info, 1);
|
|
||||||
if (err < 0)
|
|
||||||
goto out_qlock;
|
|
||||||
ex = 1;
|
ex = 1;
|
||||||
|
/*
|
||||||
|
* Add blocks to quota file before we start a transaction since
|
||||||
|
* locking allocators ranks above a transaction start
|
||||||
|
*/
|
||||||
|
WARN_ON(journal_current_handle());
|
||||||
|
down_write(&OCFS2_I(gqinode)->ip_alloc_sem);
|
||||||
|
err = ocfs2_extend_no_holes(gqinode,
|
||||||
|
gqinode->i_size + (need_alloc << sb->s_blocksize_bits),
|
||||||
|
gqinode->i_size);
|
||||||
|
up_write(&OCFS2_I(gqinode)->ip_alloc_sem);
|
||||||
|
if (err < 0)
|
||||||
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
handle = ocfs2_start_trans(osb,
|
||||||
|
ocfs2_calc_global_qinit_credits(sb, type));
|
||||||
|
if (IS_ERR(handle)) {
|
||||||
|
err = PTR_ERR(handle);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
err = ocfs2_qinfo_lock(info, ex);
|
||||||
|
if (err < 0)
|
||||||
|
goto out_trans;
|
||||||
err = qtree_write_dquot(&info->dqi_gi, dquot);
|
err = qtree_write_dquot(&info->dqi_gi, dquot);
|
||||||
if (ex && info_dirty(sb_dqinfo(dquot->dq_sb, dquot->dq_type))) {
|
if (ex && info_dirty(sb_dqinfo(dquot->dq_sb, dquot->dq_type))) {
|
||||||
err2 = __ocfs2_global_write_info(dquot->dq_sb, dquot->dq_type);
|
err2 = __ocfs2_global_write_info(dquot->dq_sb, dquot->dq_type);
|
||||||
|
@ -438,6 +479,9 @@ out_qlock:
|
||||||
ocfs2_qinfo_unlock(info, 1);
|
ocfs2_qinfo_unlock(info, 1);
|
||||||
else
|
else
|
||||||
ocfs2_qinfo_unlock(info, 0);
|
ocfs2_qinfo_unlock(info, 0);
|
||||||
|
out_trans:
|
||||||
|
if (handle)
|
||||||
|
ocfs2_commit_trans(osb, handle);
|
||||||
out:
|
out:
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
mlog_errno(err);
|
mlog_errno(err);
|
||||||
|
@ -607,7 +651,7 @@ static void qsync_work_fn(struct work_struct *work)
|
||||||
|
|
||||||
dquot_scan_active(sb, ocfs2_sync_dquot_helper, oinfo->dqi_type);
|
dquot_scan_active(sb, ocfs2_sync_dquot_helper, oinfo->dqi_type);
|
||||||
queue_delayed_work(ocfs2_quota_wq, &oinfo->dqi_sync_work,
|
queue_delayed_work(ocfs2_quota_wq, &oinfo->dqi_sync_work,
|
||||||
oinfo->dqi_syncjiff);
|
msecs_to_jiffies(oinfo->dqi_syncms));
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -635,20 +679,18 @@ out:
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
int ocfs2_calc_qdel_credits(struct super_block *sb, int type)
|
static int ocfs2_calc_qdel_credits(struct super_block *sb, int type)
|
||||||
{
|
{
|
||||||
struct ocfs2_mem_dqinfo *oinfo;
|
struct ocfs2_mem_dqinfo *oinfo = sb_dqinfo(sb, type)->dqi_priv;
|
||||||
int features[MAXQUOTAS] = { OCFS2_FEATURE_RO_COMPAT_USRQUOTA,
|
/*
|
||||||
OCFS2_FEATURE_RO_COMPAT_GRPQUOTA };
|
* We modify tree, leaf block, global info, local chunk header,
|
||||||
|
* global and local inode; OCFS2_QINFO_WRITE_CREDITS already
|
||||||
if (!OCFS2_HAS_RO_COMPAT_FEATURE(sb, features[type]))
|
* accounts for inode update
|
||||||
return 0;
|
*/
|
||||||
|
return (oinfo->dqi_gi.dqi_qtree_depth + 2) *
|
||||||
oinfo = sb_dqinfo(sb, type)->dqi_priv;
|
OCFS2_QUOTA_BLOCK_UPDATE_CREDITS +
|
||||||
/* We modify tree, leaf block, global info, local chunk header,
|
OCFS2_QINFO_WRITE_CREDITS +
|
||||||
* global and local inode */
|
OCFS2_INODE_UPDATE_CREDITS;
|
||||||
return oinfo->dqi_gi.dqi_qtree_depth + 2 + 1 +
|
|
||||||
2 * OCFS2_INODE_UPDATE_CREDITS;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ocfs2_release_dquot(struct dquot *dquot)
|
static int ocfs2_release_dquot(struct dquot *dquot)
|
||||||
|
@ -680,33 +722,10 @@ out:
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
int ocfs2_calc_qinit_credits(struct super_block *sb, int type)
|
|
||||||
{
|
|
||||||
struct ocfs2_mem_dqinfo *oinfo;
|
|
||||||
int features[MAXQUOTAS] = { OCFS2_FEATURE_RO_COMPAT_USRQUOTA,
|
|
||||||
OCFS2_FEATURE_RO_COMPAT_GRPQUOTA };
|
|
||||||
struct ocfs2_dinode *lfe, *gfe;
|
|
||||||
|
|
||||||
if (!OCFS2_HAS_RO_COMPAT_FEATURE(sb, features[type]))
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
oinfo = sb_dqinfo(sb, type)->dqi_priv;
|
|
||||||
gfe = (struct ocfs2_dinode *)oinfo->dqi_gqi_bh->b_data;
|
|
||||||
lfe = (struct ocfs2_dinode *)oinfo->dqi_lqi_bh->b_data;
|
|
||||||
/* We can extend local file + global file. In local file we
|
|
||||||
* can modify info, chunk header block and dquot block. In
|
|
||||||
* global file we can modify info, tree and leaf block */
|
|
||||||
return ocfs2_calc_extend_credits(sb, &lfe->id2.i_list, 0) +
|
|
||||||
ocfs2_calc_extend_credits(sb, &gfe->id2.i_list, 0) +
|
|
||||||
3 + oinfo->dqi_gi.dqi_qtree_depth + 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int ocfs2_acquire_dquot(struct dquot *dquot)
|
static int ocfs2_acquire_dquot(struct dquot *dquot)
|
||||||
{
|
{
|
||||||
handle_t *handle;
|
|
||||||
struct ocfs2_mem_dqinfo *oinfo =
|
struct ocfs2_mem_dqinfo *oinfo =
|
||||||
sb_dqinfo(dquot->dq_sb, dquot->dq_type)->dqi_priv;
|
sb_dqinfo(dquot->dq_sb, dquot->dq_type)->dqi_priv;
|
||||||
struct ocfs2_super *osb = OCFS2_SB(dquot->dq_sb);
|
|
||||||
int status = 0;
|
int status = 0;
|
||||||
|
|
||||||
mlog_entry("id=%u, type=%d", dquot->dq_id, dquot->dq_type);
|
mlog_entry("id=%u, type=%d", dquot->dq_id, dquot->dq_type);
|
||||||
|
@ -715,16 +734,7 @@ static int ocfs2_acquire_dquot(struct dquot *dquot)
|
||||||
status = ocfs2_lock_global_qf(oinfo, 1);
|
status = ocfs2_lock_global_qf(oinfo, 1);
|
||||||
if (status < 0)
|
if (status < 0)
|
||||||
goto out;
|
goto out;
|
||||||
handle = ocfs2_start_trans(osb,
|
|
||||||
ocfs2_calc_qinit_credits(dquot->dq_sb, dquot->dq_type));
|
|
||||||
if (IS_ERR(handle)) {
|
|
||||||
status = PTR_ERR(handle);
|
|
||||||
mlog_errno(status);
|
|
||||||
goto out_ilock;
|
|
||||||
}
|
|
||||||
status = dquot_acquire(dquot);
|
status = dquot_acquire(dquot);
|
||||||
ocfs2_commit_trans(osb, handle);
|
|
||||||
out_ilock:
|
|
||||||
ocfs2_unlock_global_qf(oinfo, 1);
|
ocfs2_unlock_global_qf(oinfo, 1);
|
||||||
out:
|
out:
|
||||||
mlog_exit(status);
|
mlog_exit(status);
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
#include "sysfile.h"
|
#include "sysfile.h"
|
||||||
#include "dlmglue.h"
|
#include "dlmglue.h"
|
||||||
#include "quota.h"
|
#include "quota.h"
|
||||||
|
#include "uptodate.h"
|
||||||
|
|
||||||
/* Number of local quota structures per block */
|
/* Number of local quota structures per block */
|
||||||
static inline unsigned int ol_quota_entries_per_block(struct super_block *sb)
|
static inline unsigned int ol_quota_entries_per_block(struct super_block *sb)
|
||||||
|
@ -100,7 +101,8 @@ static int ocfs2_modify_bh(struct inode *inode, struct buffer_head *bh,
|
||||||
handle_t *handle;
|
handle_t *handle;
|
||||||
int status;
|
int status;
|
||||||
|
|
||||||
handle = ocfs2_start_trans(OCFS2_SB(sb), 1);
|
handle = ocfs2_start_trans(OCFS2_SB(sb),
|
||||||
|
OCFS2_QUOTA_BLOCK_UPDATE_CREDITS);
|
||||||
if (IS_ERR(handle)) {
|
if (IS_ERR(handle)) {
|
||||||
status = PTR_ERR(handle);
|
status = PTR_ERR(handle);
|
||||||
mlog_errno(status);
|
mlog_errno(status);
|
||||||
|
@ -610,7 +612,8 @@ int ocfs2_finish_quota_recovery(struct ocfs2_super *osb,
|
||||||
goto out_bh;
|
goto out_bh;
|
||||||
/* Mark quota file as clean if we are recovering quota file of
|
/* Mark quota file as clean if we are recovering quota file of
|
||||||
* some other node. */
|
* some other node. */
|
||||||
handle = ocfs2_start_trans(osb, 1);
|
handle = ocfs2_start_trans(osb,
|
||||||
|
OCFS2_LOCAL_QINFO_WRITE_CREDITS);
|
||||||
if (IS_ERR(handle)) {
|
if (IS_ERR(handle)) {
|
||||||
status = PTR_ERR(handle);
|
status = PTR_ERR(handle);
|
||||||
mlog_errno(status);
|
mlog_errno(status);
|
||||||
|
@ -940,7 +943,7 @@ static struct ocfs2_quota_chunk *ocfs2_local_quota_add_chunk(
|
||||||
struct ocfs2_local_disk_chunk *dchunk;
|
struct ocfs2_local_disk_chunk *dchunk;
|
||||||
int status;
|
int status;
|
||||||
handle_t *handle;
|
handle_t *handle;
|
||||||
struct buffer_head *bh = NULL;
|
struct buffer_head *bh = NULL, *dbh = NULL;
|
||||||
u64 p_blkno;
|
u64 p_blkno;
|
||||||
|
|
||||||
/* We are protected by dqio_sem so no locking needed */
|
/* We are protected by dqio_sem so no locking needed */
|
||||||
|
@ -964,32 +967,35 @@ static struct ocfs2_quota_chunk *ocfs2_local_quota_add_chunk(
|
||||||
mlog_errno(status);
|
mlog_errno(status);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
/* Local quota info and two new blocks we initialize */
|
||||||
down_read(&OCFS2_I(lqinode)->ip_alloc_sem);
|
handle = ocfs2_start_trans(OCFS2_SB(sb),
|
||||||
status = ocfs2_extent_map_get_blocks(lqinode, oinfo->dqi_blocks,
|
OCFS2_LOCAL_QINFO_WRITE_CREDITS +
|
||||||
&p_blkno, NULL, NULL);
|
2 * OCFS2_QUOTA_BLOCK_UPDATE_CREDITS);
|
||||||
up_read(&OCFS2_I(lqinode)->ip_alloc_sem);
|
|
||||||
if (status < 0) {
|
|
||||||
mlog_errno(status);
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
bh = sb_getblk(sb, p_blkno);
|
|
||||||
if (!bh) {
|
|
||||||
status = -ENOMEM;
|
|
||||||
mlog_errno(status);
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
dchunk = (struct ocfs2_local_disk_chunk *)bh->b_data;
|
|
||||||
|
|
||||||
handle = ocfs2_start_trans(OCFS2_SB(sb), 2);
|
|
||||||
if (IS_ERR(handle)) {
|
if (IS_ERR(handle)) {
|
||||||
status = PTR_ERR(handle);
|
status = PTR_ERR(handle);
|
||||||
mlog_errno(status);
|
mlog_errno(status);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Initialize chunk header */
|
||||||
|
down_read(&OCFS2_I(lqinode)->ip_alloc_sem);
|
||||||
|
status = ocfs2_extent_map_get_blocks(lqinode, oinfo->dqi_blocks,
|
||||||
|
&p_blkno, NULL, NULL);
|
||||||
|
up_read(&OCFS2_I(lqinode)->ip_alloc_sem);
|
||||||
|
if (status < 0) {
|
||||||
|
mlog_errno(status);
|
||||||
|
goto out_trans;
|
||||||
|
}
|
||||||
|
bh = sb_getblk(sb, p_blkno);
|
||||||
|
if (!bh) {
|
||||||
|
status = -ENOMEM;
|
||||||
|
mlog_errno(status);
|
||||||
|
goto out_trans;
|
||||||
|
}
|
||||||
|
dchunk = (struct ocfs2_local_disk_chunk *)bh->b_data;
|
||||||
|
ocfs2_set_new_buffer_uptodate(lqinode, bh);
|
||||||
status = ocfs2_journal_access_dq(handle, lqinode, bh,
|
status = ocfs2_journal_access_dq(handle, lqinode, bh,
|
||||||
OCFS2_JOURNAL_ACCESS_WRITE);
|
OCFS2_JOURNAL_ACCESS_CREATE);
|
||||||
if (status < 0) {
|
if (status < 0) {
|
||||||
mlog_errno(status);
|
mlog_errno(status);
|
||||||
goto out_trans;
|
goto out_trans;
|
||||||
|
@ -999,7 +1005,6 @@ static struct ocfs2_quota_chunk *ocfs2_local_quota_add_chunk(
|
||||||
memset(dchunk->dqc_bitmap, 0,
|
memset(dchunk->dqc_bitmap, 0,
|
||||||
sb->s_blocksize - sizeof(struct ocfs2_local_disk_chunk) -
|
sb->s_blocksize - sizeof(struct ocfs2_local_disk_chunk) -
|
||||||
OCFS2_QBLK_RESERVED_SPACE);
|
OCFS2_QBLK_RESERVED_SPACE);
|
||||||
set_buffer_uptodate(bh);
|
|
||||||
unlock_buffer(bh);
|
unlock_buffer(bh);
|
||||||
status = ocfs2_journal_dirty(handle, bh);
|
status = ocfs2_journal_dirty(handle, bh);
|
||||||
if (status < 0) {
|
if (status < 0) {
|
||||||
|
@ -1007,6 +1012,38 @@ static struct ocfs2_quota_chunk *ocfs2_local_quota_add_chunk(
|
||||||
goto out_trans;
|
goto out_trans;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Initialize new block with structures */
|
||||||
|
down_read(&OCFS2_I(lqinode)->ip_alloc_sem);
|
||||||
|
status = ocfs2_extent_map_get_blocks(lqinode, oinfo->dqi_blocks + 1,
|
||||||
|
&p_blkno, NULL, NULL);
|
||||||
|
up_read(&OCFS2_I(lqinode)->ip_alloc_sem);
|
||||||
|
if (status < 0) {
|
||||||
|
mlog_errno(status);
|
||||||
|
goto out_trans;
|
||||||
|
}
|
||||||
|
dbh = sb_getblk(sb, p_blkno);
|
||||||
|
if (!dbh) {
|
||||||
|
status = -ENOMEM;
|
||||||
|
mlog_errno(status);
|
||||||
|
goto out_trans;
|
||||||
|
}
|
||||||
|
ocfs2_set_new_buffer_uptodate(lqinode, dbh);
|
||||||
|
status = ocfs2_journal_access_dq(handle, lqinode, dbh,
|
||||||
|
OCFS2_JOURNAL_ACCESS_CREATE);
|
||||||
|
if (status < 0) {
|
||||||
|
mlog_errno(status);
|
||||||
|
goto out_trans;
|
||||||
|
}
|
||||||
|
lock_buffer(dbh);
|
||||||
|
memset(dbh->b_data, 0, sb->s_blocksize - OCFS2_QBLK_RESERVED_SPACE);
|
||||||
|
unlock_buffer(dbh);
|
||||||
|
status = ocfs2_journal_dirty(handle, dbh);
|
||||||
|
if (status < 0) {
|
||||||
|
mlog_errno(status);
|
||||||
|
goto out_trans;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Update local quotafile info */
|
||||||
oinfo->dqi_blocks += 2;
|
oinfo->dqi_blocks += 2;
|
||||||
oinfo->dqi_chunks++;
|
oinfo->dqi_chunks++;
|
||||||
status = ocfs2_local_write_info(sb, type);
|
status = ocfs2_local_write_info(sb, type);
|
||||||
|
@ -1031,6 +1068,7 @@ out_trans:
|
||||||
ocfs2_commit_trans(OCFS2_SB(sb), handle);
|
ocfs2_commit_trans(OCFS2_SB(sb), handle);
|
||||||
out:
|
out:
|
||||||
brelse(bh);
|
brelse(bh);
|
||||||
|
brelse(dbh);
|
||||||
kmem_cache_free(ocfs2_qf_chunk_cachep, chunk);
|
kmem_cache_free(ocfs2_qf_chunk_cachep, chunk);
|
||||||
return ERR_PTR(status);
|
return ERR_PTR(status);
|
||||||
}
|
}
|
||||||
|
@ -1048,6 +1086,8 @@ static struct ocfs2_quota_chunk *ocfs2_extend_local_quota_file(
|
||||||
struct ocfs2_local_disk_chunk *dchunk;
|
struct ocfs2_local_disk_chunk *dchunk;
|
||||||
int epb = ol_quota_entries_per_block(sb);
|
int epb = ol_quota_entries_per_block(sb);
|
||||||
unsigned int chunk_blocks;
|
unsigned int chunk_blocks;
|
||||||
|
struct buffer_head *bh;
|
||||||
|
u64 p_blkno;
|
||||||
int status;
|
int status;
|
||||||
handle_t *handle;
|
handle_t *handle;
|
||||||
|
|
||||||
|
@ -1075,12 +1115,49 @@ static struct ocfs2_quota_chunk *ocfs2_extend_local_quota_file(
|
||||||
mlog_errno(status);
|
mlog_errno(status);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
handle = ocfs2_start_trans(OCFS2_SB(sb), 2);
|
|
||||||
|
/* Get buffer from the just added block */
|
||||||
|
down_read(&OCFS2_I(lqinode)->ip_alloc_sem);
|
||||||
|
status = ocfs2_extent_map_get_blocks(lqinode, oinfo->dqi_blocks,
|
||||||
|
&p_blkno, NULL, NULL);
|
||||||
|
up_read(&OCFS2_I(lqinode)->ip_alloc_sem);
|
||||||
|
if (status < 0) {
|
||||||
|
mlog_errno(status);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
bh = sb_getblk(sb, p_blkno);
|
||||||
|
if (!bh) {
|
||||||
|
status = -ENOMEM;
|
||||||
|
mlog_errno(status);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
ocfs2_set_new_buffer_uptodate(lqinode, bh);
|
||||||
|
|
||||||
|
/* Local quota info, chunk header and the new block we initialize */
|
||||||
|
handle = ocfs2_start_trans(OCFS2_SB(sb),
|
||||||
|
OCFS2_LOCAL_QINFO_WRITE_CREDITS +
|
||||||
|
2 * OCFS2_QUOTA_BLOCK_UPDATE_CREDITS);
|
||||||
if (IS_ERR(handle)) {
|
if (IS_ERR(handle)) {
|
||||||
status = PTR_ERR(handle);
|
status = PTR_ERR(handle);
|
||||||
mlog_errno(status);
|
mlog_errno(status);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
/* Zero created block */
|
||||||
|
status = ocfs2_journal_access_dq(handle, lqinode, bh,
|
||||||
|
OCFS2_JOURNAL_ACCESS_CREATE);
|
||||||
|
if (status < 0) {
|
||||||
|
mlog_errno(status);
|
||||||
|
goto out_trans;
|
||||||
|
}
|
||||||
|
lock_buffer(bh);
|
||||||
|
memset(bh->b_data, 0, sb->s_blocksize);
|
||||||
|
unlock_buffer(bh);
|
||||||
|
status = ocfs2_journal_dirty(handle, bh);
|
||||||
|
if (status < 0) {
|
||||||
|
mlog_errno(status);
|
||||||
|
goto out_trans;
|
||||||
|
}
|
||||||
|
/* Update chunk header */
|
||||||
status = ocfs2_journal_access_dq(handle, lqinode, chunk->qc_headerbh,
|
status = ocfs2_journal_access_dq(handle, lqinode, chunk->qc_headerbh,
|
||||||
OCFS2_JOURNAL_ACCESS_WRITE);
|
OCFS2_JOURNAL_ACCESS_WRITE);
|
||||||
if (status < 0) {
|
if (status < 0) {
|
||||||
|
@ -1097,6 +1174,7 @@ static struct ocfs2_quota_chunk *ocfs2_extend_local_quota_file(
|
||||||
mlog_errno(status);
|
mlog_errno(status);
|
||||||
goto out_trans;
|
goto out_trans;
|
||||||
}
|
}
|
||||||
|
/* Update file header */
|
||||||
oinfo->dqi_blocks++;
|
oinfo->dqi_blocks++;
|
||||||
status = ocfs2_local_write_info(sb, type);
|
status = ocfs2_local_write_info(sb, type);
|
||||||
if (status < 0) {
|
if (status < 0) {
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
* General Public License for more details.
|
* General Public License for more details.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <linux/kernel.h>
|
||||||
#include <linux/crc32.h>
|
#include <linux/crc32.h>
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
|
|
||||||
|
@ -153,7 +154,7 @@ static int status_map[] = {
|
||||||
|
|
||||||
static int dlm_status_to_errno(enum dlm_status status)
|
static int dlm_status_to_errno(enum dlm_status status)
|
||||||
{
|
{
|
||||||
BUG_ON(status > (sizeof(status_map) / sizeof(status_map[0])));
|
BUG_ON(status < 0 || status >= ARRAY_SIZE(status_map));
|
||||||
|
|
||||||
return status_map[status];
|
return status_map[status];
|
||||||
}
|
}
|
||||||
|
|
|
@ -777,6 +777,7 @@ static int ocfs2_sb_probe(struct super_block *sb,
|
||||||
}
|
}
|
||||||
di = (struct ocfs2_dinode *) (*bh)->b_data;
|
di = (struct ocfs2_dinode *) (*bh)->b_data;
|
||||||
memset(stats, 0, sizeof(struct ocfs2_blockcheck_stats));
|
memset(stats, 0, sizeof(struct ocfs2_blockcheck_stats));
|
||||||
|
spin_lock_init(&stats->b_lock);
|
||||||
status = ocfs2_verify_volume(di, *bh, blksize, stats);
|
status = ocfs2_verify_volume(di, *bh, blksize, stats);
|
||||||
if (status >= 0)
|
if (status >= 0)
|
||||||
goto bail;
|
goto bail;
|
||||||
|
@ -1182,7 +1183,7 @@ static int ocfs2_fill_super(struct super_block *sb, void *data, int silent)
|
||||||
wake_up(&osb->osb_mount_event);
|
wake_up(&osb->osb_mount_event);
|
||||||
|
|
||||||
/* Start this when the mount is almost sure of being successful */
|
/* Start this when the mount is almost sure of being successful */
|
||||||
ocfs2_orphan_scan_init(osb);
|
ocfs2_orphan_scan_start(osb);
|
||||||
|
|
||||||
mlog_exit(status);
|
mlog_exit(status);
|
||||||
return status;
|
return status;
|
||||||
|
@ -1213,14 +1214,27 @@ static int ocfs2_get_sb(struct file_system_type *fs_type,
|
||||||
mnt);
|
mnt);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void ocfs2_kill_sb(struct super_block *sb)
|
||||||
|
{
|
||||||
|
struct ocfs2_super *osb = OCFS2_SB(sb);
|
||||||
|
|
||||||
|
/* Prevent further queueing of inode drop events */
|
||||||
|
spin_lock(&dentry_list_lock);
|
||||||
|
ocfs2_set_osb_flag(osb, OCFS2_OSB_DROP_DENTRY_LOCK_IMMED);
|
||||||
|
spin_unlock(&dentry_list_lock);
|
||||||
|
/* Wait for work to finish and/or remove it */
|
||||||
|
cancel_work_sync(&osb->dentry_lock_work);
|
||||||
|
|
||||||
|
kill_block_super(sb);
|
||||||
|
}
|
||||||
|
|
||||||
static struct file_system_type ocfs2_fs_type = {
|
static struct file_system_type ocfs2_fs_type = {
|
||||||
.owner = THIS_MODULE,
|
.owner = THIS_MODULE,
|
||||||
.name = "ocfs2",
|
.name = "ocfs2",
|
||||||
.get_sb = ocfs2_get_sb, /* is this called when we mount
|
.get_sb = ocfs2_get_sb, /* is this called when we mount
|
||||||
* the fs? */
|
* the fs? */
|
||||||
.kill_sb = kill_block_super, /* set to the generic one
|
.kill_sb = ocfs2_kill_sb,
|
||||||
* right now, but do we
|
|
||||||
* need to change that? */
|
|
||||||
.fs_flags = FS_REQUIRES_DEV|FS_RENAME_DOES_D_MOVE,
|
.fs_flags = FS_REQUIRES_DEV|FS_RENAME_DOES_D_MOVE,
|
||||||
.next = NULL
|
.next = NULL
|
||||||
};
|
};
|
||||||
|
@ -1819,6 +1833,12 @@ static void ocfs2_dismount_volume(struct super_block *sb, int mnt_err)
|
||||||
|
|
||||||
debugfs_remove(osb->osb_ctxt);
|
debugfs_remove(osb->osb_ctxt);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Flush inode dropping work queue so that deletes are
|
||||||
|
* performed while the filesystem is still working
|
||||||
|
*/
|
||||||
|
ocfs2_drop_all_dl_inodes(osb);
|
||||||
|
|
||||||
/* Orphan scan should be stopped as early as possible */
|
/* Orphan scan should be stopped as early as possible */
|
||||||
ocfs2_orphan_scan_stop(osb);
|
ocfs2_orphan_scan_stop(osb);
|
||||||
|
|
||||||
|
@ -1981,6 +2001,8 @@ static int ocfs2_initialize_super(struct super_block *sb,
|
||||||
snprintf(osb->dev_str, sizeof(osb->dev_str), "%u,%u",
|
snprintf(osb->dev_str, sizeof(osb->dev_str), "%u,%u",
|
||||||
MAJOR(osb->sb->s_dev), MINOR(osb->sb->s_dev));
|
MAJOR(osb->sb->s_dev), MINOR(osb->sb->s_dev));
|
||||||
|
|
||||||
|
ocfs2_orphan_scan_init(osb);
|
||||||
|
|
||||||
status = ocfs2_recovery_init(osb);
|
status = ocfs2_recovery_init(osb);
|
||||||
if (status) {
|
if (status) {
|
||||||
mlog(ML_ERROR, "Unable to initialize recovery state\n");
|
mlog(ML_ERROR, "Unable to initialize recovery state\n");
|
||||||
|
|
|
@ -1052,7 +1052,8 @@ static int ocfs2_xattr_block_get(struct inode *inode,
|
||||||
struct ocfs2_xattr_block *xb;
|
struct ocfs2_xattr_block *xb;
|
||||||
struct ocfs2_xattr_value_root *xv;
|
struct ocfs2_xattr_value_root *xv;
|
||||||
size_t size;
|
size_t size;
|
||||||
int ret = -ENODATA, name_offset, name_len, block_off, i;
|
int ret = -ENODATA, name_offset, name_len, i;
|
||||||
|
int uninitialized_var(block_off);
|
||||||
|
|
||||||
xs->bucket = ocfs2_xattr_bucket_new(inode);
|
xs->bucket = ocfs2_xattr_bucket_new(inode);
|
||||||
if (!xs->bucket) {
|
if (!xs->bucket) {
|
||||||
|
|
|
@ -234,23 +234,20 @@ static int check_mem_permission(struct task_struct *task)
|
||||||
|
|
||||||
struct mm_struct *mm_for_maps(struct task_struct *task)
|
struct mm_struct *mm_for_maps(struct task_struct *task)
|
||||||
{
|
{
|
||||||
struct mm_struct *mm = get_task_mm(task);
|
struct mm_struct *mm;
|
||||||
if (!mm)
|
|
||||||
|
if (mutex_lock_killable(&task->cred_guard_mutex))
|
||||||
return NULL;
|
return NULL;
|
||||||
down_read(&mm->mmap_sem);
|
|
||||||
task_lock(task);
|
mm = get_task_mm(task);
|
||||||
if (task->mm != mm)
|
if (mm && mm != current->mm &&
|
||||||
goto out;
|
!ptrace_may_access(task, PTRACE_MODE_READ)) {
|
||||||
if (task->mm != current->mm &&
|
mmput(mm);
|
||||||
__ptrace_may_access(task, PTRACE_MODE_READ) < 0)
|
mm = NULL;
|
||||||
goto out;
|
}
|
||||||
task_unlock(task);
|
mutex_unlock(&task->cred_guard_mutex);
|
||||||
|
|
||||||
return mm;
|
return mm;
|
||||||
out:
|
|
||||||
task_unlock(task);
|
|
||||||
up_read(&mm->mmap_sem);
|
|
||||||
mmput(mm);
|
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int proc_pid_cmdline(struct task_struct *task, char * buffer)
|
static int proc_pid_cmdline(struct task_struct *task, char * buffer)
|
||||||
|
|
|
@ -119,6 +119,7 @@ static void *m_start(struct seq_file *m, loff_t *pos)
|
||||||
mm = mm_for_maps(priv->task);
|
mm = mm_for_maps(priv->task);
|
||||||
if (!mm)
|
if (!mm)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
down_read(&mm->mmap_sem);
|
||||||
|
|
||||||
tail_vma = get_gate_vma(priv->task);
|
tail_vma = get_gate_vma(priv->task);
|
||||||
priv->tail_vma = tail_vma;
|
priv->tail_vma = tail_vma;
|
||||||
|
|
|
@ -189,6 +189,7 @@ static void *m_start(struct seq_file *m, loff_t *pos)
|
||||||
priv->task = NULL;
|
priv->task = NULL;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
down_read(&mm->mmap_sem);
|
||||||
|
|
||||||
/* start from the Nth VMA */
|
/* start from the Nth VMA */
|
||||||
for (p = rb_first(&mm->mm_rb); p; p = rb_next(p))
|
for (p = rb_first(&mm->mm_rb); p; p = rb_next(p))
|
||||||
|
|
|
@ -770,7 +770,7 @@ xfs_buf_associate_memory(
|
||||||
bp->b_pages = NULL;
|
bp->b_pages = NULL;
|
||||||
bp->b_addr = mem;
|
bp->b_addr = mem;
|
||||||
|
|
||||||
rval = _xfs_buf_get_pages(bp, page_count, 0);
|
rval = _xfs_buf_get_pages(bp, page_count, XBF_DONT_BLOCK);
|
||||||
if (rval)
|
if (rval)
|
||||||
return rval;
|
return rval;
|
||||||
|
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue