Commit 55b66332d0921146a914d5d75a7b870a65dc4938

Authored by Dave Chinner
Committed by Alex Elder
1 parent 99428ad0f6

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

... ... @@ -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 = &reg,
  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 = &reg,
  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 &copy_off, &copy_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 }
... ... @@ -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.