From: Greg Kroah-Hartman Date: Tue, 22 Nov 2011 21:49:07 +0000 (-0800) Subject: 3.0 patches X-Git-Tag: v3.0.11~4 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=663c24ca9ff7237283e0ff540f5326c93722ebdf;p=thirdparty%2Fkernel%2Fstable-queue.git 3.0 patches added patches: drm-i915-always-set-fdi-composite-sync-bit.patch drm-i915-fix-ivb-cursor-support.patch xfs-avoid-direct-i-o-write-vs-buffered-i-o-race.patch xfs-dont-serialise-direct-io-reads-on-page-cache.patch xfs-fix-buffer-flushing-during-unmount.patch xfs-fix-error-handling-for-synchronous-writes.patch xfs-fix-possible-memory-corruption-in-xfs_readlink.patch xfs-fix-write_inode-return-values.patch xfs-fix-xfs_mark_inode_dirty-during-umount.patch xfs-return-eio-when-xfs_vn_getattr-failed.patch xfs-use-doalloc-flag-in-xfs_qm_dqattach_one.patch --- diff --git a/queue-3.0/drm-i915-always-set-fdi-composite-sync-bit.patch b/queue-3.0/drm-i915-always-set-fdi-composite-sync-bit.patch new file mode 100644 index 00000000000..7c51f07ac2e --- /dev/null +++ b/queue-3.0/drm-i915-always-set-fdi-composite-sync-bit.patch @@ -0,0 +1,52 @@ +From c4f9c4c2b3f1831e932e04db992cf6fe92c2a95a Mon Sep 17 00:00:00 2001 +From: Jesse Barnes +Date: Mon, 10 Oct 2011 14:28:52 -0700 +Subject: drm/i915: always set FDI composite sync bit + +From: Jesse Barnes + +commit c4f9c4c2b3f1831e932e04db992cf6fe92c2a95a upstream. + +It's needed for 3 pipe support as well as just regular functionality +(e.g. DisplayPort). + +Signed-off-by: Jesse Barnes +Tested-by: Adam Jackson +Tested-by: Eugeni Dodonov +Signed-off-by: Keith Packard +Signed-off-by: Robert Hooker +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/gpu/drm/i915/i915_reg.h | 1 + + drivers/gpu/drm/i915/intel_display.c | 2 ++ + 2 files changed, 3 insertions(+) + +--- a/drivers/gpu/drm/i915/i915_reg.h ++++ b/drivers/gpu/drm/i915/i915_reg.h +@@ -3141,6 +3141,7 @@ + #define FDI_LINK_TRAIN_NONE_IVB (3<<8) + + /* both Tx and Rx */ ++#define FDI_COMPOSITE_SYNC (1<<11) + #define FDI_LINK_TRAIN_AUTO (1<<10) + #define FDI_SCRAMBLING_ENABLE (0<<7) + #define FDI_SCRAMBLING_DISABLE (1<<7) +--- a/drivers/gpu/drm/i915/intel_display.c ++++ b/drivers/gpu/drm/i915/intel_display.c +@@ -2340,6 +2340,7 @@ static void ivb_manual_fdi_link_train(st + temp |= FDI_LINK_TRAIN_PATTERN_1_IVB; + temp &= ~FDI_LINK_TRAIN_VOL_EMP_MASK; + temp |= FDI_LINK_TRAIN_400MV_0DB_SNB_B; ++ temp |= FDI_COMPOSITE_SYNC; + I915_WRITE(reg, temp | FDI_TX_ENABLE); + + reg = FDI_RX_CTL(pipe); +@@ -2347,6 +2348,7 @@ static void ivb_manual_fdi_link_train(st + temp &= ~FDI_LINK_TRAIN_AUTO; + temp &= ~FDI_LINK_TRAIN_PATTERN_MASK_CPT; + temp |= FDI_LINK_TRAIN_PATTERN_1_CPT; ++ temp |= FDI_COMPOSITE_SYNC; + I915_WRITE(reg, temp | FDI_RX_ENABLE); + + POSTING_READ(reg); diff --git a/queue-3.0/drm-i915-fix-ivb-cursor-support.patch b/queue-3.0/drm-i915-fix-ivb-cursor-support.patch new file mode 100644 index 00000000000..2cec42b5b2f --- /dev/null +++ b/queue-3.0/drm-i915-fix-ivb-cursor-support.patch @@ -0,0 +1,101 @@ +From 65a21cd65316145f9302594be8e69074369e1050 Mon Sep 17 00:00:00 2001 +From: Jesse Barnes +Date: Wed, 12 Oct 2011 11:10:21 -0700 +Subject: drm/i915: fix IVB cursor support + +From: Jesse Barnes + +commit 65a21cd65316145f9302594be8e69074369e1050 upstream. + +The cursor regs have moved around, add the offsets and new macros for +getting at them. + +Signed-off-by: Jesse Barnes +Tested-By: Eugeni Dodonov +Reviewed-By: Eugeni Dodonov +Signed-off-by: Keith Packard +Signed-off-by: Robert Hooker +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/gpu/drm/i915/i915_reg.h | 8 +++++++ + drivers/gpu/drm/i915/intel_display.c | 40 ++++++++++++++++++++++++++++++----- + 2 files changed, 43 insertions(+), 5 deletions(-) + +--- a/drivers/gpu/drm/i915/i915_reg.h ++++ b/drivers/gpu/drm/i915/i915_reg.h +@@ -2544,10 +2544,18 @@ + #define _CURBBASE 0x700c4 + #define _CURBPOS 0x700c8 + ++#define _CURBCNTR_IVB 0x71080 ++#define _CURBBASE_IVB 0x71084 ++#define _CURBPOS_IVB 0x71088 ++ + #define CURCNTR(pipe) _PIPE(pipe, _CURACNTR, _CURBCNTR) + #define CURBASE(pipe) _PIPE(pipe, _CURABASE, _CURBBASE) + #define CURPOS(pipe) _PIPE(pipe, _CURAPOS, _CURBPOS) + ++#define CURCNTR_IVB(pipe) _PIPE(pipe, _CURACNTR, _CURBCNTR_IVB) ++#define CURBASE_IVB(pipe) _PIPE(pipe, _CURABASE, _CURBBASE_IVB) ++#define CURPOS_IVB(pipe) _PIPE(pipe, _CURAPOS, _CURBPOS_IVB) ++ + /* Display A control */ + #define _DSPACNTR 0x70180 + #define DISPLAY_PLANE_ENABLE (1<<31) +--- a/drivers/gpu/drm/i915/intel_display.c ++++ b/drivers/gpu/drm/i915/intel_display.c +@@ -5334,6 +5334,31 @@ static void i9xx_update_cursor(struct dr + I915_WRITE(CURBASE(pipe), base); + } + ++static void ivb_update_cursor(struct drm_crtc *crtc, u32 base) ++{ ++ struct drm_device *dev = crtc->dev; ++ struct drm_i915_private *dev_priv = dev->dev_private; ++ struct intel_crtc *intel_crtc = to_intel_crtc(crtc); ++ int pipe = intel_crtc->pipe; ++ bool visible = base != 0; ++ ++ if (intel_crtc->cursor_visible != visible) { ++ uint32_t cntl = I915_READ(CURCNTR_IVB(pipe)); ++ if (base) { ++ cntl &= ~CURSOR_MODE; ++ cntl |= CURSOR_MODE_64_ARGB_AX | MCURSOR_GAMMA_ENABLE; ++ } else { ++ cntl &= ~(CURSOR_MODE | MCURSOR_GAMMA_ENABLE); ++ cntl |= CURSOR_MODE_DISABLE; ++ } ++ I915_WRITE(CURCNTR_IVB(pipe), cntl); ++ ++ intel_crtc->cursor_visible = visible; ++ } ++ /* and commit changes on next vblank */ ++ I915_WRITE(CURBASE_IVB(pipe), base); ++} ++ + /* If no-part of the cursor is visible on the framebuffer, then the GPU may hang... */ + static void intel_crtc_update_cursor(struct drm_crtc *crtc, + bool on) +@@ -5381,11 +5406,16 @@ static void intel_crtc_update_cursor(str + if (!visible && !intel_crtc->cursor_visible) + return; + +- I915_WRITE(CURPOS(pipe), pos); +- if (IS_845G(dev) || IS_I865G(dev)) +- i845_update_cursor(crtc, base); +- else +- i9xx_update_cursor(crtc, base); ++ if (IS_IVYBRIDGE(dev)) { ++ I915_WRITE(CURPOS_IVB(pipe), pos); ++ ivb_update_cursor(crtc, base); ++ } else { ++ I915_WRITE(CURPOS(pipe), pos); ++ if (IS_845G(dev) || IS_I865G(dev)) ++ i845_update_cursor(crtc, base); ++ else ++ i9xx_update_cursor(crtc, base); ++ } + + if (visible) + intel_mark_busy(dev, to_intel_framebuffer(crtc->fb)->obj); diff --git a/queue-3.0/series b/queue-3.0/series index f9541451804..1d34a4b3d3c 100644 --- a/queue-3.0/series +++ b/queue-3.0/series @@ -40,3 +40,14 @@ usb-storage-accept-8020i-protocol-commands-longer-than-12-bytes.patch usb-ehci-fix-hub-tt-scheduling-issue-with-iso-transfer.patch usb-add-quirk-for-logitech-c600-web-cam.patch usb-quirks-adding-more-quirky-webcams-to-avoid-squeaky-audio.patch +xfs-fix-error-handling-for-synchronous-writes.patch +xfs-fix-xfs_mark_inode_dirty-during-umount.patch +xfs-dont-serialise-direct-io-reads-on-page-cache.patch +xfs-avoid-direct-i-o-write-vs-buffered-i-o-race.patch +xfs-return-eio-when-xfs_vn_getattr-failed.patch +xfs-fix-buffer-flushing-during-unmount.patch +xfs-fix-possible-memory-corruption-in-xfs_readlink.patch +xfs-use-doalloc-flag-in-xfs_qm_dqattach_one.patch +xfs-fix-write_inode-return-values.patch +drm-i915-fix-ivb-cursor-support.patch +drm-i915-always-set-fdi-composite-sync-bit.patch diff --git a/queue-3.0/xfs-avoid-direct-i-o-write-vs-buffered-i-o-race.patch b/queue-3.0/xfs-avoid-direct-i-o-write-vs-buffered-i-o-race.patch new file mode 100644 index 00000000000..c17c91730e6 --- /dev/null +++ b/queue-3.0/xfs-avoid-direct-i-o-write-vs-buffered-i-o-race.patch @@ -0,0 +1,73 @@ +From hch@infradead.org Tue Nov 22 13:36:45 2011 +From: Christoph Hellwig +Date: Sat, 19 Nov 2011 13:13:41 -0500 +Subject: xfs: avoid direct I/O write vs buffered I/O race +To: stable@vger.kernel.org +Cc: xfs@oss.sgi.com, Alex Elder +Message-ID: <20111119181544.434721480@bombadil.infradead.org> + +From: Christoph Hellwig + +commit c58cb165bd44de8aaee9755a144136ae743be116 upstream. + +Currently a buffered reader or writer can add pages to the pagecache +while we are waiting for the iolock in xfs_file_dio_aio_write. Prevent +this by re-checking mapping->nrpages after we got the iolock, and if +nessecary upgrade the lock to exclusive mode. To simplify this a bit +only take the ilock inside of xfs_file_aio_write_checks. + +Signed-off-by: Christoph Hellwig +Reviewed-by: Dave Chinner +Signed-off-by: Alex Elder +Signed-off-by: Greg Kroah-Hartman + +--- + fs/xfs/linux-2.6/xfs_file.c | 17 ++++++++++++++--- + 1 file changed, 14 insertions(+), 3 deletions(-) + +--- a/fs/xfs/linux-2.6/xfs_file.c ++++ b/fs/xfs/linux-2.6/xfs_file.c +@@ -669,6 +669,7 @@ xfs_file_aio_write_checks( + xfs_fsize_t new_size; + int error = 0; + ++ xfs_rw_ilock(ip, XFS_ILOCK_EXCL); + error = generic_write_checks(file, pos, count, S_ISBLK(inode->i_mode)); + if (error) { + xfs_rw_iunlock(ip, XFS_ILOCK_EXCL | *iolock); +@@ -760,14 +761,24 @@ xfs_file_dio_aio_write( + *iolock = XFS_IOLOCK_EXCL; + else + *iolock = XFS_IOLOCK_SHARED; +- xfs_rw_ilock(ip, XFS_ILOCK_EXCL | *iolock); ++ xfs_rw_ilock(ip, *iolock); + + ret = xfs_file_aio_write_checks(file, &pos, &count, iolock); + if (ret) + return ret; + ++ /* ++ * Recheck if there are cached pages that need invalidate after we got ++ * the iolock to protect against other threads adding new pages while ++ * we were waiting for the iolock. ++ */ ++ if (mapping->nrpages && *iolock == XFS_IOLOCK_SHARED) { ++ xfs_rw_iunlock(ip, *iolock); ++ *iolock = XFS_IOLOCK_EXCL; ++ xfs_rw_ilock(ip, *iolock); ++ } ++ + if (mapping->nrpages) { +- WARN_ON(*iolock != XFS_IOLOCK_EXCL); + ret = -xfs_flushinval_pages(ip, (pos & PAGE_CACHE_MASK), -1, + FI_REMAPF_LOCKED); + if (ret) +@@ -812,7 +823,7 @@ xfs_file_buffered_aio_write( + size_t count = ocount; + + *iolock = XFS_IOLOCK_EXCL; +- xfs_rw_ilock(ip, XFS_ILOCK_EXCL | *iolock); ++ xfs_rw_ilock(ip, *iolock); + + ret = xfs_file_aio_write_checks(file, &pos, &count, iolock); + if (ret) diff --git a/queue-3.0/xfs-dont-serialise-direct-io-reads-on-page-cache.patch b/queue-3.0/xfs-dont-serialise-direct-io-reads-on-page-cache.patch new file mode 100644 index 00000000000..6956c6e0ff2 --- /dev/null +++ b/queue-3.0/xfs-dont-serialise-direct-io-reads-on-page-cache.patch @@ -0,0 +1,67 @@ +From hch@infradead.org Tue Nov 22 13:35:52 2011 +From: Dave Chinner +Date: Sat, 19 Nov 2011 13:13:40 -0500 +Subject: xfs: dont serialise direct IO reads on page cache +To: stable@vger.kernel.org +Cc: xfs@oss.sgi.com, Dave Chinner , Alex Elder +Message-ID: <20111119181544.111984285@bombadil.infradead.org> + +From: Dave Chinner + +commit 0c38a2512df272b14ef4238b476a2e4f70da1479 upstream. + +There is no need to grab the i_mutex of the IO lock in exclusive +mode if we don't need to invalidate the page cache. Taking these +locks on every direct IO effective serialises them as taking the IO +lock in exclusive mode has to wait for all shared holders to drop +the lock. That only happens when IO is complete, so effective it +prevents dispatch of concurrent direct IO reads to the same inode. + +Fix this by taking the IO lock shared to check the page cache state, +and only then drop it and take the IO lock exclusively if there is +work to be done. Hence for the normal direct IO case, no exclusive +locking will occur. + +Signed-off-by: Dave Chinner +Tested-by: Joern Engel +Reviewed-by: Christoph Hellwig +Signed-off-by: Alex Elder +Signed-off-by: Greg Kroah-Hartman + +--- + fs/xfs/linux-2.6/xfs_file.c | 17 ++++++++++++++--- + 1 file changed, 14 insertions(+), 3 deletions(-) + +--- a/fs/xfs/linux-2.6/xfs_file.c ++++ b/fs/xfs/linux-2.6/xfs_file.c +@@ -309,7 +309,19 @@ xfs_file_aio_read( + if (XFS_FORCED_SHUTDOWN(mp)) + return -EIO; + +- if (unlikely(ioflags & IO_ISDIRECT)) { ++ /* ++ * Locking is a bit tricky here. If we take an exclusive lock ++ * for direct IO, we effectively serialise all new concurrent ++ * read IO to this file and block it behind IO that is currently in ++ * progress because IO in progress holds the IO lock shared. We only ++ * need to hold the lock exclusive to blow away the page cache, so ++ * only take lock exclusively if the page cache needs invalidation. ++ * This allows the normal direct IO case of no page cache pages to ++ * proceeed concurrently without serialisation. ++ */ ++ xfs_rw_ilock(ip, XFS_IOLOCK_SHARED); ++ if ((ioflags & IO_ISDIRECT) && inode->i_mapping->nrpages) { ++ xfs_rw_iunlock(ip, XFS_IOLOCK_SHARED); + xfs_rw_ilock(ip, XFS_IOLOCK_EXCL); + + if (inode->i_mapping->nrpages) { +@@ -322,8 +334,7 @@ xfs_file_aio_read( + } + } + xfs_rw_ilock_demote(ip, XFS_IOLOCK_EXCL); +- } else +- xfs_rw_ilock(ip, XFS_IOLOCK_SHARED); ++ } + + trace_xfs_file_read(ip, size, iocb->ki_pos, ioflags); + diff --git a/queue-3.0/xfs-fix-buffer-flushing-during-unmount.patch b/queue-3.0/xfs-fix-buffer-flushing-during-unmount.patch new file mode 100644 index 00000000000..30464eaaf72 --- /dev/null +++ b/queue-3.0/xfs-fix-buffer-flushing-during-unmount.patch @@ -0,0 +1,103 @@ +From hch@infradead.org Tue Nov 22 13:38:03 2011 +From: Christoph Hellwig +Date: Sat, 19 Nov 2011 13:13:43 -0500 +Subject: [PATCH 7/9] [PATCH 7/9] xfs: fix buffer flushing during unmount +To: stable@vger.kernel.org +Cc: xfs@oss.sgi.com, Alex Elder +Message-ID: <20111119181544.971499446@bombadil.infradead.org> + +From: Christoph Hellwig + +commit 87c7bec7fc3377b3873eb3a0f4b603981ea16ebb upstream. + +The code to flush buffers in the umount code is a bit iffy: we first +flush all delwri buffers out, but then might be able to queue up a +new one when logging the sb counts. On a normal shutdown that one +would get flushed out when doing the synchronous superblock write in +xfs_unmountfs_writesb, but we skip that one if the filesystem has +been shut down. + +Fix this by moving the delwri list flushing until just before unmounting +the log, and while we're at it also remove the superflous delwri list +and buffer lru flusing for the rt and log device that can never have +cached or delwri buffers. + +Signed-off-by: Christoph Hellwig +Reported-by: Amit Sahrawat +Tested-by: Amit Sahrawat +Signed-off-by: Alex Elder +Signed-off-by: Greg Kroah-Hartman +--- + fs/xfs/linux-2.6/xfs_buf.h | 1 - + fs/xfs/xfs_mount.c | 29 ++++++++++------------------- + 2 files changed, 10 insertions(+), 20 deletions(-) + +--- a/fs/xfs/linux-2.6/xfs_buf.h ++++ b/fs/xfs/linux-2.6/xfs_buf.h +@@ -346,7 +346,6 @@ extern struct list_head *xfs_get_buftarg + #define xfs_getsize_buftarg(buftarg) block_size((buftarg)->bt_bdev) + #define xfs_readonly_buftarg(buftarg) bdev_read_only((buftarg)->bt_bdev) + +-#define xfs_binval(buftarg) xfs_flush_buftarg(buftarg, 1) + #define XFS_bflush(buftarg) xfs_flush_buftarg(buftarg, 1) + + #endif /* __XFS_BUF_H__ */ +--- a/fs/xfs/xfs_mount.c ++++ b/fs/xfs/xfs_mount.c +@@ -44,9 +44,6 @@ + #include "xfs_trace.h" + + +-STATIC void xfs_unmountfs_wait(xfs_mount_t *); +- +- + #ifdef HAVE_PERCPU_SB + STATIC void xfs_icsb_balance_counter(xfs_mount_t *, xfs_sb_field_t, + int); +@@ -1507,11 +1504,6 @@ xfs_unmountfs( + */ + xfs_log_force(mp, XFS_LOG_SYNC); + +- xfs_binval(mp->m_ddev_targp); +- if (mp->m_rtdev_targp) { +- xfs_binval(mp->m_rtdev_targp); +- } +- + /* + * Unreserve any blocks we have so that when we unmount we don't account + * the reserved free space as used. This is really only necessary for +@@ -1537,7 +1529,16 @@ xfs_unmountfs( + xfs_warn(mp, "Unable to update superblock counters. " + "Freespace may not be correct on next mount."); + xfs_unmountfs_writesb(mp); +- xfs_unmountfs_wait(mp); /* wait for async bufs */ ++ ++ /* ++ * Make sure all buffers have been flushed and completed before ++ * unmounting the log. ++ */ ++ error = xfs_flush_buftarg(mp->m_ddev_targp, 1); ++ if (error) ++ xfs_warn(mp, "%d busy buffers during unmount.", error); ++ xfs_wait_buftarg(mp->m_ddev_targp); ++ + xfs_log_unmount_write(mp); + xfs_log_unmount(mp); + xfs_uuid_unmount(mp); +@@ -1548,16 +1549,6 @@ xfs_unmountfs( + xfs_free_perag(mp); + } + +-STATIC void +-xfs_unmountfs_wait(xfs_mount_t *mp) +-{ +- if (mp->m_logdev_targp != mp->m_ddev_targp) +- xfs_wait_buftarg(mp->m_logdev_targp); +- if (mp->m_rtdev_targp) +- xfs_wait_buftarg(mp->m_rtdev_targp); +- xfs_wait_buftarg(mp->m_ddev_targp); +-} +- + int + xfs_fs_writable(xfs_mount_t *mp) + { diff --git a/queue-3.0/xfs-fix-error-handling-for-synchronous-writes.patch b/queue-3.0/xfs-fix-error-handling-for-synchronous-writes.patch new file mode 100644 index 00000000000..fc407e56851 --- /dev/null +++ b/queue-3.0/xfs-fix-error-handling-for-synchronous-writes.patch @@ -0,0 +1,42 @@ +From hch@infradead.org Tue Nov 22 13:29:58 2011 +From: Christoph Hellwig +Date: Sat, 19 Nov 2011 13:13:37 -0500 +Subject: xfs: fix error handling for synchronous writes +To: stable@vger.kernel.org +Cc: xfs@oss.sgi.com, Ajeet Yadav , Alex Elder +Message-ID: <20111119181543.361506649@bombadil.infradead.org> + +From: Christoph Hellwig + +If removed storage while synchronous buffer write underway, +"xfslogd" hangs. + +Detailed log http://oss.sgi.com/archives/xfs/2011-07/msg00740.html + +Related work bfc60177f8ab509bc225becbb58f7e53a0e33e81 +"xfs: fix error handling for synchronous writes" + +Given that xfs_bwrite actually does the shutdown already after +waiting for the b_iodone completion and given that we actually +found that calling xfs_force_shutdown from inside +xfs_buf_iodone_callbacks was a major contributor the problem +it better to drop this call. + +Signed-off-by: Ajeet Yadav +Reviewed-by: Christoph Hellwig +Signed-off-by: Alex Elder +Signed-off-by: Greg Kroah-Hartman +--- + fs/xfs/xfs_buf_item.c | 1 - + 1 file changed, 1 deletion(-) + +--- a/fs/xfs/xfs_buf_item.c ++++ b/fs/xfs/xfs_buf_item.c +@@ -1023,7 +1023,6 @@ xfs_buf_iodone_callbacks( + XFS_BUF_UNDELAYWRITE(bp); + + trace_xfs_buf_error_relse(bp, _RET_IP_); +- xfs_force_shutdown(mp, SHUTDOWN_META_IO_ERROR); + + do_callbacks: + xfs_buf_do_callbacks(bp); diff --git a/queue-3.0/xfs-fix-possible-memory-corruption-in-xfs_readlink.patch b/queue-3.0/xfs-fix-possible-memory-corruption-in-xfs_readlink.patch new file mode 100644 index 00000000000..98bbd842e66 --- /dev/null +++ b/queue-3.0/xfs-fix-possible-memory-corruption-in-xfs_readlink.patch @@ -0,0 +1,71 @@ +From hch@infradead.org Tue Nov 22 13:38:33 2011 +From: Carlos Maiolino +Date: Sat, 19 Nov 2011 13:13:44 -0500 +Subject: xfs: Fix possible memory corruption in xfs_readlink +To: stable@vger.kernel.org +Cc: xfs@oss.sgi.com, Alex Elder , Carlos Maiolino +Message-ID: <20111119181545.235475776@bombadil.infradead.org> + +From: Carlos Maiolino + +commit b52a360b2aa1c59ba9970fb0f52bbb093fcc7a24 upstream. + +Fixes a possible memory corruption when the link is larger than +MAXPATHLEN and XFS_DEBUG is not enabled. This also remove the +S_ISLNK assert, since the inode mode is checked previously in +xfs_readlink_by_handle() and via VFS. + +Updated to address concerns raised by Ben Hutchings about the loose +attention paid to 32- vs 64-bit values, and the lack of handling a +potentially negative pathlen value: + - Changed type of "pathlen" to be xfs_fsize_t, to match that of + ip->i_d.di_size + - Added checking for a negative pathlen to the too-long pathlen + test, and generalized the message that gets reported in that case + to reflect the change +As a result, if a negative pathlen were encountered, this function +would return EFSCORRUPTED (and would fail an assertion for a debug +build)--just as would a too-long pathlen. + +Signed-off-by: Alex Elder +Signed-off-by: Carlos Maiolino +Reviewed-by: Christoph Hellwig +Signed-off-by: Greg Kroah-Hartman +--- + fs/xfs/xfs_vnodeops.c | 14 ++++++++++---- + 1 file changed, 10 insertions(+), 4 deletions(-) + +--- a/fs/xfs/xfs_vnodeops.c ++++ b/fs/xfs/xfs_vnodeops.c +@@ -535,7 +535,7 @@ xfs_readlink( + char *link) + { + xfs_mount_t *mp = ip->i_mount; +- int pathlen; ++ xfs_fsize_t pathlen; + int error = 0; + + trace_xfs_readlink(ip); +@@ -545,13 +545,19 @@ xfs_readlink( + + xfs_ilock(ip, XFS_ILOCK_SHARED); + +- ASSERT((ip->i_d.di_mode & S_IFMT) == S_IFLNK); +- ASSERT(ip->i_d.di_size <= MAXPATHLEN); +- + pathlen = ip->i_d.di_size; + if (!pathlen) + goto out; + ++ if (pathlen < 0 || pathlen > MAXPATHLEN) { ++ xfs_alert(mp, "%s: inode (%llu) bad symlink length (%lld)", ++ __func__, (unsigned long long) ip->i_ino, ++ (long long) pathlen); ++ ASSERT(0); ++ return XFS_ERROR(EFSCORRUPTED); ++ } ++ ++ + if (ip->i_df.if_flags & XFS_IFINLINE) { + memcpy(link, ip->i_df.if_u1.if_data, pathlen); + link[pathlen] = '\0'; diff --git a/queue-3.0/xfs-fix-write_inode-return-values.patch b/queue-3.0/xfs-fix-write_inode-return-values.patch new file mode 100644 index 00000000000..762bf5c0a4e --- /dev/null +++ b/queue-3.0/xfs-fix-write_inode-return-values.patch @@ -0,0 +1,94 @@ +From hch@infradead.org Tue Nov 22 13:31:47 2011 +From: Christoph Hellwig +Date: Sat, 19 Nov 2011 13:13:39 -0500 +Subject: xfs: fix ->write_inode return values +To: stable@vger.kernel.org +Cc: xfs@oss.sgi.com, Alex Elder +Message-ID: <20111119181543.809288814@bombadil.infradead.org> + +From: Christoph Hellwig + +patch 58d84c4ee0389ddeb86238d5d8359a982c9f7a5b upstream. + +Currently we always redirty an inode that was attempted to be written out +synchronously but has been cleaned by an AIL pushed internall, which is +rather bogus. Fix that by doing the i_update_core check early on and +return 0 for it. Also include async calls for it, as doing any work for +those is just as pointless. While we're at it also fix the sign for the +EIO return in case of a filesystem shutdown, and fix the completely +non-sensical locking around xfs_log_inode. + +Signed-off-by: Christoph Hellwig +Reviewed-by: Dave Chinner +Signed-off-by: Alex Elder +Signed-off-by: Greg Kroah-Hartman +--- + fs/xfs/linux-2.6/xfs_super.c | 34 +++++++++------------------------- + 1 file changed, 9 insertions(+), 25 deletions(-) + +--- a/fs/xfs/linux-2.6/xfs_super.c ++++ b/fs/xfs/linux-2.6/xfs_super.c +@@ -878,33 +878,17 @@ xfs_log_inode( + struct xfs_trans *tp; + int error; + +- xfs_iunlock(ip, XFS_ILOCK_SHARED); + tp = xfs_trans_alloc(mp, XFS_TRANS_FSYNC_TS); + error = xfs_trans_reserve(tp, 0, XFS_FSYNC_TS_LOG_RES(mp), 0, 0, 0); +- + if (error) { + xfs_trans_cancel(tp, 0); +- /* we need to return with the lock hold shared */ +- xfs_ilock(ip, XFS_ILOCK_SHARED); + return error; + } + + xfs_ilock(ip, XFS_ILOCK_EXCL); +- +- /* +- * Note - it's possible that we might have pushed ourselves out of the +- * way during trans_reserve which would flush the inode. But there's +- * no guarantee that the inode buffer has actually gone out yet (it's +- * delwri). Plus the buffer could be pinned anyway if it's part of +- * an inode in another recent transaction. So we play it safe and +- * fire off the transaction anyway. +- */ +- xfs_trans_ijoin(tp, ip); ++ xfs_trans_ijoin_ref(tp, ip, XFS_ILOCK_EXCL); + xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE); +- error = xfs_trans_commit(tp, 0); +- xfs_ilock_demote(ip, XFS_ILOCK_EXCL); +- +- return error; ++ return xfs_trans_commit(tp, 0); + } + + STATIC int +@@ -919,7 +903,9 @@ xfs_fs_write_inode( + trace_xfs_write_inode(ip); + + if (XFS_FORCED_SHUTDOWN(mp)) +- return XFS_ERROR(EIO); ++ return -XFS_ERROR(EIO); ++ if (!ip->i_update_core) ++ return 0; + + if (wbc->sync_mode == WB_SYNC_ALL) { + /* +@@ -930,12 +916,10 @@ xfs_fs_write_inode( + * of synchronous log foces dramatically. + */ + xfs_ioend_wait(ip); +- xfs_ilock(ip, XFS_ILOCK_SHARED); +- if (ip->i_update_core) { +- error = xfs_log_inode(ip); +- if (error) +- goto out_unlock; +- } ++ error = xfs_log_inode(ip); ++ if (error) ++ goto out; ++ return 0; + } else { + /* + * We make this non-blocking if the inode is contended, return diff --git a/queue-3.0/xfs-fix-xfs_mark_inode_dirty-during-umount.patch b/queue-3.0/xfs-fix-xfs_mark_inode_dirty-during-umount.patch new file mode 100644 index 00000000000..728e05a056d --- /dev/null +++ b/queue-3.0/xfs-fix-xfs_mark_inode_dirty-during-umount.patch @@ -0,0 +1,71 @@ +From hch@infradead.org Tue Nov 22 13:31:23 2011 +From: Christoph Hellwig +Date: Sat, 19 Nov 2011 13:13:38 -0500 +Subject: xfs: fix xfs_mark_inode_dirty during umount +To: stable@vger.kernel.org +Cc: xfs@oss.sgi.com, Alex Elder +Message-ID: <20111119181543.605305176@bombadil.infradead.org> + +From: Christoph Hellwig + +commit 866e4ed77448a0c311e1b055eb72ea05423fd799 upstream. + +During umount we do not add a dirty inode to the lru and wait for it to +become clean first, but force writeback of data and metadata with +I_WILL_FREE set. Currently there is no way for XFS to detect that the +inode has been redirtied for metadata operations, as we skip the +mark_inode_dirty call during teardown. Fix this by setting i_update_core +nanually in that case, so that the inode gets flushed during inode reclaim. + +Alternatively we could enable calling mark_inode_dirty for inodes in +I_WILL_FREE state, and let the VFS dirty tracking handle this. I decided +against this as we will get better I/O patterns from reclaim compared to +the synchronous writeout in write_inode_now, and always marking the inode +dirty in some way from xfs_mark_inode_dirty is a better safetly net in +either case. + +Signed-off-by: Christoph Hellwig +Reviewed-by: Dave Chinner +Signed-off-by: Alex Elder +Signed-off-by: Greg Kroah-Hartman +--- + fs/xfs/linux-2.6/xfs_iops.c | 14 +++++++++++--- + 1 file changed, 11 insertions(+), 3 deletions(-) + +--- a/fs/xfs/linux-2.6/xfs_iops.c ++++ b/fs/xfs/linux-2.6/xfs_iops.c +@@ -69,9 +69,8 @@ xfs_synchronize_times( + } + + /* +- * If the linux inode is valid, mark it dirty. +- * Used when committing a dirty inode into a transaction so that +- * the inode will get written back by the linux code ++ * If the linux inode is valid, mark it dirty, else mark the dirty state ++ * in the XFS inode to make sure we pick it up when reclaiming the inode. + */ + void + xfs_mark_inode_dirty_sync( +@@ -81,6 +80,10 @@ xfs_mark_inode_dirty_sync( + + if (!(inode->i_state & (I_WILL_FREE|I_FREEING))) + mark_inode_dirty_sync(inode); ++ else { ++ barrier(); ++ ip->i_update_core = 1; ++ } + } + + void +@@ -91,6 +94,11 @@ xfs_mark_inode_dirty( + + if (!(inode->i_state & (I_WILL_FREE|I_FREEING))) + mark_inode_dirty(inode); ++ else { ++ barrier(); ++ ip->i_update_core = 1; ++ } ++ + } + + /* diff --git a/queue-3.0/xfs-return-eio-when-xfs_vn_getattr-failed.patch b/queue-3.0/xfs-return-eio-when-xfs_vn_getattr-failed.patch new file mode 100644 index 00000000000..bf5e2d29e4b --- /dev/null +++ b/queue-3.0/xfs-return-eio-when-xfs_vn_getattr-failed.patch @@ -0,0 +1,40 @@ +From hch@infradead.org Tue Nov 22 13:37:09 2011 +From: Mitsuo Hayasaka +Date: Sat, 19 Nov 2011 13:13:42 -0500 +Subject: xfs: Return -EIO when xfs_vn_getattr() failed +To: stable@vger.kernel.org +Cc: xfs@oss.sgi.com, Mitsuo Hayasaka , Alex Elder +Message-ID: <20111119181544.706389934@bombadil.infradead.org> + +From: Mitsuo Hayasaka + +commit ed32201e65e15f3e6955cb84cbb544b08f81e5a5 upstream. + +An attribute of inode can be fetched via xfs_vn_getattr() in XFS. +Currently it returns EIO, not negative value, when it failed. As a +result, the system call returns not negative value even though an +error occured. The stat(2), ls and mv commands cannot handle this +error and do not work correctly. + +This patch fixes this bug, and returns -EIO, not EIO when an error +is detected in xfs_vn_getattr(). + +Signed-off-by: Mitsuo Hayasaka +Reviewed-by: Christoph Hellwig +Signed-off-by: Alex Elder +Signed-off-by: Greg Kroah-Hartman +--- + fs/xfs/linux-2.6/xfs_iops.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/fs/xfs/linux-2.6/xfs_iops.c ++++ b/fs/xfs/linux-2.6/xfs_iops.c +@@ -464,7 +464,7 @@ xfs_vn_getattr( + trace_xfs_getattr(ip); + + if (XFS_FORCED_SHUTDOWN(mp)) +- return XFS_ERROR(EIO); ++ return -XFS_ERROR(EIO); + + stat->size = XFS_ISIZE(ip); + stat->dev = inode->i_sb->s_dev; diff --git a/queue-3.0/xfs-use-doalloc-flag-in-xfs_qm_dqattach_one.patch b/queue-3.0/xfs-use-doalloc-flag-in-xfs_qm_dqattach_one.patch new file mode 100644 index 00000000000..4002cee56d5 --- /dev/null +++ b/queue-3.0/xfs-use-doalloc-flag-in-xfs_qm_dqattach_one.patch @@ -0,0 +1,51 @@ +From hch@infradead.org Tue Nov 22 13:39:12 2011 +From: Christoph Hellwig +Date: Sat, 19 Nov 2011 13:13:45 -0500 +Subject: xfs: use doalloc flag in xfs_qm_dqattach_one() +To: stable@vger.kernel.org +Cc: xfs@oss.sgi.com, Mitsuo Hayasaka , Alex Elder , Ben Myers +Message-ID: <20111119181545.413417685@bombadil.infradead.org> + +From: Mitsuo Hayasaka + +commit db3e74b582915d66e10b0c73a62763418f54c340 upstream + +The doalloc arg in xfs_qm_dqattach_one() is a flag that indicates +whether a new area to handle quota information will be allocated +if needed. Originally, it was passed to xfs_qm_dqget(), but has +been removed by the following commit (probably by mistake): + + commit 8e9b6e7fa4544ea8a0e030c8987b918509c8ff47 + Author: Christoph Hellwig + Date: Sun Feb 8 21:51:42 2009 +0100 + + xfs: remove the unused XFS_QMOPT_DQLOCK flag + +As the result, xfs_qm_dqget() called from xfs_qm_dqattach_one() +never allocates the new area even if it is needed. + +This patch gives the doalloc arg to xfs_qm_dqget() in +xfs_qm_dqattach_one() to fix this problem. + +Signed-off-by: Mitsuo Hayasaka +Cc: Alex Elder +Cc: Christoph Hellwig +Reviewed-by: Christoph Hellwig +Signed-off-by: Ben Myers +Signed-off-by: Greg Kroah-Hartman +--- + fs/xfs/quota/xfs_qm.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +--- a/fs/xfs/quota/xfs_qm.c ++++ b/fs/xfs/quota/xfs_qm.c +@@ -714,7 +714,8 @@ xfs_qm_dqattach_one( + * disk and we didn't ask it to allocate; + * ESRCH if quotas got turned off suddenly. + */ +- error = xfs_qm_dqget(ip->i_mount, ip, id, type, XFS_QMOPT_DOWARN, &dqp); ++ error = xfs_qm_dqget(ip->i_mount, ip, id, type, ++ doalloc | XFS_QMOPT_DOWARN, &dqp); + if (error) + return error; +