aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2012-09-21 15:43:01 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2012-09-21 15:43:01 -0400
commit789f95b788146ec27ab068103aacd546d05db266 (patch)
treeffb65a0be5e859be6fe93966a3f53999269ade78 /fs
parent36a21fe6399cafc440163890035ccd9b891de00f (diff)
parent0ba6e5368c302819da7aff537e0d7eff2616c6a6 (diff)
Merge tag 'for-linus-v3.6-rc7' of git://oss.sgi.com/xfs/xfs
Pull xfs bugfixes from Ben Myers: - fix a regression related to xfs_sync_worker racing with unmount. - fix a race while discarding xfs buffers. * tag 'for-linus-v3.6-rc7' of git://oss.sgi.com/xfs/xfs: xfs: stop the sync worker before xfs_unmountfs xfs: fix race while discarding buffers [V4]
Diffstat (limited to 'fs')
-rw-r--r--fs/xfs/xfs_buf.c5
-rw-r--r--fs/xfs/xfs_buf.h41
-rw-r--r--fs/xfs/xfs_super.c1
3 files changed, 29 insertions, 18 deletions
diff --git a/fs/xfs/xfs_buf.c b/fs/xfs/xfs_buf.c
index d7a9dd735e1e..933b7930b863 100644
--- a/fs/xfs/xfs_buf.c
+++ b/fs/xfs/xfs_buf.c
@@ -96,6 +96,7 @@ xfs_buf_lru_add(
96 atomic_inc(&bp->b_hold); 96 atomic_inc(&bp->b_hold);
97 list_add_tail(&bp->b_lru, &btp->bt_lru); 97 list_add_tail(&bp->b_lru, &btp->bt_lru);
98 btp->bt_lru_nr++; 98 btp->bt_lru_nr++;
99 bp->b_lru_flags &= ~_XBF_LRU_DISPOSE;
99 } 100 }
100 spin_unlock(&btp->bt_lru_lock); 101 spin_unlock(&btp->bt_lru_lock);
101} 102}
@@ -154,7 +155,8 @@ xfs_buf_stale(
154 struct xfs_buftarg *btp = bp->b_target; 155 struct xfs_buftarg *btp = bp->b_target;
155 156
156 spin_lock(&btp->bt_lru_lock); 157 spin_lock(&btp->bt_lru_lock);
157 if (!list_empty(&bp->b_lru)) { 158 if (!list_empty(&bp->b_lru) &&
159 !(bp->b_lru_flags & _XBF_LRU_DISPOSE)) {
158 list_del_init(&bp->b_lru); 160 list_del_init(&bp->b_lru);
159 btp->bt_lru_nr--; 161 btp->bt_lru_nr--;
160 atomic_dec(&bp->b_hold); 162 atomic_dec(&bp->b_hold);
@@ -1501,6 +1503,7 @@ xfs_buftarg_shrink(
1501 */ 1503 */
1502 list_move(&bp->b_lru, &dispose); 1504 list_move(&bp->b_lru, &dispose);
1503 btp->bt_lru_nr--; 1505 btp->bt_lru_nr--;
1506 bp->b_lru_flags |= _XBF_LRU_DISPOSE;
1504 } 1507 }
1505 spin_unlock(&btp->bt_lru_lock); 1508 spin_unlock(&btp->bt_lru_lock);
1506 1509
diff --git a/fs/xfs/xfs_buf.h b/fs/xfs/xfs_buf.h
index d03b73b9604e..7c0b6a0a1557 100644
--- a/fs/xfs/xfs_buf.h
+++ b/fs/xfs/xfs_buf.h
@@ -38,27 +38,28 @@ typedef enum {
38 XBRW_ZERO = 3, /* Zero target memory */ 38 XBRW_ZERO = 3, /* Zero target memory */
39} xfs_buf_rw_t; 39} xfs_buf_rw_t;
40 40
41#define XBF_READ (1 << 0) /* buffer intended for reading from device */ 41#define XBF_READ (1 << 0) /* buffer intended for reading from device */
42#define XBF_WRITE (1 << 1) /* buffer intended for writing to device */ 42#define XBF_WRITE (1 << 1) /* buffer intended for writing to device */
43#define XBF_READ_AHEAD (1 << 2) /* asynchronous read-ahead */ 43#define XBF_READ_AHEAD (1 << 2) /* asynchronous read-ahead */
44#define XBF_ASYNC (1 << 4) /* initiator will not wait for completion */ 44#define XBF_ASYNC (1 << 4) /* initiator will not wait for completion */
45#define XBF_DONE (1 << 5) /* all pages in the buffer uptodate */ 45#define XBF_DONE (1 << 5) /* all pages in the buffer uptodate */
46#define XBF_STALE (1 << 6) /* buffer has been staled, do not find it */ 46#define XBF_STALE (1 << 6) /* buffer has been staled, do not find it */
47 47
48/* I/O hints for the BIO layer */ 48/* I/O hints for the BIO layer */
49#define XBF_SYNCIO (1 << 10)/* treat this buffer as synchronous I/O */ 49#define XBF_SYNCIO (1 << 10)/* treat this buffer as synchronous I/O */
50#define XBF_FUA (1 << 11)/* force cache write through mode */ 50#define XBF_FUA (1 << 11)/* force cache write through mode */
51#define XBF_FLUSH (1 << 12)/* flush the disk cache before a write */ 51#define XBF_FLUSH (1 << 12)/* flush the disk cache before a write */
52 52
53/* flags used only as arguments to access routines */ 53/* flags used only as arguments to access routines */
54#define XBF_TRYLOCK (1 << 16)/* lock requested, but do not wait */ 54#define XBF_TRYLOCK (1 << 16)/* lock requested, but do not wait */
55#define XBF_UNMAPPED (1 << 17)/* do not map the buffer */ 55#define XBF_UNMAPPED (1 << 17)/* do not map the buffer */
56 56
57/* flags used only internally */ 57/* flags used only internally */
58#define _XBF_PAGES (1 << 20)/* backed by refcounted pages */ 58#define _XBF_PAGES (1 << 20)/* backed by refcounted pages */
59#define _XBF_KMEM (1 << 21)/* backed by heap memory */ 59#define _XBF_KMEM (1 << 21)/* backed by heap memory */
60#define _XBF_DELWRI_Q (1 << 22)/* buffer on a delwri queue */ 60#define _XBF_DELWRI_Q (1 << 22)/* buffer on a delwri queue */
61#define _XBF_COMPOUND (1 << 23)/* compound buffer */ 61#define _XBF_COMPOUND (1 << 23)/* compound buffer */
62#define _XBF_LRU_DISPOSE (1 << 24)/* buffer being discarded */
62 63
63typedef unsigned int xfs_buf_flags_t; 64typedef unsigned int xfs_buf_flags_t;
64 65
@@ -72,12 +73,13 @@ typedef unsigned int xfs_buf_flags_t;
72 { XBF_SYNCIO, "SYNCIO" }, \ 73 { XBF_SYNCIO, "SYNCIO" }, \
73 { XBF_FUA, "FUA" }, \ 74 { XBF_FUA, "FUA" }, \
74 { XBF_FLUSH, "FLUSH" }, \ 75 { XBF_FLUSH, "FLUSH" }, \
75 { XBF_TRYLOCK, "TRYLOCK" }, /* should never be set */\ 76 { XBF_TRYLOCK, "TRYLOCK" }, /* should never be set */\
76 { XBF_UNMAPPED, "UNMAPPED" }, /* ditto */\ 77 { XBF_UNMAPPED, "UNMAPPED" }, /* ditto */\
77 { _XBF_PAGES, "PAGES" }, \ 78 { _XBF_PAGES, "PAGES" }, \
78 { _XBF_KMEM, "KMEM" }, \ 79 { _XBF_KMEM, "KMEM" }, \
79 { _XBF_DELWRI_Q, "DELWRI_Q" }, \ 80 { _XBF_DELWRI_Q, "DELWRI_Q" }, \
80 { _XBF_COMPOUND, "COMPOUND" } 81 { _XBF_COMPOUND, "COMPOUND" }, \
82 { _XBF_LRU_DISPOSE, "LRU_DISPOSE" }
81 83
82typedef struct xfs_buftarg { 84typedef struct xfs_buftarg {
83 dev_t bt_dev; 85 dev_t bt_dev;
@@ -124,7 +126,12 @@ typedef struct xfs_buf {
124 xfs_buf_flags_t b_flags; /* status flags */ 126 xfs_buf_flags_t b_flags; /* status flags */
125 struct semaphore b_sema; /* semaphore for lockables */ 127 struct semaphore b_sema; /* semaphore for lockables */
126 128
129 /*
130 * concurrent access to b_lru and b_lru_flags are protected by
131 * bt_lru_lock and not by b_sema
132 */
127 struct list_head b_lru; /* lru list */ 133 struct list_head b_lru; /* lru list */
134 xfs_buf_flags_t b_lru_flags; /* internal lru status flags */
128 wait_queue_head_t b_waiters; /* unpin waiters */ 135 wait_queue_head_t b_waiters; /* unpin waiters */
129 struct list_head b_list; 136 struct list_head b_list;
130 struct xfs_perag *b_pag; /* contains rbtree root */ 137 struct xfs_perag *b_pag; /* contains rbtree root */
diff --git a/fs/xfs/xfs_super.c b/fs/xfs/xfs_super.c
index bdaf4cb9f4a2..19e2380fb867 100644
--- a/fs/xfs/xfs_super.c
+++ b/fs/xfs/xfs_super.c
@@ -919,6 +919,7 @@ xfs_fs_put_super(
919 struct xfs_mount *mp = XFS_M(sb); 919 struct xfs_mount *mp = XFS_M(sb);
920 920
921 xfs_filestream_unmount(mp); 921 xfs_filestream_unmount(mp);
922 cancel_delayed_work_sync(&mp->m_sync_work);
922 xfs_unmountfs(mp); 923 xfs_unmountfs(mp);
923 xfs_syncd_stop(mp); 924 xfs_syncd_stop(mp);
924 xfs_freesb(mp); 925 xfs_freesb(mp);