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