1264 lines
41 KiB
Diff
1264 lines
41 KiB
Diff
diff --git a/Makefile b/Makefile
|
|
index c44d720..7d2192c 100644
|
|
diff --git a/arch/x86/include/asm/xen/page.h b/arch/x86/include/asm/xen/page.h
|
|
index 64a619d..7ff4669 100644
|
|
--- a/arch/x86/include/asm/xen/page.h
|
|
+++ b/arch/x86/include/asm/xen/page.h
|
|
@@ -39,7 +39,7 @@ typedef struct xpaddr {
|
|
((unsigned long)((u64)CONFIG_XEN_MAX_DOMAIN_MEMORY * 1024 * 1024 * 1024 / PAGE_SIZE))
|
|
|
|
extern unsigned long *machine_to_phys_mapping;
|
|
-extern unsigned int machine_to_phys_order;
|
|
+extern unsigned long machine_to_phys_nr;
|
|
|
|
extern unsigned long get_phys_to_machine(unsigned long pfn);
|
|
extern bool set_phys_to_machine(unsigned long pfn, unsigned long mfn);
|
|
@@ -87,7 +87,7 @@ static inline unsigned long mfn_to_pfn(unsigned long mfn)
|
|
if (xen_feature(XENFEAT_auto_translated_physmap))
|
|
return mfn;
|
|
|
|
- if (unlikely((mfn >> machine_to_phys_order) != 0)) {
|
|
+ if (unlikely(mfn >= machine_to_phys_nr)) {
|
|
pfn = ~0;
|
|
goto try_override;
|
|
}
|
|
diff --git a/arch/x86/kernel/apic/x2apic_uv_x.c b/arch/x86/kernel/apic/x2apic_uv_x.c
|
|
index adc66c3..34b1859 100644
|
|
--- a/arch/x86/kernel/apic/x2apic_uv_x.c
|
|
+++ b/arch/x86/kernel/apic/x2apic_uv_x.c
|
|
@@ -207,7 +207,6 @@ static int __cpuinit uv_wakeup_secondary(int phys_apicid, unsigned long start_ri
|
|
((start_rip << UVH_IPI_INT_VECTOR_SHFT) >> 12) |
|
|
APIC_DM_INIT;
|
|
uv_write_global_mmr64(pnode, UVH_IPI_INT, val);
|
|
- mdelay(10);
|
|
|
|
val = (1UL << UVH_IPI_INT_SEND_SHFT) |
|
|
(phys_apicid << UVH_IPI_INT_APIC_ID_SHFT) |
|
|
diff --git a/arch/x86/kernel/cpu/intel.c b/arch/x86/kernel/cpu/intel.c
|
|
index da0d779..ed6086e 100644
|
|
--- a/arch/x86/kernel/cpu/intel.c
|
|
+++ b/arch/x86/kernel/cpu/intel.c
|
|
@@ -465,11 +465,11 @@ static void __cpuinit init_intel(struct cpuinfo_x86 *c)
|
|
u64 epb;
|
|
|
|
rdmsrl(MSR_IA32_ENERGY_PERF_BIAS, epb);
|
|
- if ((epb & 0xF) == 0) {
|
|
- printk_once(KERN_WARNING, "x86: updated energy_perf_bias"
|
|
- " to 'normal' from 'performance'\n"
|
|
- "You can view and update epb via utility,"
|
|
- " such as x86_energy_perf_policy(8)\n");
|
|
+ if ((epb & 0xF) == ENERGY_PERF_BIAS_PERFORMANCE) {
|
|
+ printk_once(KERN_WARNING "ENERGY_PERF_BIAS:"
|
|
+ " Set to 'normal', was 'performance'\n"
|
|
+ "ENERGY_PERF_BIAS: View and update with"
|
|
+ " x86_energy_perf_policy(8)\n");
|
|
epb = (epb & ~0xF) | ENERGY_PERF_BIAS_NORMAL;
|
|
wrmsrl(MSR_IA32_ENERGY_PERF_BIAS, epb);
|
|
}
|
|
diff --git a/arch/x86/kernel/cpu/mtrr/main.c b/arch/x86/kernel/cpu/mtrr/main.c
|
|
index 929739a..3d17bc7 100644
|
|
--- a/arch/x86/kernel/cpu/mtrr/main.c
|
|
+++ b/arch/x86/kernel/cpu/mtrr/main.c
|
|
@@ -248,6 +248,25 @@ set_mtrr(unsigned int reg, unsigned long base, unsigned long size, mtrr_type typ
|
|
unsigned long flags;
|
|
int cpu;
|
|
|
|
+#ifdef CONFIG_SMP
|
|
+ /*
|
|
+ * If this cpu is not yet active, we are in the cpu online path. There
|
|
+ * can be no stop_machine() in parallel, as stop machine ensures this
|
|
+ * by using get_online_cpus(). We can skip taking the stop_cpus_mutex,
|
|
+ * as we don't need it and also we can't afford to block while waiting
|
|
+ * for the mutex.
|
|
+ *
|
|
+ * If this cpu is active, we need to prevent stop_machine() happening
|
|
+ * in parallel by taking the stop cpus mutex.
|
|
+ *
|
|
+ * Also, this is called in the context of cpu online path or in the
|
|
+ * context where cpu hotplug is prevented. So checking the active status
|
|
+ * of the raw_smp_processor_id() is safe.
|
|
+ */
|
|
+ if (cpu_active(raw_smp_processor_id()))
|
|
+ mutex_lock(&stop_cpus_mutex);
|
|
+#endif
|
|
+
|
|
preempt_disable();
|
|
|
|
data.smp_reg = reg;
|
|
@@ -330,6 +349,10 @@ set_mtrr(unsigned int reg, unsigned long base, unsigned long size, mtrr_type typ
|
|
|
|
local_irq_restore(flags);
|
|
preempt_enable();
|
|
+#ifdef CONFIG_SMP
|
|
+ if (cpu_active(raw_smp_processor_id()))
|
|
+ mutex_unlock(&stop_cpus_mutex);
|
|
+#endif
|
|
}
|
|
|
|
/**
|
|
diff --git a/arch/x86/platform/olpc/olpc.c b/arch/x86/platform/olpc/olpc.c
|
|
index 0060fd5..02e3934 100644
|
|
--- a/arch/x86/platform/olpc/olpc.c
|
|
+++ b/arch/x86/platform/olpc/olpc.c
|
|
@@ -157,13 +157,13 @@ restart:
|
|
if (inbuf && inlen) {
|
|
/* write data to EC */
|
|
for (i = 0; i < inlen; i++) {
|
|
+ pr_devel("olpc-ec: sending cmd arg 0x%x\n", inbuf[i]);
|
|
+ outb(inbuf[i], 0x68);
|
|
if (wait_on_ibf(0x6c, 0)) {
|
|
printk(KERN_ERR "olpc-ec: timeout waiting for"
|
|
" EC accept data!\n");
|
|
goto err;
|
|
}
|
|
- pr_devel("olpc-ec: sending cmd arg 0x%x\n", inbuf[i]);
|
|
- outb(inbuf[i], 0x68);
|
|
}
|
|
}
|
|
if (outbuf && outlen) {
|
|
diff --git a/arch/x86/vdso/vdso32/sysenter.S b/arch/x86/vdso/vdso32/sysenter.S
|
|
index e2800af..e354bce 100644
|
|
--- a/arch/x86/vdso/vdso32/sysenter.S
|
|
+++ b/arch/x86/vdso/vdso32/sysenter.S
|
|
@@ -43,7 +43,7 @@ __kernel_vsyscall:
|
|
.space 7,0x90
|
|
|
|
/* 14: System call restart point is here! (SYSENTER_RETURN-2) */
|
|
- jmp .Lenter_kernel
|
|
+ int $0x80
|
|
/* 16: System call normal return point is here! */
|
|
VDSO32_SYSENTER_RETURN: /* Symbol used by sysenter.c via vdso32-syms.h */
|
|
pop %ebp
|
|
diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c
|
|
index 5325742..67d69f1 100644
|
|
--- a/arch/x86/xen/enlighten.c
|
|
+++ b/arch/x86/xen/enlighten.c
|
|
@@ -77,8 +77,8 @@ EXPORT_SYMBOL_GPL(xen_domain_type);
|
|
|
|
unsigned long *machine_to_phys_mapping = (void *)MACH2PHYS_VIRT_START;
|
|
EXPORT_SYMBOL(machine_to_phys_mapping);
|
|
-unsigned int machine_to_phys_order;
|
|
-EXPORT_SYMBOL(machine_to_phys_order);
|
|
+unsigned long machine_to_phys_nr;
|
|
+EXPORT_SYMBOL(machine_to_phys_nr);
|
|
|
|
struct start_info *xen_start_info;
|
|
EXPORT_SYMBOL_GPL(xen_start_info);
|
|
diff --git a/arch/x86/xen/mmu.c b/arch/x86/xen/mmu.c
|
|
index 0ccccb6..5f76c0a 100644
|
|
--- a/arch/x86/xen/mmu.c
|
|
+++ b/arch/x86/xen/mmu.c
|
|
@@ -1626,15 +1626,19 @@ static void __init xen_map_identity_early(pmd_t *pmd, unsigned long max_pfn)
|
|
void __init xen_setup_machphys_mapping(void)
|
|
{
|
|
struct xen_machphys_mapping mapping;
|
|
- unsigned long machine_to_phys_nr_ents;
|
|
|
|
if (HYPERVISOR_memory_op(XENMEM_machphys_mapping, &mapping) == 0) {
|
|
machine_to_phys_mapping = (unsigned long *)mapping.v_start;
|
|
- machine_to_phys_nr_ents = mapping.max_mfn + 1;
|
|
+ machine_to_phys_nr = mapping.max_mfn + 1;
|
|
} else {
|
|
- machine_to_phys_nr_ents = MACH2PHYS_NR_ENTRIES;
|
|
+ machine_to_phys_nr = MACH2PHYS_NR_ENTRIES;
|
|
}
|
|
- machine_to_phys_order = fls(machine_to_phys_nr_ents - 1);
|
|
+#ifdef CONFIG_X86_32
|
|
+ if ((machine_to_phys_mapping + machine_to_phys_nr)
|
|
+ < machine_to_phys_mapping)
|
|
+ machine_to_phys_nr = (unsigned long *)NULL
|
|
+ - machine_to_phys_mapping;
|
|
+#endif
|
|
}
|
|
|
|
#ifdef CONFIG_X86_64
|
|
diff --git a/arch/x86/xen/smp.c b/arch/x86/xen/smp.c
|
|
index b4533a8..e79dbb9 100644
|
|
--- a/arch/x86/xen/smp.c
|
|
+++ b/arch/x86/xen/smp.c
|
|
@@ -521,8 +521,6 @@ static void __init xen_hvm_smp_prepare_cpus(unsigned int max_cpus)
|
|
native_smp_prepare_cpus(max_cpus);
|
|
WARN_ON(xen_smp_intr_init(0));
|
|
|
|
- if (!xen_have_vector_callback)
|
|
- return;
|
|
xen_init_lock_cpu(0);
|
|
xen_init_spinlocks();
|
|
}
|
|
@@ -546,6 +544,8 @@ static void xen_hvm_cpu_die(unsigned int cpu)
|
|
|
|
void __init xen_hvm_smp_init(void)
|
|
{
|
|
+ if (!xen_have_vector_callback)
|
|
+ return;
|
|
smp_ops.smp_prepare_cpus = xen_hvm_smp_prepare_cpus;
|
|
smp_ops.smp_send_reschedule = xen_smp_send_reschedule;
|
|
smp_ops.cpu_up = xen_hvm_cpu_up;
|
|
diff --git a/drivers/block/loop.c b/drivers/block/loop.c
|
|
index 76c8da7..2ebacf0 100644
|
|
--- a/drivers/block/loop.c
|
|
+++ b/drivers/block/loop.c
|
|
@@ -750,10 +750,10 @@ static ssize_t loop_attr_backing_file_show(struct loop_device *lo, char *buf)
|
|
ssize_t ret;
|
|
char *p = NULL;
|
|
|
|
- mutex_lock(&lo->lo_ctl_mutex);
|
|
+ spin_lock_irq(&lo->lo_lock);
|
|
if (lo->lo_backing_file)
|
|
p = d_path(&lo->lo_backing_file->f_path, buf, PAGE_SIZE - 1);
|
|
- mutex_unlock(&lo->lo_ctl_mutex);
|
|
+ spin_unlock_irq(&lo->lo_lock);
|
|
|
|
if (IS_ERR_OR_NULL(p))
|
|
ret = PTR_ERR(p);
|
|
@@ -1007,7 +1007,9 @@ static int loop_clr_fd(struct loop_device *lo, struct block_device *bdev)
|
|
|
|
kthread_stop(lo->lo_thread);
|
|
|
|
+ spin_lock_irq(&lo->lo_lock);
|
|
lo->lo_backing_file = NULL;
|
|
+ spin_unlock_irq(&lo->lo_lock);
|
|
|
|
loop_release_xfer(lo);
|
|
lo->transfer = NULL;
|
|
diff --git a/drivers/block/xen-blkfront.c b/drivers/block/xen-blkfront.c
|
|
index b536a9c..9ea8c25 100644
|
|
--- a/drivers/block/xen-blkfront.c
|
|
+++ b/drivers/block/xen-blkfront.c
|
|
@@ -123,8 +123,8 @@ static DEFINE_SPINLOCK(minor_lock);
|
|
#define BLKIF_MINOR_EXT(dev) ((dev)&(~EXTENDED))
|
|
#define EMULATED_HD_DISK_MINOR_OFFSET (0)
|
|
#define EMULATED_HD_DISK_NAME_OFFSET (EMULATED_HD_DISK_MINOR_OFFSET / 256)
|
|
-#define EMULATED_SD_DISK_MINOR_OFFSET (EMULATED_HD_DISK_MINOR_OFFSET + (4 * 16))
|
|
-#define EMULATED_SD_DISK_NAME_OFFSET (EMULATED_HD_DISK_NAME_OFFSET + 4)
|
|
+#define EMULATED_SD_DISK_MINOR_OFFSET (0)
|
|
+#define EMULATED_SD_DISK_NAME_OFFSET (EMULATED_SD_DISK_MINOR_OFFSET / 256)
|
|
|
|
#define DEV_NAME "xvd" /* name in /dev */
|
|
|
|
@@ -529,7 +529,7 @@ static int xlvbd_alloc_gendisk(blkif_sector_t capacity,
|
|
minor = BLKIF_MINOR_EXT(info->vdevice);
|
|
nr_parts = PARTS_PER_EXT_DISK;
|
|
offset = minor / nr_parts;
|
|
- if (xen_hvm_domain() && offset <= EMULATED_HD_DISK_NAME_OFFSET + 4)
|
|
+ if (xen_hvm_domain() && offset < EMULATED_HD_DISK_NAME_OFFSET + 4)
|
|
printk(KERN_WARNING "blkfront: vdevice 0x%x might conflict with "
|
|
"emulated IDE disks,\n\t choose an xvd device name"
|
|
"from xvde on\n", info->vdevice);
|
|
diff --git a/drivers/edac/i7core_edac.c b/drivers/edac/i7core_edac.c
|
|
index 04f1e7c..f6cf448 100644
|
|
--- a/drivers/edac/i7core_edac.c
|
|
+++ b/drivers/edac/i7core_edac.c
|
|
@@ -1670,7 +1670,7 @@ static void i7core_mce_output_error(struct mem_ctl_info *mci,
|
|
char *type, *optype, *err, *msg;
|
|
unsigned long error = m->status & 0x1ff0000l;
|
|
u32 optypenum = (m->status >> 4) & 0x07;
|
|
- u32 core_err_cnt = (m->status >> 38) && 0x7fff;
|
|
+ u32 core_err_cnt = (m->status >> 38) & 0x7fff;
|
|
u32 dimm = (m->misc >> 16) & 0x3;
|
|
u32 channel = (m->misc >> 18) & 0x3;
|
|
u32 syndrome = m->misc >> 32;
|
|
diff --git a/drivers/gpu/drm/radeon/radeon_connectors.c b/drivers/gpu/drm/radeon/radeon_connectors.c
|
|
index 6ab6c41..d1b36f8 100644
|
|
--- a/drivers/gpu/drm/radeon/radeon_connectors.c
|
|
+++ b/drivers/gpu/drm/radeon/radeon_connectors.c
|
|
@@ -466,6 +466,16 @@ static bool radeon_connector_needs_extended_probe(struct radeon_device *dev,
|
|
(supported_device == ATOM_DEVICE_DFP2_SUPPORT))
|
|
return true;
|
|
}
|
|
+ /* TOSHIBA Satellite L300D with ATI Mobility Radeon x1100
|
|
+ * (RS690M) sends data to i2c bus for a HDMI connector that
|
|
+ * is not implemented */
|
|
+ if ((dev->pdev->device == 0x791f) &&
|
|
+ (dev->pdev->subsystem_vendor == 0x1179) &&
|
|
+ (dev->pdev->subsystem_device == 0xff68)) {
|
|
+ if ((connector_type == DRM_MODE_CONNECTOR_HDMIA) &&
|
|
+ (supported_device == ATOM_DEVICE_DFP2_SUPPORT))
|
|
+ return true;
|
|
+ }
|
|
|
|
/* Default: no EDID header probe required for DDC probing */
|
|
return false;
|
|
diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c
|
|
index 2e618b5..b7f0726 100644
|
|
--- a/drivers/gpu/drm/ttm/ttm_bo.c
|
|
+++ b/drivers/gpu/drm/ttm/ttm_bo.c
|
|
@@ -353,8 +353,10 @@ static int ttm_bo_add_ttm(struct ttm_buffer_object *bo, bool zero_alloc)
|
|
|
|
ret = ttm_tt_set_user(bo->ttm, current,
|
|
bo->buffer_start, bo->num_pages);
|
|
- if (unlikely(ret != 0))
|
|
+ if (unlikely(ret != 0)) {
|
|
ttm_tt_destroy(bo->ttm);
|
|
+ bo->ttm = NULL;
|
|
+ }
|
|
break;
|
|
default:
|
|
printk(KERN_ERR TTM_PFX "Illegal buffer object type\n");
|
|
diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
|
|
index 58d5436..6d3de08 100644
|
|
--- a/drivers/mmc/host/sdhci.c
|
|
+++ b/drivers/mmc/host/sdhci.c
|
|
@@ -1863,9 +1863,6 @@ static void sdhci_tasklet_finish(unsigned long param)
|
|
|
|
del_timer(&host->timer);
|
|
|
|
- if (host->version >= SDHCI_SPEC_300)
|
|
- del_timer(&host->tuning_timer);
|
|
-
|
|
mrq = host->mrq;
|
|
|
|
/*
|
|
diff --git a/drivers/net/igb/e1000_82575.c b/drivers/net/igb/e1000_82575.c
|
|
index 0f563c8..493e331 100644
|
|
--- a/drivers/net/igb/e1000_82575.c
|
|
+++ b/drivers/net/igb/e1000_82575.c
|
|
@@ -1735,6 +1735,7 @@ static s32 igb_reset_hw_82580(struct e1000_hw *hw)
|
|
ctrl |= E1000_CTRL_RST;
|
|
|
|
wr32(E1000_CTRL, ctrl);
|
|
+ wrfl();
|
|
|
|
/* Add delay to insure DEV_RST has time to complete */
|
|
if (global_device_reset)
|
|
diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.c b/drivers/net/wireless/rt2x00/rt2x00usb.c
|
|
index 8f90f62..241a099 100644
|
|
--- a/drivers/net/wireless/rt2x00/rt2x00usb.c
|
|
+++ b/drivers/net/wireless/rt2x00/rt2x00usb.c
|
|
@@ -262,23 +262,20 @@ static void rt2x00usb_interrupt_txdone(struct urb *urb)
|
|
struct queue_entry *entry = (struct queue_entry *)urb->context;
|
|
struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
|
|
|
|
- if (!test_and_clear_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags))
|
|
+ if (!test_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags))
|
|
return;
|
|
-
|
|
- if (rt2x00dev->ops->lib->tx_dma_done)
|
|
- rt2x00dev->ops->lib->tx_dma_done(entry);
|
|
-
|
|
- /*
|
|
- * Report the frame as DMA done
|
|
- */
|
|
- rt2x00lib_dmadone(entry);
|
|
-
|
|
/*
|
|
* Check if the frame was correctly uploaded
|
|
*/
|
|
if (urb->status)
|
|
set_bit(ENTRY_DATA_IO_FAILED, &entry->flags);
|
|
+ /*
|
|
+ * Report the frame as DMA done
|
|
+ */
|
|
+ rt2x00lib_dmadone(entry);
|
|
|
|
+ if (rt2x00dev->ops->lib->tx_dma_done)
|
|
+ rt2x00dev->ops->lib->tx_dma_done(entry);
|
|
/*
|
|
* Schedule the delayed work for reading the TX status
|
|
* from the device.
|
|
diff --git a/fs/befs/linuxvfs.c b/fs/befs/linuxvfs.c
|
|
index 54b8c28..720d885 100644
|
|
--- a/fs/befs/linuxvfs.c
|
|
+++ b/fs/befs/linuxvfs.c
|
|
@@ -474,17 +474,22 @@ befs_follow_link(struct dentry *dentry, struct nameidata *nd)
|
|
befs_data_stream *data = &befs_ino->i_data.ds;
|
|
befs_off_t len = data->size;
|
|
|
|
- befs_debug(sb, "Follow long symlink");
|
|
-
|
|
- link = kmalloc(len, GFP_NOFS);
|
|
- if (!link) {
|
|
- link = ERR_PTR(-ENOMEM);
|
|
- } else if (befs_read_lsymlink(sb, data, link, len) != len) {
|
|
- kfree(link);
|
|
- befs_error(sb, "Failed to read entire long symlink");
|
|
+ if (len == 0) {
|
|
+ befs_error(sb, "Long symlink with illegal length");
|
|
link = ERR_PTR(-EIO);
|
|
} else {
|
|
- link[len - 1] = '\0';
|
|
+ befs_debug(sb, "Follow long symlink");
|
|
+
|
|
+ link = kmalloc(len, GFP_NOFS);
|
|
+ if (!link) {
|
|
+ link = ERR_PTR(-ENOMEM);
|
|
+ } else if (befs_read_lsymlink(sb, data, link, len) != len) {
|
|
+ kfree(link);
|
|
+ befs_error(sb, "Failed to read entire long symlink");
|
|
+ link = ERR_PTR(-EIO);
|
|
+ } else {
|
|
+ link[len - 1] = '\0';
|
|
+ }
|
|
}
|
|
} else {
|
|
link = befs_ino->i_data.symlink;
|
|
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c
|
|
index 71cd456..7e20a65 100644
|
|
--- a/fs/btrfs/extent-tree.c
|
|
+++ b/fs/btrfs/extent-tree.c
|
|
@@ -1784,6 +1784,9 @@ static int btrfs_discard_extent(struct btrfs_root *root, u64 bytenr,
|
|
|
|
|
|
for (i = 0; i < multi->num_stripes; i++, stripe++) {
|
|
+ if (!stripe->dev->can_discard)
|
|
+ continue;
|
|
+
|
|
ret = btrfs_issue_discard(stripe->dev->bdev,
|
|
stripe->physical,
|
|
stripe->length);
|
|
@@ -1791,11 +1794,16 @@ static int btrfs_discard_extent(struct btrfs_root *root, u64 bytenr,
|
|
discarded_bytes += stripe->length;
|
|
else if (ret != -EOPNOTSUPP)
|
|
break;
|
|
+
|
|
+ /*
|
|
+ * Just in case we get back EOPNOTSUPP for some reason,
|
|
+ * just ignore the return value so we don't screw up
|
|
+ * people calling discard_extent.
|
|
+ */
|
|
+ ret = 0;
|
|
}
|
|
kfree(multi);
|
|
}
|
|
- if (discarded_bytes && ret == -EOPNOTSUPP)
|
|
- ret = 0;
|
|
|
|
if (actual_bytes)
|
|
*actual_bytes = discarded_bytes;
|
|
diff --git a/fs/btrfs/tree-log.c b/fs/btrfs/tree-log.c
|
|
index 4ce8a9f..7fa128d 100644
|
|
--- a/fs/btrfs/tree-log.c
|
|
+++ b/fs/btrfs/tree-log.c
|
|
@@ -799,14 +799,15 @@ static noinline int add_inode_ref(struct btrfs_trans_handle *trans,
|
|
struct extent_buffer *eb, int slot,
|
|
struct btrfs_key *key)
|
|
{
|
|
- struct inode *dir;
|
|
- int ret;
|
|
struct btrfs_inode_ref *ref;
|
|
+ struct btrfs_dir_item *di;
|
|
+ struct inode *dir;
|
|
struct inode *inode;
|
|
- char *name;
|
|
- int namelen;
|
|
unsigned long ref_ptr;
|
|
unsigned long ref_end;
|
|
+ char *name;
|
|
+ int namelen;
|
|
+ int ret;
|
|
int search_done = 0;
|
|
|
|
/*
|
|
@@ -909,6 +910,25 @@ again:
|
|
}
|
|
btrfs_release_path(path);
|
|
|
|
+ /* look for a conflicting sequence number */
|
|
+ di = btrfs_lookup_dir_index_item(trans, root, path, btrfs_ino(dir),
|
|
+ btrfs_inode_ref_index(eb, ref),
|
|
+ name, namelen, 0);
|
|
+ if (di && !IS_ERR(di)) {
|
|
+ ret = drop_one_dir_item(trans, root, path, dir, di);
|
|
+ BUG_ON(ret);
|
|
+ }
|
|
+ btrfs_release_path(path);
|
|
+
|
|
+ /* look for a conflicing name */
|
|
+ di = btrfs_lookup_dir_item(trans, root, path, btrfs_ino(dir),
|
|
+ name, namelen, 0);
|
|
+ if (di && !IS_ERR(di)) {
|
|
+ ret = drop_one_dir_item(trans, root, path, dir, di);
|
|
+ BUG_ON(ret);
|
|
+ }
|
|
+ btrfs_release_path(path);
|
|
+
|
|
insert:
|
|
/* insert our name */
|
|
ret = btrfs_add_link(trans, dir, inode, name, namelen, 0,
|
|
diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c
|
|
index 19450bc..43baaf0 100644
|
|
--- a/fs/btrfs/volumes.c
|
|
+++ b/fs/btrfs/volumes.c
|
|
@@ -500,6 +500,9 @@ static int __btrfs_close_devices(struct btrfs_fs_devices *fs_devices)
|
|
fs_devices->rw_devices--;
|
|
}
|
|
|
|
+ if (device->can_discard)
|
|
+ fs_devices->num_can_discard--;
|
|
+
|
|
new_device = kmalloc(sizeof(*new_device), GFP_NOFS);
|
|
BUG_ON(!new_device);
|
|
memcpy(new_device, device, sizeof(*new_device));
|
|
@@ -508,6 +511,7 @@ static int __btrfs_close_devices(struct btrfs_fs_devices *fs_devices)
|
|
new_device->bdev = NULL;
|
|
new_device->writeable = 0;
|
|
new_device->in_fs_metadata = 0;
|
|
+ new_device->can_discard = 0;
|
|
list_replace_rcu(&device->dev_list, &new_device->dev_list);
|
|
|
|
call_rcu(&device->rcu, free_device);
|
|
@@ -547,6 +551,7 @@ int btrfs_close_devices(struct btrfs_fs_devices *fs_devices)
|
|
static int __btrfs_open_devices(struct btrfs_fs_devices *fs_devices,
|
|
fmode_t flags, void *holder)
|
|
{
|
|
+ struct request_queue *q;
|
|
struct block_device *bdev;
|
|
struct list_head *head = &fs_devices->devices;
|
|
struct btrfs_device *device;
|
|
@@ -603,6 +608,12 @@ static int __btrfs_open_devices(struct btrfs_fs_devices *fs_devices,
|
|
seeding = 0;
|
|
}
|
|
|
|
+ q = bdev_get_queue(bdev);
|
|
+ if (blk_queue_discard(q)) {
|
|
+ device->can_discard = 1;
|
|
+ fs_devices->num_can_discard++;
|
|
+ }
|
|
+
|
|
device->bdev = bdev;
|
|
device->in_fs_metadata = 0;
|
|
device->mode = flags;
|
|
@@ -1542,6 +1553,7 @@ error:
|
|
|
|
int btrfs_init_new_device(struct btrfs_root *root, char *device_path)
|
|
{
|
|
+ struct request_queue *q;
|
|
struct btrfs_trans_handle *trans;
|
|
struct btrfs_device *device;
|
|
struct block_device *bdev;
|
|
@@ -1611,6 +1623,9 @@ int btrfs_init_new_device(struct btrfs_root *root, char *device_path)
|
|
|
|
lock_chunks(root);
|
|
|
|
+ q = bdev_get_queue(bdev);
|
|
+ if (blk_queue_discard(q))
|
|
+ device->can_discard = 1;
|
|
device->writeable = 1;
|
|
device->work.func = pending_bios_fn;
|
|
generate_random_uuid(device->uuid);
|
|
@@ -1646,6 +1661,8 @@ int btrfs_init_new_device(struct btrfs_root *root, char *device_path)
|
|
root->fs_info->fs_devices->num_devices++;
|
|
root->fs_info->fs_devices->open_devices++;
|
|
root->fs_info->fs_devices->rw_devices++;
|
|
+ if (device->can_discard)
|
|
+ root->fs_info->fs_devices->num_can_discard++;
|
|
root->fs_info->fs_devices->total_rw_bytes += device->total_bytes;
|
|
|
|
if (!blk_queue_nonrot(bdev_get_queue(bdev)))
|
|
diff --git a/fs/btrfs/volumes.h b/fs/btrfs/volumes.h
|
|
index 7c12d61..6d866db 100644
|
|
--- a/fs/btrfs/volumes.h
|
|
+++ b/fs/btrfs/volumes.h
|
|
@@ -48,6 +48,7 @@ struct btrfs_device {
|
|
int writeable;
|
|
int in_fs_metadata;
|
|
int missing;
|
|
+ int can_discard;
|
|
|
|
spinlock_t io_lock;
|
|
|
|
@@ -104,6 +105,7 @@ struct btrfs_fs_devices {
|
|
u64 rw_devices;
|
|
u64 missing_devices;
|
|
u64 total_rw_bytes;
|
|
+ u64 num_can_discard;
|
|
struct block_device *latest_bdev;
|
|
|
|
/* all of the devices in the FS, protected by a mutex
|
|
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
|
|
index ccc1afa..e0ea721 100644
|
|
--- a/fs/cifs/connect.c
|
|
+++ b/fs/cifs/connect.c
|
|
@@ -2838,7 +2838,8 @@ cleanup_volume_info_contents(struct smb_vol *volume_info)
|
|
kfree(volume_info->username);
|
|
kzfree(volume_info->password);
|
|
kfree(volume_info->UNC);
|
|
- kfree(volume_info->UNCip);
|
|
+ if (volume_info->UNCip != volume_info->UNC + 2)
|
|
+ kfree(volume_info->UNCip);
|
|
kfree(volume_info->domainname);
|
|
kfree(volume_info->iocharset);
|
|
kfree(volume_info->prepath);
|
|
diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c
|
|
index d8d26f3..16cdd6d 100644
|
|
--- a/fs/cifs/dir.c
|
|
+++ b/fs/cifs/dir.c
|
|
@@ -110,8 +110,8 @@ cifs_bp_rename_retry:
|
|
}
|
|
rcu_read_unlock();
|
|
if (namelen != dfsplen || read_seqretry(&rename_lock, seq)) {
|
|
- cERROR(1, "did not end path lookup where expected namelen is %d",
|
|
- namelen);
|
|
+ cFYI(1, "did not end path lookup where expected. namelen=%d "
|
|
+ "dfsplen=%d", namelen, dfsplen);
|
|
/* presumably this is only possible if racing with a rename
|
|
of one of the parent directories (we can not lock the dentries
|
|
above us to prevent this, but retrying should be harmless) */
|
|
diff --git a/fs/ext4/ext4_jbd2.h b/fs/ext4/ext4_jbd2.h
|
|
index bb85757..5802fa1 100644
|
|
--- a/fs/ext4/ext4_jbd2.h
|
|
+++ b/fs/ext4/ext4_jbd2.h
|
|
@@ -289,10 +289,10 @@ static inline int ext4_should_order_data(struct inode *inode)
|
|
|
|
static inline int ext4_should_writeback_data(struct inode *inode)
|
|
{
|
|
- if (!S_ISREG(inode->i_mode))
|
|
- return 0;
|
|
if (EXT4_JOURNAL(inode) == NULL)
|
|
return 1;
|
|
+ if (!S_ISREG(inode->i_mode))
|
|
+ return 0;
|
|
if (ext4_test_inode_flag(inode, EXT4_INODE_JOURNAL_DATA))
|
|
return 0;
|
|
if (test_opt(inode->i_sb, DATA_FLAGS) == EXT4_MOUNT_WRITEBACK_DATA)
|
|
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
|
|
index e3126c0..b864839 100644
|
|
--- a/fs/ext4/inode.c
|
|
+++ b/fs/ext4/inode.c
|
|
@@ -189,6 +189,12 @@ void ext4_evict_inode(struct inode *inode)
|
|
int err;
|
|
|
|
trace_ext4_evict_inode(inode);
|
|
+
|
|
+ mutex_lock(&inode->i_mutex);
|
|
+ ext4_flush_completed_IO(inode);
|
|
+ mutex_unlock(&inode->i_mutex);
|
|
+ ext4_ioend_wait(inode);
|
|
+
|
|
if (inode->i_nlink) {
|
|
truncate_inode_pages(&inode->i_data, 0);
|
|
goto no_delete;
|
|
@@ -1849,6 +1855,8 @@ static int ext4_journalled_write_end(struct file *file,
|
|
from = pos & (PAGE_CACHE_SIZE - 1);
|
|
to = from + len;
|
|
|
|
+ BUG_ON(!ext4_handle_valid(handle));
|
|
+
|
|
if (copied < len) {
|
|
if (!PageUptodate(page))
|
|
copied = 0;
|
|
@@ -2148,7 +2156,12 @@ static int mpage_da_submit_io(struct mpage_da_data *mpd,
|
|
else if (test_opt(inode->i_sb, MBLK_IO_SUBMIT))
|
|
err = ext4_bio_write_page(&io_submit, page,
|
|
len, mpd->wbc);
|
|
- else
|
|
+ else if (buffer_uninit(page_bufs)) {
|
|
+ ext4_set_bh_endio(page_bufs, inode);
|
|
+ err = block_write_full_page_endio(page,
|
|
+ noalloc_get_block_write,
|
|
+ mpd->wbc, ext4_end_io_buffer_write);
|
|
+ } else
|
|
err = block_write_full_page(page,
|
|
noalloc_get_block_write, mpd->wbc);
|
|
|
|
@@ -2564,6 +2577,8 @@ static int __ext4_journalled_writepage(struct page *page,
|
|
goto out;
|
|
}
|
|
|
|
+ BUG_ON(!ext4_handle_valid(handle));
|
|
+
|
|
ret = walk_page_buffers(handle, page_bufs, 0, len, NULL,
|
|
do_journal_get_write_access);
|
|
|
|
@@ -3635,8 +3650,15 @@ static void ext4_end_io_buffer_write(struct buffer_head *bh, int uptodate)
|
|
goto out;
|
|
}
|
|
|
|
- io_end->flag = EXT4_IO_END_UNWRITTEN;
|
|
+ /*
|
|
+ * It may be over-defensive here to check EXT4_IO_END_UNWRITTEN now,
|
|
+ * but being more careful is always safe for the future change.
|
|
+ */
|
|
inode = io_end->inode;
|
|
+ if (!(io_end->flag & EXT4_IO_END_UNWRITTEN)) {
|
|
+ io_end->flag |= EXT4_IO_END_UNWRITTEN;
|
|
+ atomic_inc(&EXT4_I(inode)->i_aiodio_unwritten);
|
|
+ }
|
|
|
|
/* Add the io_end to per-inode completed io list*/
|
|
spin_lock_irqsave(&EXT4_I(inode)->i_completed_io_lock, flags);
|
|
diff --git a/fs/ext4/page-io.c b/fs/ext4/page-io.c
|
|
index 7bb8f76..97e5e98 100644
|
|
--- a/fs/ext4/page-io.c
|
|
+++ b/fs/ext4/page-io.c
|
|
@@ -338,8 +338,10 @@ submit_and_retry:
|
|
if ((io_end->num_io_pages >= MAX_IO_PAGES) &&
|
|
(io_end->pages[io_end->num_io_pages-1] != io_page))
|
|
goto submit_and_retry;
|
|
- if (buffer_uninit(bh))
|
|
- io->io_end->flag |= EXT4_IO_END_UNWRITTEN;
|
|
+ if (buffer_uninit(bh) && !(io_end->flag & EXT4_IO_END_UNWRITTEN)) {
|
|
+ io_end->flag |= EXT4_IO_END_UNWRITTEN;
|
|
+ atomic_inc(&EXT4_I(inode)->i_aiodio_unwritten);
|
|
+ }
|
|
io->io_end->size += bh->b_size;
|
|
io->io_next_block++;
|
|
ret = bio_add_page(io->io_bio, bh->b_page, bh->b_size, bh_offset(bh));
|
|
diff --git a/fs/ext4/super.c b/fs/ext4/super.c
|
|
index 9ea71aa..111ed9d 100644
|
|
--- a/fs/ext4/super.c
|
|
+++ b/fs/ext4/super.c
|
|
@@ -892,7 +892,6 @@ static void ext4_i_callback(struct rcu_head *head)
|
|
|
|
static void ext4_destroy_inode(struct inode *inode)
|
|
{
|
|
- ext4_ioend_wait(inode);
|
|
if (!list_empty(&(EXT4_I(inode)->i_orphan))) {
|
|
ext4_msg(inode->i_sb, KERN_ERR,
|
|
"Inode %lu (%p): orphan list check failed!",
|
|
diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c
|
|
index 640fc22..168a80f 100644
|
|
--- a/fs/fuse/dev.c
|
|
+++ b/fs/fuse/dev.c
|
|
@@ -1358,6 +1358,10 @@ static int fuse_notify_inval_entry(struct fuse_conn *fc, unsigned int size,
|
|
if (outarg.namelen > FUSE_NAME_MAX)
|
|
goto err;
|
|
|
|
+ err = -EINVAL;
|
|
+ if (size != sizeof(outarg) + outarg.namelen + 1)
|
|
+ goto err;
|
|
+
|
|
name.name = buf;
|
|
name.len = outarg.namelen;
|
|
err = fuse_copy_one(cs, buf, outarg.namelen + 1);
|
|
diff --git a/fs/nfs/callback.h b/fs/nfs/callback.h
|
|
index b257383..07df5f1 100644
|
|
--- a/fs/nfs/callback.h
|
|
+++ b/fs/nfs/callback.h
|
|
@@ -38,6 +38,7 @@ enum nfs4_callback_opnum {
|
|
struct cb_process_state {
|
|
__be32 drc_status;
|
|
struct nfs_client *clp;
|
|
+ int slotid;
|
|
};
|
|
|
|
struct cb_compound_hdr_arg {
|
|
@@ -166,7 +167,6 @@ extern unsigned nfs4_callback_layoutrecall(
|
|
void *dummy, struct cb_process_state *cps);
|
|
|
|
extern void nfs4_check_drain_bc_complete(struct nfs4_session *ses);
|
|
-extern void nfs4_cb_take_slot(struct nfs_client *clp);
|
|
|
|
struct cb_devicenotifyitem {
|
|
uint32_t cbd_notify_type;
|
|
diff --git a/fs/nfs/callback_proc.c b/fs/nfs/callback_proc.c
|
|
index d4d1954..aaa09e9 100644
|
|
--- a/fs/nfs/callback_proc.c
|
|
+++ b/fs/nfs/callback_proc.c
|
|
@@ -333,7 +333,7 @@ validate_seqid(struct nfs4_slot_table *tbl, struct cb_sequenceargs * args)
|
|
/* Normal */
|
|
if (likely(args->csa_sequenceid == slot->seq_nr + 1)) {
|
|
slot->seq_nr++;
|
|
- return htonl(NFS4_OK);
|
|
+ goto out_ok;
|
|
}
|
|
|
|
/* Replay */
|
|
@@ -352,11 +352,14 @@ validate_seqid(struct nfs4_slot_table *tbl, struct cb_sequenceargs * args)
|
|
/* Wraparound */
|
|
if (args->csa_sequenceid == 1 && (slot->seq_nr + 1) == 0) {
|
|
slot->seq_nr = 1;
|
|
- return htonl(NFS4_OK);
|
|
+ goto out_ok;
|
|
}
|
|
|
|
/* Misordered request */
|
|
return htonl(NFS4ERR_SEQ_MISORDERED);
|
|
+out_ok:
|
|
+ tbl->highest_used_slotid = args->csa_slotid;
|
|
+ return htonl(NFS4_OK);
|
|
}
|
|
|
|
/*
|
|
@@ -418,26 +421,37 @@ __be32 nfs4_callback_sequence(struct cb_sequenceargs *args,
|
|
struct cb_sequenceres *res,
|
|
struct cb_process_state *cps)
|
|
{
|
|
+ struct nfs4_slot_table *tbl;
|
|
struct nfs_client *clp;
|
|
int i;
|
|
__be32 status = htonl(NFS4ERR_BADSESSION);
|
|
|
|
- cps->clp = NULL;
|
|
-
|
|
clp = nfs4_find_client_sessionid(args->csa_addr, &args->csa_sessionid);
|
|
if (clp == NULL)
|
|
goto out;
|
|
|
|
+ tbl = &clp->cl_session->bc_slot_table;
|
|
+
|
|
+ spin_lock(&tbl->slot_tbl_lock);
|
|
/* state manager is resetting the session */
|
|
if (test_bit(NFS4_SESSION_DRAINING, &clp->cl_session->session_state)) {
|
|
- status = NFS4ERR_DELAY;
|
|
+ spin_unlock(&tbl->slot_tbl_lock);
|
|
+ status = htonl(NFS4ERR_DELAY);
|
|
+ /* Return NFS4ERR_BADSESSION if we're draining the session
|
|
+ * in order to reset it.
|
|
+ */
|
|
+ if (test_bit(NFS4CLNT_SESSION_RESET, &clp->cl_state))
|
|
+ status = htonl(NFS4ERR_BADSESSION);
|
|
goto out;
|
|
}
|
|
|
|
status = validate_seqid(&clp->cl_session->bc_slot_table, args);
|
|
+ spin_unlock(&tbl->slot_tbl_lock);
|
|
if (status)
|
|
goto out;
|
|
|
|
+ cps->slotid = args->csa_slotid;
|
|
+
|
|
/*
|
|
* Check for pending referring calls. If a match is found, a
|
|
* related callback was received before the response to the original
|
|
@@ -454,7 +468,6 @@ __be32 nfs4_callback_sequence(struct cb_sequenceargs *args,
|
|
res->csr_slotid = args->csa_slotid;
|
|
res->csr_highestslotid = NFS41_BC_MAX_CALLBACKS - 1;
|
|
res->csr_target_highestslotid = NFS41_BC_MAX_CALLBACKS - 1;
|
|
- nfs4_cb_take_slot(clp);
|
|
|
|
out:
|
|
cps->clp = clp; /* put in nfs4_callback_compound */
|
|
diff --git a/fs/nfs/callback_xdr.c b/fs/nfs/callback_xdr.c
|
|
index c6c86a7..918ad64 100644
|
|
--- a/fs/nfs/callback_xdr.c
|
|
+++ b/fs/nfs/callback_xdr.c
|
|
@@ -754,26 +754,15 @@ static void nfs4_callback_free_slot(struct nfs4_session *session)
|
|
* Let the state manager know callback processing done.
|
|
* A single slot, so highest used slotid is either 0 or -1
|
|
*/
|
|
- tbl->highest_used_slotid--;
|
|
+ tbl->highest_used_slotid = -1;
|
|
nfs4_check_drain_bc_complete(session);
|
|
spin_unlock(&tbl->slot_tbl_lock);
|
|
}
|
|
|
|
-static void nfs4_cb_free_slot(struct nfs_client *clp)
|
|
+static void nfs4_cb_free_slot(struct cb_process_state *cps)
|
|
{
|
|
- if (clp && clp->cl_session)
|
|
- nfs4_callback_free_slot(clp->cl_session);
|
|
-}
|
|
-
|
|
-/* A single slot, so highest used slotid is either 0 or -1 */
|
|
-void nfs4_cb_take_slot(struct nfs_client *clp)
|
|
-{
|
|
- struct nfs4_slot_table *tbl = &clp->cl_session->bc_slot_table;
|
|
-
|
|
- spin_lock(&tbl->slot_tbl_lock);
|
|
- tbl->highest_used_slotid++;
|
|
- BUG_ON(tbl->highest_used_slotid != 0);
|
|
- spin_unlock(&tbl->slot_tbl_lock);
|
|
+ if (cps->slotid != -1)
|
|
+ nfs4_callback_free_slot(cps->clp->cl_session);
|
|
}
|
|
|
|
#else /* CONFIG_NFS_V4_1 */
|
|
@@ -784,7 +773,7 @@ preprocess_nfs41_op(int nop, unsigned int op_nr, struct callback_op **op)
|
|
return htonl(NFS4ERR_MINOR_VERS_MISMATCH);
|
|
}
|
|
|
|
-static void nfs4_cb_free_slot(struct nfs_client *clp)
|
|
+static void nfs4_cb_free_slot(struct cb_process_state *cps)
|
|
{
|
|
}
|
|
#endif /* CONFIG_NFS_V4_1 */
|
|
@@ -866,6 +855,7 @@ static __be32 nfs4_callback_compound(struct svc_rqst *rqstp, void *argp, void *r
|
|
struct cb_process_state cps = {
|
|
.drc_status = 0,
|
|
.clp = NULL,
|
|
+ .slotid = -1,
|
|
};
|
|
unsigned int nops = 0;
|
|
|
|
@@ -906,7 +896,7 @@ static __be32 nfs4_callback_compound(struct svc_rqst *rqstp, void *argp, void *r
|
|
|
|
*hdr_res.status = status;
|
|
*hdr_res.nops = htonl(nops);
|
|
- nfs4_cb_free_slot(cps.clp);
|
|
+ nfs4_cb_free_slot(&cps);
|
|
nfs_put_client(cps.clp);
|
|
dprintk("%s: done, status = %u\n", __func__, ntohl(status));
|
|
return rpc_success;
|
|
diff --git a/fs/nfs/objlayout/objio_osd.c b/fs/nfs/objlayout/objio_osd.c
|
|
index 8ff2ea3..1d1dc1e 100644
|
|
--- a/fs/nfs/objlayout/objio_osd.c
|
|
+++ b/fs/nfs/objlayout/objio_osd.c
|
|
@@ -479,7 +479,6 @@ static int _io_check(struct objio_state *ios, bool is_write)
|
|
for (i = 0; i < ios->numdevs; i++) {
|
|
struct osd_sense_info osi;
|
|
struct osd_request *or = ios->per_dev[i].or;
|
|
- unsigned dev;
|
|
int ret;
|
|
|
|
if (!or)
|
|
@@ -500,9 +499,8 @@ static int _io_check(struct objio_state *ios, bool is_write)
|
|
|
|
continue; /* we recovered */
|
|
}
|
|
- dev = ios->per_dev[i].dev;
|
|
- objlayout_io_set_result(&ios->ol_state, dev,
|
|
- &ios->layout->comps[dev].oc_object_id,
|
|
+ objlayout_io_set_result(&ios->ol_state, i,
|
|
+ &ios->layout->comps[i].oc_object_id,
|
|
osd_pri_2_pnfs_err(osi.osd_err_pri),
|
|
ios->per_dev[i].offset,
|
|
ios->per_dev[i].length,
|
|
@@ -589,22 +587,19 @@ static void _calc_stripe_info(struct objio_state *ios, u64 file_offset,
|
|
}
|
|
|
|
static int _add_stripe_unit(struct objio_state *ios, unsigned *cur_pg,
|
|
- unsigned pgbase, struct _objio_per_comp *per_dev, int cur_len,
|
|
+ unsigned pgbase, struct _objio_per_comp *per_dev, int len,
|
|
gfp_t gfp_flags)
|
|
{
|
|
unsigned pg = *cur_pg;
|
|
+ int cur_len = len;
|
|
struct request_queue *q =
|
|
osd_request_queue(_io_od(ios, per_dev->dev));
|
|
|
|
- per_dev->length += cur_len;
|
|
-
|
|
if (per_dev->bio == NULL) {
|
|
- unsigned stripes = ios->layout->num_comps /
|
|
- ios->layout->mirrors_p1;
|
|
- unsigned pages_in_stripe = stripes *
|
|
+ unsigned pages_in_stripe = ios->layout->group_width *
|
|
(ios->layout->stripe_unit / PAGE_SIZE);
|
|
unsigned bio_size = (ios->ol_state.nr_pages + pages_in_stripe) /
|
|
- stripes;
|
|
+ ios->layout->group_width;
|
|
|
|
if (BIO_MAX_PAGES_KMALLOC < bio_size)
|
|
bio_size = BIO_MAX_PAGES_KMALLOC;
|
|
@@ -632,6 +627,7 @@ static int _add_stripe_unit(struct objio_state *ios, unsigned *cur_pg,
|
|
}
|
|
BUG_ON(cur_len);
|
|
|
|
+ per_dev->length += len;
|
|
*cur_pg = pg;
|
|
return 0;
|
|
}
|
|
@@ -650,7 +646,7 @@ static int _prepare_one_group(struct objio_state *ios, u64 length,
|
|
int ret = 0;
|
|
|
|
while (length) {
|
|
- struct _objio_per_comp *per_dev = &ios->per_dev[dev];
|
|
+ struct _objio_per_comp *per_dev = &ios->per_dev[dev - first_dev];
|
|
unsigned cur_len, page_off = 0;
|
|
|
|
if (!per_dev->length) {
|
|
@@ -670,8 +666,8 @@ static int _prepare_one_group(struct objio_state *ios, u64 length,
|
|
cur_len = stripe_unit;
|
|
}
|
|
|
|
- if (max_comp < dev)
|
|
- max_comp = dev;
|
|
+ if (max_comp < dev - first_dev)
|
|
+ max_comp = dev - first_dev;
|
|
} else {
|
|
cur_len = stripe_unit;
|
|
}
|
|
@@ -806,7 +802,7 @@ static int _read_mirrors(struct objio_state *ios, unsigned cur_comp)
|
|
struct _objio_per_comp *per_dev = &ios->per_dev[cur_comp];
|
|
unsigned dev = per_dev->dev;
|
|
struct pnfs_osd_object_cred *cred =
|
|
- &ios->layout->comps[dev];
|
|
+ &ios->layout->comps[cur_comp];
|
|
struct osd_obj_id obj = {
|
|
.partition = cred->oc_object_id.oid_partition_id,
|
|
.id = cred->oc_object_id.oid_object_id,
|
|
@@ -904,7 +900,7 @@ static int _write_mirrors(struct objio_state *ios, unsigned cur_comp)
|
|
for (; cur_comp < last_comp; ++cur_comp, ++dev) {
|
|
struct osd_request *or = NULL;
|
|
struct pnfs_osd_object_cred *cred =
|
|
- &ios->layout->comps[dev];
|
|
+ &ios->layout->comps[cur_comp];
|
|
struct osd_obj_id obj = {
|
|
.partition = cred->oc_object_id.oid_partition_id,
|
|
.id = cred->oc_object_id.oid_object_id,
|
|
diff --git a/fs/nfs/objlayout/pnfs_osd_xdr_cli.c b/fs/nfs/objlayout/pnfs_osd_xdr_cli.c
|
|
index 16fc758..b3918f7 100644
|
|
--- a/fs/nfs/objlayout/pnfs_osd_xdr_cli.c
|
|
+++ b/fs/nfs/objlayout/pnfs_osd_xdr_cli.c
|
|
@@ -170,6 +170,9 @@ int pnfs_osd_xdr_decode_layout_map(struct pnfs_osd_layout *layout,
|
|
p = _osd_xdr_decode_data_map(p, &layout->olo_map);
|
|
layout->olo_comps_index = be32_to_cpup(p++);
|
|
layout->olo_num_comps = be32_to_cpup(p++);
|
|
+ dprintk("%s: olo_comps_index=%d olo_num_comps=%d\n", __func__,
|
|
+ layout->olo_comps_index, layout->olo_num_comps);
|
|
+
|
|
iter->total_comps = layout->olo_num_comps;
|
|
return 0;
|
|
}
|
|
diff --git a/include/linux/personality.h b/include/linux/personality.h
|
|
index eec3bae..8fc7dd1a 100644
|
|
--- a/include/linux/personality.h
|
|
+++ b/include/linux/personality.h
|
|
@@ -22,6 +22,7 @@ extern int __set_personality(unsigned int);
|
|
* These occupy the top three bytes.
|
|
*/
|
|
enum {
|
|
+ UNAME26 = 0x0020000,
|
|
ADDR_NO_RANDOMIZE = 0x0040000, /* disable randomization of VA space */
|
|
FDPIC_FUNCPTRS = 0x0080000, /* userspace function ptrs point to descriptors
|
|
* (signal handling)
|
|
diff --git a/include/linux/stop_machine.h b/include/linux/stop_machine.h
|
|
index 092dc9b..14d3524 100644
|
|
--- a/include/linux/stop_machine.h
|
|
+++ b/include/linux/stop_machine.h
|
|
@@ -27,6 +27,8 @@ struct cpu_stop_work {
|
|
struct cpu_stop_done *done;
|
|
};
|
|
|
|
+extern struct mutex stop_cpus_mutex;
|
|
+
|
|
int stop_one_cpu(unsigned int cpu, cpu_stop_fn_t fn, void *arg);
|
|
void stop_one_cpu_nowait(unsigned int cpu, cpu_stop_fn_t fn, void *arg,
|
|
struct cpu_stop_work *work_buf);
|
|
diff --git a/kernel/irq/generic-chip.c b/kernel/irq/generic-chip.c
|
|
index 3a2cab4..e38544d 100644
|
|
--- a/kernel/irq/generic-chip.c
|
|
+++ b/kernel/irq/generic-chip.c
|
|
@@ -246,7 +246,7 @@ void irq_setup_generic_chip(struct irq_chip_generic *gc, u32 msk,
|
|
gc->mask_cache = irq_reg_readl(gc->reg_base + ct->regs.mask);
|
|
|
|
for (i = gc->irq_base; msk; msk >>= 1, i++) {
|
|
- if (!msk & 0x01)
|
|
+ if (!(msk & 0x01))
|
|
continue;
|
|
|
|
if (flags & IRQ_GC_INIT_NESTED_LOCK)
|
|
@@ -301,7 +301,7 @@ void irq_remove_generic_chip(struct irq_chip_generic *gc, u32 msk,
|
|
raw_spin_unlock(&gc_lock);
|
|
|
|
for (; msk; msk >>= 1, i++) {
|
|
- if (!msk & 0x01)
|
|
+ if (!(msk & 0x01))
|
|
continue;
|
|
|
|
/* Remove handler first. That will mask the irq line */
|
|
diff --git a/kernel/stop_machine.c b/kernel/stop_machine.c
|
|
index e3516b2..0cae1cc 100644
|
|
--- a/kernel/stop_machine.c
|
|
+++ b/kernel/stop_machine.c
|
|
@@ -132,8 +132,8 @@ void stop_one_cpu_nowait(unsigned int cpu, cpu_stop_fn_t fn, void *arg,
|
|
cpu_stop_queue_work(&per_cpu(cpu_stopper, cpu), work_buf);
|
|
}
|
|
|
|
+DEFINE_MUTEX(stop_cpus_mutex);
|
|
/* static data for stop_cpus */
|
|
-static DEFINE_MUTEX(stop_cpus_mutex);
|
|
static DEFINE_PER_CPU(struct cpu_stop_work, stop_cpus_work);
|
|
|
|
int __stop_cpus(const struct cpumask *cpumask, cpu_stop_fn_t fn, void *arg)
|
|
diff --git a/kernel/sys.c b/kernel/sys.c
|
|
index e4128b2..5c942cf 100644
|
|
--- a/kernel/sys.c
|
|
+++ b/kernel/sys.c
|
|
@@ -38,6 +38,8 @@
|
|
#include <linux/fs_struct.h>
|
|
#include <linux/gfp.h>
|
|
#include <linux/syscore_ops.h>
|
|
+#include <linux/version.h>
|
|
+#include <linux/ctype.h>
|
|
|
|
#include <linux/compat.h>
|
|
#include <linux/syscalls.h>
|
|
@@ -45,6 +47,8 @@
|
|
#include <linux/user_namespace.h>
|
|
|
|
#include <linux/kmsg_dump.h>
|
|
+/* Move somewhere else to avoid recompiling? */
|
|
+#include <generated/utsrelease.h>
|
|
|
|
#include <asm/uaccess.h>
|
|
#include <asm/io.h>
|
|
@@ -1124,6 +1128,34 @@ DECLARE_RWSEM(uts_sem);
|
|
#define override_architecture(name) 0
|
|
#endif
|
|
|
|
+/*
|
|
+ * Work around broken programs that cannot handle "Linux 3.0".
|
|
+ * Instead we map 3.x to 2.6.40+x, so e.g. 3.0 would be 2.6.40
|
|
+ */
|
|
+static int override_release(char __user *release, int len)
|
|
+{
|
|
+ int ret = 0;
|
|
+ char buf[len];
|
|
+
|
|
+ if (current->personality & UNAME26) {
|
|
+ char *rest = UTS_RELEASE;
|
|
+ int ndots = 0;
|
|
+ unsigned v;
|
|
+
|
|
+ while (*rest) {
|
|
+ if (*rest == '.' && ++ndots >= 3)
|
|
+ break;
|
|
+ if (!isdigit(*rest) && *rest != '.')
|
|
+ break;
|
|
+ rest++;
|
|
+ }
|
|
+ v = ((LINUX_VERSION_CODE >> 8) & 0xff) + 40;
|
|
+ snprintf(buf, len, "2.6.%u%s", v, rest);
|
|
+ ret = copy_to_user(release, buf, len);
|
|
+ }
|
|
+ return ret;
|
|
+}
|
|
+
|
|
SYSCALL_DEFINE1(newuname, struct new_utsname __user *, name)
|
|
{
|
|
int errno = 0;
|
|
@@ -1133,6 +1165,8 @@ SYSCALL_DEFINE1(newuname, struct new_utsname __user *, name)
|
|
errno = -EFAULT;
|
|
up_read(&uts_sem);
|
|
|
|
+ if (!errno && override_release(name->release, sizeof(name->release)))
|
|
+ errno = -EFAULT;
|
|
if (!errno && override_architecture(name))
|
|
errno = -EFAULT;
|
|
return errno;
|
|
@@ -1154,6 +1188,8 @@ SYSCALL_DEFINE1(uname, struct old_utsname __user *, name)
|
|
error = -EFAULT;
|
|
up_read(&uts_sem);
|
|
|
|
+ if (!error && override_release(name->release, sizeof(name->release)))
|
|
+ error = -EFAULT;
|
|
if (!error && override_architecture(name))
|
|
error = -EFAULT;
|
|
return error;
|
|
@@ -1188,6 +1224,8 @@ SYSCALL_DEFINE1(olduname, struct oldold_utsname __user *, name)
|
|
|
|
if (!error && override_architecture(name))
|
|
error = -EFAULT;
|
|
+ if (!error && override_release(name->release, sizeof(name->release)))
|
|
+ error = -EFAULT;
|
|
return error ? -EFAULT : 0;
|
|
}
|
|
#endif
|
|
diff --git a/sound/pci/ac97/ac97_patch.c b/sound/pci/ac97/ac97_patch.c
|
|
index 200c9a1..a872d0a 100644
|
|
--- a/sound/pci/ac97/ac97_patch.c
|
|
+++ b/sound/pci/ac97/ac97_patch.c
|
|
@@ -1909,6 +1909,7 @@ static unsigned int ad1981_jacks_whitelist[] = {
|
|
0x103c0944, /* HP nc6220 */
|
|
0x103c0934, /* HP nc8220 */
|
|
0x103c006d, /* HP nx9105 */
|
|
+ 0x103c300d, /* HP Compaq dc5100 SFF(PT003AW) */
|
|
0x17340088, /* FSC Scenic-W */
|
|
0 /* end */
|
|
};
|
|
diff --git a/sound/usb/caiaq/audio.c b/sound/usb/caiaq/audio.c
|
|
index aa52b3e..2cf87f5 100644
|
|
--- a/sound/usb/caiaq/audio.c
|
|
+++ b/sound/usb/caiaq/audio.c
|
|
@@ -139,8 +139,12 @@ static void stream_stop(struct snd_usb_caiaqdev *dev)
|
|
|
|
for (i = 0; i < N_URBS; i++) {
|
|
usb_kill_urb(dev->data_urbs_in[i]);
|
|
- usb_kill_urb(dev->data_urbs_out[i]);
|
|
+
|
|
+ if (test_bit(i, &dev->outurb_active_mask))
|
|
+ usb_kill_urb(dev->data_urbs_out[i]);
|
|
}
|
|
+
|
|
+ dev->outurb_active_mask = 0;
|
|
}
|
|
|
|
static int snd_usb_caiaq_substream_open(struct snd_pcm_substream *substream)
|
|
@@ -612,8 +616,8 @@ static void read_completed(struct urb *urb)
|
|
{
|
|
struct snd_usb_caiaq_cb_info *info = urb->context;
|
|
struct snd_usb_caiaqdev *dev;
|
|
- struct urb *out;
|
|
- int frame, len, send_it = 0, outframe = 0;
|
|
+ struct urb *out = NULL;
|
|
+ int i, frame, len, send_it = 0, outframe = 0;
|
|
size_t offset = 0;
|
|
|
|
if (urb->status || !info)
|
|
@@ -624,7 +628,17 @@ static void read_completed(struct urb *urb)
|
|
if (!dev->streaming)
|
|
return;
|
|
|
|
- out = dev->data_urbs_out[info->index];
|
|
+ /* find an unused output urb that is unused */
|
|
+ for (i = 0; i < N_URBS; i++)
|
|
+ if (test_and_set_bit(i, &dev->outurb_active_mask) == 0) {
|
|
+ out = dev->data_urbs_out[i];
|
|
+ break;
|
|
+ }
|
|
+
|
|
+ if (!out) {
|
|
+ log("Unable to find an output urb to use\n");
|
|
+ goto requeue;
|
|
+ }
|
|
|
|
/* read the recently received packet and send back one which has
|
|
* the same layout */
|
|
@@ -655,8 +669,12 @@ static void read_completed(struct urb *urb)
|
|
out->number_of_packets = outframe;
|
|
out->transfer_flags = URB_ISO_ASAP;
|
|
usb_submit_urb(out, GFP_ATOMIC);
|
|
+ } else {
|
|
+ struct snd_usb_caiaq_cb_info *oinfo = out->context;
|
|
+ clear_bit(oinfo->index, &dev->outurb_active_mask);
|
|
}
|
|
|
|
+requeue:
|
|
/* re-submit inbound urb */
|
|
for (frame = 0; frame < FRAMES_PER_URB; frame++) {
|
|
urb->iso_frame_desc[frame].offset = BYTES_PER_FRAME * frame;
|
|
@@ -678,6 +696,8 @@ static void write_completed(struct urb *urb)
|
|
dev->output_running = 1;
|
|
wake_up(&dev->prepare_wait_queue);
|
|
}
|
|
+
|
|
+ clear_bit(info->index, &dev->outurb_active_mask);
|
|
}
|
|
|
|
static struct urb **alloc_urbs(struct snd_usb_caiaqdev *dev, int dir, int *ret)
|
|
@@ -829,6 +849,9 @@ int snd_usb_caiaq_audio_init(struct snd_usb_caiaqdev *dev)
|
|
if (!dev->data_cb_info)
|
|
return -ENOMEM;
|
|
|
|
+ dev->outurb_active_mask = 0;
|
|
+ BUILD_BUG_ON(N_URBS > (sizeof(dev->outurb_active_mask) * 8));
|
|
+
|
|
for (i = 0; i < N_URBS; i++) {
|
|
dev->data_cb_info[i].dev = dev;
|
|
dev->data_cb_info[i].index = i;
|
|
diff --git a/sound/usb/caiaq/device.h b/sound/usb/caiaq/device.h
|
|
index b2b3101..3f9c633 100644
|
|
--- a/sound/usb/caiaq/device.h
|
|
+++ b/sound/usb/caiaq/device.h
|
|
@@ -96,6 +96,7 @@ struct snd_usb_caiaqdev {
|
|
int input_panic, output_panic, warned;
|
|
char *audio_in_buf, *audio_out_buf;
|
|
unsigned int samplerates, bpp;
|
|
+ unsigned long outurb_active_mask;
|
|
|
|
struct snd_pcm_substream *sub_playback[MAX_STREAMS];
|
|
struct snd_pcm_substream *sub_capture[MAX_STREAMS];
|
|
diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c
|
|
index c04d7c7..cdd19d7 100644
|
|
--- a/sound/usb/mixer.c
|
|
+++ b/sound/usb/mixer.c
|
|
@@ -152,6 +152,7 @@ static inline void check_mapped_dB(const struct usbmix_name_map *p,
|
|
if (p && p->dB) {
|
|
cval->dBmin = p->dB->min;
|
|
cval->dBmax = p->dB->max;
|
|
+ cval->initialized = 1;
|
|
}
|
|
}
|
|
|
|
@@ -1092,7 +1093,7 @@ static void build_feature_ctl(struct mixer_build *state, void *raw_desc,
|
|
" Switch" : " Volume");
|
|
if (control == UAC_FU_VOLUME) {
|
|
check_mapped_dB(map, cval);
|
|
- if (cval->dBmin < cval->dBmax) {
|
|
+ if (cval->dBmin < cval->dBmax || !cval->initialized) {
|
|
kctl->tlv.c = mixer_vol_tlv;
|
|
kctl->vd[0].access |=
|
|
SNDRV_CTL_ELEM_ACCESS_TLV_READ |
|