aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/xfs/xfs_log.c137
-rw-r--r--fs/xfs/xfs_log_priv.h9
-rw-r--r--fs/xfs/xfs_vfsops.c12
3 files changed, 21 insertions, 137 deletions
diff --git a/fs/xfs/xfs_log.c b/fs/xfs/xfs_log.c
index 7a5b12d93537..3cf115d8de75 100644
--- a/fs/xfs/xfs_log.c
+++ b/fs/xfs/xfs_log.c
@@ -41,6 +41,7 @@
41#include "xfs_inode.h" 41#include "xfs_inode.h"
42#include "xfs_rw.h" 42#include "xfs_rw.h"
43 43
44kmem_zone_t *xfs_log_ticket_zone;
44 45
45#define xlog_write_adv_cnt(ptr, len, off, bytes) \ 46#define xlog_write_adv_cnt(ptr, len, off, bytes) \
46 { (ptr) += (bytes); \ 47 { (ptr) += (bytes); \
@@ -73,8 +74,6 @@ STATIC int xlog_state_get_iclog_space(xlog_t *log,
73 xlog_ticket_t *ticket, 74 xlog_ticket_t *ticket,
74 int *continued_write, 75 int *continued_write,
75 int *logoffsetp); 76 int *logoffsetp);
76STATIC void xlog_state_put_ticket(xlog_t *log,
77 xlog_ticket_t *tic);
78STATIC int xlog_state_release_iclog(xlog_t *log, 77STATIC int xlog_state_release_iclog(xlog_t *log,
79 xlog_in_core_t *iclog); 78 xlog_in_core_t *iclog);
80STATIC void xlog_state_switch_iclogs(xlog_t *log, 79STATIC void xlog_state_switch_iclogs(xlog_t *log,
@@ -101,7 +100,6 @@ STATIC void xlog_ungrant_log_space(xlog_t *log,
101 100
102 101
103/* local ticket functions */ 102/* local ticket functions */
104STATIC void xlog_state_ticket_alloc(xlog_t *log);
105STATIC xlog_ticket_t *xlog_ticket_get(xlog_t *log, 103STATIC xlog_ticket_t *xlog_ticket_get(xlog_t *log,
106 int unit_bytes, 104 int unit_bytes,
107 int count, 105 int count,
@@ -330,7 +328,7 @@ xfs_log_done(xfs_mount_t *mp,
330 */ 328 */
331 xlog_trace_loggrant(log, ticket, "xfs_log_done: (non-permanent)"); 329 xlog_trace_loggrant(log, ticket, "xfs_log_done: (non-permanent)");
332 xlog_ungrant_log_space(log, ticket); 330 xlog_ungrant_log_space(log, ticket);
333 xlog_state_put_ticket(log, ticket); 331 xlog_ticket_put(log, ticket);
334 } else { 332 } else {
335 xlog_trace_loggrant(log, ticket, "xfs_log_done: (permanent)"); 333 xlog_trace_loggrant(log, ticket, "xfs_log_done: (permanent)");
336 xlog_regrant_reserve_log_space(log, ticket); 334 xlog_regrant_reserve_log_space(log, ticket);
@@ -469,6 +467,8 @@ xfs_log_reserve(xfs_mount_t *mp,
469 /* may sleep if need to allocate more tickets */ 467 /* may sleep if need to allocate more tickets */
470 internal_ticket = xlog_ticket_get(log, unit_bytes, cnt, 468 internal_ticket = xlog_ticket_get(log, unit_bytes, cnt,
471 client, flags); 469 client, flags);
470 if (!internal_ticket)
471 return XFS_ERROR(ENOMEM);
472 internal_ticket->t_trans_type = t_type; 472 internal_ticket->t_trans_type = t_type;
473 *ticket = internal_ticket; 473 *ticket = internal_ticket;
474 xlog_trace_loggrant(log, internal_ticket, 474 xlog_trace_loggrant(log, internal_ticket,
@@ -693,7 +693,7 @@ xfs_log_unmount_write(xfs_mount_t *mp)
693 if (tic) { 693 if (tic) {
694 xlog_trace_loggrant(log, tic, "unmount rec"); 694 xlog_trace_loggrant(log, tic, "unmount rec");
695 xlog_ungrant_log_space(log, tic); 695 xlog_ungrant_log_space(log, tic);
696 xlog_state_put_ticket(log, tic); 696 xlog_ticket_put(log, tic);
697 } 697 }
698 } else { 698 } else {
699 /* 699 /*
@@ -1208,7 +1208,6 @@ xlog_alloc_log(xfs_mount_t *mp,
1208 spin_lock_init(&log->l_icloglock); 1208 spin_lock_init(&log->l_icloglock);
1209 spin_lock_init(&log->l_grant_lock); 1209 spin_lock_init(&log->l_grant_lock);
1210 initnsema(&log->l_flushsema, 0, "ic-flush"); 1210 initnsema(&log->l_flushsema, 0, "ic-flush");
1211 xlog_state_ticket_alloc(log); /* wait until after icloglock inited */
1212 1211
1213 /* log record size must be multiple of BBSIZE; see xlog_rec_header_t */ 1212 /* log record size must be multiple of BBSIZE; see xlog_rec_header_t */
1214 ASSERT((XFS_BUF_SIZE(bp) & BBMASK) == 0); 1213 ASSERT((XFS_BUF_SIZE(bp) & BBMASK) == 0);
@@ -1538,7 +1537,6 @@ STATIC void
1538xlog_dealloc_log(xlog_t *log) 1537xlog_dealloc_log(xlog_t *log)
1539{ 1538{
1540 xlog_in_core_t *iclog, *next_iclog; 1539 xlog_in_core_t *iclog, *next_iclog;
1541 xlog_ticket_t *tic, *next_tic;
1542 int i; 1540 int i;
1543 1541
1544 iclog = log->l_iclog; 1542 iclog = log->l_iclog;
@@ -1559,22 +1557,6 @@ xlog_dealloc_log(xlog_t *log)
1559 spinlock_destroy(&log->l_icloglock); 1557 spinlock_destroy(&log->l_icloglock);
1560 spinlock_destroy(&log->l_grant_lock); 1558 spinlock_destroy(&log->l_grant_lock);
1561 1559
1562 /* XXXsup take a look at this again. */
1563 if ((log->l_ticket_cnt != log->l_ticket_tcnt) &&
1564 !XLOG_FORCED_SHUTDOWN(log)) {
1565 xfs_fs_cmn_err(CE_WARN, log->l_mp,
1566 "xlog_dealloc_log: (cnt: %d, total: %d)",
1567 log->l_ticket_cnt, log->l_ticket_tcnt);
1568 /* ASSERT(log->l_ticket_cnt == log->l_ticket_tcnt); */
1569
1570 } else {
1571 tic = log->l_unmount_free;
1572 while (tic) {
1573 next_tic = tic->t_next;
1574 kmem_free(tic, PAGE_SIZE);
1575 tic = next_tic;
1576 }
1577 }
1578 xfs_buf_free(log->l_xbuf); 1560 xfs_buf_free(log->l_xbuf);
1579#ifdef XFS_LOG_TRACE 1561#ifdef XFS_LOG_TRACE
1580 if (log->l_trace != NULL) { 1562 if (log->l_trace != NULL) {
@@ -2795,18 +2777,6 @@ xlog_ungrant_log_space(xlog_t *log,
2795 2777
2796 2778
2797/* 2779/*
2798 * Atomically put back used ticket.
2799 */
2800STATIC void
2801xlog_state_put_ticket(xlog_t *log,
2802 xlog_ticket_t *tic)
2803{
2804 spin_lock(&log->l_icloglock);
2805 xlog_ticket_put(log, tic);
2806 spin_unlock(&log->l_icloglock);
2807} /* xlog_state_put_ticket */
2808
2809/*
2810 * Flush iclog to disk if this is the last reference to the given iclog and 2780 * Flush iclog to disk if this is the last reference to the given iclog and
2811 * the WANT_SYNC bit is set. 2781 * the WANT_SYNC bit is set.
2812 * 2782 *
@@ -3176,92 +3146,19 @@ xlog_state_want_sync(xlog_t *log, xlog_in_core_t *iclog)
3176 */ 3146 */
3177 3147
3178/* 3148/*
3179 * Algorithm doesn't take into account page size. ;-( 3149 * Free a used ticket.
3180 */
3181STATIC void
3182xlog_state_ticket_alloc(xlog_t *log)
3183{
3184 xlog_ticket_t *t_list;
3185 xlog_ticket_t *next;
3186 xfs_caddr_t buf;
3187 uint i = (PAGE_SIZE / sizeof(xlog_ticket_t)) - 2;
3188
3189 /*
3190 * The kmem_zalloc may sleep, so we shouldn't be holding the
3191 * global lock. XXXmiken: may want to use zone allocator.
3192 */
3193 buf = (xfs_caddr_t) kmem_zalloc(PAGE_SIZE, KM_SLEEP);
3194
3195 spin_lock(&log->l_icloglock);
3196
3197 /* Attach 1st ticket to Q, so we can keep track of allocated memory */
3198 t_list = (xlog_ticket_t *)buf;
3199 t_list->t_next = log->l_unmount_free;
3200 log->l_unmount_free = t_list++;
3201 log->l_ticket_cnt++;
3202 log->l_ticket_tcnt++;
3203
3204 /* Next ticket becomes first ticket attached to ticket free list */
3205 if (log->l_freelist != NULL) {
3206 ASSERT(log->l_tail != NULL);
3207 log->l_tail->t_next = t_list;
3208 } else {
3209 log->l_freelist = t_list;
3210 }
3211 log->l_ticket_cnt++;
3212 log->l_ticket_tcnt++;
3213
3214 /* Cycle through rest of alloc'ed memory, building up free Q */
3215 for ( ; i > 0; i--) {
3216 next = t_list + 1;
3217 t_list->t_next = next;
3218 t_list = next;
3219 log->l_ticket_cnt++;
3220 log->l_ticket_tcnt++;
3221 }
3222 t_list->t_next = NULL;
3223 log->l_tail = t_list;
3224 spin_unlock(&log->l_icloglock);
3225} /* xlog_state_ticket_alloc */
3226
3227
3228/*
3229 * Put ticket into free list
3230 *
3231 * Assumption: log lock is held around this call.
3232 */ 3150 */
3233STATIC void 3151STATIC void
3234xlog_ticket_put(xlog_t *log, 3152xlog_ticket_put(xlog_t *log,
3235 xlog_ticket_t *ticket) 3153 xlog_ticket_t *ticket)
3236{ 3154{
3237 sv_destroy(&ticket->t_sema); 3155 sv_destroy(&ticket->t_sema);
3238 3156 kmem_zone_free(xfs_log_ticket_zone, ticket);
3239 /*
3240 * Don't think caching will make that much difference. It's
3241 * more important to make debug easier.
3242 */
3243#if 0
3244 /* real code will want to use LIFO for caching */
3245 ticket->t_next = log->l_freelist;
3246 log->l_freelist = ticket;
3247 /* no need to clear fields */
3248#else
3249 /* When we debug, it is easier if tickets are cycled */
3250 ticket->t_next = NULL;
3251 if (log->l_tail) {
3252 log->l_tail->t_next = ticket;
3253 } else {
3254 ASSERT(log->l_freelist == NULL);
3255 log->l_freelist = ticket;
3256 }
3257 log->l_tail = ticket;
3258#endif /* DEBUG */
3259 log->l_ticket_cnt++;
3260} /* xlog_ticket_put */ 3157} /* xlog_ticket_put */
3261 3158
3262 3159
3263/* 3160/*
3264 * Grab ticket off freelist or allocation some more 3161 * Allocate and initialise a new log ticket.
3265 */ 3162 */
3266STATIC xlog_ticket_t * 3163STATIC xlog_ticket_t *
3267xlog_ticket_get(xlog_t *log, 3164xlog_ticket_get(xlog_t *log,
@@ -3273,21 +3170,9 @@ xlog_ticket_get(xlog_t *log,
3273 xlog_ticket_t *tic; 3170 xlog_ticket_t *tic;
3274 uint num_headers; 3171 uint num_headers;
3275 3172
3276 alloc: 3173 tic = kmem_zone_zalloc(xfs_log_ticket_zone, KM_SLEEP|KM_MAYFAIL);
3277 if (log->l_freelist == NULL) 3174 if (!tic)
3278 xlog_state_ticket_alloc(log); /* potentially sleep */ 3175 return NULL;
3279
3280 spin_lock(&log->l_icloglock);
3281 if (log->l_freelist == NULL) {
3282 spin_unlock(&log->l_icloglock);
3283 goto alloc;
3284 }
3285 tic = log->l_freelist;
3286 log->l_freelist = tic->t_next;
3287 if (log->l_freelist == NULL)
3288 log->l_tail = NULL;
3289 log->l_ticket_cnt--;
3290 spin_unlock(&log->l_icloglock);
3291 3176
3292 /* 3177 /*
3293 * Permanent reservations have up to 'cnt'-1 active log operations 3178 * Permanent reservations have up to 'cnt'-1 active log operations
diff --git a/fs/xfs/xfs_log_priv.h b/fs/xfs/xfs_log_priv.h
index 104b623aa082..c1583960009d 100644
--- a/fs/xfs/xfs_log_priv.h
+++ b/fs/xfs/xfs_log_priv.h
@@ -242,7 +242,7 @@ typedef struct xlog_res {
242 242
243typedef struct xlog_ticket { 243typedef struct xlog_ticket {
244 sv_t t_sema; /* sleep on this semaphore : 20 */ 244 sv_t t_sema; /* sleep on this semaphore : 20 */
245 struct xlog_ticket *t_next; /* :4|8 */ 245 struct xlog_ticket *t_next; /* :4|8 */
246 struct xlog_ticket *t_prev; /* :4|8 */ 246 struct xlog_ticket *t_prev; /* :4|8 */
247 xlog_tid_t t_tid; /* transaction identifier : 4 */ 247 xlog_tid_t t_tid; /* transaction identifier : 4 */
248 int t_curr_res; /* current reservation in bytes : 4 */ 248 int t_curr_res; /* current reservation in bytes : 4 */
@@ -406,13 +406,8 @@ typedef struct log {
406 sema_t l_flushsema; /* iclog flushing semaphore */ 406 sema_t l_flushsema; /* iclog flushing semaphore */
407 int l_flushcnt; /* # of procs waiting on this 407 int l_flushcnt; /* # of procs waiting on this
408 * sema */ 408 * sema */
409 int l_ticket_cnt; /* free ticket count */
410 int l_ticket_tcnt; /* total ticket count */
411 int l_covered_state;/* state of "covering disk 409 int l_covered_state;/* state of "covering disk
412 * log entries" */ 410 * log entries" */
413 xlog_ticket_t *l_freelist; /* free list of tickets */
414 xlog_ticket_t *l_unmount_free;/* kmem_free these addresses */
415 xlog_ticket_t *l_tail; /* free list of tickets */
416 xlog_in_core_t *l_iclog; /* head log queue */ 411 xlog_in_core_t *l_iclog; /* head log queue */
417 spinlock_t l_icloglock; /* grab to change iclog state */ 412 spinlock_t l_icloglock; /* grab to change iclog state */
418 xfs_lsn_t l_tail_lsn; /* lsn of 1st LR with unflushed 413 xfs_lsn_t l_tail_lsn; /* lsn of 1st LR with unflushed
@@ -478,6 +473,8 @@ extern struct xfs_buf *xlog_get_bp(xlog_t *, int);
478extern void xlog_put_bp(struct xfs_buf *); 473extern void xlog_put_bp(struct xfs_buf *);
479extern int xlog_bread(xlog_t *, xfs_daddr_t, int, struct xfs_buf *); 474extern int xlog_bread(xlog_t *, xfs_daddr_t, int, struct xfs_buf *);
480 475
476extern kmem_zone_t *xfs_log_ticket_zone;
477
481/* iclog tracing */ 478/* iclog tracing */
482#define XLOG_TRACE_GRAB_FLUSH 1 479#define XLOG_TRACE_GRAB_FLUSH 1
483#define XLOG_TRACE_REL_FLUSH 2 480#define XLOG_TRACE_REL_FLUSH 2
diff --git a/fs/xfs/xfs_vfsops.c b/fs/xfs/xfs_vfsops.c
index c21e4d168297..ea94593b5313 100644
--- a/fs/xfs/xfs_vfsops.c
+++ b/fs/xfs/xfs_vfsops.c
@@ -69,15 +69,17 @@ xfs_init(void)
69 /* 69 /*
70 * Initialize all of the zone allocators we use. 70 * Initialize all of the zone allocators we use.
71 */ 71 */
72 xfs_log_ticket_zone = kmem_zone_init(sizeof(xlog_ticket_t),
73 "xfs_log_ticket");
72 xfs_bmap_free_item_zone = kmem_zone_init(sizeof(xfs_bmap_free_item_t), 74 xfs_bmap_free_item_zone = kmem_zone_init(sizeof(xfs_bmap_free_item_t),
73 "xfs_bmap_free_item"); 75 "xfs_bmap_free_item");
74 xfs_btree_cur_zone = kmem_zone_init(sizeof(xfs_btree_cur_t), 76 xfs_btree_cur_zone = kmem_zone_init(sizeof(xfs_btree_cur_t),
75 "xfs_btree_cur"); 77 "xfs_btree_cur");
76 xfs_trans_zone = kmem_zone_init(sizeof(xfs_trans_t), "xfs_trans"); 78 xfs_da_state_zone = kmem_zone_init(sizeof(xfs_da_state_t),
77 xfs_da_state_zone = 79 "xfs_da_state");
78 kmem_zone_init(sizeof(xfs_da_state_t), "xfs_da_state");
79 xfs_dabuf_zone = kmem_zone_init(sizeof(xfs_dabuf_t), "xfs_dabuf"); 80 xfs_dabuf_zone = kmem_zone_init(sizeof(xfs_dabuf_t), "xfs_dabuf");
80 xfs_ifork_zone = kmem_zone_init(sizeof(xfs_ifork_t), "xfs_ifork"); 81 xfs_ifork_zone = kmem_zone_init(sizeof(xfs_ifork_t), "xfs_ifork");
82 xfs_trans_zone = kmem_zone_init(sizeof(xfs_trans_t), "xfs_trans");
81 xfs_acl_zone_init(xfs_acl_zone, "xfs_acl"); 83 xfs_acl_zone_init(xfs_acl_zone, "xfs_acl");
82 xfs_mru_cache_init(); 84 xfs_mru_cache_init();
83 xfs_filestream_init(); 85 xfs_filestream_init();