From: Greg Kroah-Hartman Date: Tue, 11 Sep 2012 16:47:34 +0000 (-0700) Subject: 3.0-stable patches X-Git-Tag: v3.5.4~11 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=c98df80dca95fa20fec688c03632847c761ad563;p=thirdparty%2Fkernel%2Fstable-queue.git 3.0-stable patches added patches: ext3-fix-fdatasync-for-files-with-only-i_size-changes.patch fuse-fix-retrieve-length.patch scsi-fix-device-not-ready-issue-on-mpt2sas.patch scsi-megaraid_sas-move-poll_aen_lock-initializer.patch scsi-mpt2sas-fix-for-driver-oops-when-loading-driver-with-max_queue_depth-command-line-option-to-a-very-small-value.patch udf-fix-data-corruption-for-files-in-icb.patch --- diff --git a/queue-3.0/ext3-fix-fdatasync-for-files-with-only-i_size-changes.patch b/queue-3.0/ext3-fix-fdatasync-for-files-with-only-i_size-changes.patch new file mode 100644 index 00000000000..2cb84cf8376 --- /dev/null +++ b/queue-3.0/ext3-fix-fdatasync-for-files-with-only-i_size-changes.patch @@ -0,0 +1,72 @@ +From 156bddd8e505b295540f3ca0e27dda68cb0d49aa Mon Sep 17 00:00:00 2001 +From: Jan Kara +Date: Mon, 3 Sep 2012 16:50:42 +0200 +Subject: ext3: Fix fdatasync() for files with only i_size changes + +From: Jan Kara + +commit 156bddd8e505b295540f3ca0e27dda68cb0d49aa upstream. + +Code tracking when transaction needs to be committed on fdatasync(2) forgets +to handle a situation when only inode's i_size is changed. Thus in such +situations fdatasync(2) doesn't force transaction with new i_size to disk +and that can result in wrong i_size after a crash. + +Fix the issue by updating inode's i_datasync_tid whenever its size is +updated. + +Reported-by: Kristian Nielsen +Signed-off-by: Jan Kara +Signed-off-by: Greg Kroah-Hartman + +--- + fs/ext3/inode.c | 17 ++++++++++++++--- + 1 file changed, 14 insertions(+), 3 deletions(-) + +--- a/fs/ext3/inode.c ++++ b/fs/ext3/inode.c +@@ -3013,6 +3013,8 @@ static int ext3_do_update_inode(handle_t + struct ext3_inode_info *ei = EXT3_I(inode); + struct buffer_head *bh = iloc->bh; + int err = 0, rc, block; ++ int need_datasync = 0; ++ __le32 disksize; + + again: + /* we can't allow multiple procs in here at once, its a bit racey */ +@@ -3050,7 +3052,11 @@ again: + raw_inode->i_gid_high = 0; + } + raw_inode->i_links_count = cpu_to_le16(inode->i_nlink); +- raw_inode->i_size = cpu_to_le32(ei->i_disksize); ++ disksize = cpu_to_le32(ei->i_disksize); ++ if (disksize != raw_inode->i_size) { ++ need_datasync = 1; ++ raw_inode->i_size = disksize; ++ } + raw_inode->i_atime = cpu_to_le32(inode->i_atime.tv_sec); + raw_inode->i_ctime = cpu_to_le32(inode->i_ctime.tv_sec); + raw_inode->i_mtime = cpu_to_le32(inode->i_mtime.tv_sec); +@@ -3066,8 +3072,11 @@ again: + if (!S_ISREG(inode->i_mode)) { + raw_inode->i_dir_acl = cpu_to_le32(ei->i_dir_acl); + } else { +- raw_inode->i_size_high = +- cpu_to_le32(ei->i_disksize >> 32); ++ disksize = cpu_to_le32(ei->i_disksize >> 32); ++ if (disksize != raw_inode->i_size_high) { ++ raw_inode->i_size_high = disksize; ++ need_datasync = 1; ++ } + if (ei->i_disksize > 0x7fffffffULL) { + struct super_block *sb = inode->i_sb; + if (!EXT3_HAS_RO_COMPAT_FEATURE(sb, +@@ -3120,6 +3129,8 @@ again: + ext3_clear_inode_state(inode, EXT3_STATE_NEW); + + atomic_set(&ei->i_sync_tid, handle->h_transaction->t_tid); ++ if (need_datasync) ++ atomic_set(&ei->i_datasync_tid, handle->h_transaction->t_tid); + out_brelse: + brelse (bh); + ext3_std_error(inode->i_sb, err); diff --git a/queue-3.0/fuse-fix-retrieve-length.patch b/queue-3.0/fuse-fix-retrieve-length.patch new file mode 100644 index 00000000000..9f42ff42d28 --- /dev/null +++ b/queue-3.0/fuse-fix-retrieve-length.patch @@ -0,0 +1,29 @@ +From c9e67d483776d8d2a5f3f70491161b205930ffe1 Mon Sep 17 00:00:00 2001 +From: Miklos Szeredi +Date: Tue, 4 Sep 2012 18:45:54 +0200 +Subject: fuse: fix retrieve length + +From: Miklos Szeredi + +commit c9e67d483776d8d2a5f3f70491161b205930ffe1 upstream. + +In some cases fuse_retrieve() would return a short byte count if offset was +non-zero. The data returned was correct, though. + +Signed-off-by: Miklos Szeredi +Signed-off-by: Greg Kroah-Hartman + +--- + fs/fuse/dev.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/fs/fuse/dev.c ++++ b/fs/fuse/dev.c +@@ -1524,6 +1524,7 @@ static int fuse_retrieve(struct fuse_con + req->pages[req->num_pages] = page; + req->num_pages++; + ++ offset = 0; + num -= this_num; + total_len += this_num; + index++; diff --git a/queue-3.0/scsi-fix-device-not-ready-issue-on-mpt2sas.patch b/queue-3.0/scsi-fix-device-not-ready-issue-on-mpt2sas.patch new file mode 100644 index 00000000000..d357a4d7cbc --- /dev/null +++ b/queue-3.0/scsi-fix-device-not-ready-issue-on-mpt2sas.patch @@ -0,0 +1,108 @@ +From 14216561e164671ce147458653b1fea06a4ada1e Mon Sep 17 00:00:00 2001 +From: James Bottomley +Date: Wed, 25 Jul 2012 23:55:55 +0400 +Subject: SCSI: Fix 'Device not ready' issue on mpt2sas + +From: James Bottomley + +commit 14216561e164671ce147458653b1fea06a4ada1e upstream. + +This is a particularly nasty SCSI ATA Translation Layer (SATL) problem. + +SAT-2 says (section 8.12.2) + + if the device is in the stopped state as the result of + processing a START STOP UNIT command (see 9.11), then the SATL + shall terminate the TEST UNIT READY command with CHECK CONDITION + status with the sense key set to NOT READY and the additional + sense code of LOGICAL UNIT NOT READY, INITIALIZING COMMAND + REQUIRED; + +mpt2sas internal SATL seems to implement this. The result is very confusing +standby behaviour (using hdparm -y). If you suspend a drive and then send +another command, usually it wakes up. However, if the next command is a TEST +UNIT READY, the SATL sees that the drive is suspended and proceeds to follow +the SATL rules for this, returning NOT READY to all subsequent commands. This +means that the ordering of TEST UNIT READY is crucial: if you send TUR and +then a command, you get a NOT READY to both back. If you send a command and +then a TUR, you get GOOD status because the preceeding command woke the drive. + +This bit us badly because + +commit 85ef06d1d252f6a2e73b678591ab71caad4667bb +Author: Tejun Heo +Date: Fri Jul 1 16:17:47 2011 +0200 + + block: flush MEDIA_CHANGE from drivers on close(2) + +Changed our ordering on TEST UNIT READY commands meaning that SATA drives +connected to an mpt2sas now suspend and refuse to wake (because the mpt2sas +SATL sees the suspend *before* the drives get awoken by the next ATA command) +resulting in lots of failed commands. + +The standard is completely nuts forcing this inconsistent behaviour, but we +have to work around it. + +The fix for this is twofold: + + 1. Set the allow_restart flag so we wake the drive when we see it has been + suspended + + 2. Return all TEST UNIT READY status directly to the mid layer without any + further error handling which prevents us causing error handling which + may offline the device just because of a media check TUR. + +Reported-by: Matthias Prager +Signed-off-by: James Bottomley +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/scsi/scsi_error.c | 10 ++++++++++ + drivers/scsi/scsi_scan.c | 10 ++++++++++ + 2 files changed, 20 insertions(+) + +--- a/drivers/scsi/scsi_error.c ++++ b/drivers/scsi/scsi_error.c +@@ -41,6 +41,8 @@ + + #include + ++static void scsi_eh_done(struct scsi_cmnd *scmd); ++ + #define SENSE_TIMEOUT (10*HZ) + + /* +@@ -240,6 +242,14 @@ static int scsi_check_sense(struct scsi_ + if (! scsi_command_normalize_sense(scmd, &sshdr)) + return FAILED; /* no valid sense data */ + ++ if (scmd->cmnd[0] == TEST_UNIT_READY && scmd->scsi_done != scsi_eh_done) ++ /* ++ * nasty: for mid-layer issued TURs, we need to return the ++ * actual sense data without any recovery attempt. For eh ++ * issued ones, we need to try to recover and interpret ++ */ ++ return SUCCESS; ++ + if (scsi_sense_is_deferred(&sshdr)) + return NEEDS_RETRY; + +--- a/drivers/scsi/scsi_scan.c ++++ b/drivers/scsi/scsi_scan.c +@@ -776,6 +776,16 @@ static int scsi_add_lun(struct scsi_devi + sdev->model = (char *) (sdev->inquiry + 16); + sdev->rev = (char *) (sdev->inquiry + 32); + ++ if (strncmp(sdev->vendor, "ATA ", 8) == 0) { ++ /* ++ * sata emulation layer device. This is a hack to work around ++ * the SATL power management specifications which state that ++ * when the SATL detects the device has gone into standby ++ * mode, it shall respond with NOT READY. ++ */ ++ sdev->allow_restart = 1; ++ } ++ + if (*bflags & BLIST_ISROM) { + sdev->type = TYPE_ROM; + sdev->removable = 1; diff --git a/queue-3.0/scsi-megaraid_sas-move-poll_aen_lock-initializer.patch b/queue-3.0/scsi-megaraid_sas-move-poll_aen_lock-initializer.patch new file mode 100644 index 00000000000..f7b0a1c4147 --- /dev/null +++ b/queue-3.0/scsi-megaraid_sas-move-poll_aen_lock-initializer.patch @@ -0,0 +1,42 @@ +From bd8d6dd43a77bfd2b8fef5b094b9d6095e169dee Mon Sep 17 00:00:00 2001 +From: Kashyap Desai +Date: Tue, 17 Jul 2012 18:20:44 -0700 +Subject: SCSI: megaraid_sas: Move poll_aen_lock initializer + +From: Kashyap Desai + +commit bd8d6dd43a77bfd2b8fef5b094b9d6095e169dee upstream. + +The following patch moves the poll_aen_lock initializer from +megasas_probe_one() to megasas_init(). This prevents a crash when a user +loads the driver and tries to issue a poll() system call on the ioctl +interface with no adapters present. + +Signed-off-by: Kashyap Desai +Signed-off-by: Adam Radford +Signed-off-by: James Bottomley +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/scsi/megaraid/megaraid_sas_base.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +--- a/drivers/scsi/megaraid/megaraid_sas_base.c ++++ b/drivers/scsi/megaraid/megaraid_sas_base.c +@@ -4052,7 +4052,6 @@ megasas_probe_one(struct pci_dev *pdev, + spin_lock_init(&instance->cmd_pool_lock); + spin_lock_init(&instance->hba_lock); + spin_lock_init(&instance->completion_lock); +- spin_lock_init(&poll_aen_lock); + + mutex_init(&instance->aen_mutex); + mutex_init(&instance->reset_mutex); +@@ -5380,6 +5379,8 @@ static int __init megasas_init(void) + printk(KERN_INFO "megasas: %s %s\n", MEGASAS_VERSION, + MEGASAS_EXT_VERSION); + ++ spin_lock_init(&poll_aen_lock); ++ + support_poll_for_event = 2; + support_device_change = 1; + diff --git a/queue-3.0/scsi-mpt2sas-fix-for-driver-oops-when-loading-driver-with-max_queue_depth-command-line-option-to-a-very-small-value.patch b/queue-3.0/scsi-mpt2sas-fix-for-driver-oops-when-loading-driver-with-max_queue_depth-command-line-option-to-a-very-small-value.patch new file mode 100644 index 00000000000..2993e558db3 --- /dev/null +++ b/queue-3.0/scsi-mpt2sas-fix-for-driver-oops-when-loading-driver-with-max_queue_depth-command-line-option-to-a-very-small-value.patch @@ -0,0 +1,60 @@ +From 338b131a3269881c7431234855c93c219b0979b6 Mon Sep 17 00:00:00 2001 +From: "sreekanth.reddy@lsi.com" +Date: Tue, 17 Jul 2012 15:57:05 +0530 +Subject: SCSI: mpt2sas: Fix for Driver oops, when loading driver with max_queue_depth command line option to a very small value + +From: "sreekanth.reddy@lsi.com" + +commit 338b131a3269881c7431234855c93c219b0979b6 upstream. + +If the specified max_queue_depth setting is less than the +expected number of internal commands, then driver will calculate +the queue depth size to a negitive number. This negitive number +is actually a very large number because variable is unsigned +16bit integer. So, the driver will ask for a very large amount of +memory for message frames and resulting into oops as memory +allocation routines will not able to handle such a large request. + +So, in order to limit this kind of oops, The driver need to set +the max_queue_depth to a scsi mid layer's can_queue value. Then +the overall message frames required for IO is minimum of either +(max_queue_depth plus internal commands) or the IOC global +credits. + +Signed-off-by: Sreekanth Reddy +Signed-off-by: James Bottomley +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/scsi/mpt2sas/mpt2sas_base.c | 13 ++++++++----- + 1 file changed, 8 insertions(+), 5 deletions(-) + +--- a/drivers/scsi/mpt2sas/mpt2sas_base.c ++++ b/drivers/scsi/mpt2sas/mpt2sas_base.c +@@ -2140,10 +2140,13 @@ _base_allocate_memory_pools(struct MPT2S + } + + /* command line tunables for max controller queue depth */ +- if (max_queue_depth != -1) +- max_request_credit = (max_queue_depth < facts->RequestCredit) +- ? max_queue_depth : facts->RequestCredit; +- else ++ if (max_queue_depth != -1 && max_queue_depth != 0) { ++ max_request_credit = min_t(u16, max_queue_depth + ++ ioc->hi_priority_depth + ioc->internal_depth, ++ facts->RequestCredit); ++ if (max_request_credit > MAX_HBA_QUEUE_DEPTH) ++ max_request_credit = MAX_HBA_QUEUE_DEPTH; ++ } else + max_request_credit = min_t(u16, facts->RequestCredit, + MAX_HBA_QUEUE_DEPTH); + +@@ -2218,7 +2221,7 @@ _base_allocate_memory_pools(struct MPT2S + /* set the scsi host can_queue depth + * with some internal commands that could be outstanding + */ +- ioc->shost->can_queue = ioc->scsiio_depth - (2); ++ ioc->shost->can_queue = ioc->scsiio_depth; + dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "scsi host: " + "can_queue depth (%d)\n", ioc->name, ioc->shost->can_queue)); + diff --git a/queue-3.0/series b/queue-3.0/series index 9ea42081a41..7d9fa1c2fa3 100644 --- a/queue-3.0/series +++ b/queue-3.0/series @@ -33,3 +33,9 @@ usb-cdc-acm-fix-null-pointer-dereference.patch powerpc-fix-dscr-inheritance-in-copy_thread.patch powerpc-restore-correct-dscr-in-context-switch.patch remove-user-triggerable-bug-from-mpol_to_str.patch +scsi-megaraid_sas-move-poll_aen_lock-initializer.patch +scsi-mpt2sas-fix-for-driver-oops-when-loading-driver-with-max_queue_depth-command-line-option-to-a-very-small-value.patch +scsi-fix-device-not-ready-issue-on-mpt2sas.patch +udf-fix-data-corruption-for-files-in-icb.patch +ext3-fix-fdatasync-for-files-with-only-i_size-changes.patch +fuse-fix-retrieve-length.patch diff --git a/queue-3.0/udf-fix-data-corruption-for-files-in-icb.patch b/queue-3.0/udf-fix-data-corruption-for-files-in-icb.patch new file mode 100644 index 00000000000..4edb0728d27 --- /dev/null +++ b/queue-3.0/udf-fix-data-corruption-for-files-in-icb.patch @@ -0,0 +1,95 @@ +From 9c2fc0de1a6e638fe58c354a463f544f42a90a09 Mon Sep 17 00:00:00 2001 +From: Jan Kara +Date: Wed, 5 Sep 2012 15:48:23 +0200 +Subject: udf: Fix data corruption for files in ICB + +From: Jan Kara + +commit 9c2fc0de1a6e638fe58c354a463f544f42a90a09 upstream. + +When a file is stored in ICB (inode), we overwrite part of the file, and +the page containing file's data is not in page cache, we end up corrupting +file's data by overwriting them with zeros. The problem is we use +simple_write_begin() which simply zeroes parts of the page which are not +written to. The problem has been introduced by be021ee4 (udf: convert to +new aops). + +Fix the problem by providing a ->write_begin function which makes the page +properly uptodate. + +Reported-by: Ian Abbott +Signed-off-by: Jan Kara +Signed-off-by: Greg Kroah-Hartman + +--- + fs/udf/file.c | 35 +++++++++++++++++++++++++++++------ + 1 file changed, 29 insertions(+), 6 deletions(-) + +--- a/fs/udf/file.c ++++ b/fs/udf/file.c +@@ -39,20 +39,24 @@ + #include "udf_i.h" + #include "udf_sb.h" + +-static int udf_adinicb_readpage(struct file *file, struct page *page) ++static void __udf_adinicb_readpage(struct page *page) + { + struct inode *inode = page->mapping->host; + char *kaddr; + struct udf_inode_info *iinfo = UDF_I(inode); + +- BUG_ON(!PageLocked(page)); +- + kaddr = kmap(page); +- memset(kaddr, 0, PAGE_CACHE_SIZE); + memcpy(kaddr, iinfo->i_ext.i_data + iinfo->i_lenEAttr, inode->i_size); ++ memset(kaddr + inode->i_size, 0, PAGE_CACHE_SIZE - inode->i_size); + flush_dcache_page(page); + SetPageUptodate(page); + kunmap(page); ++} ++ ++static int udf_adinicb_readpage(struct file *file, struct page *page) ++{ ++ BUG_ON(!PageLocked(page)); ++ __udf_adinicb_readpage(page); + unlock_page(page); + + return 0; +@@ -77,6 +81,25 @@ static int udf_adinicb_writepage(struct + return 0; + } + ++static int udf_adinicb_write_begin(struct file *file, ++ struct address_space *mapping, loff_t pos, ++ unsigned len, unsigned flags, struct page **pagep, ++ void **fsdata) ++{ ++ struct page *page; ++ ++ if (WARN_ON_ONCE(pos >= PAGE_CACHE_SIZE)) ++ return -EIO; ++ page = grab_cache_page_write_begin(mapping, 0, flags); ++ if (!page) ++ return -ENOMEM; ++ *pagep = page; ++ ++ if (!PageUptodate(page) && len != PAGE_CACHE_SIZE) ++ __udf_adinicb_readpage(page); ++ return 0; ++} ++ + static int udf_adinicb_write_end(struct file *file, + struct address_space *mapping, + loff_t pos, unsigned len, unsigned copied, +@@ -98,8 +121,8 @@ static int udf_adinicb_write_end(struct + const struct address_space_operations udf_adinicb_aops = { + .readpage = udf_adinicb_readpage, + .writepage = udf_adinicb_writepage, +- .write_begin = simple_write_begin, +- .write_end = udf_adinicb_write_end, ++ .write_begin = udf_adinicb_write_begin, ++ .write_end = udf_adinicb_write_end, + }; + + static ssize_t udf_file_aio_write(struct kiocb *iocb, const struct iovec *iov,