diff options
author | Matthew Wilcox <willy@linux.intel.com> | 2008-05-19 02:34:27 -0400 |
---|---|---|
committer | Niv Sardi <xaiki@debian.org> | 2008-07-28 02:58:12 -0400 |
commit | d748c62367eb630cc30b91d561a5362f597a0892 (patch) | |
tree | 551fc30d6237517822edc6729456349e1bd0ab28 | |
parent | d729eae8933cb3eb8edf1446532c178b66b293a9 (diff) |
[XFS] Convert l_flushsema to a sv_t
The l_flushsema doesn't exactly have completion semantics, nor mutex
semantics. It's used as a list of tasks which are waiting to be notified
that a flush has completed. It was also being used in a way that was
potentially racy, depending on the semaphore implementation.
By using a sv_t instead of a semaphore we avoid the need for a separate
counter, since we know we just need to wake everything on the queue.
Original waitqueue implementation from Matthew Wilcox. Cleanup and
conversion to sv_t by Christoph Hellwig.
SGI-PV: 981507
SGI-Modid: xfs-linux-melb:xfs-kern:31059a
Signed-off-by: Matthew Wilcox <willy@linux.intel.com>
Signed-off-by: Christoph Hellwig <hch@infradead.org>
Signed-off-by: David Chinner <dgc@sgi.com>
Signed-off-by: Lachlan McIlroy <lachlan@sgi.com>
-rw-r--r-- | fs/xfs/xfs_log.c | 29 | ||||
-rw-r--r-- | fs/xfs/xfs_log_priv.h | 6 |
2 files changed, 15 insertions, 20 deletions
diff --git a/fs/xfs/xfs_log.c b/fs/xfs/xfs_log.c index 6195cc880101..91b00a5686cd 100644 --- a/fs/xfs/xfs_log.c +++ b/fs/xfs/xfs_log.c | |||
@@ -1232,7 +1232,7 @@ xlog_alloc_log(xfs_mount_t *mp, | |||
1232 | 1232 | ||
1233 | spin_lock_init(&log->l_icloglock); | 1233 | spin_lock_init(&log->l_icloglock); |
1234 | spin_lock_init(&log->l_grant_lock); | 1234 | spin_lock_init(&log->l_grant_lock); |
1235 | initnsema(&log->l_flushsema, 0, "ic-flush"); | 1235 | sv_init(&log->l_flush_wait, 0, "flush_wait"); |
1236 | 1236 | ||
1237 | /* log record size must be multiple of BBSIZE; see xlog_rec_header_t */ | 1237 | /* log record size must be multiple of BBSIZE; see xlog_rec_header_t */ |
1238 | ASSERT((XFS_BUF_SIZE(bp) & BBMASK) == 0); | 1238 | ASSERT((XFS_BUF_SIZE(bp) & BBMASK) == 0); |
@@ -1577,7 +1577,6 @@ xlog_dealloc_log(xlog_t *log) | |||
1577 | kmem_free(iclog); | 1577 | kmem_free(iclog); |
1578 | iclog = next_iclog; | 1578 | iclog = next_iclog; |
1579 | } | 1579 | } |
1580 | freesema(&log->l_flushsema); | ||
1581 | spinlock_destroy(&log->l_icloglock); | 1580 | spinlock_destroy(&log->l_icloglock); |
1582 | spinlock_destroy(&log->l_grant_lock); | 1581 | spinlock_destroy(&log->l_grant_lock); |
1583 | 1582 | ||
@@ -2101,6 +2100,7 @@ xlog_state_do_callback( | |||
2101 | int funcdidcallbacks; /* flag: function did callbacks */ | 2100 | int funcdidcallbacks; /* flag: function did callbacks */ |
2102 | int repeats; /* for issuing console warnings if | 2101 | int repeats; /* for issuing console warnings if |
2103 | * looping too many times */ | 2102 | * looping too many times */ |
2103 | int wake = 0; | ||
2104 | 2104 | ||
2105 | spin_lock(&log->l_icloglock); | 2105 | spin_lock(&log->l_icloglock); |
2106 | first_iclog = iclog = log->l_iclog; | 2106 | first_iclog = iclog = log->l_iclog; |
@@ -2282,15 +2282,13 @@ xlog_state_do_callback( | |||
2282 | } | 2282 | } |
2283 | #endif | 2283 | #endif |
2284 | 2284 | ||
2285 | flushcnt = 0; | 2285 | if (log->l_iclog->ic_state & (XLOG_STATE_ACTIVE|XLOG_STATE_IOERROR)) |
2286 | if (log->l_iclog->ic_state & (XLOG_STATE_ACTIVE|XLOG_STATE_IOERROR)) { | 2286 | wake = 1; |
2287 | flushcnt = log->l_flushcnt; | ||
2288 | log->l_flushcnt = 0; | ||
2289 | } | ||
2290 | spin_unlock(&log->l_icloglock); | 2287 | spin_unlock(&log->l_icloglock); |
2291 | while (flushcnt--) | 2288 | |
2292 | vsema(&log->l_flushsema); | 2289 | if (wake) |
2293 | } /* xlog_state_do_callback */ | 2290 | sv_broadcast(&log->l_flush_wait); |
2291 | } | ||
2294 | 2292 | ||
2295 | 2293 | ||
2296 | /* | 2294 | /* |
@@ -2388,16 +2386,15 @@ restart: | |||
2388 | } | 2386 | } |
2389 | 2387 | ||
2390 | iclog = log->l_iclog; | 2388 | iclog = log->l_iclog; |
2391 | if (! (iclog->ic_state == XLOG_STATE_ACTIVE)) { | 2389 | if (iclog->ic_state != XLOG_STATE_ACTIVE) { |
2392 | log->l_flushcnt++; | ||
2393 | spin_unlock(&log->l_icloglock); | ||
2394 | xlog_trace_iclog(iclog, XLOG_TRACE_SLEEP_FLUSH); | 2390 | xlog_trace_iclog(iclog, XLOG_TRACE_SLEEP_FLUSH); |
2395 | XFS_STATS_INC(xs_log_noiclogs); | 2391 | XFS_STATS_INC(xs_log_noiclogs); |
2396 | /* Ensure that log writes happen */ | 2392 | |
2397 | psema(&log->l_flushsema, PINOD); | 2393 | /* Wait for log writes to have flushed */ |
2394 | sv_wait(&log->l_flush_wait, 0, &log->l_icloglock, 0); | ||
2398 | goto restart; | 2395 | goto restart; |
2399 | } | 2396 | } |
2400 | ASSERT(iclog->ic_state == XLOG_STATE_ACTIVE); | 2397 | |
2401 | head = &iclog->ic_header; | 2398 | head = &iclog->ic_header; |
2402 | 2399 | ||
2403 | atomic_inc(&iclog->ic_refcnt); /* prevents sync */ | 2400 | atomic_inc(&iclog->ic_refcnt); /* prevents sync */ |
diff --git a/fs/xfs/xfs_log_priv.h b/fs/xfs/xfs_log_priv.h index 8952a392b5f3..6245913196b4 100644 --- a/fs/xfs/xfs_log_priv.h +++ b/fs/xfs/xfs_log_priv.h | |||
@@ -423,10 +423,8 @@ typedef struct log { | |||
423 | int l_logBBsize; /* size of log in BB chunks */ | 423 | int l_logBBsize; /* size of log in BB chunks */ |
424 | 424 | ||
425 | /* The following block of fields are changed while holding icloglock */ | 425 | /* The following block of fields are changed while holding icloglock */ |
426 | sema_t l_flushsema ____cacheline_aligned_in_smp; | 426 | sv_t l_flush_wait ____cacheline_aligned_in_smp; |
427 | /* iclog flushing semaphore */ | 427 | /* waiting for iclog flush */ |
428 | int l_flushcnt; /* # of procs waiting on this | ||
429 | * sema */ | ||
430 | int l_covered_state;/* state of "covering disk | 428 | int l_covered_state;/* state of "covering disk |
431 | * log entries" */ | 429 | * log entries" */ |
432 | xlog_in_core_t *l_iclog; /* head log queue */ | 430 | xlog_in_core_t *l_iclog; /* head log queue */ |