Commit 55b66332d0921146a914d5d75a7b870a65dc4938
Committed by
Alex Elder
1 parent
99428ad0f6
Exists in
master
and in
7 other branches
xfs: introduce new internal log vector structure
The current log IO vector structure is a flat array and not extensible. To make it possible to keep separate log IO vectors for individual log items, we need a method of chaining log IO vectors together. Introduce a new log vector type that can be used to wrap the existing log IO vectors on use that internally to the log. This means that the existing external interface (xfs_log_write) does not change and hence no changes to the transaction commit code are required. Signed-off-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Dave Chinner <dchinner@redhat.com> Reviewed-by: Dave Chinner <dchinner@redhat.com>
Showing 2 changed files with 90 additions and 59 deletions Side-by-side Diff
fs/xfs/xfs_log.c
... | ... | @@ -50,7 +50,7 @@ |
50 | 50 | (off) += (bytes);} |
51 | 51 | |
52 | 52 | /* Local miscellaneous function prototypes */ |
53 | -STATIC int xlog_commit_record(xfs_mount_t *mp, xlog_ticket_t *ticket, | |
53 | +STATIC int xlog_commit_record(struct log *log, struct xlog_ticket *ticket, | |
54 | 54 | xlog_in_core_t **, xfs_lsn_t *); |
55 | 55 | STATIC xlog_t * xlog_alloc_log(xfs_mount_t *mp, |
56 | 56 | xfs_buftarg_t *log_target, |
... | ... | @@ -59,11 +59,9 @@ |
59 | 59 | STATIC int xlog_space_left(xlog_t *log, int cycle, int bytes); |
60 | 60 | STATIC int xlog_sync(xlog_t *log, xlog_in_core_t *iclog); |
61 | 61 | STATIC void xlog_dealloc_log(xlog_t *log); |
62 | -STATIC int xlog_write(xfs_mount_t *mp, xfs_log_iovec_t region[], | |
63 | - int nentries, struct xlog_ticket *tic, | |
64 | - xfs_lsn_t *start_lsn, | |
65 | - xlog_in_core_t **commit_iclog, | |
66 | - uint flags); | |
62 | +STATIC int xlog_write(struct log *log, struct xfs_log_vec *log_vector, | |
63 | + struct xlog_ticket *tic, xfs_lsn_t *start_lsn, | |
64 | + xlog_in_core_t **commit_iclog, uint flags); | |
67 | 65 | |
68 | 66 | /* local state machine functions */ |
69 | 67 | STATIC void xlog_state_done_syncing(xlog_in_core_t *iclog, int); |
... | ... | @@ -258,7 +256,7 @@ |
258 | 256 | * If we get an error, just continue and give back the log ticket. |
259 | 257 | */ |
260 | 258 | (((ticket->t_flags & XLOG_TIC_INITED) == 0) && |
261 | - (xlog_commit_record(mp, ticket, iclog, &lsn)))) { | |
259 | + (xlog_commit_record(log, ticket, iclog, &lsn)))) { | |
262 | 260 | lsn = (xfs_lsn_t) -1; |
263 | 261 | if (ticket->t_flags & XLOG_TIC_PERM_RESERV) { |
264 | 262 | flags |= XFS_LOG_REL_PERM_RESERV; |
265 | 263 | |
... | ... | @@ -516,18 +514,10 @@ |
516 | 514 | #ifdef DEBUG |
517 | 515 | xlog_in_core_t *first_iclog; |
518 | 516 | #endif |
519 | - xfs_log_iovec_t reg[1]; | |
520 | 517 | xlog_ticket_t *tic = NULL; |
521 | 518 | xfs_lsn_t lsn; |
522 | 519 | int error; |
523 | 520 | |
524 | - /* the data section must be 32 bit size aligned */ | |
525 | - struct { | |
526 | - __uint16_t magic; | |
527 | - __uint16_t pad1; | |
528 | - __uint32_t pad2; /* may as well make it 64 bits */ | |
529 | - } magic = { XLOG_UNMOUNT_TYPE, 0, 0 }; | |
530 | - | |
531 | 521 | /* |
532 | 522 | * Don't write out unmount record on read-only mounts. |
533 | 523 | * Or, if we are doing a forced umount (typically because of IO errors). |
534 | 524 | |
535 | 525 | |
... | ... | @@ -549,16 +539,30 @@ |
549 | 539 | } while (iclog != first_iclog); |
550 | 540 | #endif |
551 | 541 | if (! (XLOG_FORCED_SHUTDOWN(log))) { |
552 | - reg[0].i_addr = (void*)&magic; | |
553 | - reg[0].i_len = sizeof(magic); | |
554 | - reg[0].i_type = XLOG_REG_TYPE_UNMOUNT; | |
555 | - | |
556 | 542 | error = xfs_log_reserve(mp, 600, 1, &tic, |
557 | 543 | XFS_LOG, 0, XLOG_UNMOUNT_REC_TYPE); |
558 | 544 | if (!error) { |
545 | + /* the data section must be 32 bit size aligned */ | |
546 | + struct { | |
547 | + __uint16_t magic; | |
548 | + __uint16_t pad1; | |
549 | + __uint32_t pad2; /* may as well make it 64 bits */ | |
550 | + } magic = { | |
551 | + .magic = XLOG_UNMOUNT_TYPE, | |
552 | + }; | |
553 | + struct xfs_log_iovec reg = { | |
554 | + .i_addr = (void *)&magic, | |
555 | + .i_len = sizeof(magic), | |
556 | + .i_type = XLOG_REG_TYPE_UNMOUNT, | |
557 | + }; | |
558 | + struct xfs_log_vec vec = { | |
559 | + .lv_niovecs = 1, | |
560 | + .lv_iovecp = ®, | |
561 | + }; | |
562 | + | |
559 | 563 | /* remove inited flag */ |
560 | - ((xlog_ticket_t *)tic)->t_flags = 0; | |
561 | - error = xlog_write(mp, reg, 1, tic, &lsn, | |
564 | + tic->t_flags = 0; | |
565 | + error = xlog_write(log, &vec, tic, &lsn, | |
562 | 566 | NULL, XLOG_UNMOUNT_TRANS); |
563 | 567 | /* |
564 | 568 | * At this point, we're umounting anyway, |
565 | 569 | |
... | ... | @@ -679,11 +683,15 @@ |
679 | 683 | { |
680 | 684 | struct log *log = mp->m_log; |
681 | 685 | int error; |
686 | + struct xfs_log_vec vec = { | |
687 | + .lv_niovecs = nentries, | |
688 | + .lv_iovecp = reg, | |
689 | + }; | |
682 | 690 | |
683 | 691 | if (XLOG_FORCED_SHUTDOWN(log)) |
684 | 692 | return XFS_ERROR(EIO); |
685 | 693 | |
686 | - error = xlog_write(mp, reg, nentries, tic, start_lsn, NULL, 0); | |
694 | + error = xlog_write(log, &vec, tic, start_lsn, NULL, 0); | |
687 | 695 | if (error) |
688 | 696 | xfs_force_shutdown(mp, SHUTDOWN_LOG_IO_ERROR); |
689 | 697 | return error; |
690 | 698 | |
691 | 699 | |
692 | 700 | |
693 | 701 | |
694 | 702 | |
695 | 703 | |
... | ... | @@ -1190,27 +1198,32 @@ |
1190 | 1198 | * ticket. Return the lsn of the commit record. |
1191 | 1199 | */ |
1192 | 1200 | STATIC int |
1193 | -xlog_commit_record(xfs_mount_t *mp, | |
1194 | - xlog_ticket_t *ticket, | |
1195 | - xlog_in_core_t **iclog, | |
1196 | - xfs_lsn_t *commitlsnp) | |
1201 | +xlog_commit_record( | |
1202 | + struct log *log, | |
1203 | + struct xlog_ticket *ticket, | |
1204 | + struct xlog_in_core **iclog, | |
1205 | + xfs_lsn_t *commitlsnp) | |
1197 | 1206 | { |
1198 | - int error; | |
1199 | - xfs_log_iovec_t reg[1]; | |
1207 | + struct xfs_mount *mp = log->l_mp; | |
1208 | + int error; | |
1209 | + struct xfs_log_iovec reg = { | |
1210 | + .i_addr = NULL, | |
1211 | + .i_len = 0, | |
1212 | + .i_type = XLOG_REG_TYPE_COMMIT, | |
1213 | + }; | |
1214 | + struct xfs_log_vec vec = { | |
1215 | + .lv_niovecs = 1, | |
1216 | + .lv_iovecp = ®, | |
1217 | + }; | |
1200 | 1218 | |
1201 | - reg[0].i_addr = NULL; | |
1202 | - reg[0].i_len = 0; | |
1203 | - reg[0].i_type = XLOG_REG_TYPE_COMMIT; | |
1204 | - | |
1205 | 1219 | ASSERT_ALWAYS(iclog); |
1206 | - if ((error = xlog_write(mp, reg, 1, ticket, commitlsnp, | |
1207 | - iclog, XLOG_COMMIT_TRANS))) { | |
1220 | + error = xlog_write(log, &vec, ticket, commitlsnp, iclog, | |
1221 | + XLOG_COMMIT_TRANS); | |
1222 | + if (error) | |
1208 | 1223 | xfs_force_shutdown(mp, SHUTDOWN_LOG_IO_ERROR); |
1209 | - } | |
1210 | 1224 | return error; |
1211 | -} /* xlog_commit_record */ | |
1225 | +} | |
1212 | 1226 | |
1213 | - | |
1214 | 1227 | /* |
1215 | 1228 | * Push on the buffer cache code if we ever use more than 75% of the on-disk |
1216 | 1229 | * log space. This code pushes on the lsn which would supposedly free up |
1217 | 1230 | |
... | ... | @@ -1636,9 +1649,9 @@ |
1636 | 1649 | static int |
1637 | 1650 | xlog_write_calc_vec_length( |
1638 | 1651 | struct xlog_ticket *ticket, |
1639 | - struct xfs_log_iovec reg[], | |
1640 | - int nentries) | |
1652 | + struct xfs_log_vec *log_vector) | |
1641 | 1653 | { |
1654 | + struct xfs_log_vec *lv; | |
1642 | 1655 | int headers = 0; |
1643 | 1656 | int len = 0; |
1644 | 1657 | int i; |
1645 | 1658 | |
... | ... | @@ -1647,12 +1660,15 @@ |
1647 | 1660 | if (ticket->t_flags & XLOG_TIC_INITED) |
1648 | 1661 | headers++; |
1649 | 1662 | |
1650 | - for (i = 0; i < nentries; i++) { | |
1651 | - /* each region gets >= 1 */ | |
1652 | - headers++; | |
1663 | + for (lv = log_vector; lv; lv = lv->lv_next) { | |
1664 | + headers += lv->lv_niovecs; | |
1653 | 1665 | |
1654 | - len += reg[i].i_len; | |
1655 | - xlog_tic_add_region(ticket, reg[i].i_len, reg[i].i_type); | |
1666 | + for (i = 0; i < lv->lv_niovecs; i++) { | |
1667 | + struct xfs_log_iovec *vecp = &lv->lv_iovecp[i]; | |
1668 | + | |
1669 | + len += vecp->i_len; | |
1670 | + xlog_tic_add_region(ticket, vecp->i_len, vecp->i_type); | |
1671 | + } | |
1656 | 1672 | } |
1657 | 1673 | |
1658 | 1674 | ticket->t_res_num_ophdrs += headers; |
1659 | 1675 | |
1660 | 1676 | |
... | ... | @@ -1858,16 +1874,16 @@ |
1858 | 1874 | */ |
1859 | 1875 | STATIC int |
1860 | 1876 | xlog_write( |
1861 | - struct xfs_mount *mp, | |
1862 | - struct xfs_log_iovec reg[], | |
1863 | - int nentries, | |
1877 | + struct log *log, | |
1878 | + struct xfs_log_vec *log_vector, | |
1864 | 1879 | struct xlog_ticket *ticket, |
1865 | 1880 | xfs_lsn_t *start_lsn, |
1866 | 1881 | struct xlog_in_core **commit_iclog, |
1867 | 1882 | uint flags) |
1868 | 1883 | { |
1869 | - struct log *log = mp->m_log; | |
1870 | 1884 | struct xlog_in_core *iclog = NULL; |
1885 | + struct xfs_log_iovec *vecp; | |
1886 | + struct xfs_log_vec *lv; | |
1871 | 1887 | int len; |
1872 | 1888 | int index; |
1873 | 1889 | int partial_copy = 0; |
1874 | 1890 | |
1875 | 1891 | |
1876 | 1892 | |
1877 | 1893 | |
... | ... | @@ -1879,25 +1895,28 @@ |
1879 | 1895 | |
1880 | 1896 | *start_lsn = 0; |
1881 | 1897 | |
1882 | - len = xlog_write_calc_vec_length(ticket, reg, nentries); | |
1898 | + len = xlog_write_calc_vec_length(ticket, log_vector); | |
1883 | 1899 | if (ticket->t_curr_res < len) { |
1884 | - xlog_print_tic_res(mp, ticket); | |
1900 | + xlog_print_tic_res(log->l_mp, ticket); | |
1885 | 1901 | #ifdef DEBUG |
1886 | 1902 | xlog_panic( |
1887 | 1903 | "xfs_log_write: reservation ran out. Need to up reservation"); |
1888 | 1904 | #else |
1889 | 1905 | /* Customer configurable panic */ |
1890 | - xfs_cmn_err(XFS_PTAG_LOGRES, CE_ALERT, mp, | |
1906 | + xfs_cmn_err(XFS_PTAG_LOGRES, CE_ALERT, log->l_mp, | |
1891 | 1907 | "xfs_log_write: reservation ran out. Need to up reservation"); |
1892 | 1908 | |
1893 | 1909 | /* If we did not panic, shutdown the filesystem */ |
1894 | - xfs_force_shutdown(mp, SHUTDOWN_CORRUPT_INCORE); | |
1910 | + xfs_force_shutdown(log->l_mp, SHUTDOWN_CORRUPT_INCORE); | |
1895 | 1911 | #endif |
1896 | 1912 | } |
1897 | 1913 | |
1898 | 1914 | ticket->t_curr_res -= len; |
1899 | 1915 | |
1900 | - for (index = 0; index < nentries; ) { | |
1916 | + index = 0; | |
1917 | + lv = log_vector; | |
1918 | + vecp = lv->lv_iovecp; | |
1919 | + while (lv && index < lv->lv_niovecs) { | |
1901 | 1920 | __psint_t ptr; |
1902 | 1921 | int log_offset; |
1903 | 1922 | |
1904 | 1923 | |
... | ... | @@ -1917,13 +1936,14 @@ |
1917 | 1936 | * This loop writes out as many regions as can fit in the amount |
1918 | 1937 | * of space which was allocated by xlog_state_get_iclog_space(). |
1919 | 1938 | */ |
1920 | - while (index < nentries) { | |
1939 | + while (lv && index < lv->lv_niovecs) { | |
1940 | + struct xfs_log_iovec *reg = &vecp[index]; | |
1921 | 1941 | struct xlog_op_header *ophdr; |
1922 | 1942 | int start_rec_copy; |
1923 | 1943 | int copy_len; |
1924 | 1944 | int copy_off; |
1925 | 1945 | |
1926 | - ASSERT(reg[index].i_len % sizeof(__int32_t) == 0); | |
1946 | + ASSERT(reg->i_len % sizeof(__int32_t) == 0); | |
1927 | 1947 | ASSERT((__psint_t)ptr % sizeof(__int32_t) == 0); |
1928 | 1948 | |
1929 | 1949 | start_rec_copy = xlog_write_start_rec(ptr, ticket); |
... | ... | @@ -1942,7 +1962,7 @@ |
1942 | 1962 | |
1943 | 1963 | len += xlog_write_setup_copy(ticket, ophdr, |
1944 | 1964 | iclog->ic_size-log_offset, |
1945 | - reg[index].i_len, | |
1965 | + reg->i_len, | |
1946 | 1966 | ©_off, ©_len, |
1947 | 1967 | &partial_copy, |
1948 | 1968 | &partial_copy_len); |
... | ... | @@ -1950,7 +1970,7 @@ |
1950 | 1970 | |
1951 | 1971 | /* copy region */ |
1952 | 1972 | ASSERT(copy_len >= 0); |
1953 | - memcpy((xfs_caddr_t)ptr, reg[index].i_addr + copy_off, | |
1973 | + memcpy((xfs_caddr_t)ptr, reg->i_addr + copy_off, | |
1954 | 1974 | copy_len); |
1955 | 1975 | xlog_write_adv_cnt(ptr, len, log_offset, copy_len); |
1956 | 1976 | |
1957 | 1977 | |
... | ... | @@ -1982,9 +2002,14 @@ |
1982 | 2002 | if (partial_copy) |
1983 | 2003 | break; |
1984 | 2004 | |
1985 | - index++; | |
2005 | + if (++index == lv->lv_niovecs) { | |
2006 | + lv = lv->lv_next; | |
2007 | + index = 0; | |
2008 | + if (lv) | |
2009 | + vecp = lv->lv_iovecp; | |
2010 | + } | |
1986 | 2011 | if (record_cnt == 0) { |
1987 | - if (index == nentries) | |
2012 | + if (!lv) | |
1988 | 2013 | return 0; |
1989 | 2014 | break; |
1990 | 2015 | } |
fs/xfs/xfs_log.h
... | ... | @@ -110,6 +110,12 @@ |
110 | 110 | uint i_type; /* type of region */ |
111 | 111 | } xfs_log_iovec_t; |
112 | 112 | |
113 | +struct xfs_log_vec { | |
114 | + struct xfs_log_vec *lv_next; /* next lv in build list */ | |
115 | + int lv_niovecs; /* number of iovecs in lv */ | |
116 | + struct xfs_log_iovec *lv_iovecp; /* iovec array */ | |
117 | +}; | |
118 | + | |
113 | 119 | /* |
114 | 120 | * Structure used to pass callback function and the function's argument |
115 | 121 | * to the log manager. |