From 5afa6d6bb79971c96a7fa0b3682c5267d0633ce2 Mon Sep 17 00:00:00 2001 From: Xiaotian Feng Date: Tue, 4 Dec 2012 19:33:54 +0800 Subject: [PATCH] --- yaml --- r: 336222 b: refs/heads/master c: c1d390d8e6128b050f0f66b1c33d390760deb3f4 h: refs/heads/master v: v3 --- [refs] | 2 +- trunk/Makefile | 2 +- trunk/arch/arm64/include/asm/unistd32.h | 2 +- trunk/arch/parisc/kernel/syscall_table.S | 2 +- trunk/arch/s390/kernel/compat_wrapper.S | 2 +- trunk/arch/sparc/boot/piggyback.c | 12 +- trunk/arch/sparc/kernel/sys32.S | 2 +- trunk/arch/sparc/kernel/syscalls.S | 14 +- trunk/arch/sparc/kernel/systbls_64.S | 2 +- trunk/drivers/char/raw.c | 2 +- trunk/drivers/edac/edac_mc.c | 14 +- trunk/drivers/edac/i7300_edac.c | 8 +- trunk/drivers/edac/i7core_edac.c | 6 +- trunk/drivers/edac/i82975x_edac.c | 11 +- trunk/drivers/md/raid1.c | 2 +- trunk/drivers/md/raid10.c | 2 +- .../media/platform/exynos-gsc/gsc-m2m.c | 4 +- .../media/platform/exynos-gsc/gsc-regs.h | 16 +- .../media/platform/s5p-fimc/fimc-capture.c | 10 +- .../media/platform/s5p-fimc/fimc-lite.c | 6 +- .../media/platform/s5p-fimc/fimc-m2m.c | 3 +- .../media/platform/s5p-fimc/fimc-mdevice.c | 4 +- .../drivers/media/platform/s5p-mfc/s5p_mfc.c | 7 +- .../media/platform/s5p-mfc/s5p_mfc_opr_v6.c | 2 +- trunk/drivers/net/bonding/bond_main.c | 93 ++++++---- trunk/drivers/net/bonding/bond_sysfs.c | 36 ++-- trunk/drivers/net/ethernet/realtek/8139cp.c | 11 +- trunk/drivers/net/wireless/iwlwifi/dvm/rxon.c | 12 +- trunk/drivers/scsi/megaraid/megaraid_sas.h | 2 +- .../drivers/scsi/megaraid/megaraid_sas_base.c | 14 +- trunk/fs/block_dev.c | 160 +++++++++++++++++- trunk/fs/buffer.c | 145 ++++------------ trunk/fs/cifs/readdir.c | 5 +- trunk/fs/direct-io.c | 8 +- trunk/fs/file.c | 14 +- trunk/fs/namei.c | 5 - trunk/fs/nfs/dir.c | 7 +- trunk/include/linux/fs.h | 5 + trunk/kernel/sched/auto_group.c | 4 + trunk/kernel/sched/auto_group.h | 5 + trunk/net/ipv4/tcp.c | 15 +- trunk/net/mac80211/offchannel.c | 2 + 42 files changed, 389 insertions(+), 291 deletions(-) diff --git a/[refs] b/[refs] index a5d6b2abd4c4..dbb213381fcb 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 609e3ff3ff797c0ddba1c61c8eb83923586ed079 +refs/heads/master: c1d390d8e6128b050f0f66b1c33d390760deb3f4 diff --git a/trunk/Makefile b/trunk/Makefile index 346e28f5de52..6cab75b74365 100644 --- a/trunk/Makefile +++ b/trunk/Makefile @@ -1,7 +1,7 @@ VERSION = 3 PATCHLEVEL = 7 SUBLEVEL = 0 -EXTRAVERSION = -rc8 +EXTRAVERSION = -rc7 NAME = Terrified Chipmunk # *DOCUMENTATION* diff --git a/trunk/arch/arm64/include/asm/unistd32.h b/trunk/arch/arm64/include/asm/unistd32.h index 656a6f291a35..6d909faebf28 100644 --- a/trunk/arch/arm64/include/asm/unistd32.h +++ b/trunk/arch/arm64/include/asm/unistd32.h @@ -392,7 +392,7 @@ __SYSCALL(367, sys_fanotify_init) __SYSCALL(368, compat_sys_fanotify_mark_wrapper) __SYSCALL(369, sys_prlimit64) __SYSCALL(370, sys_name_to_handle_at) -__SYSCALL(371, compat_sys_open_by_handle_at) +__SYSCALL(371, sys_open_by_handle_at) __SYSCALL(372, sys_clock_adjtime) __SYSCALL(373, sys_syncfs) diff --git a/trunk/arch/parisc/kernel/syscall_table.S b/trunk/arch/parisc/kernel/syscall_table.S index cbf5d59d5d6a..3735abd7f8f6 100644 --- a/trunk/arch/parisc/kernel/syscall_table.S +++ b/trunk/arch/parisc/kernel/syscall_table.S @@ -60,7 +60,7 @@ ENTRY_SAME(fork_wrapper) ENTRY_SAME(read) ENTRY_SAME(write) - ENTRY_COMP(open) /* 5 */ + ENTRY_SAME(open) /* 5 */ ENTRY_SAME(close) ENTRY_SAME(waitpid) ENTRY_SAME(creat) diff --git a/trunk/arch/s390/kernel/compat_wrapper.S b/trunk/arch/s390/kernel/compat_wrapper.S index 827e094a2f49..ad79b846535c 100644 --- a/trunk/arch/s390/kernel/compat_wrapper.S +++ b/trunk/arch/s390/kernel/compat_wrapper.S @@ -28,7 +28,7 @@ ENTRY(sys32_open_wrapper) llgtr %r2,%r2 # const char * lgfr %r3,%r3 # int lgfr %r4,%r4 # int - jg compat_sys_open # branch to system call + jg sys_open # branch to system call ENTRY(sys32_close_wrapper) llgfr %r2,%r2 # unsigned int diff --git a/trunk/arch/sparc/boot/piggyback.c b/trunk/arch/sparc/boot/piggyback.c index bb7c95161d71..c0a798fcf030 100644 --- a/trunk/arch/sparc/boot/piggyback.c +++ b/trunk/arch/sparc/boot/piggyback.c @@ -81,18 +81,18 @@ static void usage(void) static int start_line(const char *line) { - if (strcmp(line + 10, " _start\n") == 0) + if (strcmp(line + 8, " T _start\n") == 0) return 1; - else if (strcmp(line + 18, " _start\n") == 0) + else if (strcmp(line + 16, " T _start\n") == 0) return 1; return 0; } static int end_line(const char *line) { - if (strcmp(line + 10, " _end\n") == 0) + if (strcmp(line + 8, " A _end\n") == 0) return 1; - else if (strcmp (line + 18, " _end\n") == 0) + else if (strcmp (line + 16, " A _end\n") == 0) return 1; return 0; } @@ -100,8 +100,8 @@ static int end_line(const char *line) /* * Find address for start and end in System.map. * The file looks like this: - * f0004000 ... _start - * f0379f79 ... _end + * f0004000 T _start + * f0379f79 A _end * 1234567890123456 * ^coloumn 1 * There is support for 64 bit addresses too. diff --git a/trunk/arch/sparc/kernel/sys32.S b/trunk/arch/sparc/kernel/sys32.S index 8475a474273a..44025f4ba41f 100644 --- a/trunk/arch/sparc/kernel/sys32.S +++ b/trunk/arch/sparc/kernel/sys32.S @@ -47,7 +47,7 @@ STUB: sra REG1, 0, REG1; \ sra REG4, 0, REG4 SIGN1(sys32_exit, sparc_exit, %o0) -SIGN1(sys32_exit_group, sparc_exit_group, %o0) +SIGN1(sys32_exit_group, sys_exit_group, %o0) SIGN1(sys32_wait4, compat_sys_wait4, %o2) SIGN1(sys32_creat, sys_creat, %o1) SIGN1(sys32_mknod, sys_mknod, %o1) diff --git a/trunk/arch/sparc/kernel/syscalls.S b/trunk/arch/sparc/kernel/syscalls.S index bf2347794e33..7f5f65d0b3fd 100644 --- a/trunk/arch/sparc/kernel/syscalls.S +++ b/trunk/arch/sparc/kernel/syscalls.S @@ -118,20 +118,10 @@ ret_from_syscall: ba,pt %xcc, ret_sys_call ldx [%sp + PTREGS_OFF + PT_V9_I0], %o0 - .globl sparc_exit_group - .type sparc_exit_group,#function -sparc_exit_group: - sethi %hi(sys_exit_group), %g7 - ba,pt %xcc, 1f - or %g7, %lo(sys_exit_group), %g7 - .size sparc_exit_group,.-sparc_exit_group - .globl sparc_exit .type sparc_exit,#function sparc_exit: - sethi %hi(sys_exit), %g7 - or %g7, %lo(sys_exit), %g7 -1: rdpr %pstate, %g2 + rdpr %pstate, %g2 wrpr %g2, PSTATE_IE, %pstate rdpr %otherwin, %g1 rdpr %cansave, %g3 @@ -139,7 +129,7 @@ sparc_exit: wrpr %g3, 0x0, %cansave wrpr %g0, 0x0, %otherwin wrpr %g2, 0x0, %pstate - jmpl %g7, %g0 + ba,pt %xcc, sys_exit stb %g0, [%g6 + TI_WSAVED] .size sparc_exit,.-sparc_exit diff --git a/trunk/arch/sparc/kernel/systbls_64.S b/trunk/arch/sparc/kernel/systbls_64.S index 017b74a63dcb..1c9af9fa38e9 100644 --- a/trunk/arch/sparc/kernel/systbls_64.S +++ b/trunk/arch/sparc/kernel/systbls_64.S @@ -133,7 +133,7 @@ sys_call_table: /*170*/ .word sys_lsetxattr, sys_fsetxattr, sys_getxattr, sys_lgetxattr, sys_getdents .word sys_setsid, sys_fchdir, sys_fgetxattr, sys_listxattr, sys_llistxattr /*180*/ .word sys_flistxattr, sys_removexattr, sys_lremovexattr, sys_nis_syscall, sys_ni_syscall - .word sys_setpgid, sys_fremovexattr, sys_tkill, sparc_exit_group, sys_newuname + .word sys_setpgid, sys_fremovexattr, sys_tkill, sys_exit_group, sys_newuname /*190*/ .word sys_init_module, sys_sparc64_personality, sys_remap_file_pages, sys_epoll_create, sys_epoll_ctl .word sys_epoll_wait, sys_ioprio_set, sys_getppid, sys_nis_syscall, sys_sgetmask /*200*/ .word sys_ssetmask, sys_nis_syscall, sys_newlstat, sys_uselib, sys_nis_syscall diff --git a/trunk/drivers/char/raw.c b/trunk/drivers/char/raw.c index 54a3a6d09819..0bb207eaef2f 100644 --- a/trunk/drivers/char/raw.c +++ b/trunk/drivers/char/raw.c @@ -285,7 +285,7 @@ static long raw_ctl_compat_ioctl(struct file *file, unsigned int cmd, static const struct file_operations raw_fops = { .read = do_sync_read, - .aio_read = generic_file_aio_read, + .aio_read = blkdev_aio_read, .write = do_sync_write, .aio_write = blkdev_aio_write, .fsync = blkdev_fsync, diff --git a/trunk/drivers/edac/edac_mc.c b/trunk/drivers/edac/edac_mc.c index 75c0a1a85fc3..90f0b730e9bb 100644 --- a/trunk/drivers/edac/edac_mc.c +++ b/trunk/drivers/edac/edac_mc.c @@ -416,18 +416,10 @@ struct mem_ctl_info *edac_mc_alloc(unsigned mc_num, dimm->cschannel = chn; /* Increment csrow location */ - if (layers[0].is_virt_csrow) { + row++; + if (row == tot_csrows) { + row = 0; chn++; - if (chn == tot_channels) { - chn = 0; - row++; - } - } else { - row++; - if (row == tot_csrows) { - row = 0; - chn++; - } } /* Increment dimm location */ diff --git a/trunk/drivers/edac/i7300_edac.c b/trunk/drivers/edac/i7300_edac.c index 9d669cd43618..a09d0667f72a 100644 --- a/trunk/drivers/edac/i7300_edac.c +++ b/trunk/drivers/edac/i7300_edac.c @@ -197,8 +197,8 @@ static const char *ferr_fat_fbd_name[] = { [0] = "Memory Write error on non-redundant retry or " "FBD configuration Write error on retry", }; -#define GET_FBD_FAT_IDX(fbderr) (((fbderr) >> 28) & 3) -#define FERR_FAT_FBD_ERR_MASK ((1 << 0) | (1 << 1) | (1 << 2) | (1 << 22)) +#define GET_FBD_FAT_IDX(fbderr) (fbderr & (3 << 28)) +#define FERR_FAT_FBD_ERR_MASK ((1 << 0) | (1 << 1) | (1 << 2) | (1 << 3)) #define FERR_NF_FBD 0xa0 static const char *ferr_nf_fbd_name[] = { @@ -225,7 +225,7 @@ static const char *ferr_nf_fbd_name[] = { [1] = "Aliased Uncorrectable Non-Mirrored Demand Data ECC", [0] = "Uncorrectable Data ECC on Replay", }; -#define GET_FBD_NF_IDX(fbderr) (((fbderr) >> 28) & 3) +#define GET_FBD_NF_IDX(fbderr) (fbderr & (3 << 28)) #define FERR_NF_FBD_ERR_MASK ((1 << 24) | (1 << 23) | (1 << 22) | (1 << 21) |\ (1 << 18) | (1 << 17) | (1 << 16) | (1 << 15) |\ (1 << 14) | (1 << 13) | (1 << 11) | (1 << 10) |\ @@ -464,7 +464,7 @@ static void i7300_process_fbd_error(struct mem_ctl_info *mci) errnum = find_first_bit(&errors, ARRAY_SIZE(ferr_nf_fbd_name)); specific = GET_ERR_FROM_TABLE(ferr_nf_fbd_name, errnum); - branch = (GET_FBD_NF_IDX(error_reg) == 2) ? 1 : 0; + branch = (GET_FBD_FAT_IDX(error_reg) == 2) ? 1 : 0; pci_read_config_dword(pvt->pci_dev_16_1_fsb_addr_map, REDMEMA, &syndrome); diff --git a/trunk/drivers/edac/i7core_edac.c b/trunk/drivers/edac/i7core_edac.c index 10c8c00d6469..3672101023bd 100644 --- a/trunk/drivers/edac/i7core_edac.c +++ b/trunk/drivers/edac/i7core_edac.c @@ -816,7 +816,7 @@ static ssize_t i7core_inject_store_##param( \ struct device_attribute *mattr, \ const char *data, size_t count) \ { \ - struct mem_ctl_info *mci = dev_get_drvdata(dev); \ + struct mem_ctl_info *mci = to_mci(dev); \ struct i7core_pvt *pvt; \ long value; \ int rc; \ @@ -845,7 +845,7 @@ static ssize_t i7core_inject_show_##param( \ struct device_attribute *mattr, \ char *data) \ { \ - struct mem_ctl_info *mci = dev_get_drvdata(dev); \ + struct mem_ctl_info *mci = to_mci(dev); \ struct i7core_pvt *pvt; \ \ pvt = mci->pvt_info; \ @@ -1052,7 +1052,7 @@ static ssize_t i7core_show_counter_##param( \ struct device_attribute *mattr, \ char *data) \ { \ - struct mem_ctl_info *mci = dev_get_drvdata(dev); \ + struct mem_ctl_info *mci = to_mci(dev); \ struct i7core_pvt *pvt = mci->pvt_info; \ \ edac_dbg(1, "\n"); \ diff --git a/trunk/drivers/edac/i82975x_edac.c b/trunk/drivers/edac/i82975x_edac.c index a98020409fa9..069e26c11c4f 100644 --- a/trunk/drivers/edac/i82975x_edac.c +++ b/trunk/drivers/edac/i82975x_edac.c @@ -370,6 +370,10 @@ static enum dev_type i82975x_dram_type(void __iomem *mch_window, int rank) static void i82975x_init_csrows(struct mem_ctl_info *mci, struct pci_dev *pdev, void __iomem *mch_window) { + static const char *labels[4] = { + "DIMM A1", "DIMM A2", + "DIMM B1", "DIMM B2" + }; struct csrow_info *csrow; unsigned long last_cumul_size; u8 value; @@ -419,10 +423,9 @@ static void i82975x_init_csrows(struct mem_ctl_info *mci, dimm = mci->csrows[index]->channels[chan]->dimm; dimm->nr_pages = nr_pages / csrow->nr_channels; - - snprintf(csrow->channels[chan]->dimm->label, EDAC_MC_LABEL_LEN, "DIMM %c%d", - (chan == 0) ? 'A' : 'B', - index); + strncpy(csrow->channels[chan]->dimm->label, + labels[(index >> 1) + (chan * 2)], + EDAC_MC_LABEL_LEN); dimm->grain = 1 << 7; /* 128Byte cache-line resolution */ dimm->dtype = i82975x_dram_type(mch_window, index); dimm->mtype = MEM_DDR2; /* I82975x supports only DDR2 */ diff --git a/trunk/drivers/md/raid1.c b/trunk/drivers/md/raid1.c index a0f73092176e..636bae0405e8 100644 --- a/trunk/drivers/md/raid1.c +++ b/trunk/drivers/md/raid1.c @@ -963,7 +963,7 @@ static void raid1_unplug(struct blk_plug_cb *cb, bool from_schedule) struct r1conf *conf = mddev->private; struct bio *bio; - if (from_schedule || current->bio_list) { + if (from_schedule) { spin_lock_irq(&conf->device_lock); bio_list_merge(&conf->pending_bio_list, &plug->pending); conf->pending_count += plug->pending_cnt; diff --git a/trunk/drivers/md/raid10.c b/trunk/drivers/md/raid10.c index c9acbd717131..0d5d0ff2c0f7 100644 --- a/trunk/drivers/md/raid10.c +++ b/trunk/drivers/md/raid10.c @@ -1069,7 +1069,7 @@ static void raid10_unplug(struct blk_plug_cb *cb, bool from_schedule) struct r10conf *conf = mddev->private; struct bio *bio; - if (from_schedule || current->bio_list) { + if (from_schedule) { spin_lock_irq(&conf->device_lock); bio_list_merge(&conf->pending_bio_list, &plug->pending); conf->pending_count += plug->pending_cnt; diff --git a/trunk/drivers/media/platform/exynos-gsc/gsc-m2m.c b/trunk/drivers/media/platform/exynos-gsc/gsc-m2m.c index c065d040ed94..3c7f00577bd9 100644 --- a/trunk/drivers/media/platform/exynos-gsc/gsc-m2m.c +++ b/trunk/drivers/media/platform/exynos-gsc/gsc-m2m.c @@ -657,7 +657,8 @@ static int gsc_m2m_release(struct file *file) pr_debug("pid: %d, state: 0x%lx, refcnt= %d", task_pid_nr(current), gsc->state, gsc->m2m.refcnt); - mutex_lock(&gsc->lock); + if (mutex_lock_interruptible(&gsc->lock)) + return -ERESTARTSYS; v4l2_m2m_ctx_release(ctx->m2m_ctx); gsc_ctrls_delete(ctx); @@ -731,7 +732,6 @@ int gsc_register_m2m_device(struct gsc_dev *gsc) gsc->vdev.ioctl_ops = &gsc_m2m_ioctl_ops; gsc->vdev.release = video_device_release_empty; gsc->vdev.lock = &gsc->lock; - gsc->vdev.vfl_dir = VFL_DIR_M2M; snprintf(gsc->vdev.name, sizeof(gsc->vdev.name), "%s.%d:m2m", GSC_MODULE_NAME, gsc->id); diff --git a/trunk/drivers/media/platform/exynos-gsc/gsc-regs.h b/trunk/drivers/media/platform/exynos-gsc/gsc-regs.h index 4678f9a6a4fd..533e9947a925 100644 --- a/trunk/drivers/media/platform/exynos-gsc/gsc-regs.h +++ b/trunk/drivers/media/platform/exynos-gsc/gsc-regs.h @@ -40,10 +40,10 @@ #define GSC_IN_ROT_YFLIP (2 << 16) #define GSC_IN_ROT_XFLIP (1 << 16) #define GSC_IN_RGB_TYPE_MASK (3 << 14) -#define GSC_IN_RGB_HD_NARROW (3 << 14) -#define GSC_IN_RGB_HD_WIDE (2 << 14) -#define GSC_IN_RGB_SD_NARROW (1 << 14) -#define GSC_IN_RGB_SD_WIDE (0 << 14) +#define GSC_IN_RGB_HD_WIDE (3 << 14) +#define GSC_IN_RGB_HD_NARROW (2 << 14) +#define GSC_IN_RGB_SD_WIDE (1 << 14) +#define GSC_IN_RGB_SD_NARROW (0 << 14) #define GSC_IN_YUV422_1P_ORDER_MASK (1 << 13) #define GSC_IN_YUV422_1P_ORDER_LSB_Y (0 << 13) #define GSC_IN_YUV422_1P_OEDER_LSB_C (1 << 13) @@ -85,10 +85,10 @@ #define GSC_OUT_GLOBAL_ALPHA_MASK (0xff << 24) #define GSC_OUT_GLOBAL_ALPHA(x) ((x) << 24) #define GSC_OUT_RGB_TYPE_MASK (3 << 10) -#define GSC_OUT_RGB_HD_WIDE (3 << 10) -#define GSC_OUT_RGB_HD_NARROW (2 << 10) -#define GSC_OUT_RGB_SD_WIDE (1 << 10) -#define GSC_OUT_RGB_SD_NARROW (0 << 10) +#define GSC_OUT_RGB_HD_NARROW (3 << 10) +#define GSC_OUT_RGB_HD_WIDE (2 << 10) +#define GSC_OUT_RGB_SD_NARROW (1 << 10) +#define GSC_OUT_RGB_SD_WIDE (0 << 10) #define GSC_OUT_YUV422_1P_ORDER_MASK (1 << 9) #define GSC_OUT_YUV422_1P_ORDER_LSB_Y (0 << 9) #define GSC_OUT_YUV422_1P_OEDER_LSB_C (1 << 9) diff --git a/trunk/drivers/media/platform/s5p-fimc/fimc-capture.c b/trunk/drivers/media/platform/s5p-fimc/fimc-capture.c index 891ee873c62b..3d39d97abaa5 100644 --- a/trunk/drivers/media/platform/s5p-fimc/fimc-capture.c +++ b/trunk/drivers/media/platform/s5p-fimc/fimc-capture.c @@ -556,7 +556,8 @@ static int fimc_capture_close(struct file *file) dbg("pid: %d, state: 0x%lx", task_pid_nr(current), fimc->state); - mutex_lock(&fimc->lock); + if (mutex_lock_interruptible(&fimc->lock)) + return -ERESTARTSYS; if (--fimc->vid_cap.refcnt == 0) { clear_bit(ST_CAPT_BUSY, &fimc->state); @@ -1773,13 +1774,9 @@ static int fimc_capture_subdev_registered(struct v4l2_subdev *sd) if (ret) return ret; - fimc->pipeline_ops = v4l2_get_subdev_hostdata(sd); - ret = fimc_register_capture_device(fimc, sd->v4l2_dev); - if (ret) { + if (ret) fimc_unregister_m2m_device(fimc); - fimc->pipeline_ops = NULL; - } return ret; } @@ -1796,7 +1793,6 @@ static void fimc_capture_subdev_unregistered(struct v4l2_subdev *sd) if (video_is_registered(&fimc->vid_cap.vfd)) { video_unregister_device(&fimc->vid_cap.vfd); media_entity_cleanup(&fimc->vid_cap.vfd.entity); - fimc->pipeline_ops = NULL; } kfree(fimc->vid_cap.ctx); fimc->vid_cap.ctx = NULL; diff --git a/trunk/drivers/media/platform/s5p-fimc/fimc-lite.c b/trunk/drivers/media/platform/s5p-fimc/fimc-lite.c index 1b309a72f09f..9db246bed841 100644 --- a/trunk/drivers/media/platform/s5p-fimc/fimc-lite.c +++ b/trunk/drivers/media/platform/s5p-fimc/fimc-lite.c @@ -491,7 +491,8 @@ static int fimc_lite_close(struct file *file) struct fimc_lite *fimc = video_drvdata(file); int ret; - mutex_lock(&fimc->lock); + if (mutex_lock_interruptible(&fimc->lock)) + return -ERESTARTSYS; if (--fimc->ref_count == 0 && fimc->out_path == FIMC_IO_DMA) { clear_bit(ST_FLITE_IN_USE, &fimc->state); @@ -1262,12 +1263,10 @@ static int fimc_lite_subdev_registered(struct v4l2_subdev *sd) return ret; video_set_drvdata(vfd, fimc); - fimc->pipeline_ops = v4l2_get_subdev_hostdata(sd); ret = video_register_device(vfd, VFL_TYPE_GRABBER, -1); if (ret < 0) { media_entity_cleanup(&vfd->entity); - fimc->pipeline_ops = NULL; return ret; } @@ -1286,7 +1285,6 @@ static void fimc_lite_subdev_unregistered(struct v4l2_subdev *sd) if (video_is_registered(&fimc->vfd)) { video_unregister_device(&fimc->vfd); media_entity_cleanup(&fimc->vfd.entity); - fimc->pipeline_ops = NULL; } } diff --git a/trunk/drivers/media/platform/s5p-fimc/fimc-m2m.c b/trunk/drivers/media/platform/s5p-fimc/fimc-m2m.c index 62afed3162ea..4500e44f6857 100644 --- a/trunk/drivers/media/platform/s5p-fimc/fimc-m2m.c +++ b/trunk/drivers/media/platform/s5p-fimc/fimc-m2m.c @@ -718,7 +718,8 @@ static int fimc_m2m_release(struct file *file) dbg("pid: %d, state: 0x%lx, refcnt= %d", task_pid_nr(current), fimc->state, fimc->m2m.refcnt); - mutex_lock(&fimc->lock); + if (mutex_lock_interruptible(&fimc->lock)) + return -ERESTARTSYS; v4l2_m2m_ctx_release(ctx->m2m_ctx); fimc_ctrls_delete(ctx); diff --git a/trunk/drivers/media/platform/s5p-fimc/fimc-mdevice.c b/trunk/drivers/media/platform/s5p-fimc/fimc-mdevice.c index 0531ab70a94c..38ea4d143a49 100644 --- a/trunk/drivers/media/platform/s5p-fimc/fimc-mdevice.c +++ b/trunk/drivers/media/platform/s5p-fimc/fimc-mdevice.c @@ -352,7 +352,6 @@ static int fimc_register_callback(struct device *dev, void *p) sd = &fimc->vid_cap.subdev; sd->grp_id = FIMC_GROUP_ID; - v4l2_set_subdev_hostdata(sd, (void *)&fimc_pipeline_ops); ret = v4l2_device_register_subdev(&fmd->v4l2_dev, sd); if (ret) { @@ -361,6 +360,7 @@ static int fimc_register_callback(struct device *dev, void *p) return ret; } + fimc->pipeline_ops = &fimc_pipeline_ops; fmd->fimc[fimc->id] = fimc; return 0; } @@ -375,7 +375,6 @@ static int fimc_lite_register_callback(struct device *dev, void *p) return 0; fimc->subdev.grp_id = FLITE_GROUP_ID; - v4l2_set_subdev_hostdata(&fimc->subdev, (void *)&fimc_pipeline_ops); ret = v4l2_device_register_subdev(&fmd->v4l2_dev, &fimc->subdev); if (ret) { @@ -385,6 +384,7 @@ static int fimc_lite_register_callback(struct device *dev, void *p) return ret; } + fimc->pipeline_ops = &fimc_pipeline_ops; fmd->fimc_lite[fimc->index] = fimc; return 0; } diff --git a/trunk/drivers/media/platform/s5p-mfc/s5p_mfc.c b/trunk/drivers/media/platform/s5p-mfc/s5p_mfc.c index 3afe879d54d7..130f4ac8649e 100644 --- a/trunk/drivers/media/platform/s5p-mfc/s5p_mfc.c +++ b/trunk/drivers/media/platform/s5p-mfc/s5p_mfc.c @@ -381,8 +381,11 @@ static void s5p_mfc_handle_frame(struct s5p_mfc_ctx *ctx, ctx->consumed_stream += s5p_mfc_hw_call(dev->mfc_ops, get_consumed_stream, dev); if (ctx->codec_mode != S5P_MFC_CODEC_H264_DEC && - ctx->consumed_stream + STUFF_BYTE < - src_buf->b->v4l2_planes[0].bytesused) { + s5p_mfc_hw_call(dev->mfc_ops, + get_dec_frame_type, dev) == + S5P_FIMV_DECODE_FRAME_P_FRAME + && ctx->consumed_stream + STUFF_BYTE < + src_buf->b->v4l2_planes[0].bytesused) { /* Run MFC again on the same buffer */ mfc_debug(2, "Running again the same buffer\n"); ctx->after_packed_pb = 1; diff --git a/trunk/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.c b/trunk/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.c index 3a8cfd9fc1bd..50b5bee3c44e 100644 --- a/trunk/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.c +++ b/trunk/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.c @@ -1762,7 +1762,7 @@ int s5p_mfc_get_dspl_y_adr_v6(struct s5p_mfc_dev *dev) int s5p_mfc_get_dec_y_adr_v6(struct s5p_mfc_dev *dev) { - return mfc_read(dev, S5P_FIMV_D_DECODED_LUMA_ADDR_V6); + return mfc_read(dev, S5P_FIMV_D_DISPLAY_LUMA_ADDR_V6); } int s5p_mfc_get_dspl_status_v6(struct s5p_mfc_dev *dev) diff --git a/trunk/drivers/net/bonding/bond_main.c b/trunk/drivers/net/bonding/bond_main.c index a7d47350ea4b..5f5b69f37d2e 100644 --- a/trunk/drivers/net/bonding/bond_main.c +++ b/trunk/drivers/net/bonding/bond_main.c @@ -3459,28 +3459,6 @@ static int bond_xmit_hash_policy_l34(struct sk_buff *skb, int count) /*-------------------------- Device entry points ----------------------------*/ -static void bond_work_init_all(struct bonding *bond) -{ - INIT_DELAYED_WORK(&bond->mcast_work, - bond_resend_igmp_join_requests_delayed); - INIT_DELAYED_WORK(&bond->alb_work, bond_alb_monitor); - INIT_DELAYED_WORK(&bond->mii_work, bond_mii_monitor); - if (bond->params.mode == BOND_MODE_ACTIVEBACKUP) - INIT_DELAYED_WORK(&bond->arp_work, bond_activebackup_arp_mon); - else - INIT_DELAYED_WORK(&bond->arp_work, bond_loadbalance_arp_mon); - INIT_DELAYED_WORK(&bond->ad_work, bond_3ad_state_machine_handler); -} - -static void bond_work_cancel_all(struct bonding *bond) -{ - cancel_delayed_work_sync(&bond->mii_work); - cancel_delayed_work_sync(&bond->arp_work); - cancel_delayed_work_sync(&bond->alb_work); - cancel_delayed_work_sync(&bond->ad_work); - cancel_delayed_work_sync(&bond->mcast_work); -} - static int bond_open(struct net_device *bond_dev) { struct bonding *bond = netdev_priv(bond_dev); @@ -3503,27 +3481,41 @@ static int bond_open(struct net_device *bond_dev) } read_unlock(&bond->lock); - bond_work_init_all(bond); + INIT_DELAYED_WORK(&bond->mcast_work, bond_resend_igmp_join_requests_delayed); if (bond_is_lb(bond)) { /* bond_alb_initialize must be called before the timer * is started. */ - if (bond_alb_initialize(bond, (bond->params.mode == BOND_MODE_ALB))) + if (bond_alb_initialize(bond, (bond->params.mode == BOND_MODE_ALB))) { + /* something went wrong - fail the open operation */ return -ENOMEM; + } + + INIT_DELAYED_WORK(&bond->alb_work, bond_alb_monitor); queue_delayed_work(bond->wq, &bond->alb_work, 0); } - if (bond->params.miimon) /* link check interval, in milliseconds. */ + if (bond->params.miimon) { /* link check interval, in milliseconds. */ + INIT_DELAYED_WORK(&bond->mii_work, bond_mii_monitor); queue_delayed_work(bond->wq, &bond->mii_work, 0); + } if (bond->params.arp_interval) { /* arp interval, in milliseconds. */ + if (bond->params.mode == BOND_MODE_ACTIVEBACKUP) + INIT_DELAYED_WORK(&bond->arp_work, + bond_activebackup_arp_mon); + else + INIT_DELAYED_WORK(&bond->arp_work, + bond_loadbalance_arp_mon); + queue_delayed_work(bond->wq, &bond->arp_work, 0); if (bond->params.arp_validate) bond->recv_probe = bond_arp_rcv; } if (bond->params.mode == BOND_MODE_8023AD) { + INIT_DELAYED_WORK(&bond->ad_work, bond_3ad_state_machine_handler); queue_delayed_work(bond->wq, &bond->ad_work, 0); /* register to receive LACPDUs */ bond->recv_probe = bond_3ad_lacpdu_recv; @@ -3538,10 +3530,34 @@ static int bond_close(struct net_device *bond_dev) struct bonding *bond = netdev_priv(bond_dev); write_lock_bh(&bond->lock); + bond->send_peer_notif = 0; + write_unlock_bh(&bond->lock); - bond_work_cancel_all(bond); + if (bond->params.miimon) { /* link check interval, in milliseconds. */ + cancel_delayed_work_sync(&bond->mii_work); + } + + if (bond->params.arp_interval) { /* arp interval, in milliseconds. */ + cancel_delayed_work_sync(&bond->arp_work); + } + + switch (bond->params.mode) { + case BOND_MODE_8023AD: + cancel_delayed_work_sync(&bond->ad_work); + break; + case BOND_MODE_TLB: + case BOND_MODE_ALB: + cancel_delayed_work_sync(&bond->alb_work); + break; + default: + break; + } + + if (delayed_work_pending(&bond->mcast_work)) + cancel_delayed_work_sync(&bond->mcast_work); + if (bond_is_lb(bond)) { /* Must be called only after all * slaves have been released @@ -4420,6 +4436,26 @@ static void bond_setup(struct net_device *bond_dev) bond_dev->features |= bond_dev->hw_features; } +static void bond_work_cancel_all(struct bonding *bond) +{ + if (bond->params.miimon && delayed_work_pending(&bond->mii_work)) + cancel_delayed_work_sync(&bond->mii_work); + + if (bond->params.arp_interval && delayed_work_pending(&bond->arp_work)) + cancel_delayed_work_sync(&bond->arp_work); + + if (bond->params.mode == BOND_MODE_ALB && + delayed_work_pending(&bond->alb_work)) + cancel_delayed_work_sync(&bond->alb_work); + + if (bond->params.mode == BOND_MODE_8023AD && + delayed_work_pending(&bond->ad_work)) + cancel_delayed_work_sync(&bond->ad_work); + + if (delayed_work_pending(&bond->mcast_work)) + cancel_delayed_work_sync(&bond->mcast_work); +} + /* * Destroy a bonding device. * Must be under rtnl_lock when this function is called. @@ -4670,13 +4706,12 @@ static int bond_check_params(struct bond_params *params) arp_ip_count++) { /* not complete check, but should be good enough to catch mistakes */ - __be32 ip = in_aton(arp_ip_target[arp_ip_count]); - if (!isdigit(arp_ip_target[arp_ip_count][0]) || - ip == 0 || ip == htonl(INADDR_BROADCAST)) { + if (!isdigit(arp_ip_target[arp_ip_count][0])) { pr_warning("Warning: bad arp_ip_target module parameter (%s), ARP monitoring will not be performed\n", arp_ip_target[arp_ip_count]); arp_interval = 0; } else { + __be32 ip = in_aton(arp_ip_target[arp_ip_count]); arp_target[arp_ip_count] = ip; } } diff --git a/trunk/drivers/net/bonding/bond_sysfs.c b/trunk/drivers/net/bonding/bond_sysfs.c index 1877ed7ca086..ef8d2a080d17 100644 --- a/trunk/drivers/net/bonding/bond_sysfs.c +++ b/trunk/drivers/net/bonding/bond_sysfs.c @@ -513,8 +513,6 @@ static ssize_t bonding_store_arp_interval(struct device *d, int new_value, ret = count; struct bonding *bond = to_bond(d); - if (!rtnl_trylock()) - return restart_syscall(); if (sscanf(buf, "%d", &new_value) != 1) { pr_err("%s: no arp_interval value specified.\n", bond->dev->name); @@ -541,6 +539,10 @@ static ssize_t bonding_store_arp_interval(struct device *d, pr_info("%s: ARP monitoring cannot be used with MII monitoring. %s Disabling MII monitoring.\n", bond->dev->name, bond->dev->name); bond->params.miimon = 0; + if (delayed_work_pending(&bond->mii_work)) { + cancel_delayed_work(&bond->mii_work); + flush_workqueue(bond->wq); + } } if (!bond->params.arp_targets[0]) { pr_info("%s: ARP monitoring has been set up, but no ARP targets have been specified.\n", @@ -552,12 +554,19 @@ static ssize_t bonding_store_arp_interval(struct device *d, * timer will get fired off when the open function * is called. */ - cancel_delayed_work_sync(&bond->mii_work); - queue_delayed_work(bond->wq, &bond->arp_work, 0); + if (!delayed_work_pending(&bond->arp_work)) { + if (bond->params.mode == BOND_MODE_ACTIVEBACKUP) + INIT_DELAYED_WORK(&bond->arp_work, + bond_activebackup_arp_mon); + else + INIT_DELAYED_WORK(&bond->arp_work, + bond_loadbalance_arp_mon); + + queue_delayed_work(bond->wq, &bond->arp_work, 0); + } } out: - rtnl_unlock(); return ret; } static DEVICE_ATTR(arp_interval, S_IRUGO | S_IWUSR, @@ -953,8 +962,6 @@ static ssize_t bonding_store_miimon(struct device *d, int new_value, ret = count; struct bonding *bond = to_bond(d); - if (!rtnl_trylock()) - return restart_syscall(); if (sscanf(buf, "%d", &new_value) != 1) { pr_err("%s: no miimon value specified.\n", bond->dev->name); @@ -986,6 +993,10 @@ static ssize_t bonding_store_miimon(struct device *d, bond->params.arp_validate = BOND_ARP_VALIDATE_NONE; } + if (delayed_work_pending(&bond->arp_work)) { + cancel_delayed_work(&bond->arp_work); + flush_workqueue(bond->wq); + } } if (bond->dev->flags & IFF_UP) { @@ -994,12 +1005,15 @@ static ssize_t bonding_store_miimon(struct device *d, * timer will get fired off when the open function * is called. */ - cancel_delayed_work_sync(&bond->arp_work); - queue_delayed_work(bond->wq, &bond->mii_work, 0); + if (!delayed_work_pending(&bond->mii_work)) { + INIT_DELAYED_WORK(&bond->mii_work, + bond_mii_monitor); + queue_delayed_work(bond->wq, + &bond->mii_work, 0); + } } } out: - rtnl_unlock(); return ret; } static DEVICE_ATTR(miimon, S_IRUGO | S_IWUSR, @@ -1568,7 +1582,6 @@ static ssize_t bonding_store_slaves_active(struct device *d, goto out; } - read_lock(&bond->lock); bond_for_each_slave(bond, slave, i) { if (!bond_is_active_slave(slave)) { if (new_value) @@ -1577,7 +1590,6 @@ static ssize_t bonding_store_slaves_active(struct device *d, slave->inactive = 1; } } - read_unlock(&bond->lock); out: return ret; } diff --git a/trunk/drivers/net/ethernet/realtek/8139cp.c b/trunk/drivers/net/ethernet/realtek/8139cp.c index 609125a249d9..b01f83a044c4 100644 --- a/trunk/drivers/net/ethernet/realtek/8139cp.c +++ b/trunk/drivers/net/ethernet/realtek/8139cp.c @@ -1060,22 +1060,17 @@ static int cp_init_rings (struct cp_private *cp) static int cp_alloc_rings (struct cp_private *cp) { - struct device *d = &cp->pdev->dev; void *mem; - int rc; - mem = dma_alloc_coherent(d, CP_RING_BYTES, &cp->ring_dma, GFP_KERNEL); + mem = dma_alloc_coherent(&cp->pdev->dev, CP_RING_BYTES, + &cp->ring_dma, GFP_KERNEL); if (!mem) return -ENOMEM; cp->rx_ring = mem; cp->tx_ring = &cp->rx_ring[CP_RX_RING_SIZE]; - rc = cp_init_rings(cp); - if (rc < 0) - dma_free_coherent(d, CP_RING_BYTES, cp->rx_ring, cp->ring_dma); - - return rc; + return cp_init_rings(cp); } static void cp_clean_rings (struct cp_private *cp) diff --git a/trunk/drivers/net/wireless/iwlwifi/dvm/rxon.c b/trunk/drivers/net/wireless/iwlwifi/dvm/rxon.c index 2830ea290502..10896393e5a0 100644 --- a/trunk/drivers/net/wireless/iwlwifi/dvm/rxon.c +++ b/trunk/drivers/net/wireless/iwlwifi/dvm/rxon.c @@ -1012,12 +1012,12 @@ static void iwl_calc_basic_rates(struct iwl_priv *priv, * As a consequence, it's not as complicated as it sounds, just add * any lower rates to the ACK rate bitmap. */ - if (IWL_RATE_11M_INDEX < lowest_present_cck) - cck |= IWL_RATE_11M_MASK >> IWL_FIRST_CCK_RATE; - if (IWL_RATE_5M_INDEX < lowest_present_cck) - cck |= IWL_RATE_5M_MASK >> IWL_FIRST_CCK_RATE; - if (IWL_RATE_2M_INDEX < lowest_present_cck) - cck |= IWL_RATE_2M_MASK >> IWL_FIRST_CCK_RATE; + if (IWL_RATE_11M_INDEX < lowest_present_ofdm) + ofdm |= IWL_RATE_11M_MASK >> IWL_FIRST_CCK_RATE; + if (IWL_RATE_5M_INDEX < lowest_present_ofdm) + ofdm |= IWL_RATE_5M_MASK >> IWL_FIRST_CCK_RATE; + if (IWL_RATE_2M_INDEX < lowest_present_ofdm) + ofdm |= IWL_RATE_2M_MASK >> IWL_FIRST_CCK_RATE; /* 1M already there or needed so always add */ cck |= IWL_RATE_1M_MASK >> IWL_FIRST_CCK_RATE; diff --git a/trunk/drivers/scsi/megaraid/megaraid_sas.h b/trunk/drivers/scsi/megaraid/megaraid_sas.h index 16b7a72a70c4..3b2365c8eab2 100644 --- a/trunk/drivers/scsi/megaraid/megaraid_sas.h +++ b/trunk/drivers/scsi/megaraid/megaraid_sas.h @@ -1276,7 +1276,7 @@ struct megasas_evt_detail { } __attribute__ ((packed)); struct megasas_aen_event { - struct work_struct hotplug_work; + struct delayed_work hotplug_work; struct megasas_instance *instance; }; diff --git a/trunk/drivers/scsi/megaraid/megaraid_sas_base.c b/trunk/drivers/scsi/megaraid/megaraid_sas_base.c index d2c5366aff7f..e4f2baacf1e1 100644 --- a/trunk/drivers/scsi/megaraid/megaraid_sas_base.c +++ b/trunk/drivers/scsi/megaraid/megaraid_sas_base.c @@ -2060,9 +2060,9 @@ megasas_service_aen(struct megasas_instance *instance, struct megasas_cmd *cmd) } else { ev->instance = instance; instance->ev = ev; - INIT_WORK(&ev->hotplug_work, megasas_aen_polling); - schedule_delayed_work( - (struct delayed_work *)&ev->hotplug_work, 0); + INIT_DELAYED_WORK(&ev->hotplug_work, + megasas_aen_polling); + schedule_delayed_work(&ev->hotplug_work, 0); } } } @@ -4352,8 +4352,7 @@ megasas_suspend(struct pci_dev *pdev, pm_message_t state) /* cancel the delayed work if this work still in queue */ if (instance->ev != NULL) { struct megasas_aen_event *ev = instance->ev; - cancel_delayed_work_sync( - (struct delayed_work *)&ev->hotplug_work); + cancel_delayed_work_sync(&ev->hotplug_work); instance->ev = NULL; } @@ -4545,8 +4544,7 @@ static void __devexit megasas_detach_one(struct pci_dev *pdev) /* cancel the delayed work if this work still in queue*/ if (instance->ev != NULL) { struct megasas_aen_event *ev = instance->ev; - cancel_delayed_work_sync( - (struct delayed_work *)&ev->hotplug_work); + cancel_delayed_work_sync(&ev->hotplug_work); instance->ev = NULL; } @@ -5190,7 +5188,7 @@ static void megasas_aen_polling(struct work_struct *work) { struct megasas_aen_event *ev = - container_of(work, struct megasas_aen_event, hotplug_work); + container_of(work, struct megasas_aen_event, hotplug_work.work); struct megasas_instance *instance = ev->instance; union megasas_evt_class_locale class_locale; struct Scsi_Host *host; diff --git a/trunk/fs/block_dev.c b/trunk/fs/block_dev.c index a1e09b4fe1ba..1a1e5e3b1eaf 100644 --- a/trunk/fs/block_dev.c +++ b/trunk/fs/block_dev.c @@ -70,6 +70,19 @@ static void bdev_inode_switch_bdi(struct inode *inode, spin_unlock(&dst->wb.list_lock); } +sector_t blkdev_max_block(struct block_device *bdev) +{ + sector_t retval = ~((sector_t)0); + loff_t sz = i_size_read(bdev->bd_inode); + + if (sz) { + unsigned int size = block_size(bdev); + unsigned int sizebits = blksize_bits(size); + retval = (sz >> sizebits); + } + return retval; +} + /* Kill _all_ buffers and pagecache , dirty or not.. */ void kill_bdev(struct block_device *bdev) { @@ -103,6 +116,8 @@ EXPORT_SYMBOL(invalidate_bdev); int set_blocksize(struct block_device *bdev, int size) { + struct address_space *mapping; + /* Size must be a power of two, and between 512 and PAGE_SIZE */ if (size > PAGE_SIZE || size < 512 || !is_power_of_2(size)) return -EINVAL; @@ -111,6 +126,19 @@ int set_blocksize(struct block_device *bdev, int size) if (size < bdev_logical_block_size(bdev)) return -EINVAL; + /* Prevent starting I/O or mapping the device */ + percpu_down_write(&bdev->bd_block_size_semaphore); + + /* Check that the block device is not memory mapped */ + mapping = bdev->bd_inode->i_mapping; + mutex_lock(&mapping->i_mmap_mutex); + if (mapping_mapped(mapping)) { + mutex_unlock(&mapping->i_mmap_mutex); + percpu_up_write(&bdev->bd_block_size_semaphore); + return -EBUSY; + } + mutex_unlock(&mapping->i_mmap_mutex); + /* Don't change the size if it is same as current */ if (bdev->bd_block_size != size) { sync_blockdev(bdev); @@ -118,6 +146,9 @@ int set_blocksize(struct block_device *bdev, int size) bdev->bd_inode->i_blkbits = blksize_bits(size); kill_bdev(bdev); } + + percpu_up_write(&bdev->bd_block_size_semaphore); + return 0; } @@ -150,12 +181,52 @@ static int blkdev_get_block(struct inode *inode, sector_t iblock, struct buffer_head *bh, int create) { + if (iblock >= blkdev_max_block(I_BDEV(inode))) { + if (create) + return -EIO; + + /* + * for reads, we're just trying to fill a partial page. + * return a hole, they will have to call get_block again + * before they can fill it, and they will get -EIO at that + * time + */ + return 0; + } bh->b_bdev = I_BDEV(inode); bh->b_blocknr = iblock; set_buffer_mapped(bh); return 0; } +static int +blkdev_get_blocks(struct inode *inode, sector_t iblock, + struct buffer_head *bh, int create) +{ + sector_t end_block = blkdev_max_block(I_BDEV(inode)); + unsigned long max_blocks = bh->b_size >> inode->i_blkbits; + + if ((iblock + max_blocks) > end_block) { + max_blocks = end_block - iblock; + if ((long)max_blocks <= 0) { + if (create) + return -EIO; /* write fully beyond EOF */ + /* + * It is a read which is fully beyond EOF. We return + * a !buffer_mapped buffer + */ + max_blocks = 0; + } + } + + bh->b_bdev = I_BDEV(inode); + bh->b_blocknr = iblock; + bh->b_size = max_blocks << inode->i_blkbits; + if (max_blocks) + set_buffer_mapped(bh); + return 0; +} + static ssize_t blkdev_direct_IO(int rw, struct kiocb *iocb, const struct iovec *iov, loff_t offset, unsigned long nr_segs) @@ -164,7 +235,7 @@ blkdev_direct_IO(int rw, struct kiocb *iocb, const struct iovec *iov, struct inode *inode = file->f_mapping->host; return __blockdev_direct_IO(rw, iocb, inode, I_BDEV(inode), iov, offset, - nr_segs, blkdev_get_block, NULL, NULL, 0); + nr_segs, blkdev_get_blocks, NULL, NULL, 0); } int __sync_blockdev(struct block_device *bdev, int wait) @@ -388,6 +459,12 @@ static struct inode *bdev_alloc_inode(struct super_block *sb) struct bdev_inode *ei = kmem_cache_alloc(bdev_cachep, GFP_KERNEL); if (!ei) return NULL; + + if (unlikely(percpu_init_rwsem(&ei->bdev.bd_block_size_semaphore))) { + kmem_cache_free(bdev_cachep, ei); + return NULL; + } + return &ei->vfs_inode; } @@ -396,6 +473,8 @@ static void bdev_i_callback(struct rcu_head *head) struct inode *inode = container_of(head, struct inode, i_rcu); struct bdev_inode *bdi = BDEV_I(inode); + percpu_free_rwsem(&bdi->bdev.bd_block_size_semaphore); + kmem_cache_free(bdev_cachep, bdi); } @@ -1514,6 +1593,22 @@ static long block_ioctl(struct file *file, unsigned cmd, unsigned long arg) return blkdev_ioctl(bdev, mode, cmd, arg); } +ssize_t blkdev_aio_read(struct kiocb *iocb, const struct iovec *iov, + unsigned long nr_segs, loff_t pos) +{ + ssize_t ret; + struct block_device *bdev = I_BDEV(iocb->ki_filp->f_mapping->host); + + percpu_down_read(&bdev->bd_block_size_semaphore); + + ret = generic_file_aio_read(iocb, iov, nr_segs, pos); + + percpu_up_read(&bdev->bd_block_size_semaphore); + + return ret; +} +EXPORT_SYMBOL_GPL(blkdev_aio_read); + /* * Write data to the block device. Only intended for the block device itself * and the raw driver which basically is a fake block device. @@ -1525,12 +1620,16 @@ ssize_t blkdev_aio_write(struct kiocb *iocb, const struct iovec *iov, unsigned long nr_segs, loff_t pos) { struct file *file = iocb->ki_filp; + struct block_device *bdev = I_BDEV(file->f_mapping->host); struct blk_plug plug; ssize_t ret; BUG_ON(iocb->ki_pos != pos); blk_start_plug(&plug); + + percpu_down_read(&bdev->bd_block_size_semaphore); + ret = __generic_file_aio_write(iocb, iov, nr_segs, &iocb->ki_pos); if (ret > 0 || ret == -EIOCBQUEUED) { ssize_t err; @@ -1539,11 +1638,62 @@ ssize_t blkdev_aio_write(struct kiocb *iocb, const struct iovec *iov, if (err < 0 && ret > 0) ret = err; } + + percpu_up_read(&bdev->bd_block_size_semaphore); + blk_finish_plug(&plug); + return ret; } EXPORT_SYMBOL_GPL(blkdev_aio_write); +static int blkdev_mmap(struct file *file, struct vm_area_struct *vma) +{ + int ret; + struct block_device *bdev = I_BDEV(file->f_mapping->host); + + percpu_down_read(&bdev->bd_block_size_semaphore); + + ret = generic_file_mmap(file, vma); + + percpu_up_read(&bdev->bd_block_size_semaphore); + + return ret; +} + +static ssize_t blkdev_splice_read(struct file *file, loff_t *ppos, + struct pipe_inode_info *pipe, size_t len, + unsigned int flags) +{ + ssize_t ret; + struct block_device *bdev = I_BDEV(file->f_mapping->host); + + percpu_down_read(&bdev->bd_block_size_semaphore); + + ret = generic_file_splice_read(file, ppos, pipe, len, flags); + + percpu_up_read(&bdev->bd_block_size_semaphore); + + return ret; +} + +static ssize_t blkdev_splice_write(struct pipe_inode_info *pipe, + struct file *file, loff_t *ppos, size_t len, + unsigned int flags) +{ + ssize_t ret; + struct block_device *bdev = I_BDEV(file->f_mapping->host); + + percpu_down_read(&bdev->bd_block_size_semaphore); + + ret = generic_file_splice_write(pipe, file, ppos, len, flags); + + percpu_up_read(&bdev->bd_block_size_semaphore); + + return ret; +} + + /* * Try to release a page associated with block device when the system * is under memory pressure. @@ -1574,16 +1724,16 @@ const struct file_operations def_blk_fops = { .llseek = block_llseek, .read = do_sync_read, .write = do_sync_write, - .aio_read = generic_file_aio_read, + .aio_read = blkdev_aio_read, .aio_write = blkdev_aio_write, - .mmap = generic_file_mmap, + .mmap = blkdev_mmap, .fsync = blkdev_fsync, .unlocked_ioctl = block_ioctl, #ifdef CONFIG_COMPAT .compat_ioctl = compat_blkdev_ioctl, #endif - .splice_read = generic_file_splice_read, - .splice_write = generic_file_splice_write, + .splice_read = blkdev_splice_read, + .splice_write = blkdev_splice_write, }; int ioctl_by_bdev(struct block_device *bdev, unsigned cmd, unsigned long arg) diff --git a/trunk/fs/buffer.c b/trunk/fs/buffer.c index c4e11390a44c..b5f044283edb 100644 --- a/trunk/fs/buffer.c +++ b/trunk/fs/buffer.c @@ -911,18 +911,6 @@ link_dev_buffers(struct page *page, struct buffer_head *head) attach_page_buffers(page, head); } -static sector_t blkdev_max_block(struct block_device *bdev, unsigned int size) -{ - sector_t retval = ~((sector_t)0); - loff_t sz = i_size_read(bdev->bd_inode); - - if (sz) { - unsigned int sizebits = blksize_bits(size); - retval = (sz >> sizebits); - } - return retval; -} - /* * Initialise the state of a blockdev page's buffers. */ @@ -933,7 +921,7 @@ init_page_buffers(struct page *page, struct block_device *bdev, struct buffer_head *head = page_buffers(page); struct buffer_head *bh = head; int uptodate = PageUptodate(page); - sector_t end_block = blkdev_max_block(I_BDEV(bdev->bd_inode), size); + sector_t end_block = blkdev_max_block(I_BDEV(bdev->bd_inode)); do { if (!buffer_mapped(bh)) { @@ -1564,28 +1552,6 @@ void unmap_underlying_metadata(struct block_device *bdev, sector_t block) } EXPORT_SYMBOL(unmap_underlying_metadata); -/* - * Size is a power-of-two in the range 512..PAGE_SIZE, - * and the case we care about most is PAGE_SIZE. - * - * So this *could* possibly be written with those - * constraints in mind (relevant mostly if some - * architecture has a slow bit-scan instruction) - */ -static inline int block_size_bits(unsigned int blocksize) -{ - return ilog2(blocksize); -} - -static struct buffer_head *create_page_buffers(struct page *page, struct inode *inode, unsigned int b_state) -{ - BUG_ON(!PageLocked(page)); - - if (!page_has_buffers(page)) - create_empty_buffers(page, 1 << ACCESS_ONCE(inode->i_blkbits), b_state); - return page_buffers(page); -} - /* * NOTE! All mapped/uptodate combinations are valid: * @@ -1623,13 +1589,19 @@ static int __block_write_full_page(struct inode *inode, struct page *page, sector_t block; sector_t last_block; struct buffer_head *bh, *head; - unsigned int blocksize, bbits; + const unsigned blocksize = 1 << inode->i_blkbits; int nr_underway = 0; int write_op = (wbc->sync_mode == WB_SYNC_ALL ? WRITE_SYNC : WRITE); - head = create_page_buffers(page, inode, + BUG_ON(!PageLocked(page)); + + last_block = (i_size_read(inode) - 1) >> inode->i_blkbits; + + if (!page_has_buffers(page)) { + create_empty_buffers(page, blocksize, (1 << BH_Dirty)|(1 << BH_Uptodate)); + } /* * Be very careful. We have no exclusion from __set_page_dirty_buffers @@ -1641,12 +1613,9 @@ static int __block_write_full_page(struct inode *inode, struct page *page, * handle that here by just cleaning them. */ + block = (sector_t)page->index << (PAGE_CACHE_SHIFT - inode->i_blkbits); + head = page_buffers(page); bh = head; - blocksize = bh->b_size; - bbits = block_size_bits(blocksize); - - block = (sector_t)page->index << (PAGE_CACHE_SHIFT - bbits); - last_block = (i_size_read(inode) - 1) >> bbits; /* * Get all the dirty buffers mapped to disk addresses and @@ -1837,10 +1806,12 @@ int __block_write_begin(struct page *page, loff_t pos, unsigned len, BUG_ON(to > PAGE_CACHE_SIZE); BUG_ON(from > to); - head = create_page_buffers(page, inode, 0); - blocksize = head->b_size; - bbits = block_size_bits(blocksize); + blocksize = 1 << inode->i_blkbits; + if (!page_has_buffers(page)) + create_empty_buffers(page, blocksize, 0); + head = page_buffers(page); + bbits = inode->i_blkbits; block = (sector_t)page->index << (PAGE_CACHE_SHIFT - bbits); for(bh = head, block_start = 0; bh != head || !block_start; @@ -1910,11 +1881,11 @@ static int __block_commit_write(struct inode *inode, struct page *page, unsigned blocksize; struct buffer_head *bh, *head; - bh = head = page_buffers(page); - blocksize = bh->b_size; + blocksize = 1 << inode->i_blkbits; - block_start = 0; - do { + for(bh = head = page_buffers(page), block_start = 0; + bh != head || !block_start; + block_start=block_end, bh = bh->b_this_page) { block_end = block_start + blocksize; if (block_end <= from || block_start >= to) { if (!buffer_uptodate(bh)) @@ -1924,10 +1895,7 @@ static int __block_commit_write(struct inode *inode, struct page *page, mark_buffer_dirty(bh); } clear_buffer_new(bh); - - block_start = block_end; - bh = bh->b_this_page; - } while (bh != head); + } /* * If this is a partial write which happened to make all buffers @@ -2052,6 +2020,7 @@ EXPORT_SYMBOL(generic_write_end); int block_is_partially_uptodate(struct page *page, read_descriptor_t *desc, unsigned long from) { + struct inode *inode = page->mapping->host; unsigned block_start, block_end, blocksize; unsigned to; struct buffer_head *bh, *head; @@ -2060,13 +2029,13 @@ int block_is_partially_uptodate(struct page *page, read_descriptor_t *desc, if (!page_has_buffers(page)) return 0; - head = page_buffers(page); - blocksize = head->b_size; + blocksize = 1 << inode->i_blkbits; to = min_t(unsigned, PAGE_CACHE_SIZE - from, desc->count); to = from + to; if (from < blocksize && to > PAGE_CACHE_SIZE - blocksize) return 0; + head = page_buffers(page); bh = head; block_start = 0; do { @@ -2099,16 +2068,18 @@ int block_read_full_page(struct page *page, get_block_t *get_block) struct inode *inode = page->mapping->host; sector_t iblock, lblock; struct buffer_head *bh, *head, *arr[MAX_BUF_PER_PAGE]; - unsigned int blocksize, bbits; + unsigned int blocksize; int nr, i; int fully_mapped = 1; - head = create_page_buffers(page, inode, 0); - blocksize = head->b_size; - bbits = block_size_bits(blocksize); + BUG_ON(!PageLocked(page)); + blocksize = 1 << inode->i_blkbits; + if (!page_has_buffers(page)) + create_empty_buffers(page, blocksize, 0); + head = page_buffers(page); - iblock = (sector_t)page->index << (PAGE_CACHE_SHIFT - bbits); - lblock = (i_size_read(inode)+blocksize-1) >> bbits; + iblock = (sector_t)page->index << (PAGE_CACHE_SHIFT - inode->i_blkbits); + lblock = (i_size_read(inode)+blocksize-1) >> inode->i_blkbits; bh = head; nr = 0; i = 0; @@ -2893,55 +2864,6 @@ static void end_bio_bh_io_sync(struct bio *bio, int err) bio_put(bio); } -/* - * This allows us to do IO even on the odd last sectors - * of a device, even if the bh block size is some multiple - * of the physical sector size. - * - * We'll just truncate the bio to the size of the device, - * and clear the end of the buffer head manually. - * - * Truly out-of-range accesses will turn into actual IO - * errors, this only handles the "we need to be able to - * do IO at the final sector" case. - */ -static void guard_bh_eod(int rw, struct bio *bio, struct buffer_head *bh) -{ - sector_t maxsector; - unsigned bytes; - - maxsector = i_size_read(bio->bi_bdev->bd_inode) >> 9; - if (!maxsector) - return; - - /* - * If the *whole* IO is past the end of the device, - * let it through, and the IO layer will turn it into - * an EIO. - */ - if (unlikely(bio->bi_sector >= maxsector)) - return; - - maxsector -= bio->bi_sector; - bytes = bio->bi_size; - if (likely((bytes >> 9) <= maxsector)) - return; - - /* Uhhuh. We've got a bh that straddles the device size! */ - bytes = maxsector << 9; - - /* Truncate the bio.. */ - bio->bi_size = bytes; - bio->bi_io_vec[0].bv_len = bytes; - - /* ..and clear the end of the buffer for reads */ - if (rw & READ) { - void *kaddr = kmap_atomic(bh->b_page); - memset(kaddr + bh_offset(bh) + bytes, 0, bh->b_size - bytes); - kunmap_atomic(kaddr); - } -} - int submit_bh(int rw, struct buffer_head * bh) { struct bio *bio; @@ -2978,9 +2900,6 @@ int submit_bh(int rw, struct buffer_head * bh) bio->bi_end_io = end_bio_bh_io_sync; bio->bi_private = bh; - /* Take care of bh's that straddle the end of the device */ - guard_bh_eod(rw, bio, bh); - bio_get(bio); submit_bio(rw, bio); diff --git a/trunk/fs/cifs/readdir.c b/trunk/fs/cifs/readdir.c index 1c576e871366..f9b5d3d6cf33 100644 --- a/trunk/fs/cifs/readdir.c +++ b/trunk/fs/cifs/readdir.c @@ -86,17 +86,14 @@ cifs_readdir_lookup(struct dentry *parent, struct qstr *name, dentry = d_lookup(parent, name); if (dentry) { - int err; inode = dentry->d_inode; /* update inode in place if i_ino didn't change */ if (inode && CIFS_I(inode)->uniqueid == fattr->cf_uniqueid) { cifs_fattr_to_inode(inode, fattr); return dentry; } - err = d_invalidate(dentry); + d_drop(dentry); dput(dentry); - if (err) - return NULL; } dentry = d_alloc(parent, name); diff --git a/trunk/fs/direct-io.c b/trunk/fs/direct-io.c index cf5b44b10c67..f86c720dba0e 100644 --- a/trunk/fs/direct-io.c +++ b/trunk/fs/direct-io.c @@ -540,7 +540,6 @@ static int get_more_blocks(struct dio *dio, struct dio_submit *sdio, sector_t fs_endblk; /* Into file, in filesystem-sized blocks */ unsigned long fs_count; /* Number of filesystem-sized blocks */ int create; - unsigned int i_blkbits = sdio->blkbits + sdio->blkfactor; /* * If there was a memory error and we've overwritten all the @@ -555,7 +554,7 @@ static int get_more_blocks(struct dio *dio, struct dio_submit *sdio, fs_count = fs_endblk - fs_startblk + 1; map_bh->b_state = 0; - map_bh->b_size = fs_count << i_blkbits; + map_bh->b_size = fs_count << dio->inode->i_blkbits; /* * For writes inside i_size on a DIO_SKIP_HOLES filesystem we @@ -1054,8 +1053,7 @@ do_blockdev_direct_IO(int rw, struct kiocb *iocb, struct inode *inode, int seg; size_t size; unsigned long addr; - unsigned i_blkbits = ACCESS_ONCE(inode->i_blkbits); - unsigned blkbits = i_blkbits; + unsigned blkbits = inode->i_blkbits; unsigned blocksize_mask = (1 << blkbits) - 1; ssize_t retval = -EINVAL; loff_t end = offset; @@ -1151,7 +1149,7 @@ do_blockdev_direct_IO(int rw, struct kiocb *iocb, struct inode *inode, dio->inode = inode; dio->rw = rw; sdio.blkbits = blkbits; - sdio.blkfactor = i_blkbits - blkbits; + sdio.blkfactor = inode->i_blkbits - blkbits; sdio.block_in_file = offset >> blkbits; sdio.get_block = get_block; diff --git a/trunk/fs/file.c b/trunk/fs/file.c index eff23162485f..7cb71b992603 100644 --- a/trunk/fs/file.c +++ b/trunk/fs/file.c @@ -994,18 +994,16 @@ int iterate_fd(struct files_struct *files, unsigned n, const void *p) { struct fdtable *fdt; + struct file *file; int res = 0; if (!files) return 0; spin_lock(&files->file_lock); - for (fdt = files_fdtable(files); n < fdt->max_fds; n++) { - struct file *file; - file = rcu_dereference_check_fdtable(files, fdt->fd[n]); - if (!file) - continue; - res = f(p, file, n); - if (res) - break; + fdt = files_fdtable(files); + while (!res && n < fdt->max_fds) { + file = rcu_dereference_check_fdtable(files, fdt->fd[n++]); + if (file) + res = f(p, file, n); } spin_unlock(&files->file_lock); return res; diff --git a/trunk/fs/namei.c b/trunk/fs/namei.c index 5f4cdf3ad913..937f9d50c84b 100644 --- a/trunk/fs/namei.c +++ b/trunk/fs/namei.c @@ -2131,11 +2131,6 @@ struct dentry *lookup_one_len(const char *name, struct dentry *base, int len) if (!len) return ERR_PTR(-EACCES); - if (unlikely(name[0] == '.')) { - if (len < 2 || (len == 2 && name[1] == '.')) - return ERR_PTR(-EACCES); - } - while (len--) { c = *(const unsigned char *)name++; if (c == '/' || c == '\0') diff --git a/trunk/fs/nfs/dir.c b/trunk/fs/nfs/dir.c index b9e66b7e0c14..ce8cb926526b 100644 --- a/trunk/fs/nfs/dir.c +++ b/trunk/fs/nfs/dir.c @@ -450,8 +450,7 @@ void nfs_prime_dcache(struct dentry *parent, struct nfs_entry *entry) nfs_refresh_inode(dentry->d_inode, entry->fattr); goto out; } else { - if (d_invalidate(dentry) != 0) - goto out; + d_drop(dentry); dput(dentry); } } @@ -1101,8 +1100,6 @@ static int nfs_lookup_revalidate(struct dentry *dentry, unsigned int flags) out_zap_parent: nfs_zap_caches(dir); out_bad: - nfs_free_fattr(fattr); - nfs_free_fhandle(fhandle); nfs_mark_for_revalidate(dir); if (inode && S_ISDIR(inode->i_mode)) { /* Purge readdir caches. */ @@ -1115,6 +1112,8 @@ static int nfs_lookup_revalidate(struct dentry *dentry, unsigned int flags) shrink_dcache_parent(dentry); } d_drop(dentry); + nfs_free_fattr(fattr); + nfs_free_fhandle(fhandle); dput(parent); dfprintk(LOOKUPCACHE, "NFS: %s(%s/%s) is invalid\n", __func__, dentry->d_parent->d_name.name, diff --git a/trunk/include/linux/fs.h b/trunk/include/linux/fs.h index 75fe9a134803..b33cfc97b9ca 100644 --- a/trunk/include/linux/fs.h +++ b/trunk/include/linux/fs.h @@ -462,6 +462,8 @@ struct block_device { int bd_fsfreeze_count; /* Mutex for freeze */ struct mutex bd_fsfreeze_mutex; + /* A semaphore that prevents I/O while block size is being changed */ + struct percpu_rw_semaphore bd_block_size_semaphore; }; /* @@ -2047,6 +2049,7 @@ extern void unregister_blkdev(unsigned int, const char *); extern struct block_device *bdget(dev_t); extern struct block_device *bdgrab(struct block_device *bdev); extern void bd_set_size(struct block_device *, loff_t size); +extern sector_t blkdev_max_block(struct block_device *bdev); extern void bd_forget(struct inode *inode); extern void bdput(struct block_device *); extern void invalidate_bdev(struct block_device *); @@ -2376,6 +2379,8 @@ extern int generic_segment_checks(const struct iovec *iov, unsigned long *nr_segs, size_t *count, int access_flags); /* fs/block_dev.c */ +extern ssize_t blkdev_aio_read(struct kiocb *iocb, const struct iovec *iov, + unsigned long nr_segs, loff_t pos); extern ssize_t blkdev_aio_write(struct kiocb *iocb, const struct iovec *iov, unsigned long nr_segs, loff_t pos); extern int blkdev_fsync(struct file *filp, loff_t start, loff_t end, diff --git a/trunk/kernel/sched/auto_group.c b/trunk/kernel/sched/auto_group.c index 15f60d01198b..0984a21076a3 100644 --- a/trunk/kernel/sched/auto_group.c +++ b/trunk/kernel/sched/auto_group.c @@ -143,11 +143,15 @@ autogroup_move_group(struct task_struct *p, struct autogroup *ag) p->signal->autogroup = autogroup_kref_get(ag); + if (!ACCESS_ONCE(sysctl_sched_autogroup_enabled)) + goto out; + t = p; do { sched_move_task(t); } while_each_thread(p, t); +out: unlock_task_sighand(p, &flags); autogroup_kref_put(prev); } diff --git a/trunk/kernel/sched/auto_group.h b/trunk/kernel/sched/auto_group.h index 443232ebbb53..8bd047142816 100644 --- a/trunk/kernel/sched/auto_group.h +++ b/trunk/kernel/sched/auto_group.h @@ -4,6 +4,11 @@ #include struct autogroup { + /* + * reference doesn't mean how many thread attach to this + * autogroup now. It just stands for the number of task + * could use this autogroup. + */ struct kref kref; struct task_group *tg; struct rw_semaphore lock; diff --git a/trunk/net/ipv4/tcp.c b/trunk/net/ipv4/tcp.c index e457c7ab2e28..083092e3aed6 100644 --- a/trunk/net/ipv4/tcp.c +++ b/trunk/net/ipv4/tcp.c @@ -830,8 +830,8 @@ static int tcp_send_mss(struct sock *sk, int *size_goal, int flags) return mss_now; } -static ssize_t do_tcp_sendpages(struct sock *sk, struct page *page, int offset, - size_t size, int flags) +static ssize_t do_tcp_sendpages(struct sock *sk, struct page **pages, int poffset, + size_t psize, int flags) { struct tcp_sock *tp = tcp_sk(sk); int mss_now, size_goal; @@ -858,9 +858,12 @@ static ssize_t do_tcp_sendpages(struct sock *sk, struct page *page, int offset, if (sk->sk_err || (sk->sk_shutdown & SEND_SHUTDOWN)) goto out_err; - while (size > 0) { + while (psize > 0) { struct sk_buff *skb = tcp_write_queue_tail(sk); + struct page *page = pages[poffset / PAGE_SIZE]; int copy, i; + int offset = poffset % PAGE_SIZE; + int size = min_t(size_t, psize, PAGE_SIZE - offset); bool can_coalesce; if (!tcp_send_head(sk) || (copy = size_goal - skb->len) <= 0) { @@ -909,8 +912,8 @@ static ssize_t do_tcp_sendpages(struct sock *sk, struct page *page, int offset, TCP_SKB_CB(skb)->tcp_flags &= ~TCPHDR_PSH; copied += copy; - offset += copy; - if (!(size -= copy)) + poffset += copy; + if (!(psize -= copy)) goto out; if (skb->len < size_goal || (flags & MSG_OOB)) @@ -957,7 +960,7 @@ int tcp_sendpage(struct sock *sk, struct page *page, int offset, flags); lock_sock(sk); - res = do_tcp_sendpages(sk, page, offset, size, flags); + res = do_tcp_sendpages(sk, &page, offset, size, flags); release_sock(sk); return res; } diff --git a/trunk/net/mac80211/offchannel.c b/trunk/net/mac80211/offchannel.c index 2c84185dfdb0..83608ac16780 100644 --- a/trunk/net/mac80211/offchannel.c +++ b/trunk/net/mac80211/offchannel.c @@ -458,6 +458,8 @@ void ieee80211_roc_purge(struct ieee80211_sub_if_data *sdata) list_move_tail(&roc->list, &tmp_list); roc->abort = true; } + + ieee80211_start_next_roc(local); mutex_unlock(&local->mtx); list_for_each_entry_safe(roc, tmp, &tmp_list, list) {