1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18#include "xfs.h"
19#include "xfs_fs.h"
20#include "xfs_types.h"
21#include "xfs_bit.h"
22#include "xfs_log.h"
23#include "xfs_inum.h"
24#include "xfs_trans.h"
25#include "xfs_sb.h"
26#include "xfs_ag.h"
27#include "xfs_dir2.h"
28#include "xfs_dmapi.h"
29#include "xfs_mount.h"
30#include "xfs_error.h"
31#include "xfs_log_priv.h"
32#include "xfs_buf_item.h"
33#include "xfs_bmap_btree.h"
34#include "xfs_alloc_btree.h"
35#include "xfs_ialloc_btree.h"
36#include "xfs_log_recover.h"
37#include "xfs_trans_priv.h"
38#include "xfs_dir2_sf.h"
39#include "xfs_attr_sf.h"
40#include "xfs_dinode.h"
41#include "xfs_inode.h"
42#include "xfs_rw.h"
43
44kmem_zone_t *xfs_log_ticket_zone;
45
46#define xlog_write_adv_cnt(ptr, len, off, bytes) \
47 { (ptr) += (bytes); \
48 (len) -= (bytes); \
49 (off) += (bytes);}
50
51
52STATIC int xlog_bdstrat_cb(struct xfs_buf *);
53STATIC int xlog_commit_record(xfs_mount_t *mp, xlog_ticket_t *ticket,
54 xlog_in_core_t **, xfs_lsn_t *);
55STATIC xlog_t * xlog_alloc_log(xfs_mount_t *mp,
56 xfs_buftarg_t *log_target,
57 xfs_daddr_t blk_offset,
58 int num_bblks);
59STATIC int xlog_space_left(xlog_t *log, int cycle, int bytes);
60STATIC int xlog_sync(xlog_t *log, xlog_in_core_t *iclog);
61STATIC void xlog_dealloc_log(xlog_t *log);
62STATIC int xlog_write(xfs_mount_t *mp, xfs_log_iovec_t region[],
63 int nentries, xfs_log_ticket_t tic,
64 xfs_lsn_t *start_lsn,
65 xlog_in_core_t **commit_iclog,
66 uint flags);
67
68
69STATIC void xlog_state_done_syncing(xlog_in_core_t *iclog, int);
70STATIC void xlog_state_do_callback(xlog_t *log,int aborted, xlog_in_core_t *iclog);
71STATIC int xlog_state_get_iclog_space(xlog_t *log,
72 int len,
73 xlog_in_core_t **iclog,
74 xlog_ticket_t *ticket,
75 int *continued_write,
76 int *logoffsetp);
77STATIC int xlog_state_release_iclog(xlog_t *log,
78 xlog_in_core_t *iclog);
79STATIC void xlog_state_switch_iclogs(xlog_t *log,
80 xlog_in_core_t *iclog,
81 int eventual_size);
82STATIC int xlog_state_sync(xlog_t *log,
83 xfs_lsn_t lsn,
84 uint flags,
85 int *log_flushed);
86STATIC int xlog_state_sync_all(xlog_t *log, uint flags, int *log_flushed);
87STATIC void xlog_state_want_sync(xlog_t *log, xlog_in_core_t *iclog);
88
89
90STATIC int xlog_grant_log_space(xlog_t *log,
91 xlog_ticket_t *xtic);
92STATIC void xlog_grant_push_ail(xfs_mount_t *mp,
93 int need_bytes);
94STATIC void xlog_regrant_reserve_log_space(xlog_t *log,
95 xlog_ticket_t *ticket);
96STATIC int xlog_regrant_write_log_space(xlog_t *log,
97 xlog_ticket_t *ticket);
98STATIC void xlog_ungrant_log_space(xlog_t *log,
99 xlog_ticket_t *ticket);
100
101
102
103STATIC xlog_ticket_t *xlog_ticket_alloc(xlog_t *log,
104 int unit_bytes,
105 int count,
106 char clientid,
107 uint flags);
108
109#if defined(DEBUG)
110STATIC void xlog_verify_dest_ptr(xlog_t *log, __psint_t ptr);
111STATIC void xlog_verify_grant_head(xlog_t *log, int equals);
112STATIC void xlog_verify_iclog(xlog_t *log, xlog_in_core_t *iclog,
113 int count, boolean_t syncing);
114STATIC void xlog_verify_tail_lsn(xlog_t *log, xlog_in_core_t *iclog,
115 xfs_lsn_t tail_lsn);
116#else
117#define xlog_verify_dest_ptr(a,b)
118#define xlog_verify_grant_head(a,b)
119#define xlog_verify_iclog(a,b,c,d)
120#define xlog_verify_tail_lsn(a,b,c)
121#endif
122
123STATIC int xlog_iclogs_empty(xlog_t *log);
124
125#if defined(XFS_LOG_TRACE)
126
127#define XLOG_TRACE_LOGGRANT_SIZE 2048
128#define XLOG_TRACE_ICLOG_SIZE 256
129
130void
131xlog_trace_loggrant_alloc(xlog_t *log)
132{
133 log->l_grant_trace = ktrace_alloc(XLOG_TRACE_LOGGRANT_SIZE, KM_NOFS);
134}
135
136void
137xlog_trace_loggrant_dealloc(xlog_t *log)
138{
139 ktrace_free(log->l_grant_trace);
140}
141
142void
143xlog_trace_loggrant(xlog_t *log, xlog_ticket_t *tic, xfs_caddr_t string)
144{
145 unsigned long cnts;
146
147
148 cnts = ((unsigned long)tic->t_ocnt) | ((unsigned long)tic->t_cnt) << 8;
149
150 ktrace_enter(log->l_grant_trace,
151 (void *)tic,
152 (void *)log->l_reserve_headq,
153 (void *)log->l_write_headq,
154 (void *)((unsigned long)log->l_grant_reserve_cycle),
155 (void *)((unsigned long)log->l_grant_reserve_bytes),
156 (void *)((unsigned long)log->l_grant_write_cycle),
157 (void *)((unsigned long)log->l_grant_write_bytes),
158 (void *)((unsigned long)log->l_curr_cycle),
159 (void *)((unsigned long)log->l_curr_block),
160 (void *)((unsigned long)CYCLE_LSN(log->l_tail_lsn)),
161 (void *)((unsigned long)BLOCK_LSN(log->l_tail_lsn)),
162 (void *)string,
163 (void *)((unsigned long)tic->t_trans_type),
164 (void *)cnts,
165 (void *)((unsigned long)tic->t_curr_res),
166 (void *)((unsigned long)tic->t_unit_res));
167}
168
169void
170xlog_trace_iclog_alloc(xlog_in_core_t *iclog)
171{
172 iclog->ic_trace = ktrace_alloc(XLOG_TRACE_ICLOG_SIZE, KM_NOFS);
173}
174
175void
176xlog_trace_iclog_dealloc(xlog_in_core_t *iclog)
177{
178 ktrace_free(iclog->ic_trace);
179}
180
181void
182xlog_trace_iclog(xlog_in_core_t *iclog, uint state)
183{
184 ktrace_enter(iclog->ic_trace,
185 (void *)((unsigned long)state),
186 (void *)((unsigned long)current_pid()),
187 (void *)NULL, (void *)NULL, (void *)NULL, (void *)NULL,
188 (void *)NULL, (void *)NULL, (void *)NULL, (void *)NULL,
189 (void *)NULL, (void *)NULL, (void *)NULL, (void *)NULL,
190 (void *)NULL, (void *)NULL);
191}
192#else
193
194#define xlog_trace_loggrant_alloc(log)
195#define xlog_trace_loggrant_dealloc(log)
196#define xlog_trace_loggrant(log,tic,string)
197
198#define xlog_trace_iclog_alloc(iclog)
199#define xlog_trace_iclog_dealloc(iclog)
200#define xlog_trace_iclog(iclog,state)
201
202#endif
203
204
205static void
206xlog_ins_ticketq(struct xlog_ticket **qp, struct xlog_ticket *tic)
207{
208 if (*qp) {
209 tic->t_next = (*qp);
210 tic->t_prev = (*qp)->t_prev;
211 (*qp)->t_prev->t_next = tic;
212 (*qp)->t_prev = tic;
213 } else {
214 tic->t_prev = tic->t_next = tic;
215 *qp = tic;
216 }
217
218 tic->t_flags |= XLOG_TIC_IN_Q;
219}
220
221static void
222xlog_del_ticketq(struct xlog_ticket **qp, struct xlog_ticket *tic)
223{
224 if (tic == tic->t_next) {
225 *qp = NULL;
226 } else {
227 *qp = tic->t_next;
228 tic->t_next->t_prev = tic->t_prev;
229 tic->t_prev->t_next = tic->t_next;
230 }
231
232 tic->t_next = tic->t_prev = NULL;
233 tic->t_flags &= ~XLOG_TIC_IN_Q;
234}
235
236static void
237xlog_grant_sub_space(struct log *log, int bytes)
238{
239 log->l_grant_write_bytes -= bytes;
240 if (log->l_grant_write_bytes < 0) {
241 log->l_grant_write_bytes += log->l_logsize;
242 log->l_grant_write_cycle--;
243 }
244
245 log->l_grant_reserve_bytes -= bytes;
246 if ((log)->l_grant_reserve_bytes < 0) {
247 log->l_grant_reserve_bytes += log->l_logsize;
248 log->l_grant_reserve_cycle--;
249 }
250
251}
252
253static void
254xlog_grant_add_space_write(struct log *log, int bytes)
255{
256 int tmp = log->l_logsize - log->l_grant_write_bytes;
257 if (tmp > bytes)
258 log->l_grant_write_bytes += bytes;
259 else {
260 log->l_grant_write_cycle++;
261 log->l_grant_write_bytes = bytes - tmp;
262 }
263}
264
265static void
266xlog_grant_add_space_reserve(struct log *log, int bytes)
267{
268 int tmp = log->l_logsize - log->l_grant_reserve_bytes;
269 if (tmp > bytes)
270 log->l_grant_reserve_bytes += bytes;
271 else {
272 log->l_grant_reserve_cycle++;
273 log->l_grant_reserve_bytes = bytes - tmp;
274 }
275}
276
277static inline void
278xlog_grant_add_space(struct log *log, int bytes)
279{
280 xlog_grant_add_space_write(log, bytes);
281 xlog_grant_add_space_reserve(log, bytes);
282}
283
284static void
285xlog_tic_reset_res(xlog_ticket_t *tic)
286{
287 tic->t_res_num = 0;
288 tic->t_res_arr_sum = 0;
289 tic->t_res_num_ophdrs = 0;
290}
291
292static void
293xlog_tic_add_region(xlog_ticket_t *tic, uint len, uint type)
294{
295 if (tic->t_res_num == XLOG_TIC_LEN_MAX) {
296
297 tic->t_res_o_flow += tic->t_res_arr_sum;
298 tic->t_res_num = 0;
299 tic->t_res_arr_sum = 0;
300 }
301
302 tic->t_res_arr[tic->t_res_num].r_len = len;
303 tic->t_res_arr[tic->t_res_num].r_type = type;
304 tic->t_res_arr_sum += len;
305 tic->t_res_num++;
306}
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329xfs_lsn_t
330xfs_log_done(xfs_mount_t *mp,
331 xfs_log_ticket_t xtic,
332 void **iclog,
333 uint flags)
334{
335 xlog_t *log = mp->m_log;
336 xlog_ticket_t *ticket = (xfs_log_ticket_t) xtic;
337 xfs_lsn_t lsn = 0;
338
339 if (XLOG_FORCED_SHUTDOWN(log) ||
340
341
342
343
344 (((ticket->t_flags & XLOG_TIC_INITED) == 0) &&
345 (xlog_commit_record(mp, ticket,
346 (xlog_in_core_t **)iclog, &lsn)))) {
347 lsn = (xfs_lsn_t) -1;
348 if (ticket->t_flags & XLOG_TIC_PERM_RESERV) {
349 flags |= XFS_LOG_REL_PERM_RESERV;
350 }
351 }
352
353
354 if ((ticket->t_flags & XLOG_TIC_PERM_RESERV) == 0 ||
355 (flags & XFS_LOG_REL_PERM_RESERV)) {
356
357
358
359
360 xlog_trace_loggrant(log, ticket, "xfs_log_done: (non-permanent)");
361 xlog_ungrant_log_space(log, ticket);
362 xfs_log_ticket_put(ticket);
363 } else {
364 xlog_trace_loggrant(log, ticket, "xfs_log_done: (permanent)");
365 xlog_regrant_reserve_log_space(log, ticket);
366
367
368
369
370 ticket->t_flags |= XLOG_TIC_INITED;
371 }
372
373 return lsn;
374}
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390int
391_xfs_log_force(
392 xfs_mount_t *mp,
393 xfs_lsn_t lsn,
394 uint flags,
395 int *log_flushed)
396{
397 xlog_t *log = mp->m_log;
398 int dummy;
399
400 if (!log_flushed)
401 log_flushed = &dummy;
402
403 ASSERT(flags & XFS_LOG_FORCE);
404
405 XFS_STATS_INC(xs_log_force);
406
407 if (log->l_flags & XLOG_IO_ERROR)
408 return XFS_ERROR(EIO);
409 if (lsn == 0)
410 return xlog_state_sync_all(log, flags, log_flushed);
411 else
412 return xlog_state_sync(log, lsn, flags, log_flushed);
413}
414
415
416
417
418
419
420void
421xfs_log_force(
422 xfs_mount_t *mp,
423 xfs_lsn_t lsn,
424 uint flags)
425{
426 int error;
427 error = _xfs_log_force(mp, lsn, flags, NULL);
428 if (error) {
429 xfs_fs_cmn_err(CE_WARN, mp, "xfs_log_force: "
430 "error %d returned.", error);
431 }
432}
433
434
435
436
437
438
439
440
441int
442xfs_log_notify(xfs_mount_t *mp,
443 void *iclog_hndl,
444 xfs_log_callback_t *cb)
445{
446 xlog_in_core_t *iclog = (xlog_in_core_t *)iclog_hndl;
447 int abortflg;
448
449 spin_lock(&iclog->ic_callback_lock);
450 abortflg = (iclog->ic_state & XLOG_STATE_IOERROR);
451 if (!abortflg) {
452 ASSERT_ALWAYS((iclog->ic_state == XLOG_STATE_ACTIVE) ||
453 (iclog->ic_state == XLOG_STATE_WANT_SYNC));
454 cb->cb_next = NULL;
455 *(iclog->ic_callback_tail) = cb;
456 iclog->ic_callback_tail = &(cb->cb_next);
457 }
458 spin_unlock(&iclog->ic_callback_lock);
459 return abortflg;
460}
461
462int
463xfs_log_release_iclog(xfs_mount_t *mp,
464 void *iclog_hndl)
465{
466 xlog_t *log = mp->m_log;
467 xlog_in_core_t *iclog = (xlog_in_core_t *)iclog_hndl;
468
469 if (xlog_state_release_iclog(log, iclog)) {
470 xfs_force_shutdown(mp, SHUTDOWN_LOG_IO_ERROR);
471 return EIO;
472 }
473
474 return 0;
475}
476
477
478
479
480
481
482
483
484
485
486
487int
488xfs_log_reserve(xfs_mount_t *mp,
489 int unit_bytes,
490 int cnt,
491 xfs_log_ticket_t *ticket,
492 __uint8_t client,
493 uint flags,
494 uint t_type)
495{
496 xlog_t *log = mp->m_log;
497 xlog_ticket_t *internal_ticket;
498 int retval = 0;
499
500 ASSERT(client == XFS_TRANSACTION || client == XFS_LOG);
501 ASSERT((flags & XFS_LOG_NOSLEEP) == 0);
502
503 if (XLOG_FORCED_SHUTDOWN(log))
504 return XFS_ERROR(EIO);
505
506 XFS_STATS_INC(xs_try_logspace);
507
508 if (*ticket != NULL) {
509 ASSERT(flags & XFS_LOG_PERM_RESERV);
510 internal_ticket = (xlog_ticket_t *)*ticket;
511 xlog_trace_loggrant(log, internal_ticket, "xfs_log_reserve: existing ticket (permanent trans)");
512 xlog_grant_push_ail(mp, internal_ticket->t_unit_res);
513 retval = xlog_regrant_write_log_space(log, internal_ticket);
514 } else {
515
516 internal_ticket = xlog_ticket_alloc(log, unit_bytes, cnt,
517 client, flags);
518 if (!internal_ticket)
519 return XFS_ERROR(ENOMEM);
520 internal_ticket->t_trans_type = t_type;
521 *ticket = internal_ticket;
522 xlog_trace_loggrant(log, internal_ticket,
523 (internal_ticket->t_flags & XLOG_TIC_PERM_RESERV) ?
524 "xfs_log_reserve: create new ticket (permanent trans)" :
525 "xfs_log_reserve: create new ticket");
526 xlog_grant_push_ail(mp,
527 (internal_ticket->t_unit_res *
528 internal_ticket->t_cnt));
529 retval = xlog_grant_log_space(log, internal_ticket);
530 }
531
532 return retval;
533}
534
535
536
537
538
539
540
541
542
543
544
545
546int
547xfs_log_mount(
548 xfs_mount_t *mp,
549 xfs_buftarg_t *log_target,
550 xfs_daddr_t blk_offset,
551 int num_bblks)
552{
553 int error;
554
555 if (!(mp->m_flags & XFS_MOUNT_NORECOVERY))
556 cmn_err(CE_NOTE, "XFS mounting filesystem %s", mp->m_fsname);
557 else {
558 cmn_err(CE_NOTE,
559 "!Mounting filesystem \"%s\" in no-recovery mode. Filesystem will be inconsistent.",
560 mp->m_fsname);
561 ASSERT(mp->m_flags & XFS_MOUNT_RDONLY);
562 }
563
564 mp->m_log = xlog_alloc_log(mp, log_target, blk_offset, num_bblks);
565 if (IS_ERR(mp->m_log)) {
566 error = -PTR_ERR(mp->m_log);
567 goto out;
568 }
569
570
571
572
573 error = xfs_trans_ail_init(mp);
574 if (error) {
575 cmn_err(CE_WARN, "XFS: AIL initialisation failed: error %d", error);
576 goto out_free_log;
577 }
578 mp->m_log->l_ailp = mp->m_ail;
579
580
581
582
583
584 if (!(mp->m_flags & XFS_MOUNT_NORECOVERY)) {
585 int readonly = (mp->m_flags & XFS_MOUNT_RDONLY);
586
587 if (readonly)
588 mp->m_flags &= ~XFS_MOUNT_RDONLY;
589
590 error = xlog_recover(mp->m_log);
591
592 if (readonly)
593 mp->m_flags |= XFS_MOUNT_RDONLY;
594 if (error) {
595 cmn_err(CE_WARN, "XFS: log mount/recovery failed: error %d", error);
596 goto out_destroy_ail;
597 }
598 }
599
600
601 mp->m_log->l_flags &= ~XLOG_ACTIVE_RECOVERY;
602
603 return 0;
604
605out_destroy_ail:
606 xfs_trans_ail_destroy(mp);
607out_free_log:
608 xlog_dealloc_log(mp->m_log);
609out:
610 return error;
611}
612
613
614
615
616
617
618
619
620
621int
622xfs_log_mount_finish(xfs_mount_t *mp)
623{
624 int error;
625
626 if (!(mp->m_flags & XFS_MOUNT_NORECOVERY))
627 error = xlog_recover_finish(mp->m_log);
628 else {
629 error = 0;
630 ASSERT(mp->m_flags & XFS_MOUNT_RDONLY);
631 }
632
633 return error;
634}
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652int
653xfs_log_unmount_write(xfs_mount_t *mp)
654{
655 xlog_t *log = mp->m_log;
656 xlog_in_core_t *iclog;
657#ifdef DEBUG
658 xlog_in_core_t *first_iclog;
659#endif
660 xfs_log_iovec_t reg[1];
661 xfs_log_ticket_t tic = NULL;
662 xfs_lsn_t lsn;
663 int error;
664
665
666 struct {
667 __uint16_t magic;
668 __uint16_t pad1;
669 __uint32_t pad2;
670 } magic = { XLOG_UNMOUNT_TYPE, 0, 0 };
671
672
673
674
675
676 if (mp->m_flags & XFS_MOUNT_RDONLY)
677 return 0;
678
679 error = _xfs_log_force(mp, 0, XFS_LOG_FORCE|XFS_LOG_SYNC, NULL);
680 ASSERT(error || !(XLOG_FORCED_SHUTDOWN(log)));
681
682#ifdef DEBUG
683 first_iclog = iclog = log->l_iclog;
684 do {
685 if (!(iclog->ic_state & XLOG_STATE_IOERROR)) {
686 ASSERT(iclog->ic_state & XLOG_STATE_ACTIVE);
687 ASSERT(iclog->ic_offset == 0);
688 }
689 iclog = iclog->ic_next;
690 } while (iclog != first_iclog);
691#endif
692 if (! (XLOG_FORCED_SHUTDOWN(log))) {
693 reg[0].i_addr = (void*)&magic;
694 reg[0].i_len = sizeof(magic);
695 XLOG_VEC_SET_TYPE(®[0], XLOG_REG_TYPE_UNMOUNT);
696
697 error = xfs_log_reserve(mp, 600, 1, &tic,
698 XFS_LOG, 0, XLOG_UNMOUNT_REC_TYPE);
699 if (!error) {
700
701 ((xlog_ticket_t *)tic)->t_flags = 0;
702 error = xlog_write(mp, reg, 1, tic, &lsn,
703 NULL, XLOG_UNMOUNT_TRANS);
704
705
706
707
708
709 }
710
711 if (error) {
712 xfs_fs_cmn_err(CE_ALERT, mp,
713 "xfs_log_unmount: unmount record failed");
714 }
715
716
717 spin_lock(&log->l_icloglock);
718 iclog = log->l_iclog;
719 atomic_inc(&iclog->ic_refcnt);
720 xlog_state_want_sync(log, iclog);
721 spin_unlock(&log->l_icloglock);
722 error = xlog_state_release_iclog(log, iclog);
723
724 spin_lock(&log->l_icloglock);
725 if (!(iclog->ic_state == XLOG_STATE_ACTIVE ||
726 iclog->ic_state == XLOG_STATE_DIRTY)) {
727 if (!XLOG_FORCED_SHUTDOWN(log)) {
728 sv_wait(&iclog->ic_force_wait, PMEM,
729 &log->l_icloglock, s);
730 } else {
731 spin_unlock(&log->l_icloglock);
732 }
733 } else {
734 spin_unlock(&log->l_icloglock);
735 }
736 if (tic) {
737 xlog_trace_loggrant(log, tic, "unmount rec");
738 xlog_ungrant_log_space(log, tic);
739 xfs_log_ticket_put(tic);
740 }
741 } else {
742
743
744
745
746
747
748
749
750
751
752
753
754
755 spin_lock(&log->l_icloglock);
756 iclog = log->l_iclog;
757 atomic_inc(&iclog->ic_refcnt);
758
759 xlog_state_want_sync(log, iclog);
760 spin_unlock(&log->l_icloglock);
761 error = xlog_state_release_iclog(log, iclog);
762
763 spin_lock(&log->l_icloglock);
764
765 if ( ! ( iclog->ic_state == XLOG_STATE_ACTIVE
766 || iclog->ic_state == XLOG_STATE_DIRTY
767 || iclog->ic_state == XLOG_STATE_IOERROR) ) {
768
769 sv_wait(&iclog->ic_force_wait, PMEM,
770 &log->l_icloglock, s);
771 } else {
772 spin_unlock(&log->l_icloglock);
773 }
774 }
775
776 return error;
777}
778
779
780
781
782
783
784
785void
786xfs_log_unmount(xfs_mount_t *mp)
787{
788 xfs_trans_ail_destroy(mp);
789 xlog_dealloc_log(mp->m_log);
790}
791
792
793
794
795
796
797int
798xfs_log_write(xfs_mount_t * mp,
799 xfs_log_iovec_t reg[],
800 int nentries,
801 xfs_log_ticket_t tic,
802 xfs_lsn_t *start_lsn)
803{
804 int error;
805 xlog_t *log = mp->m_log;
806
807 if (XLOG_FORCED_SHUTDOWN(log))
808 return XFS_ERROR(EIO);
809
810 if ((error = xlog_write(mp, reg, nentries, tic, start_lsn, NULL, 0))) {
811 xfs_force_shutdown(mp, SHUTDOWN_LOG_IO_ERROR);
812 }
813 return error;
814}
815
816
817void
818xfs_log_move_tail(xfs_mount_t *mp,
819 xfs_lsn_t tail_lsn)
820{
821 xlog_ticket_t *tic;
822 xlog_t *log = mp->m_log;
823 int need_bytes, free_bytes, cycle, bytes;
824
825 if (XLOG_FORCED_SHUTDOWN(log))
826 return;
827
828 if (tail_lsn == 0) {
829
830 spin_lock(&log->l_icloglock);
831 tail_lsn = log->l_last_sync_lsn;
832 spin_unlock(&log->l_icloglock);
833 }
834
835 spin_lock(&log->l_grant_lock);
836
837
838
839
840 if (tail_lsn != 1) {
841 log->l_tail_lsn = tail_lsn;
842 }
843
844 if ((tic = log->l_write_headq)) {
845#ifdef DEBUG
846 if (log->l_flags & XLOG_ACTIVE_RECOVERY)
847 panic("Recovery problem");
848#endif
849 cycle = log->l_grant_write_cycle;
850 bytes = log->l_grant_write_bytes;
851 free_bytes = xlog_space_left(log, cycle, bytes);
852 do {
853 ASSERT(tic->t_flags & XLOG_TIC_PERM_RESERV);
854
855 if (free_bytes < tic->t_unit_res && tail_lsn != 1)
856 break;
857 tail_lsn = 0;
858 free_bytes -= tic->t_unit_res;
859 sv_signal(&tic->t_wait);
860 tic = tic->t_next;
861 } while (tic != log->l_write_headq);
862 }
863 if ((tic = log->l_reserve_headq)) {
864#ifdef DEBUG
865 if (log->l_flags & XLOG_ACTIVE_RECOVERY)
866 panic("Recovery problem");
867#endif
868 cycle = log->l_grant_reserve_cycle;
869 bytes = log->l_grant_reserve_bytes;
870 free_bytes = xlog_space_left(log, cycle, bytes);
871 do {
872 if (tic->t_flags & XLOG_TIC_PERM_RESERV)
873 need_bytes = tic->t_unit_res*tic->t_cnt;
874 else
875 need_bytes = tic->t_unit_res;
876 if (free_bytes < need_bytes && tail_lsn != 1)
877 break;
878 tail_lsn = 0;
879 free_bytes -= need_bytes;
880 sv_signal(&tic->t_wait);
881 tic = tic->t_next;
882 } while (tic != log->l_reserve_headq);
883 }
884 spin_unlock(&log->l_grant_lock);
885}
886
887
888
889
890
891
892
893int
894xfs_log_need_covered(xfs_mount_t *mp)
895{
896 int needed = 0;
897 xlog_t *log = mp->m_log;
898
899 if (!xfs_fs_writable(mp))
900 return 0;
901
902 spin_lock(&log->l_icloglock);
903 if (((log->l_covered_state == XLOG_STATE_COVER_NEED) ||
904 (log->l_covered_state == XLOG_STATE_COVER_NEED2))
905 && !xfs_trans_ail_tail(log->l_ailp)
906 && xlog_iclogs_empty(log)) {
907 if (log->l_covered_state == XLOG_STATE_COVER_NEED)
908 log->l_covered_state = XLOG_STATE_COVER_DONE;
909 else {
910 ASSERT(log->l_covered_state == XLOG_STATE_COVER_NEED2);
911 log->l_covered_state = XLOG_STATE_COVER_DONE2;
912 }
913 needed = 1;
914 }
915 spin_unlock(&log->l_icloglock);
916 return needed;
917}
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936xfs_lsn_t
937xlog_assign_tail_lsn(xfs_mount_t *mp)
938{
939 xfs_lsn_t tail_lsn;
940 xlog_t *log = mp->m_log;
941
942 tail_lsn = xfs_trans_ail_tail(mp->m_ail);
943 spin_lock(&log->l_grant_lock);
944 if (tail_lsn != 0) {
945 log->l_tail_lsn = tail_lsn;
946 } else {
947 tail_lsn = log->l_tail_lsn = log->l_last_sync_lsn;
948 }
949 spin_unlock(&log->l_grant_lock);
950
951 return tail_lsn;
952}
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969STATIC int
970xlog_space_left(xlog_t *log, int cycle, int bytes)
971{
972 int free_bytes;
973 int tail_bytes;
974 int tail_cycle;
975
976 tail_bytes = BBTOB(BLOCK_LSN(log->l_tail_lsn));
977 tail_cycle = CYCLE_LSN(log->l_tail_lsn);
978 if ((tail_cycle == cycle) && (bytes >= tail_bytes)) {
979 free_bytes = log->l_logsize - (bytes - tail_bytes);
980 } else if ((tail_cycle + 1) < cycle) {
981 return 0;
982 } else if (tail_cycle < cycle) {
983 ASSERT(tail_cycle == (cycle - 1));
984 free_bytes = tail_bytes - bytes;
985 } else {
986
987
988
989
990
991 xfs_fs_cmn_err(CE_ALERT, log->l_mp,
992 "xlog_space_left: head behind tail\n"
993 " tail_cycle = %d, tail_bytes = %d\n"
994 " GH cycle = %d, GH bytes = %d",
995 tail_cycle, tail_bytes, cycle, bytes);
996 ASSERT(0);
997 free_bytes = log->l_logsize;
998 }
999 return free_bytes;
1000}
1001
1002
1003
1004
1005
1006
1007
1008
1009void
1010xlog_iodone(xfs_buf_t *bp)
1011{
1012 xlog_in_core_t *iclog;
1013 xlog_t *l;
1014 int aborted;
1015
1016 iclog = XFS_BUF_FSPRIVATE(bp, xlog_in_core_t *);
1017 ASSERT(XFS_BUF_FSPRIVATE2(bp, unsigned long) == (unsigned long) 2);
1018 XFS_BUF_SET_FSPRIVATE2(bp, (unsigned long)1);
1019 aborted = 0;
1020 l = iclog->ic_log;
1021
1022
1023
1024
1025
1026
1027 if (bp->b_flags & _XFS_BARRIER_FAILED) {
1028 bp->b_flags &= ~_XFS_BARRIER_FAILED;
1029 l->l_mp->m_flags &= ~XFS_MOUNT_BARRIER;
1030 xfs_fs_cmn_err(CE_WARN, l->l_mp,
1031 "xlog_iodone: Barriers are no longer supported"
1032 " by device. Disabling barriers\n");
1033 xfs_buftrace("XLOG_IODONE BARRIERS OFF", bp);
1034 }
1035
1036
1037
1038
1039 if (XFS_TEST_ERROR((XFS_BUF_GETERROR(bp)), l->l_mp,
1040 XFS_ERRTAG_IODONE_IOERR, XFS_RANDOM_IODONE_IOERR)) {
1041 xfs_ioerror_alert("xlog_iodone", l->l_mp, bp, XFS_BUF_ADDR(bp));
1042 XFS_BUF_STALE(bp);
1043 xfs_force_shutdown(l->l_mp, SHUTDOWN_LOG_IO_ERROR);
1044
1045
1046
1047
1048
1049 aborted = XFS_LI_ABORTED;
1050 } else if (iclog->ic_state & XLOG_STATE_IOERROR) {
1051 aborted = XFS_LI_ABORTED;
1052 }
1053
1054
1055 ASSERT(XFS_BUF_ISASYNC(bp));
1056 xlog_state_done_syncing(iclog, aborted);
1057
1058
1059
1060
1061
1062
1063}
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073STATIC int
1074xlog_bdstrat_cb(struct xfs_buf *bp)
1075{
1076 xlog_in_core_t *iclog;
1077
1078 iclog = XFS_BUF_FSPRIVATE(bp, xlog_in_core_t *);
1079
1080 if ((iclog->ic_state & XLOG_STATE_IOERROR) == 0) {
1081
1082
1083
1084 XFS_bdstrat(bp);
1085 return 0;
1086 }
1087
1088 xfs_buftrace("XLOG__BDSTRAT IOERROR", bp);
1089 XFS_BUF_ERROR(bp, EIO);
1090 XFS_BUF_STALE(bp);
1091 xfs_biodone(bp);
1092 return XFS_ERROR(EIO);
1093
1094
1095}
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106STATIC void
1107xlog_get_iclog_buffer_size(xfs_mount_t *mp,
1108 xlog_t *log)
1109{
1110 int size;
1111 int xhdrs;
1112
1113 if (mp->m_logbufs <= 0)
1114 log->l_iclog_bufs = XLOG_MAX_ICLOGS;
1115 else
1116 log->l_iclog_bufs = mp->m_logbufs;
1117
1118
1119
1120
1121 if (mp->m_logbsize > 0) {
1122 size = log->l_iclog_size = mp->m_logbsize;
1123 log->l_iclog_size_log = 0;
1124 while (size != 1) {
1125 log->l_iclog_size_log++;
1126 size >>= 1;
1127 }
1128
1129 if (xfs_sb_version_haslogv2(&mp->m_sb)) {
1130
1131
1132
1133
1134 xhdrs = mp->m_logbsize / XLOG_HEADER_CYCLE_SIZE;
1135 if (mp->m_logbsize % XLOG_HEADER_CYCLE_SIZE)
1136 xhdrs++;
1137 log->l_iclog_hsize = xhdrs << BBSHIFT;
1138 log->l_iclog_heads = xhdrs;
1139 } else {
1140 ASSERT(mp->m_logbsize <= XLOG_BIG_RECORD_BSIZE);
1141 log->l_iclog_hsize = BBSIZE;
1142 log->l_iclog_heads = 1;
1143 }
1144 goto done;
1145 }
1146
1147
1148 log->l_iclog_size = XLOG_BIG_RECORD_BSIZE;
1149 log->l_iclog_size_log = XLOG_BIG_RECORD_BSHIFT;
1150
1151
1152 log->l_iclog_hsize = BBSIZE;
1153 log->l_iclog_heads = 1;
1154
1155done:
1156
1157 if (mp->m_logbufs == 0)
1158 mp->m_logbufs = log->l_iclog_bufs;
1159 if (mp->m_logbsize == 0)
1160 mp->m_logbsize = log->l_iclog_size;
1161}
1162
1163
1164
1165
1166
1167
1168
1169STATIC xlog_t *
1170xlog_alloc_log(xfs_mount_t *mp,
1171 xfs_buftarg_t *log_target,
1172 xfs_daddr_t blk_offset,
1173 int num_bblks)
1174{
1175 xlog_t *log;
1176 xlog_rec_header_t *head;
1177 xlog_in_core_t **iclogp;
1178 xlog_in_core_t *iclog, *prev_iclog=NULL;
1179 xfs_buf_t *bp;
1180 int i;
1181 int iclogsize;
1182 int error = ENOMEM;
1183
1184 log = kmem_zalloc(sizeof(xlog_t), KM_MAYFAIL);
1185 if (!log) {
1186 xlog_warn("XFS: Log allocation failed: No memory!");
1187 goto out;
1188 }
1189
1190 log->l_mp = mp;
1191 log->l_targ = log_target;
1192 log->l_logsize = BBTOB(num_bblks);
1193 log->l_logBBstart = blk_offset;
1194 log->l_logBBsize = num_bblks;
1195 log->l_covered_state = XLOG_STATE_COVER_IDLE;
1196 log->l_flags |= XLOG_ACTIVE_RECOVERY;
1197
1198 log->l_prev_block = -1;
1199 log->l_tail_lsn = xlog_assign_lsn(1, 0);
1200
1201 log->l_last_sync_lsn = log->l_tail_lsn;
1202 log->l_curr_cycle = 1;
1203 log->l_grant_reserve_cycle = 1;
1204 log->l_grant_write_cycle = 1;
1205
1206 error = EFSCORRUPTED;
1207 if (xfs_sb_version_hassector(&mp->m_sb)) {
1208 log->l_sectbb_log = mp->m_sb.sb_logsectlog - BBSHIFT;
1209 if (log->l_sectbb_log < 0 ||
1210 log->l_sectbb_log > mp->m_sectbb_log) {
1211 xlog_warn("XFS: Log sector size (0x%x) out of range.",
1212 log->l_sectbb_log);
1213 goto out_free_log;
1214 }
1215
1216
1217 if (log->l_sectbb_log != 0 &&
1218 (log->l_logBBstart != 0 &&
1219 !xfs_sb_version_haslogv2(&mp->m_sb))) {
1220 xlog_warn("XFS: log sector size (0x%x) invalid "
1221 "for configuration.", log->l_sectbb_log);
1222 goto out_free_log;
1223 }
1224 if (mp->m_sb.sb_logsectlog < BBSHIFT) {
1225 xlog_warn("XFS: Log sector log (0x%x) too small.",
1226 mp->m_sb.sb_logsectlog);
1227 goto out_free_log;
1228 }
1229 }
1230 log->l_sectbb_mask = (1 << log->l_sectbb_log) - 1;
1231
1232 xlog_get_iclog_buffer_size(mp, log);
1233
1234 error = ENOMEM;
1235 bp = xfs_buf_get_empty(log->l_iclog_size, mp->m_logdev_targp);
1236 if (!bp)
1237 goto out_free_log;
1238 XFS_BUF_SET_IODONE_FUNC(bp, xlog_iodone);
1239 XFS_BUF_SET_BDSTRAT_FUNC(bp, xlog_bdstrat_cb);
1240 XFS_BUF_SET_FSPRIVATE2(bp, (unsigned long)1);
1241 ASSERT(XFS_BUF_ISBUSY(bp));
1242 ASSERT(XFS_BUF_VALUSEMA(bp) <= 0);
1243 log->l_xbuf = bp;
1244
1245 spin_lock_init(&log->l_icloglock);
1246 spin_lock_init(&log->l_grant_lock);
1247 sv_init(&log->l_flush_wait, 0, "flush_wait");
1248
1249 xlog_trace_loggrant_alloc(log);
1250
1251 ASSERT((XFS_BUF_SIZE(bp) & BBMASK) == 0);
1252
1253 iclogp = &log->l_iclog;
1254
1255
1256
1257
1258
1259
1260
1261 iclogsize = log->l_iclog_size;
1262 ASSERT(log->l_iclog_size >= 4096);
1263 for (i=0; i < log->l_iclog_bufs; i++) {
1264 *iclogp = kmem_zalloc(sizeof(xlog_in_core_t), KM_MAYFAIL);
1265 if (!*iclogp)
1266 goto out_free_iclog;
1267
1268 iclog = *iclogp;
1269 iclog->ic_prev = prev_iclog;
1270 prev_iclog = iclog;
1271
1272 bp = xfs_buf_get_noaddr(log->l_iclog_size, mp->m_logdev_targp);
1273 if (!bp)
1274 goto out_free_iclog;
1275 if (!XFS_BUF_CPSEMA(bp))
1276 ASSERT(0);
1277 XFS_BUF_SET_IODONE_FUNC(bp, xlog_iodone);
1278 XFS_BUF_SET_BDSTRAT_FUNC(bp, xlog_bdstrat_cb);
1279 XFS_BUF_SET_FSPRIVATE2(bp, (unsigned long)1);
1280 iclog->ic_bp = bp;
1281 iclog->ic_data = bp->b_addr;
1282#ifdef DEBUG
1283 log->l_iclog_bak[i] = (xfs_caddr_t)&(iclog->ic_header);
1284#endif
1285 head = &iclog->ic_header;
1286 memset(head, 0, sizeof(xlog_rec_header_t));
1287 head->h_magicno = cpu_to_be32(XLOG_HEADER_MAGIC_NUM);
1288 head->h_version = cpu_to_be32(
1289 xfs_sb_version_haslogv2(&log->l_mp->m_sb) ? 2 : 1);
1290 head->h_size = cpu_to_be32(log->l_iclog_size);
1291
1292 head->h_fmt = cpu_to_be32(XLOG_FMT);
1293 memcpy(&head->h_fs_uuid, &mp->m_sb.sb_uuid, sizeof(uuid_t));
1294
1295 iclog->ic_size = XFS_BUF_SIZE(bp) - log->l_iclog_hsize;
1296 iclog->ic_state = XLOG_STATE_ACTIVE;
1297 iclog->ic_log = log;
1298 atomic_set(&iclog->ic_refcnt, 0);
1299 spin_lock_init(&iclog->ic_callback_lock);
1300 iclog->ic_callback_tail = &(iclog->ic_callback);
1301 iclog->ic_datap = (char *)iclog->ic_data + log->l_iclog_hsize;
1302
1303 ASSERT(XFS_BUF_ISBUSY(iclog->ic_bp));
1304 ASSERT(XFS_BUF_VALUSEMA(iclog->ic_bp) <= 0);
1305 sv_init(&iclog->ic_force_wait, SV_DEFAULT, "iclog-force");
1306 sv_init(&iclog->ic_write_wait, SV_DEFAULT, "iclog-write");
1307
1308 xlog_trace_iclog_alloc(iclog);
1309
1310 iclogp = &iclog->ic_next;
1311 }
1312 *iclogp = log->l_iclog;
1313 log->l_iclog->ic_prev = prev_iclog;
1314
1315 return log;
1316
1317out_free_iclog:
1318 for (iclog = log->l_iclog; iclog; iclog = prev_iclog) {
1319 prev_iclog = iclog->ic_next;
1320 if (iclog->ic_bp) {
1321 sv_destroy(&iclog->ic_force_wait);
1322 sv_destroy(&iclog->ic_write_wait);
1323 xfs_buf_free(iclog->ic_bp);
1324 xlog_trace_iclog_dealloc(iclog);
1325 }
1326 kmem_free(iclog);
1327 }
1328 spinlock_destroy(&log->l_icloglock);
1329 spinlock_destroy(&log->l_grant_lock);
1330 xlog_trace_loggrant_dealloc(log);
1331 xfs_buf_free(log->l_xbuf);
1332out_free_log:
1333 kmem_free(log);
1334out:
1335 return ERR_PTR(-error);
1336}
1337
1338
1339
1340
1341
1342
1343STATIC int
1344xlog_commit_record(xfs_mount_t *mp,
1345 xlog_ticket_t *ticket,
1346 xlog_in_core_t **iclog,
1347 xfs_lsn_t *commitlsnp)
1348{
1349 int error;
1350 xfs_log_iovec_t reg[1];
1351
1352 reg[0].i_addr = NULL;
1353 reg[0].i_len = 0;
1354 XLOG_VEC_SET_TYPE(®[0], XLOG_REG_TYPE_COMMIT);
1355
1356 ASSERT_ALWAYS(iclog);
1357 if ((error = xlog_write(mp, reg, 1, ticket, commitlsnp,
1358 iclog, XLOG_COMMIT_TRANS))) {
1359 xfs_force_shutdown(mp, SHUTDOWN_LOG_IO_ERROR);
1360 }
1361 return error;
1362}
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372STATIC void
1373xlog_grant_push_ail(xfs_mount_t *mp,
1374 int need_bytes)
1375{
1376 xlog_t *log = mp->m_log;
1377 xfs_lsn_t tail_lsn;
1378 xfs_lsn_t threshold_lsn = 0;
1379 int free_blocks;
1380 int free_bytes;
1381 int threshold_block;
1382 int threshold_cycle;
1383 int free_threshold;
1384
1385 ASSERT(BTOBB(need_bytes) < log->l_logBBsize);
1386
1387 spin_lock(&log->l_grant_lock);
1388 free_bytes = xlog_space_left(log,
1389 log->l_grant_reserve_cycle,
1390 log->l_grant_reserve_bytes);
1391 tail_lsn = log->l_tail_lsn;
1392 free_blocks = BTOBBT(free_bytes);
1393
1394
1395
1396
1397
1398
1399 free_threshold = BTOBB(need_bytes);
1400 free_threshold = MAX(free_threshold, (log->l_logBBsize >> 2));
1401 free_threshold = MAX(free_threshold, 256);
1402 if (free_blocks < free_threshold) {
1403 threshold_block = BLOCK_LSN(tail_lsn) + free_threshold;
1404 threshold_cycle = CYCLE_LSN(tail_lsn);
1405 if (threshold_block >= log->l_logBBsize) {
1406 threshold_block -= log->l_logBBsize;
1407 threshold_cycle += 1;
1408 }
1409 threshold_lsn = xlog_assign_lsn(threshold_cycle, threshold_block);
1410
1411
1412
1413
1414 if (XFS_LSN_CMP(threshold_lsn, log->l_last_sync_lsn) > 0)
1415 threshold_lsn = log->l_last_sync_lsn;
1416 }
1417 spin_unlock(&log->l_grant_lock);
1418
1419
1420
1421
1422
1423
1424 if (threshold_lsn &&
1425 !XLOG_FORCED_SHUTDOWN(log))
1426 xfs_trans_ail_push(log->l_ailp, threshold_lsn);
1427}
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455STATIC int
1456xlog_sync(xlog_t *log,
1457 xlog_in_core_t *iclog)
1458{
1459 xfs_caddr_t dptr;
1460 xfs_buf_t *bp;
1461 int i;
1462 uint count;
1463 uint count_init;
1464 int roundoff;
1465 int split = 0;
1466 int error;
1467 int v2 = xfs_sb_version_haslogv2(&log->l_mp->m_sb);
1468
1469 XFS_STATS_INC(xs_log_writes);
1470 ASSERT(atomic_read(&iclog->ic_refcnt) == 0);
1471
1472
1473 count_init = log->l_iclog_hsize + iclog->ic_offset;
1474
1475
1476 if (v2 && log->l_mp->m_sb.sb_logsunit > 1) {
1477
1478 count = XLOG_LSUNITTOB(log, XLOG_BTOLSUNIT(log, count_init));
1479 } else {
1480 count = BBTOB(BTOBB(count_init));
1481 }
1482 roundoff = count - count_init;
1483 ASSERT(roundoff >= 0);
1484 ASSERT((v2 && log->l_mp->m_sb.sb_logsunit > 1 &&
1485 roundoff < log->l_mp->m_sb.sb_logsunit)
1486 ||
1487 (log->l_mp->m_sb.sb_logsunit <= 1 &&
1488 roundoff < BBTOB(1)));
1489
1490
1491 spin_lock(&log->l_grant_lock);
1492 xlog_grant_add_space(log, roundoff);
1493 spin_unlock(&log->l_grant_lock);
1494
1495
1496 xlog_pack_data(log, iclog, roundoff);
1497
1498
1499 if (v2) {
1500 iclog->ic_header.h_len =
1501 cpu_to_be32(iclog->ic_offset + roundoff);
1502 } else {
1503 iclog->ic_header.h_len =
1504 cpu_to_be32(iclog->ic_offset);
1505 }
1506
1507 bp = iclog->ic_bp;
1508 ASSERT(XFS_BUF_FSPRIVATE2(bp, unsigned long) == (unsigned long)1);
1509 XFS_BUF_SET_FSPRIVATE2(bp, (unsigned long)2);
1510 XFS_BUF_SET_ADDR(bp, BLOCK_LSN(be64_to_cpu(iclog->ic_header.h_lsn)));
1511
1512 XFS_STATS_ADD(xs_log_blocks, BTOBB(count));
1513
1514
1515 if (XFS_BUF_ADDR(bp) + BTOBB(count) > log->l_logBBsize) {
1516 split = count - (BBTOB(log->l_logBBsize - XFS_BUF_ADDR(bp)));
1517 count = BBTOB(log->l_logBBsize - XFS_BUF_ADDR(bp));
1518 iclog->ic_bwritecnt = 2;
1519 } else {
1520 iclog->ic_bwritecnt = 1;
1521 }
1522 XFS_BUF_SET_COUNT(bp, count);
1523 XFS_BUF_SET_FSPRIVATE(bp, iclog);
1524 XFS_BUF_ZEROFLAGS(bp);
1525 XFS_BUF_BUSY(bp);
1526 XFS_BUF_ASYNC(bp);
1527
1528
1529
1530
1531 if (!split && (log->l_mp->m_flags & XFS_MOUNT_BARRIER))
1532 XFS_BUF_ORDERED(bp);
1533
1534 ASSERT(XFS_BUF_ADDR(bp) <= log->l_logBBsize-1);
1535 ASSERT(XFS_BUF_ADDR(bp) + BTOBB(count) <= log->l_logBBsize);
1536
1537 xlog_verify_iclog(log, iclog, count, B_TRUE);
1538
1539
1540 XFS_BUF_SET_ADDR(bp, XFS_BUF_ADDR(bp) + log->l_logBBstart);
1541
1542
1543
1544
1545 XFS_BUF_WRITE(bp);
1546
1547 if ((error = XFS_bwrite(bp))) {
1548 xfs_ioerror_alert("xlog_sync", log->l_mp, bp,
1549 XFS_BUF_ADDR(bp));
1550 return error;
1551 }
1552 if (split) {
1553 bp = iclog->ic_log->l_xbuf;
1554 ASSERT(XFS_BUF_FSPRIVATE2(bp, unsigned long) ==
1555 (unsigned long)1);
1556 XFS_BUF_SET_FSPRIVATE2(bp, (unsigned long)2);
1557 XFS_BUF_SET_ADDR(bp, 0);
1558 XFS_BUF_SET_PTR(bp, (xfs_caddr_t)((__psint_t)&(iclog->ic_header)+
1559 (__psint_t)count), split);
1560 XFS_BUF_SET_FSPRIVATE(bp, iclog);
1561 XFS_BUF_ZEROFLAGS(bp);
1562 XFS_BUF_BUSY(bp);
1563 XFS_BUF_ASYNC(bp);
1564 if (log->l_mp->m_flags & XFS_MOUNT_BARRIER)
1565 XFS_BUF_ORDERED(bp);
1566 dptr = XFS_BUF_PTR(bp);
1567
1568
1569
1570
1571
1572
1573 for (i = 0; i < split; i += BBSIZE) {
1574 be32_add_cpu((__be32 *)dptr, 1);
1575 if (be32_to_cpu(*(__be32 *)dptr) == XLOG_HEADER_MAGIC_NUM)
1576 be32_add_cpu((__be32 *)dptr, 1);
1577 dptr += BBSIZE;
1578 }
1579
1580 ASSERT(XFS_BUF_ADDR(bp) <= log->l_logBBsize-1);
1581 ASSERT(XFS_BUF_ADDR(bp) + BTOBB(count) <= log->l_logBBsize);
1582
1583
1584 XFS_BUF_SET_ADDR(bp, XFS_BUF_ADDR(bp) + log->l_logBBstart);
1585 XFS_BUF_WRITE(bp);
1586 if ((error = XFS_bwrite(bp))) {
1587 xfs_ioerror_alert("xlog_sync (split)", log->l_mp,
1588 bp, XFS_BUF_ADDR(bp));
1589 return error;
1590 }
1591 }
1592 return 0;
1593}
1594
1595
1596
1597
1598
1599STATIC void
1600xlog_dealloc_log(xlog_t *log)
1601{
1602 xlog_in_core_t *iclog, *next_iclog;
1603 int i;
1604
1605 iclog = log->l_iclog;
1606 for (i=0; i<log->l_iclog_bufs; i++) {
1607 sv_destroy(&iclog->ic_force_wait);
1608 sv_destroy(&iclog->ic_write_wait);
1609 xfs_buf_free(iclog->ic_bp);
1610 xlog_trace_iclog_dealloc(iclog);
1611 next_iclog = iclog->ic_next;
1612 kmem_free(iclog);
1613 iclog = next_iclog;
1614 }
1615 spinlock_destroy(&log->l_icloglock);
1616 spinlock_destroy(&log->l_grant_lock);
1617
1618 xfs_buf_free(log->l_xbuf);
1619 xlog_trace_loggrant_dealloc(log);
1620 log->l_mp->m_log = NULL;
1621 kmem_free(log);
1622}
1623
1624
1625
1626
1627
1628static inline void
1629xlog_state_finish_copy(xlog_t *log,
1630 xlog_in_core_t *iclog,
1631 int record_cnt,
1632 int copy_bytes)
1633{
1634 spin_lock(&log->l_icloglock);
1635
1636 be32_add_cpu(&iclog->ic_header.h_num_logops, record_cnt);
1637 iclog->ic_offset += copy_bytes;
1638
1639 spin_unlock(&log->l_icloglock);
1640}
1641
1642
1643
1644
1645
1646
1647
1648
1649STATIC void
1650xlog_print_tic_res(xfs_mount_t *mp, xlog_ticket_t *ticket)
1651{
1652 uint i;
1653 uint ophdr_spc = ticket->t_res_num_ophdrs * (uint)sizeof(xlog_op_header_t);
1654
1655
1656 static char *res_type_str[XLOG_REG_TYPE_MAX] = {
1657 "bformat",
1658 "bchunk",
1659 "efi_format",
1660 "efd_format",
1661 "iformat",
1662 "icore",
1663 "iext",
1664 "ibroot",
1665 "ilocal",
1666 "iattr_ext",
1667 "iattr_broot",
1668 "iattr_local",
1669 "qformat",
1670 "dquot",
1671 "quotaoff",
1672 "LR header",
1673 "unmount",
1674 "commit",
1675 "trans header"
1676 };
1677 static char *trans_type_str[XFS_TRANS_TYPE_MAX] = {
1678 "SETATTR_NOT_SIZE",
1679 "SETATTR_SIZE",
1680 "INACTIVE",
1681 "CREATE",
1682 "CREATE_TRUNC",
1683 "TRUNCATE_FILE",
1684 "REMOVE",
1685 "LINK",
1686 "RENAME",
1687 "MKDIR",
1688 "RMDIR",
1689 "SYMLINK",
1690 "SET_DMATTRS",
1691 "GROWFS",
1692 "STRAT_WRITE",
1693 "DIOSTRAT",
1694 "WRITE_SYNC",
1695 "WRITEID",
1696 "ADDAFORK",
1697 "ATTRINVAL",
1698 "ATRUNCATE",
1699 "ATTR_SET",
1700 "ATTR_RM",
1701 "ATTR_FLAG",
1702 "CLEAR_AGI_BUCKET",
1703 "QM_SBCHANGE",
1704 "DUMMY1",
1705 "DUMMY2",
1706 "QM_QUOTAOFF",
1707 "QM_DQALLOC",
1708 "QM_SETQLIM",
1709 "QM_DQCLUSTER",
1710 "QM_QINOCREATE",
1711 "QM_QUOTAOFF_END",
1712 "SB_UNIT",
1713 "FSYNC_TS",
1714 "GROWFSRT_ALLOC",
1715 "GROWFSRT_ZERO",
1716 "GROWFSRT_FREE",
1717 "SWAPEXT"
1718 };
1719
1720 xfs_fs_cmn_err(CE_WARN, mp,
1721 "xfs_log_write: reservation summary:\n"
1722 " trans type = %s (%u)\n"
1723 " unit res = %d bytes\n"
1724 " current res = %d bytes\n"
1725 " total reg = %u bytes (o/flow = %u bytes)\n"
1726 " ophdrs = %u (ophdr space = %u bytes)\n"
1727 " ophdr + reg = %u bytes\n"
1728 " num regions = %u\n",
1729 ((ticket->t_trans_type <= 0 ||
1730 ticket->t_trans_type > XFS_TRANS_TYPE_MAX) ?
1731 "bad-trans-type" : trans_type_str[ticket->t_trans_type-1]),
1732 ticket->t_trans_type,
1733 ticket->t_unit_res,
1734 ticket->t_curr_res,
1735 ticket->t_res_arr_sum, ticket->t_res_o_flow,
1736 ticket->t_res_num_ophdrs, ophdr_spc,
1737 ticket->t_res_arr_sum +
1738 ticket->t_res_o_flow + ophdr_spc,
1739 ticket->t_res_num);
1740
1741 for (i = 0; i < ticket->t_res_num; i++) {
1742 uint r_type = ticket->t_res_arr[i].r_type;
1743 cmn_err(CE_WARN,
1744 "region[%u]: %s - %u bytes\n",
1745 i,
1746 ((r_type <= 0 || r_type > XLOG_REG_TYPE_MAX) ?
1747 "bad-rtype" : res_type_str[r_type-1]),
1748 ticket->t_res_arr[i].r_len);
1749 }
1750}
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792STATIC int
1793xlog_write(xfs_mount_t * mp,
1794 xfs_log_iovec_t reg[],
1795 int nentries,
1796 xfs_log_ticket_t tic,
1797 xfs_lsn_t *start_lsn,
1798 xlog_in_core_t **commit_iclog,
1799 uint flags)
1800{
1801 xlog_t *log = mp->m_log;
1802 xlog_ticket_t *ticket = (xlog_ticket_t *)tic;
1803 xlog_in_core_t *iclog = NULL;
1804 xlog_op_header_t *logop_head;
1805 __psint_t ptr;
1806 int len;
1807 int index;
1808 int log_offset;
1809 int start_rec_copy;
1810 int partial_copy;
1811 int partial_copy_len;
1812 int need_copy;
1813 int copy_len;
1814 int copy_off;
1815 int contwr;
1816 int error;
1817 int record_cnt = 0, data_cnt = 0;
1818
1819 partial_copy_len = partial_copy = 0;
1820
1821
1822
1823
1824 len = 0;
1825 if (ticket->t_flags & XLOG_TIC_INITED) {
1826 len += sizeof(xlog_op_header_t);
1827 ticket->t_res_num_ophdrs++;
1828 }
1829
1830 for (index = 0; index < nentries; index++) {
1831 len += sizeof(xlog_op_header_t);
1832 ticket->t_res_num_ophdrs++;
1833 len += reg[index].i_len;
1834 xlog_tic_add_region(ticket, reg[index].i_len, reg[index].i_type);
1835 }
1836 contwr = *start_lsn = 0;
1837
1838 if (ticket->t_curr_res < len) {
1839 xlog_print_tic_res(mp, ticket);
1840#ifdef DEBUG
1841 xlog_panic(
1842 "xfs_log_write: reservation ran out. Need to up reservation");
1843#else
1844
1845 xfs_cmn_err(XFS_PTAG_LOGRES, CE_ALERT, mp,
1846 "xfs_log_write: reservation ran out. Need to up reservation");
1847
1848 xfs_force_shutdown(mp, SHUTDOWN_CORRUPT_INCORE);
1849#endif
1850 } else
1851 ticket->t_curr_res -= len;
1852
1853 for (index = 0; index < nentries; ) {
1854 if ((error = xlog_state_get_iclog_space(log, len, &iclog, ticket,
1855 &contwr, &log_offset)))
1856 return error;
1857
1858 ASSERT(log_offset <= iclog->ic_size - 1);
1859 ptr = (__psint_t) ((char *)iclog->ic_datap+log_offset);
1860
1861
1862 if (! *start_lsn)
1863 *start_lsn = be64_to_cpu(iclog->ic_header.h_lsn);
1864
1865
1866
1867
1868 while (index < nentries) {
1869 ASSERT(reg[index].i_len % sizeof(__int32_t) == 0);
1870 ASSERT((__psint_t)ptr % sizeof(__int32_t) == 0);
1871 start_rec_copy = 0;
1872
1873
1874
1875
1876
1877 if (ticket->t_flags & XLOG_TIC_INITED) {
1878 logop_head = (xlog_op_header_t *)ptr;
1879 logop_head->oh_tid = cpu_to_be32(ticket->t_tid);
1880 logop_head->oh_clientid = ticket->t_clientid;
1881 logop_head->oh_len = 0;
1882 logop_head->oh_flags = XLOG_START_TRANS;
1883 logop_head->oh_res2 = 0;
1884 ticket->t_flags &= ~XLOG_TIC_INITED;
1885 record_cnt++;
1886
1887 start_rec_copy = sizeof(xlog_op_header_t);
1888 xlog_write_adv_cnt(ptr, len, log_offset, start_rec_copy);
1889 }
1890
1891
1892 logop_head = (xlog_op_header_t *)ptr;
1893 logop_head->oh_tid = cpu_to_be32(ticket->t_tid);
1894 logop_head->oh_clientid = ticket->t_clientid;
1895 logop_head->oh_res2 = 0;
1896
1897
1898 xlog_write_adv_cnt(ptr, len, log_offset, sizeof(xlog_op_header_t));
1899
1900
1901 logop_head->oh_flags = flags;
1902
1903
1904
1905
1906
1907
1908 switch (logop_head->oh_clientid) {
1909 case XFS_TRANSACTION:
1910 case XFS_VOLUME:
1911 case XFS_LOG:
1912 break;
1913 default:
1914 xfs_fs_cmn_err(CE_WARN, mp,
1915 "Bad XFS transaction clientid 0x%x in ticket 0x%p",
1916 logop_head->oh_clientid, tic);
1917 return XFS_ERROR(EIO);
1918 }
1919
1920
1921
1922
1923
1924 need_copy = reg[index].i_len - partial_copy_len;
1925
1926 copy_off = partial_copy_len;
1927 if (need_copy <= iclog->ic_size - log_offset) {
1928 copy_len = need_copy;
1929 logop_head->oh_len = cpu_to_be32(copy_len);
1930 if (partial_copy)
1931 logop_head->oh_flags|= (XLOG_END_TRANS|XLOG_WAS_CONT_TRANS);
1932 partial_copy_len = partial_copy = 0;
1933 } else {
1934 copy_len = iclog->ic_size - log_offset;
1935 logop_head->oh_len = cpu_to_be32(copy_len);
1936 logop_head->oh_flags |= XLOG_CONTINUE_TRANS;
1937 if (partial_copy)
1938 logop_head->oh_flags |= XLOG_WAS_CONT_TRANS;
1939 partial_copy_len += copy_len;
1940 partial_copy++;
1941 len += sizeof(xlog_op_header_t);
1942
1943 ticket->t_curr_res -= sizeof(xlog_op_header_t);
1944 ticket->t_res_num_ophdrs++;
1945 }
1946 xlog_verify_dest_ptr(log, ptr);
1947
1948
1949 ASSERT(copy_len >= 0);
1950 memcpy((xfs_caddr_t)ptr, reg[index].i_addr + copy_off, copy_len);
1951 xlog_write_adv_cnt(ptr, len, log_offset, copy_len);
1952
1953
1954 copy_len += start_rec_copy + sizeof(xlog_op_header_t);
1955 record_cnt++;
1956 data_cnt += contwr ? copy_len : 0;
1957 if (partial_copy) {
1958
1959 xlog_state_finish_copy(log, iclog, record_cnt, data_cnt);
1960 record_cnt = data_cnt = 0;
1961 if ((error = xlog_state_release_iclog(log, iclog)))
1962 return error;
1963 break;
1964 } else {
1965 index++;
1966 partial_copy_len = partial_copy = 0;
1967
1968 if (iclog->ic_size - log_offset <= sizeof(xlog_op_header_t)) {
1969 xlog_state_finish_copy(log, iclog, record_cnt, data_cnt);
1970 record_cnt = data_cnt = 0;
1971 spin_lock(&log->l_icloglock);
1972 xlog_state_want_sync(log, iclog);
1973 spin_unlock(&log->l_icloglock);
1974 if (commit_iclog) {
1975 ASSERT(flags & XLOG_COMMIT_TRANS);
1976 *commit_iclog = iclog;
1977 } else if ((error = xlog_state_release_iclog(log, iclog)))
1978 return error;
1979 if (index == nentries)
1980 return 0;
1981 else
1982 break;
1983 }
1984 }
1985 }
1986 }
1987 ASSERT(len == 0);
1988
1989 xlog_state_finish_copy(log, iclog, record_cnt, data_cnt);
1990 if (commit_iclog) {
1991 ASSERT(flags & XLOG_COMMIT_TRANS);
1992 *commit_iclog = iclog;
1993 return 0;
1994 }
1995 return xlog_state_release_iclog(log, iclog);
1996}
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014STATIC void
2015xlog_state_clean_log(xlog_t *log)
2016{
2017 xlog_in_core_t *iclog;
2018 int changed = 0;
2019
2020 iclog = log->l_iclog;
2021 do {
2022 if (iclog->ic_state == XLOG_STATE_DIRTY) {
2023 iclog->ic_state = XLOG_STATE_ACTIVE;
2024 iclog->ic_offset = 0;
2025 ASSERT(iclog->ic_callback == NULL);
2026
2027
2028
2029
2030
2031
2032
2033
2034 if (!changed &&
2035 (be32_to_cpu(iclog->ic_header.h_num_logops) ==
2036 XLOG_COVER_OPS)) {
2037 changed = 1;
2038 } else {
2039
2040
2041
2042
2043
2044 changed = 2;
2045 }
2046 iclog->ic_header.h_num_logops = 0;
2047 memset(iclog->ic_header.h_cycle_data, 0,
2048 sizeof(iclog->ic_header.h_cycle_data));
2049 iclog->ic_header.h_lsn = 0;
2050 } else if (iclog->ic_state == XLOG_STATE_ACTIVE)
2051 ;
2052 else
2053 break;
2054 iclog = iclog->ic_next;
2055 } while (iclog != log->l_iclog);
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065 if (changed) {
2066 switch (log->l_covered_state) {
2067 case XLOG_STATE_COVER_IDLE:
2068 case XLOG_STATE_COVER_NEED:
2069 case XLOG_STATE_COVER_NEED2:
2070 log->l_covered_state = XLOG_STATE_COVER_NEED;
2071 break;
2072
2073 case XLOG_STATE_COVER_DONE:
2074 if (changed == 1)
2075 log->l_covered_state = XLOG_STATE_COVER_NEED2;
2076 else
2077 log->l_covered_state = XLOG_STATE_COVER_NEED;
2078 break;
2079
2080 case XLOG_STATE_COVER_DONE2:
2081 if (changed == 1)
2082 log->l_covered_state = XLOG_STATE_COVER_IDLE;
2083 else
2084 log->l_covered_state = XLOG_STATE_COVER_NEED;
2085 break;
2086
2087 default:
2088 ASSERT(0);
2089 }
2090 }
2091}
2092
2093STATIC xfs_lsn_t
2094xlog_get_lowest_lsn(
2095 xlog_t *log)
2096{
2097 xlog_in_core_t *lsn_log;
2098 xfs_lsn_t lowest_lsn, lsn;
2099
2100 lsn_log = log->l_iclog;
2101 lowest_lsn = 0;
2102 do {
2103 if (!(lsn_log->ic_state & (XLOG_STATE_ACTIVE|XLOG_STATE_DIRTY))) {
2104 lsn = be64_to_cpu(lsn_log->ic_header.h_lsn);
2105 if ((lsn && !lowest_lsn) ||
2106 (XFS_LSN_CMP(lsn, lowest_lsn) < 0)) {
2107 lowest_lsn = lsn;
2108 }
2109 }
2110 lsn_log = lsn_log->ic_next;
2111 } while (lsn_log != log->l_iclog);
2112 return lowest_lsn;
2113}
2114
2115
2116STATIC void
2117xlog_state_do_callback(
2118 xlog_t *log,
2119 int aborted,
2120 xlog_in_core_t *ciclog)
2121{
2122 xlog_in_core_t *iclog;
2123 xlog_in_core_t *first_iclog;
2124
2125 xfs_log_callback_t *cb, *cb_next;
2126 int flushcnt = 0;
2127 xfs_lsn_t lowest_lsn;
2128 int ioerrors;
2129 int loopdidcallbacks;
2130 int funcdidcallbacks;
2131 int repeats;
2132
2133 int wake = 0;
2134
2135 spin_lock(&log->l_icloglock);
2136 first_iclog = iclog = log->l_iclog;
2137 ioerrors = 0;
2138 funcdidcallbacks = 0;
2139 repeats = 0;
2140
2141 do {
2142
2143
2144
2145
2146
2147
2148
2149
2150 first_iclog = log->l_iclog;
2151 iclog = log->l_iclog;
2152 loopdidcallbacks = 0;
2153 repeats++;
2154
2155 do {
2156
2157
2158 if (iclog->ic_state &
2159 (XLOG_STATE_ACTIVE|XLOG_STATE_DIRTY)) {
2160 iclog = iclog->ic_next;
2161 continue;
2162 }
2163
2164
2165
2166
2167
2168
2169
2170
2171 if (!(iclog->ic_state & XLOG_STATE_IOERROR)) {
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182 if (!(iclog->ic_state &
2183 (XLOG_STATE_DONE_SYNC |
2184 XLOG_STATE_DO_CALLBACK))) {
2185 if (ciclog && (ciclog->ic_state ==
2186 XLOG_STATE_DONE_SYNC)) {
2187 ciclog->ic_state = XLOG_STATE_DO_CALLBACK;
2188 }
2189 break;
2190 }
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203
2204
2205 lowest_lsn = xlog_get_lowest_lsn(log);
2206 if (lowest_lsn &&
2207 XFS_LSN_CMP(lowest_lsn,
2208 be64_to_cpu(iclog->ic_header.h_lsn)) < 0) {
2209 iclog = iclog->ic_next;
2210 continue;
2211
2212 }
2213
2214 iclog->ic_state = XLOG_STATE_CALLBACK;
2215
2216 spin_unlock(&log->l_icloglock);
2217
2218
2219
2220
2221
2222 spin_lock(&log->l_grant_lock);
2223 ASSERT(XFS_LSN_CMP(log->l_last_sync_lsn,
2224 be64_to_cpu(iclog->ic_header.h_lsn)) <= 0);
2225 log->l_last_sync_lsn =
2226 be64_to_cpu(iclog->ic_header.h_lsn);
2227 spin_unlock(&log->l_grant_lock);
2228
2229 } else {
2230 spin_unlock(&log->l_icloglock);
2231 ioerrors++;
2232 }
2233
2234
2235
2236
2237
2238
2239
2240
2241 spin_lock(&iclog->ic_callback_lock);
2242 cb = iclog->ic_callback;
2243 while (cb) {
2244 iclog->ic_callback_tail = &(iclog->ic_callback);
2245 iclog->ic_callback = NULL;
2246 spin_unlock(&iclog->ic_callback_lock);
2247
2248
2249 for (; cb; cb = cb_next) {
2250 cb_next = cb->cb_next;
2251 cb->cb_func(cb->cb_arg, aborted);
2252 }
2253 spin_lock(&iclog->ic_callback_lock);
2254 cb = iclog->ic_callback;
2255 }
2256
2257 loopdidcallbacks++;
2258 funcdidcallbacks++;
2259
2260 spin_lock(&log->l_icloglock);
2261 ASSERT(iclog->ic_callback == NULL);
2262 spin_unlock(&iclog->ic_callback_lock);
2263 if (!(iclog->ic_state & XLOG_STATE_IOERROR))
2264 iclog->ic_state = XLOG_STATE_DIRTY;
2265
2266
2267
2268
2269
2270 xlog_state_clean_log(log);
2271
2272
2273 sv_broadcast(&iclog->ic_force_wait);
2274
2275 iclog = iclog->ic_next;
2276 } while (first_iclog != iclog);
2277
2278 if (repeats > 5000) {
2279 flushcnt += repeats;
2280 repeats = 0;
2281 xfs_fs_cmn_err(CE_WARN, log->l_mp,
2282 "%s: possible infinite loop (%d iterations)",
2283 __func__, flushcnt);
2284 }
2285 } while (!ioerrors && loopdidcallbacks);
2286
2287
2288
2289
2290
2291#ifdef DEBUG
2292 if (funcdidcallbacks) {
2293 first_iclog = iclog = log->l_iclog;
2294 do {
2295 ASSERT(iclog->ic_state != XLOG_STATE_DO_CALLBACK);
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305 if (iclog->ic_state == XLOG_STATE_WANT_SYNC ||
2306 iclog->ic_state == XLOG_STATE_SYNCING ||
2307 iclog->ic_state == XLOG_STATE_DONE_SYNC ||
2308 iclog->ic_state == XLOG_STATE_IOERROR )
2309 break;
2310 iclog = iclog->ic_next;
2311 } while (first_iclog != iclog);
2312 }
2313#endif
2314
2315 if (log->l_iclog->ic_state & (XLOG_STATE_ACTIVE|XLOG_STATE_IOERROR))
2316 wake = 1;
2317 spin_unlock(&log->l_icloglock);
2318
2319 if (wake)
2320 sv_broadcast(&log->l_flush_wait);
2321}
2322
2323
2324
2325
2326
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337STATIC void
2338xlog_state_done_syncing(
2339 xlog_in_core_t *iclog,
2340 int aborted)
2341{
2342 xlog_t *log = iclog->ic_log;
2343
2344 spin_lock(&log->l_icloglock);
2345
2346 ASSERT(iclog->ic_state == XLOG_STATE_SYNCING ||
2347 iclog->ic_state == XLOG_STATE_IOERROR);
2348 ASSERT(atomic_read(&iclog->ic_refcnt) == 0);
2349 ASSERT(iclog->ic_bwritecnt == 1 || iclog->ic_bwritecnt == 2);
2350
2351
2352
2353
2354
2355
2356
2357
2358 if (iclog->ic_state != XLOG_STATE_IOERROR) {
2359 if (--iclog->ic_bwritecnt == 1) {
2360 spin_unlock(&log->l_icloglock);
2361 return;
2362 }
2363 iclog->ic_state = XLOG_STATE_DONE_SYNC;
2364 }
2365
2366
2367
2368
2369
2370
2371 sv_broadcast(&iclog->ic_write_wait);
2372 spin_unlock(&log->l_icloglock);
2373 xlog_state_do_callback(log, aborted, iclog);
2374}
2375
2376
2377
2378
2379
2380
2381
2382
2383
2384
2385
2386
2387
2388
2389
2390
2391
2392
2393
2394
2395STATIC int
2396xlog_state_get_iclog_space(xlog_t *log,
2397 int len,
2398 xlog_in_core_t **iclogp,
2399 xlog_ticket_t *ticket,
2400 int *continued_write,
2401 int *logoffsetp)
2402{
2403 int log_offset;
2404 xlog_rec_header_t *head;
2405 xlog_in_core_t *iclog;
2406 int error;
2407
2408restart:
2409 spin_lock(&log->l_icloglock);
2410 if (XLOG_FORCED_SHUTDOWN(log)) {
2411 spin_unlock(&log->l_icloglock);
2412 return XFS_ERROR(EIO);
2413 }
2414
2415 iclog = log->l_iclog;
2416 if (iclog->ic_state != XLOG_STATE_ACTIVE) {
2417 xlog_trace_iclog(iclog, XLOG_TRACE_SLEEP_FLUSH);
2418 XFS_STATS_INC(xs_log_noiclogs);
2419
2420
2421 sv_wait(&log->l_flush_wait, 0, &log->l_icloglock, 0);
2422 goto restart;
2423 }
2424
2425 head = &iclog->ic_header;
2426
2427 atomic_inc(&iclog->ic_refcnt);
2428 log_offset = iclog->ic_offset;
2429
2430
2431
2432
2433
2434
2435 if (log_offset == 0) {
2436 ticket->t_curr_res -= log->l_iclog_hsize;
2437 xlog_tic_add_region(ticket,
2438 log->l_iclog_hsize,
2439 XLOG_REG_TYPE_LRHEADER);
2440 head->h_cycle = cpu_to_be32(log->l_curr_cycle);
2441 head->h_lsn = cpu_to_be64(
2442 xlog_assign_lsn(log->l_curr_cycle, log->l_curr_block));
2443 ASSERT(log->l_curr_block >= 0);
2444 }
2445
2446
2447
2448
2449
2450
2451
2452
2453
2454
2455 if (iclog->ic_size - iclog->ic_offset < 2*sizeof(xlog_op_header_t)) {
2456 xlog_state_switch_iclogs(log, iclog, iclog->ic_size);
2457
2458
2459
2460
2461
2462
2463
2464
2465 if (!atomic_add_unless(&iclog->ic_refcnt, -1, 1)) {
2466
2467 spin_unlock(&log->l_icloglock);
2468 error = xlog_state_release_iclog(log, iclog);
2469 if (error)
2470 return error;
2471 } else {
2472 spin_unlock(&log->l_icloglock);
2473 }
2474 goto restart;
2475 }
2476
2477
2478
2479
2480
2481
2482
2483 if (len <= iclog->ic_size - iclog->ic_offset) {
2484 *continued_write = 0;
2485 iclog->ic_offset += len;
2486 } else {
2487 *continued_write = 1;
2488 xlog_state_switch_iclogs(log, iclog, iclog->ic_size);
2489 }
2490 *iclogp = iclog;
2491
2492 ASSERT(iclog->ic_offset <= iclog->ic_size);
2493 spin_unlock(&log->l_icloglock);
2494
2495 *logoffsetp = log_offset;
2496 return 0;
2497}
2498
2499
2500
2501
2502
2503
2504
2505STATIC int
2506xlog_grant_log_space(xlog_t *log,
2507 xlog_ticket_t *tic)
2508{
2509 int free_bytes;
2510 int need_bytes;
2511#ifdef DEBUG
2512 xfs_lsn_t tail_lsn;
2513#endif
2514
2515
2516#ifdef DEBUG
2517 if (log->l_flags & XLOG_ACTIVE_RECOVERY)
2518 panic("grant Recovery problem");
2519#endif
2520
2521
2522 spin_lock(&log->l_grant_lock);
2523 xlog_trace_loggrant(log, tic, "xlog_grant_log_space: enter");
2524
2525
2526 if (log->l_reserve_headq) {
2527 xlog_ins_ticketq(&log->l_reserve_headq, tic);
2528 xlog_trace_loggrant(log, tic,
2529 "xlog_grant_log_space: sleep 1");
2530
2531
2532
2533
2534 if (XLOG_FORCED_SHUTDOWN(log))
2535 goto error_return;
2536
2537 XFS_STATS_INC(xs_sleep_logspace);
2538 sv_wait(&tic->t_wait, PINOD|PLTWAIT, &log->l_grant_lock, s);
2539
2540
2541
2542
2543 xlog_trace_loggrant(log, tic,
2544 "xlog_grant_log_space: wake 1");
2545 spin_lock(&log->l_grant_lock);
2546 }
2547 if (tic->t_flags & XFS_LOG_PERM_RESERV)
2548 need_bytes = tic->t_unit_res*tic->t_ocnt;
2549 else
2550 need_bytes = tic->t_unit_res;
2551
2552redo:
2553 if (XLOG_FORCED_SHUTDOWN(log))
2554 goto error_return;
2555
2556 free_bytes = xlog_space_left(log, log->l_grant_reserve_cycle,
2557 log->l_grant_reserve_bytes);
2558 if (free_bytes < need_bytes) {
2559 if ((tic->t_flags & XLOG_TIC_IN_Q) == 0)
2560 xlog_ins_ticketq(&log->l_reserve_headq, tic);
2561 xlog_trace_loggrant(log, tic,
2562 "xlog_grant_log_space: sleep 2");
2563 spin_unlock(&log->l_grant_lock);
2564 xlog_grant_push_ail(log->l_mp, need_bytes);
2565 spin_lock(&log->l_grant_lock);
2566
2567 XFS_STATS_INC(xs_sleep_logspace);
2568 sv_wait(&tic->t_wait, PINOD|PLTWAIT, &log->l_grant_lock, s);
2569
2570 spin_lock(&log->l_grant_lock);
2571 if (XLOG_FORCED_SHUTDOWN(log))
2572 goto error_return;
2573
2574 xlog_trace_loggrant(log, tic,
2575 "xlog_grant_log_space: wake 2");
2576 goto redo;
2577 } else if (tic->t_flags & XLOG_TIC_IN_Q)
2578 xlog_del_ticketq(&log->l_reserve_headq, tic);
2579
2580
2581 xlog_grant_add_space(log, need_bytes);
2582#ifdef DEBUG
2583 tail_lsn = log->l_tail_lsn;
2584
2585
2586
2587
2588
2589
2590 if (CYCLE_LSN(tail_lsn) != log->l_grant_write_cycle) {
2591 ASSERT(log->l_grant_write_cycle-1 == CYCLE_LSN(tail_lsn));
2592 ASSERT(log->l_grant_write_bytes <= BBTOB(BLOCK_LSN(tail_lsn)));
2593 }
2594#endif
2595 xlog_trace_loggrant(log, tic, "xlog_grant_log_space: exit");
2596 xlog_verify_grant_head(log, 1);
2597 spin_unlock(&log->l_grant_lock);
2598 return 0;
2599
2600 error_return:
2601 if (tic->t_flags & XLOG_TIC_IN_Q)
2602 xlog_del_ticketq(&log->l_reserve_headq, tic);
2603 xlog_trace_loggrant(log, tic, "xlog_grant_log_space: err_ret");
2604
2605
2606
2607
2608
2609 tic->t_curr_res = 0;
2610 tic->t_cnt = 0;
2611 spin_unlock(&log->l_grant_lock);
2612 return XFS_ERROR(EIO);
2613}
2614
2615
2616
2617
2618
2619
2620
2621STATIC int
2622xlog_regrant_write_log_space(xlog_t *log,
2623 xlog_ticket_t *tic)
2624{
2625 int free_bytes, need_bytes;
2626 xlog_ticket_t *ntic;
2627#ifdef DEBUG
2628 xfs_lsn_t tail_lsn;
2629#endif
2630
2631 tic->t_curr_res = tic->t_unit_res;
2632 xlog_tic_reset_res(tic);
2633
2634 if (tic->t_cnt > 0)
2635 return 0;
2636
2637#ifdef DEBUG
2638 if (log->l_flags & XLOG_ACTIVE_RECOVERY)
2639 panic("regrant Recovery problem");
2640#endif
2641
2642 spin_lock(&log->l_grant_lock);
2643 xlog_trace_loggrant(log, tic, "xlog_regrant_write_log_space: enter");
2644
2645 if (XLOG_FORCED_SHUTDOWN(log))
2646 goto error_return;
2647
2648
2649
2650
2651
2652
2653
2654 need_bytes = tic->t_unit_res;
2655 if ((ntic = log->l_write_headq)) {
2656 free_bytes = xlog_space_left(log, log->l_grant_write_cycle,
2657 log->l_grant_write_bytes);
2658 do {
2659 ASSERT(ntic->t_flags & XLOG_TIC_PERM_RESERV);
2660
2661 if (free_bytes < ntic->t_unit_res)
2662 break;
2663 free_bytes -= ntic->t_unit_res;
2664 sv_signal(&ntic->t_wait);
2665 ntic = ntic->t_next;
2666 } while (ntic != log->l_write_headq);
2667
2668 if (ntic != log->l_write_headq) {
2669 if ((tic->t_flags & XLOG_TIC_IN_Q) == 0)
2670 xlog_ins_ticketq(&log->l_write_headq, tic);
2671
2672 xlog_trace_loggrant(log, tic,
2673 "xlog_regrant_write_log_space: sleep 1");
2674 spin_unlock(&log->l_grant_lock);
2675 xlog_grant_push_ail(log->l_mp, need_bytes);
2676 spin_lock(&log->l_grant_lock);
2677
2678 XFS_STATS_INC(xs_sleep_logspace);
2679 sv_wait(&tic->t_wait, PINOD|PLTWAIT,
2680 &log->l_grant_lock, s);
2681
2682
2683
2684 spin_lock(&log->l_grant_lock);
2685 if (XLOG_FORCED_SHUTDOWN(log))
2686 goto error_return;
2687
2688 xlog_trace_loggrant(log, tic,
2689 "xlog_regrant_write_log_space: wake 1");
2690 }
2691 }
2692
2693redo:
2694 if (XLOG_FORCED_SHUTDOWN(log))
2695 goto error_return;
2696
2697 free_bytes = xlog_space_left(log, log->l_grant_write_cycle,
2698 log->l_grant_write_bytes);
2699 if (free_bytes < need_bytes) {
2700 if ((tic->t_flags & XLOG_TIC_IN_Q) == 0)
2701 xlog_ins_ticketq(&log->l_write_headq, tic);
2702 spin_unlock(&log->l_grant_lock);
2703 xlog_grant_push_ail(log->l_mp, need_bytes);
2704 spin_lock(&log->l_grant_lock);
2705
2706 XFS_STATS_INC(xs_sleep_logspace);
2707 sv_wait(&tic->t_wait, PINOD|PLTWAIT, &log->l_grant_lock, s);
2708
2709
2710 spin_lock(&log->l_grant_lock);
2711 if (XLOG_FORCED_SHUTDOWN(log))
2712 goto error_return;
2713
2714 xlog_trace_loggrant(log, tic,
2715 "xlog_regrant_write_log_space: wake 2");
2716 goto redo;
2717 } else if (tic->t_flags & XLOG_TIC_IN_Q)
2718 xlog_del_ticketq(&log->l_write_headq, tic);
2719
2720
2721 xlog_grant_add_space_write(log, need_bytes);
2722#ifdef DEBUG
2723 tail_lsn = log->l_tail_lsn;
2724 if (CYCLE_LSN(tail_lsn) != log->l_grant_write_cycle) {
2725 ASSERT(log->l_grant_write_cycle-1 == CYCLE_LSN(tail_lsn));
2726 ASSERT(log->l_grant_write_bytes <= BBTOB(BLOCK_LSN(tail_lsn)));
2727 }
2728#endif
2729
2730 xlog_trace_loggrant(log, tic, "xlog_regrant_write_log_space: exit");
2731 xlog_verify_grant_head(log, 1);
2732 spin_unlock(&log->l_grant_lock);
2733 return 0;
2734
2735
2736 error_return:
2737 if (tic->t_flags & XLOG_TIC_IN_Q)
2738 xlog_del_ticketq(&log->l_reserve_headq, tic);
2739 xlog_trace_loggrant(log, tic, "xlog_regrant_write_log_space: err_ret");
2740
2741
2742
2743
2744
2745 tic->t_curr_res = 0;
2746 tic->t_cnt = 0;
2747 spin_unlock(&log->l_grant_lock);
2748 return XFS_ERROR(EIO);
2749}
2750
2751
2752
2753
2754
2755
2756
2757
2758
2759STATIC void
2760xlog_regrant_reserve_log_space(xlog_t *log,
2761 xlog_ticket_t *ticket)
2762{
2763 xlog_trace_loggrant(log, ticket,
2764 "xlog_regrant_reserve_log_space: enter");
2765 if (ticket->t_cnt > 0)
2766 ticket->t_cnt--;
2767
2768 spin_lock(&log->l_grant_lock);
2769 xlog_grant_sub_space(log, ticket->t_curr_res);
2770 ticket->t_curr_res = ticket->t_unit_res;
2771 xlog_tic_reset_res(ticket);
2772 xlog_trace_loggrant(log, ticket,
2773 "xlog_regrant_reserve_log_space: sub current res");
2774 xlog_verify_grant_head(log, 1);
2775
2776
2777 if (ticket->t_cnt > 0) {
2778 spin_unlock(&log->l_grant_lock);
2779 return;
2780 }
2781
2782 xlog_grant_add_space_reserve(log, ticket->t_unit_res);
2783 xlog_trace_loggrant(log, ticket,
2784 "xlog_regrant_reserve_log_space: exit");
2785 xlog_verify_grant_head(log, 0);
2786 spin_unlock(&log->l_grant_lock);
2787 ticket->t_curr_res = ticket->t_unit_res;
2788 xlog_tic_reset_res(ticket);
2789}
2790
2791
2792
2793
2794
2795
2796
2797
2798
2799
2800
2801
2802
2803
2804
2805
2806STATIC void
2807xlog_ungrant_log_space(xlog_t *log,
2808 xlog_ticket_t *ticket)
2809{
2810 if (ticket->t_cnt > 0)
2811 ticket->t_cnt--;
2812
2813 spin_lock(&log->l_grant_lock);
2814 xlog_trace_loggrant(log, ticket, "xlog_ungrant_log_space: enter");
2815
2816 xlog_grant_sub_space(log, ticket->t_curr_res);
2817
2818 xlog_trace_loggrant(log, ticket, "xlog_ungrant_log_space: sub current");
2819
2820
2821
2822
2823 if (ticket->t_cnt > 0) {
2824 ASSERT(ticket->t_flags & XLOG_TIC_PERM_RESERV);
2825 xlog_grant_sub_space(log, ticket->t_unit_res*ticket->t_cnt);
2826 }
2827
2828 xlog_trace_loggrant(log, ticket, "xlog_ungrant_log_space: exit");
2829 xlog_verify_grant_head(log, 1);
2830 spin_unlock(&log->l_grant_lock);
2831 xfs_log_move_tail(log->l_mp, 1);
2832}
2833
2834
2835
2836
2837
2838
2839
2840
2841
2842
2843
2844STATIC int
2845xlog_state_release_iclog(
2846 xlog_t *log,
2847 xlog_in_core_t *iclog)
2848{
2849 int sync = 0;
2850
2851 if (iclog->ic_state & XLOG_STATE_IOERROR)
2852 return XFS_ERROR(EIO);
2853
2854 ASSERT(atomic_read(&iclog->ic_refcnt) > 0);
2855 if (!atomic_dec_and_lock(&iclog->ic_refcnt, &log->l_icloglock))
2856 return 0;
2857
2858 if (iclog->ic_state & XLOG_STATE_IOERROR) {
2859 spin_unlock(&log->l_icloglock);
2860 return XFS_ERROR(EIO);
2861 }
2862 ASSERT(iclog->ic_state == XLOG_STATE_ACTIVE ||
2863 iclog->ic_state == XLOG_STATE_WANT_SYNC);
2864
2865 if (iclog->ic_state == XLOG_STATE_WANT_SYNC) {
2866
2867 xlog_assign_tail_lsn(log->l_mp);
2868 sync++;
2869 iclog->ic_state = XLOG_STATE_SYNCING;
2870 iclog->ic_header.h_tail_lsn = cpu_to_be64(log->l_tail_lsn);
2871 xlog_verify_tail_lsn(log, iclog, log->l_tail_lsn);
2872
2873 }
2874 spin_unlock(&log->l_icloglock);
2875
2876
2877
2878
2879
2880
2881
2882
2883 if (sync)
2884 return xlog_sync(log, iclog);
2885 return 0;
2886}
2887
2888
2889
2890
2891
2892
2893
2894
2895
2896STATIC void
2897xlog_state_switch_iclogs(xlog_t *log,
2898 xlog_in_core_t *iclog,
2899 int eventual_size)
2900{
2901 ASSERT(iclog->ic_state == XLOG_STATE_ACTIVE);
2902 if (!eventual_size)
2903 eventual_size = iclog->ic_offset;
2904 iclog->ic_state = XLOG_STATE_WANT_SYNC;
2905 iclog->ic_header.h_prev_block = cpu_to_be32(log->l_prev_block);
2906 log->l_prev_block = log->l_curr_block;
2907 log->l_prev_cycle = log->l_curr_cycle;
2908
2909
2910 log->l_curr_block += BTOBB(eventual_size)+BTOBB(log->l_iclog_hsize);
2911
2912
2913 if (xfs_sb_version_haslogv2(&log->l_mp->m_sb) &&
2914 log->l_mp->m_sb.sb_logsunit > 1) {
2915 __uint32_t sunit_bb = BTOBB(log->l_mp->m_sb.sb_logsunit);
2916 log->l_curr_block = roundup(log->l_curr_block, sunit_bb);
2917 }
2918
2919 if (log->l_curr_block >= log->l_logBBsize) {
2920 log->l_curr_cycle++;
2921 if (log->l_curr_cycle == XLOG_HEADER_MAGIC_NUM)
2922 log->l_curr_cycle++;
2923 log->l_curr_block -= log->l_logBBsize;
2924 ASSERT(log->l_curr_block >= 0);
2925 }
2926 ASSERT(iclog == log->l_iclog);
2927 log->l_iclog = iclog->ic_next;
2928}
2929
2930
2931
2932
2933
2934
2935
2936
2937
2938
2939
2940
2941
2942
2943
2944
2945
2946
2947
2948
2949
2950
2951
2952
2953
2954
2955
2956
2957
2958STATIC int
2959xlog_state_sync_all(xlog_t *log, uint flags, int *log_flushed)
2960{
2961 xlog_in_core_t *iclog;
2962 xfs_lsn_t lsn;
2963
2964 spin_lock(&log->l_icloglock);
2965
2966 iclog = log->l_iclog;
2967 if (iclog->ic_state & XLOG_STATE_IOERROR) {
2968 spin_unlock(&log->l_icloglock);
2969 return XFS_ERROR(EIO);
2970 }
2971
2972
2973
2974
2975 if (iclog->ic_state == XLOG_STATE_ACTIVE ||
2976 iclog->ic_state == XLOG_STATE_DIRTY) {
2977
2978
2979
2980
2981
2982
2983
2984 if (iclog->ic_state == XLOG_STATE_DIRTY ||
2985 (atomic_read(&iclog->ic_refcnt) == 0
2986 && iclog->ic_offset == 0)) {
2987 iclog = iclog->ic_prev;
2988 if (iclog->ic_state == XLOG_STATE_ACTIVE ||
2989 iclog->ic_state == XLOG_STATE_DIRTY)
2990 goto no_sleep;
2991 else
2992 goto maybe_sleep;
2993 } else {
2994 if (atomic_read(&iclog->ic_refcnt) == 0) {
2995
2996
2997
2998
2999
3000
3001 atomic_inc(&iclog->ic_refcnt);
3002 lsn = be64_to_cpu(iclog->ic_header.h_lsn);
3003 xlog_state_switch_iclogs(log, iclog, 0);
3004 spin_unlock(&log->l_icloglock);
3005
3006 if (xlog_state_release_iclog(log, iclog))
3007 return XFS_ERROR(EIO);
3008 *log_flushed = 1;
3009 spin_lock(&log->l_icloglock);
3010 if (be64_to_cpu(iclog->ic_header.h_lsn) == lsn &&
3011 iclog->ic_state != XLOG_STATE_DIRTY)
3012 goto maybe_sleep;
3013 else
3014 goto no_sleep;
3015 } else {
3016
3017
3018
3019
3020
3021 xlog_state_switch_iclogs(log, iclog, 0);
3022 goto maybe_sleep;
3023 }
3024 }
3025 }
3026
3027
3028
3029
3030
3031maybe_sleep:
3032 if (flags & XFS_LOG_SYNC) {
3033
3034
3035
3036
3037
3038
3039 if (iclog->ic_state & XLOG_STATE_IOERROR) {
3040 spin_unlock(&log->l_icloglock);
3041 return XFS_ERROR(EIO);
3042 }
3043 XFS_STATS_INC(xs_log_force_sleep);
3044 sv_wait(&iclog->ic_force_wait, PINOD, &log->l_icloglock, s);
3045
3046
3047
3048
3049
3050 if (iclog->ic_state & XLOG_STATE_IOERROR)
3051 return XFS_ERROR(EIO);
3052 *log_flushed = 1;
3053
3054 } else {
3055
3056no_sleep:
3057 spin_unlock(&log->l_icloglock);
3058 }
3059 return 0;
3060}
3061
3062
3063
3064
3065
3066
3067
3068
3069
3070
3071
3072
3073
3074
3075STATIC int
3076xlog_state_sync(xlog_t *log,
3077 xfs_lsn_t lsn,
3078 uint flags,
3079 int *log_flushed)
3080{
3081 xlog_in_core_t *iclog;
3082 int already_slept = 0;
3083
3084try_again:
3085 spin_lock(&log->l_icloglock);
3086 iclog = log->l_iclog;
3087
3088 if (iclog->ic_state & XLOG_STATE_IOERROR) {
3089 spin_unlock(&log->l_icloglock);
3090 return XFS_ERROR(EIO);
3091 }
3092
3093 do {
3094 if (be64_to_cpu(iclog->ic_header.h_lsn) != lsn) {
3095 iclog = iclog->ic_next;
3096 continue;
3097 }
3098
3099 if (iclog->ic_state == XLOG_STATE_DIRTY) {
3100 spin_unlock(&log->l_icloglock);
3101 return 0;
3102 }
3103
3104 if (iclog->ic_state == XLOG_STATE_ACTIVE) {
3105
3106
3107
3108
3109
3110
3111
3112
3113
3114
3115
3116
3117
3118
3119
3120
3121
3122 if (!already_slept &&
3123 (iclog->ic_prev->ic_state & (XLOG_STATE_WANT_SYNC |
3124 XLOG_STATE_SYNCING))) {
3125 ASSERT(!(iclog->ic_state & XLOG_STATE_IOERROR));
3126 XFS_STATS_INC(xs_log_force_sleep);
3127 sv_wait(&iclog->ic_prev->ic_write_wait, PSWP,
3128 &log->l_icloglock, s);
3129 *log_flushed = 1;
3130 already_slept = 1;
3131 goto try_again;
3132 } else {
3133 atomic_inc(&iclog->ic_refcnt);
3134 xlog_state_switch_iclogs(log, iclog, 0);
3135 spin_unlock(&log->l_icloglock);
3136 if (xlog_state_release_iclog(log, iclog))
3137 return XFS_ERROR(EIO);
3138 *log_flushed = 1;
3139 spin_lock(&log->l_icloglock);
3140 }
3141 }
3142
3143 if ((flags & XFS_LOG_SYNC) &&
3144 !(iclog->ic_state & (XLOG_STATE_ACTIVE | XLOG_STATE_DIRTY))) {
3145
3146
3147
3148
3149
3150 if (iclog->ic_state & XLOG_STATE_IOERROR) {
3151 spin_unlock(&log->l_icloglock);
3152 return XFS_ERROR(EIO);
3153 }
3154 XFS_STATS_INC(xs_log_force_sleep);
3155 sv_wait(&iclog->ic_force_wait, PSWP, &log->l_icloglock, s);
3156
3157
3158
3159
3160
3161 if (iclog->ic_state & XLOG_STATE_IOERROR)
3162 return XFS_ERROR(EIO);
3163 *log_flushed = 1;
3164 } else {
3165 spin_unlock(&log->l_icloglock);
3166 }
3167 return 0;
3168
3169 } while (iclog != log->l_iclog);
3170
3171 spin_unlock(&log->l_icloglock);
3172 return 0;
3173}
3174
3175
3176
3177
3178
3179
3180STATIC void
3181xlog_state_want_sync(xlog_t *log, xlog_in_core_t *iclog)
3182{
3183 assert_spin_locked(&log->l_icloglock);
3184
3185 if (iclog->ic_state == XLOG_STATE_ACTIVE) {
3186 xlog_state_switch_iclogs(log, iclog, 0);
3187 } else {
3188 ASSERT(iclog->ic_state &
3189 (XLOG_STATE_WANT_SYNC|XLOG_STATE_IOERROR));
3190 }
3191}
3192
3193
3194
3195
3196
3197
3198
3199
3200
3201
3202
3203
3204void
3205xfs_log_ticket_put(
3206 xlog_ticket_t *ticket)
3207{
3208 ASSERT(atomic_read(&ticket->t_ref) > 0);
3209 if (atomic_dec_and_test(&ticket->t_ref)) {
3210 sv_destroy(&ticket->t_wait);
3211 kmem_zone_free(xfs_log_ticket_zone, ticket);
3212 }
3213}
3214
3215xlog_ticket_t *
3216xfs_log_ticket_get(
3217 xlog_ticket_t *ticket)
3218{
3219 ASSERT(atomic_read(&ticket->t_ref) > 0);
3220 atomic_inc(&ticket->t_ref);
3221 return ticket;
3222}
3223
3224
3225
3226
3227STATIC xlog_ticket_t *
3228xlog_ticket_alloc(xlog_t *log,
3229 int unit_bytes,
3230 int cnt,
3231 char client,
3232 uint xflags)
3233{
3234 xlog_ticket_t *tic;
3235 uint num_headers;
3236
3237 tic = kmem_zone_zalloc(xfs_log_ticket_zone, KM_SLEEP|KM_MAYFAIL);
3238 if (!tic)
3239 return NULL;
3240
3241
3242
3243
3244
3245
3246
3247
3248
3249
3250
3251
3252
3253
3254
3255
3256
3257
3258
3259
3260
3261
3262
3263
3264
3265
3266
3267
3268
3269
3270
3271
3272
3273 unit_bytes += sizeof(xlog_op_header_t);
3274 unit_bytes += sizeof(xfs_trans_header_t);
3275
3276
3277 unit_bytes += sizeof(xlog_op_header_t);
3278
3279
3280 num_headers = ((unit_bytes + log->l_iclog_size-1) >> log->l_iclog_size_log);
3281 unit_bytes += log->l_iclog_hsize * num_headers;
3282
3283
3284 unit_bytes += log->l_iclog_hsize;
3285
3286
3287 unit_bytes += sizeof(xlog_op_header_t) * num_headers;
3288
3289
3290 if (xfs_sb_version_haslogv2(&log->l_mp->m_sb) &&
3291 log->l_mp->m_sb.sb_logsunit > 1) {
3292
3293 unit_bytes += 2*log->l_mp->m_sb.sb_logsunit;
3294 } else {
3295
3296 unit_bytes += 2*BBSIZE;
3297 }
3298
3299 atomic_set(&tic->t_ref, 1);
3300 tic->t_unit_res = unit_bytes;
3301 tic->t_curr_res = unit_bytes;
3302 tic->t_cnt = cnt;
3303 tic->t_ocnt = cnt;
3304 tic->t_tid = (xlog_tid_t)((__psint_t)tic & 0xffffffff);
3305 tic->t_clientid = client;
3306 tic->t_flags = XLOG_TIC_INITED;
3307 tic->t_trans_type = 0;
3308 if (xflags & XFS_LOG_PERM_RESERV)
3309 tic->t_flags |= XLOG_TIC_PERM_RESERV;
3310 sv_init(&(tic->t_wait), SV_DEFAULT, "logtick");
3311
3312 xlog_tic_reset_res(tic);
3313
3314 return tic;
3315}
3316
3317
3318
3319
3320
3321
3322
3323
3324#if defined(DEBUG)
3325
3326
3327
3328
3329
3330void
3331xlog_verify_dest_ptr(xlog_t *log,
3332 __psint_t ptr)
3333{
3334 int i;
3335 int good_ptr = 0;
3336
3337 for (i=0; i < log->l_iclog_bufs; i++) {
3338 if (ptr >= (__psint_t)log->l_iclog_bak[i] &&
3339 ptr <= (__psint_t)log->l_iclog_bak[i]+log->l_iclog_size)
3340 good_ptr++;
3341 }
3342 if (! good_ptr)
3343 xlog_panic("xlog_verify_dest_ptr: invalid ptr");
3344}
3345
3346STATIC void
3347xlog_verify_grant_head(xlog_t *log, int equals)
3348{
3349 if (log->l_grant_reserve_cycle == log->l_grant_write_cycle) {
3350 if (equals)
3351 ASSERT(log->l_grant_reserve_bytes >= log->l_grant_write_bytes);
3352 else
3353 ASSERT(log->l_grant_reserve_bytes > log->l_grant_write_bytes);
3354 } else {
3355 ASSERT(log->l_grant_reserve_cycle-1 == log->l_grant_write_cycle);
3356 ASSERT(log->l_grant_write_bytes >= log->l_grant_reserve_bytes);
3357 }
3358}
3359
3360
3361STATIC void
3362xlog_verify_tail_lsn(xlog_t *log,
3363 xlog_in_core_t *iclog,
3364 xfs_lsn_t tail_lsn)
3365{
3366 int blocks;
3367
3368 if (CYCLE_LSN(tail_lsn) == log->l_prev_cycle) {
3369 blocks =
3370 log->l_logBBsize - (log->l_prev_block - BLOCK_LSN(tail_lsn));
3371 if (blocks < BTOBB(iclog->ic_offset)+BTOBB(log->l_iclog_hsize))
3372 xlog_panic("xlog_verify_tail_lsn: ran out of log space");
3373 } else {
3374 ASSERT(CYCLE_LSN(tail_lsn)+1 == log->l_prev_cycle);
3375
3376 if (BLOCK_LSN(tail_lsn) == log->l_prev_block)
3377 xlog_panic("xlog_verify_tail_lsn: tail wrapped");
3378
3379 blocks = BLOCK_LSN(tail_lsn) - log->l_prev_block;
3380 if (blocks < BTOBB(iclog->ic_offset) + 1)
3381 xlog_panic("xlog_verify_tail_lsn: ran out of log space");
3382 }
3383}
3384
3385
3386
3387
3388
3389
3390
3391
3392
3393
3394
3395
3396
3397
3398
3399
3400STATIC void
3401xlog_verify_iclog(xlog_t *log,
3402 xlog_in_core_t *iclog,
3403 int count,
3404 boolean_t syncing)
3405{
3406 xlog_op_header_t *ophead;
3407 xlog_in_core_t *icptr;
3408 xlog_in_core_2_t *xhdr;
3409 xfs_caddr_t ptr;
3410 xfs_caddr_t base_ptr;
3411 __psint_t field_offset;
3412 __uint8_t clientid;
3413 int len, i, j, k, op_len;
3414 int idx;
3415
3416
3417 spin_lock(&log->l_icloglock);
3418 icptr = log->l_iclog;
3419 for (i=0; i < log->l_iclog_bufs; i++) {
3420 if (icptr == NULL)
3421 xlog_panic("xlog_verify_iclog: invalid ptr");
3422 icptr = icptr->ic_next;
3423 }
3424 if (icptr != log->l_iclog)
3425 xlog_panic("xlog_verify_iclog: corrupt iclog ring");
3426 spin_unlock(&log->l_icloglock);
3427
3428
3429 if (be32_to_cpu(iclog->ic_header.h_magicno) != XLOG_HEADER_MAGIC_NUM)
3430 xlog_panic("xlog_verify_iclog: invalid magic num");
3431
3432 ptr = (xfs_caddr_t) &iclog->ic_header;
3433 for (ptr += BBSIZE; ptr < ((xfs_caddr_t)&iclog->ic_header) + count;
3434 ptr += BBSIZE) {
3435 if (be32_to_cpu(*(__be32 *)ptr) == XLOG_HEADER_MAGIC_NUM)
3436 xlog_panic("xlog_verify_iclog: unexpected magic num");
3437 }
3438
3439
3440 len = be32_to_cpu(iclog->ic_header.h_num_logops);
3441 ptr = iclog->ic_datap;
3442 base_ptr = ptr;
3443 ophead = (xlog_op_header_t *)ptr;
3444 xhdr = iclog->ic_data;
3445 for (i = 0; i < len; i++) {
3446 ophead = (xlog_op_header_t *)ptr;
3447
3448
3449 field_offset = (__psint_t)
3450 ((xfs_caddr_t)&(ophead->oh_clientid) - base_ptr);
3451 if (syncing == B_FALSE || (field_offset & 0x1ff)) {
3452 clientid = ophead->oh_clientid;
3453 } else {
3454 idx = BTOBBT((xfs_caddr_t)&(ophead->oh_clientid) - iclog->ic_datap);
3455 if (idx >= (XLOG_HEADER_CYCLE_SIZE / BBSIZE)) {
3456 j = idx / (XLOG_HEADER_CYCLE_SIZE / BBSIZE);
3457 k = idx % (XLOG_HEADER_CYCLE_SIZE / BBSIZE);
3458 clientid = xlog_get_client_id(
3459 xhdr[j].hic_xheader.xh_cycle_data[k]);
3460 } else {
3461 clientid = xlog_get_client_id(
3462 iclog->ic_header.h_cycle_data[idx]);
3463 }
3464 }
3465 if (clientid != XFS_TRANSACTION && clientid != XFS_LOG)
3466 cmn_err(CE_WARN, "xlog_verify_iclog: "
3467 "invalid clientid %d op 0x%p offset 0x%lx",
3468 clientid, ophead, (unsigned long)field_offset);
3469
3470
3471 field_offset = (__psint_t)
3472 ((xfs_caddr_t)&(ophead->oh_len) - base_ptr);
3473 if (syncing == B_FALSE || (field_offset & 0x1ff)) {
3474 op_len = be32_to_cpu(ophead->oh_len);
3475 } else {
3476 idx = BTOBBT((__psint_t)&ophead->oh_len -
3477 (__psint_t)iclog->ic_datap);
3478 if (idx >= (XLOG_HEADER_CYCLE_SIZE / BBSIZE)) {
3479 j = idx / (XLOG_HEADER_CYCLE_SIZE / BBSIZE);
3480 k = idx % (XLOG_HEADER_CYCLE_SIZE / BBSIZE);
3481 op_len = be32_to_cpu(xhdr[j].hic_xheader.xh_cycle_data[k]);
3482 } else {
3483 op_len = be32_to_cpu(iclog->ic_header.h_cycle_data[idx]);
3484 }
3485 }
3486 ptr += sizeof(xlog_op_header_t) + op_len;
3487 }
3488}
3489#endif
3490
3491
3492
3493
3494STATIC int
3495xlog_state_ioerror(
3496 xlog_t *log)
3497{
3498 xlog_in_core_t *iclog, *ic;
3499
3500 iclog = log->l_iclog;
3501 if (! (iclog->ic_state & XLOG_STATE_IOERROR)) {
3502
3503
3504
3505
3506 ic = iclog;
3507 do {
3508 ic->ic_state = XLOG_STATE_IOERROR;
3509 ic = ic->ic_next;
3510 } while (ic != iclog);
3511 return 0;
3512 }
3513
3514
3515
3516 return 1;
3517}
3518
3519
3520
3521
3522
3523
3524
3525
3526
3527
3528
3529
3530
3531int
3532xfs_log_force_umount(
3533 struct xfs_mount *mp,
3534 int logerror)
3535{
3536 xlog_ticket_t *tic;
3537 xlog_t *log;
3538 int retval;
3539 int dummy;
3540
3541 log = mp->m_log;
3542
3543
3544
3545
3546
3547 if (!log ||
3548 log->l_flags & XLOG_ACTIVE_RECOVERY) {
3549 mp->m_flags |= XFS_MOUNT_FS_SHUTDOWN;
3550 if (mp->m_sb_bp)
3551 XFS_BUF_DONE(mp->m_sb_bp);
3552 return 0;
3553 }
3554
3555
3556
3557
3558
3559 if (logerror && log->l_iclog->ic_state & XLOG_STATE_IOERROR) {
3560 ASSERT(XLOG_FORCED_SHUTDOWN(log));
3561 return 1;
3562 }
3563 retval = 0;
3564
3565
3566
3567
3568
3569 spin_lock(&log->l_icloglock);
3570 spin_lock(&log->l_grant_lock);
3571 mp->m_flags |= XFS_MOUNT_FS_SHUTDOWN;
3572 if (mp->m_sb_bp)
3573 XFS_BUF_DONE(mp->m_sb_bp);
3574
3575
3576
3577
3578
3579
3580 log->l_flags |= XLOG_IO_ERROR;
3581
3582
3583
3584
3585
3586 if (logerror)
3587 retval = xlog_state_ioerror(log);
3588 spin_unlock(&log->l_icloglock);
3589
3590
3591
3592
3593
3594
3595
3596
3597
3598 if ((tic = log->l_reserve_headq)) {
3599 do {
3600 sv_signal(&tic->t_wait);
3601 tic = tic->t_next;
3602 } while (tic != log->l_reserve_headq);
3603 }
3604
3605 if ((tic = log->l_write_headq)) {
3606 do {
3607 sv_signal(&tic->t_wait);
3608 tic = tic->t_next;
3609 } while (tic != log->l_write_headq);
3610 }
3611 spin_unlock(&log->l_grant_lock);
3612
3613 if (! (log->l_iclog->ic_state & XLOG_STATE_IOERROR)) {
3614 ASSERT(!logerror);
3615
3616
3617
3618
3619 xlog_state_sync_all(log, XFS_LOG_FORCE|XFS_LOG_SYNC, &dummy);
3620 spin_lock(&log->l_icloglock);
3621 retval = xlog_state_ioerror(log);
3622 spin_unlock(&log->l_icloglock);
3623 }
3624
3625
3626
3627
3628
3629 xlog_state_do_callback(log, XFS_LI_ABORTED, NULL);
3630
3631#ifdef XFSERRORDEBUG
3632 {
3633 xlog_in_core_t *iclog;
3634
3635 spin_lock(&log->l_icloglock);
3636 iclog = log->l_iclog;
3637 do {
3638 ASSERT(iclog->ic_callback == 0);
3639 iclog = iclog->ic_next;
3640 } while (iclog != log->l_iclog);
3641 spin_unlock(&log->l_icloglock);
3642 }
3643#endif
3644
3645 return retval;
3646}
3647
3648STATIC int
3649xlog_iclogs_empty(xlog_t *log)
3650{
3651 xlog_in_core_t *iclog;
3652
3653 iclog = log->l_iclog;
3654 do {
3655
3656
3657
3658 if (iclog->ic_header.h_num_logops)
3659 return 0;
3660 iclog = iclog->ic_next;
3661 } while (iclog != log->l_iclog);
3662 return 1;
3663}
3664