aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDave Chinner <dchinner@redhat.com>2010-03-22 20:43:17 -0400
committerAlex Elder <aelder@sgi.com>2010-05-19 10:58:10 -0400
commit55b66332d0921146a914d5d75a7b870a65dc4938 (patch)
tree254f130969b118cc777371691e892db20e96b5a6
parent99428ad0f665a5d5b245ab36cefb6b231d977e73 (diff)
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>
-rw-r--r--fs/xfs/xfs_log.c143
-rw-r--r--fs/xfs/xfs_log.h6
2 files changed, 90 insertions, 59 deletions
diff --git a/fs/xfs/xfs_log.c b/fs/xfs/xfs_log.c
index 8c856d24538c..2e6f3b82e4b7 100644
--- a/fs/xfs/xfs_log.c
+++ b/fs/xfs/xfs_log.c
@@ -50,7 +50,7 @@ kmem_zone_t *xfs_log_ticket_zone;
50 (off) += (bytes);} 50 (off) += (bytes);}
51 51
52/* Local miscellaneous function prototypes */ 52/* Local miscellaneous function prototypes */
53STATIC int xlog_commit_record(xfs_mount_t *mp, xlog_ticket_t *ticket, 53STATIC int xlog_commit_record(struct log *log, struct xlog_ticket *ticket,
54 xlog_in_core_t **, xfs_lsn_t *); 54 xlog_in_core_t **, xfs_lsn_t *);
55STATIC xlog_t * xlog_alloc_log(xfs_mount_t *mp, 55STATIC xlog_t * xlog_alloc_log(xfs_mount_t *mp,
56 xfs_buftarg_t *log_target, 56 xfs_buftarg_t *log_target,
@@ -59,11 +59,9 @@ STATIC xlog_t * xlog_alloc_log(xfs_mount_t *mp,
59STATIC int xlog_space_left(xlog_t *log, int cycle, int bytes); 59STATIC int xlog_space_left(xlog_t *log, int cycle, int bytes);
60STATIC int xlog_sync(xlog_t *log, xlog_in_core_t *iclog); 60STATIC int xlog_sync(xlog_t *log, xlog_in_core_t *iclog);
61STATIC void xlog_dealloc_log(xlog_t *log); 61STATIC void xlog_dealloc_log(xlog_t *log);
62STATIC int xlog_write(xfs_mount_t *mp, xfs_log_iovec_t region[], 62STATIC int xlog_write(struct log *log, struct xfs_log_vec *log_vector,
63 int nentries, struct xlog_ticket *tic, 63 struct xlog_ticket *tic, xfs_lsn_t *start_lsn,
64 xfs_lsn_t *start_lsn, 64 xlog_in_core_t **commit_iclog, uint flags);
65 xlog_in_core_t **commit_iclog,
66 uint flags);
67 65
68/* local state machine functions */ 66/* local state machine functions */
69STATIC void xlog_state_done_syncing(xlog_in_core_t *iclog, int); 67STATIC void xlog_state_done_syncing(xlog_in_core_t *iclog, int);
@@ -258,7 +256,7 @@ xfs_log_done(
258 * If we get an error, just continue and give back the log ticket. 256 * If we get an error, just continue and give back the log ticket.
259 */ 257 */
260 (((ticket->t_flags & XLOG_TIC_INITED) == 0) && 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 lsn = (xfs_lsn_t) -1; 260 lsn = (xfs_lsn_t) -1;
263 if (ticket->t_flags & XLOG_TIC_PERM_RESERV) { 261 if (ticket->t_flags & XLOG_TIC_PERM_RESERV) {
264 flags |= XFS_LOG_REL_PERM_RESERV; 262 flags |= XFS_LOG_REL_PERM_RESERV;
@@ -516,18 +514,10 @@ xfs_log_unmount_write(xfs_mount_t *mp)
516#ifdef DEBUG 514#ifdef DEBUG
517 xlog_in_core_t *first_iclog; 515 xlog_in_core_t *first_iclog;
518#endif 516#endif
519 xfs_log_iovec_t reg[1];
520 xlog_ticket_t *tic = NULL; 517 xlog_ticket_t *tic = NULL;
521 xfs_lsn_t lsn; 518 xfs_lsn_t lsn;
522 int error; 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 * Don't write out unmount record on read-only mounts. 522 * Don't write out unmount record on read-only mounts.
533 * Or, if we are doing a forced umount (typically because of IO errors). 523 * Or, if we are doing a forced umount (typically because of IO errors).
@@ -549,16 +539,30 @@ xfs_log_unmount_write(xfs_mount_t *mp)
549 } while (iclog != first_iclog); 539 } while (iclog != first_iclog);
550#endif 540#endif
551 if (! (XLOG_FORCED_SHUTDOWN(log))) { 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 error = xfs_log_reserve(mp, 600, 1, &tic, 542 error = xfs_log_reserve(mp, 600, 1, &tic,
557 XFS_LOG, 0, XLOG_UNMOUNT_REC_TYPE); 543 XFS_LOG, 0, XLOG_UNMOUNT_REC_TYPE);
558 if (!error) { 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 /* remove inited flag */ 563 /* remove inited flag */
560 ((xlog_ticket_t *)tic)->t_flags = 0; 564 tic->t_flags = 0;
561 error = xlog_write(mp, reg, 1, tic, &lsn, 565 error = xlog_write(log, &vec, tic, &lsn,
562 NULL, XLOG_UNMOUNT_TRANS); 566 NULL, XLOG_UNMOUNT_TRANS);
563 /* 567 /*
564 * At this point, we're umounting anyway, 568 * At this point, we're umounting anyway,
@@ -679,11 +683,15 @@ xfs_log_write(
679{ 683{
680 struct log *log = mp->m_log; 684 struct log *log = mp->m_log;
681 int error; 685 int error;
686 struct xfs_log_vec vec = {
687 .lv_niovecs = nentries,
688 .lv_iovecp = reg,
689 };
682 690
683 if (XLOG_FORCED_SHUTDOWN(log)) 691 if (XLOG_FORCED_SHUTDOWN(log))
684 return XFS_ERROR(EIO); 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 if (error) 695 if (error)
688 xfs_force_shutdown(mp, SHUTDOWN_LOG_IO_ERROR); 696 xfs_force_shutdown(mp, SHUTDOWN_LOG_IO_ERROR);
689 return error; 697 return error;
@@ -1190,26 +1198,31 @@ out:
1190 * ticket. Return the lsn of the commit record. 1198 * ticket. Return the lsn of the commit record.
1191 */ 1199 */
1192STATIC int 1200STATIC int
1193xlog_commit_record(xfs_mount_t *mp, 1201xlog_commit_record(
1194 xlog_ticket_t *ticket, 1202 struct log *log,
1195 xlog_in_core_t **iclog, 1203 struct xlog_ticket *ticket,
1196 xfs_lsn_t *commitlsnp) 1204 struct xlog_in_core **iclog,
1205 xfs_lsn_t *commitlsnp)
1197{ 1206{
1198 int error; 1207 struct xfs_mount *mp = log->l_mp;
1199 xfs_log_iovec_t reg[1]; 1208 int error;
1200 1209 struct xfs_log_iovec reg = {
1201 reg[0].i_addr = NULL; 1210 .i_addr = NULL,
1202 reg[0].i_len = 0; 1211 .i_len = 0,
1203 reg[0].i_type = XLOG_REG_TYPE_COMMIT; 1212 .i_type = XLOG_REG_TYPE_COMMIT,
1213 };
1214 struct xfs_log_vec vec = {
1215 .lv_niovecs = 1,
1216 .lv_iovecp = &reg,
1217 };
1204 1218
1205 ASSERT_ALWAYS(iclog); 1219 ASSERT_ALWAYS(iclog);
1206 if ((error = xlog_write(mp, reg, 1, ticket, commitlsnp, 1220 error = xlog_write(log, &vec, ticket, commitlsnp, iclog,
1207 iclog, XLOG_COMMIT_TRANS))) { 1221 XLOG_COMMIT_TRANS);
1222 if (error)
1208 xfs_force_shutdown(mp, SHUTDOWN_LOG_IO_ERROR); 1223 xfs_force_shutdown(mp, SHUTDOWN_LOG_IO_ERROR);
1209 }
1210 return error; 1224 return error;
1211} /* xlog_commit_record */ 1225}
1212
1213 1226
1214/* 1227/*
1215 * Push on the buffer cache code if we ever use more than 75% of the on-disk 1228 * Push on the buffer cache code if we ever use more than 75% of the on-disk
@@ -1636,9 +1649,9 @@ xlog_print_tic_res(xfs_mount_t *mp, xlog_ticket_t *ticket)
1636static int 1649static int
1637xlog_write_calc_vec_length( 1650xlog_write_calc_vec_length(
1638 struct xlog_ticket *ticket, 1651 struct xlog_ticket *ticket,
1639 struct xfs_log_iovec reg[], 1652 struct xfs_log_vec *log_vector)
1640 int nentries)
1641{ 1653{
1654 struct xfs_log_vec *lv;
1642 int headers = 0; 1655 int headers = 0;
1643 int len = 0; 1656 int len = 0;
1644 int i; 1657 int i;
@@ -1647,12 +1660,15 @@ xlog_write_calc_vec_length(
1647 if (ticket->t_flags & XLOG_TIC_INITED) 1660 if (ticket->t_flags & XLOG_TIC_INITED)
1648 headers++; 1661 headers++;
1649 1662
1650 for (i = 0; i < nentries; i++) { 1663 for (lv = log_vector; lv; lv = lv->lv_next) {
1651 /* each region gets >= 1 */ 1664 headers += lv->lv_niovecs;
1652 headers++; 1665
1666 for (i = 0; i < lv->lv_niovecs; i++) {
1667 struct xfs_log_iovec *vecp = &lv->lv_iovecp[i];
1653 1668
1654 len += reg[i].i_len; 1669 len += vecp->i_len;
1655 xlog_tic_add_region(ticket, reg[i].i_len, reg[i].i_type); 1670 xlog_tic_add_region(ticket, vecp->i_len, vecp->i_type);
1671 }
1656 } 1672 }
1657 1673
1658 ticket->t_res_num_ophdrs += headers; 1674 ticket->t_res_num_ophdrs += headers;
@@ -1858,16 +1874,16 @@ xlog_write_copy_finish(
1858 */ 1874 */
1859STATIC int 1875STATIC int
1860xlog_write( 1876xlog_write(
1861 struct xfs_mount *mp, 1877 struct log *log,
1862 struct xfs_log_iovec reg[], 1878 struct xfs_log_vec *log_vector,
1863 int nentries,
1864 struct xlog_ticket *ticket, 1879 struct xlog_ticket *ticket,
1865 xfs_lsn_t *start_lsn, 1880 xfs_lsn_t *start_lsn,
1866 struct xlog_in_core **commit_iclog, 1881 struct xlog_in_core **commit_iclog,
1867 uint flags) 1882 uint flags)
1868{ 1883{
1869 struct log *log = mp->m_log;
1870 struct xlog_in_core *iclog = NULL; 1884 struct xlog_in_core *iclog = NULL;
1885 struct xfs_log_iovec *vecp;
1886 struct xfs_log_vec *lv;
1871 int len; 1887 int len;
1872 int index; 1888 int index;
1873 int partial_copy = 0; 1889 int partial_copy = 0;
@@ -1879,25 +1895,28 @@ xlog_write(
1879 1895
1880 *start_lsn = 0; 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 if (ticket->t_curr_res < len) { 1899 if (ticket->t_curr_res < len) {
1884 xlog_print_tic_res(mp, ticket); 1900 xlog_print_tic_res(log->l_mp, ticket);
1885#ifdef DEBUG 1901#ifdef DEBUG
1886 xlog_panic( 1902 xlog_panic(
1887 "xfs_log_write: reservation ran out. Need to up reservation"); 1903 "xfs_log_write: reservation ran out. Need to up reservation");
1888#else 1904#else
1889 /* Customer configurable panic */ 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 "xfs_log_write: reservation ran out. Need to up reservation"); 1907 "xfs_log_write: reservation ran out. Need to up reservation");
1892 1908
1893 /* If we did not panic, shutdown the filesystem */ 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#endif 1911#endif
1896 } 1912 }
1897 1913
1898 ticket->t_curr_res -= len; 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 __psint_t ptr; 1920 __psint_t ptr;
1902 int log_offset; 1921 int log_offset;
1903 1922
@@ -1917,13 +1936,14 @@ xlog_write(
1917 * This loop writes out as many regions as can fit in the amount 1936 * This loop writes out as many regions as can fit in the amount
1918 * of space which was allocated by xlog_state_get_iclog_space(). 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 struct xlog_op_header *ophdr; 1941 struct xlog_op_header *ophdr;
1922 int start_rec_copy; 1942 int start_rec_copy;
1923 int copy_len; 1943 int copy_len;
1924 int copy_off; 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 ASSERT((__psint_t)ptr % sizeof(__int32_t) == 0); 1947 ASSERT((__psint_t)ptr % sizeof(__int32_t) == 0);
1928 1948
1929 start_rec_copy = xlog_write_start_rec(ptr, ticket); 1949 start_rec_copy = xlog_write_start_rec(ptr, ticket);
@@ -1942,7 +1962,7 @@ xlog_write(
1942 1962
1943 len += xlog_write_setup_copy(ticket, ophdr, 1963 len += xlog_write_setup_copy(ticket, ophdr,
1944 iclog->ic_size-log_offset, 1964 iclog->ic_size-log_offset,
1945 reg[index].i_len, 1965 reg->i_len,
1946 &copy_off, &copy_len, 1966 &copy_off, &copy_len,
1947 &partial_copy, 1967 &partial_copy,
1948 &partial_copy_len); 1968 &partial_copy_len);
@@ -1950,7 +1970,7 @@ xlog_write(
1950 1970
1951 /* copy region */ 1971 /* copy region */
1952 ASSERT(copy_len >= 0); 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 copy_len); 1974 copy_len);
1955 xlog_write_adv_cnt(ptr, len, log_offset, copy_len); 1975 xlog_write_adv_cnt(ptr, len, log_offset, copy_len);
1956 1976
@@ -1982,9 +2002,14 @@ xlog_write(
1982 if (partial_copy) 2002 if (partial_copy)
1983 break; 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 if (record_cnt == 0) { 2011 if (record_cnt == 0) {
1987 if (index == nentries) 2012 if (!lv)
1988 return 0; 2013 return 0;
1989 break; 2014 break;
1990 } 2015 }
diff --git a/fs/xfs/xfs_log.h b/fs/xfs/xfs_log.h
index f3a564d298d0..229d1f36ba9a 100644
--- a/fs/xfs/xfs_log.h
+++ b/fs/xfs/xfs_log.h
@@ -110,6 +110,12 @@ typedef struct xfs_log_iovec {
110 uint i_type; /* type of region */ 110 uint i_type; /* type of region */
111} xfs_log_iovec_t; 111} xfs_log_iovec_t;
112 112
113struct 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 * Structure used to pass callback function and the function's argument 120 * Structure used to pass callback function and the function's argument
115 * to the log manager. 121 * to the log manager.