diff options
-rw-r--r-- | fs/xfs/xfs_log.c | 226 |
1 files changed, 120 insertions, 106 deletions
diff --git a/fs/xfs/xfs_log.c b/fs/xfs/xfs_log.c index 4a0ec592564c..8c856d24538c 100644 --- a/fs/xfs/xfs_log.c +++ b/fs/xfs/xfs_log.c | |||
@@ -1866,127 +1866,141 @@ xlog_write( | |||
1866 | struct xlog_in_core **commit_iclog, | 1866 | struct xlog_in_core **commit_iclog, |
1867 | uint flags) | 1867 | uint flags) |
1868 | { | 1868 | { |
1869 | xlog_t *log = mp->m_log; | 1869 | struct log *log = mp->m_log; |
1870 | xlog_in_core_t *iclog = NULL; /* ptr to current in-core log */ | 1870 | struct xlog_in_core *iclog = NULL; |
1871 | xlog_op_header_t *logop_head; /* ptr to log operation header */ | 1871 | int len; |
1872 | __psint_t ptr; /* copy address into data region */ | 1872 | int index; |
1873 | int len; /* # xlog_write() bytes 2 still copy */ | 1873 | int partial_copy = 0; |
1874 | int index; /* region index currently copying */ | 1874 | int partial_copy_len = 0; |
1875 | int log_offset; /* offset (from 0) into data region */ | 1875 | int contwr = 0; |
1876 | int start_rec_copy; /* # bytes to copy for start record */ | 1876 | int record_cnt = 0; |
1877 | int partial_copy; /* did we split a region? */ | 1877 | int data_cnt = 0; |
1878 | int partial_copy_len;/* # bytes copied if split region */ | 1878 | int error; |
1879 | int copy_len; /* # bytes actually memcpy'ing */ | 1879 | |
1880 | int copy_off; /* # bytes from entry start */ | 1880 | *start_lsn = 0; |
1881 | int contwr; /* continued write of in-core log? */ | 1881 | |
1882 | int error; | 1882 | len = xlog_write_calc_vec_length(ticket, reg, nentries); |
1883 | int record_cnt = 0, data_cnt = 0; | 1883 | if (ticket->t_curr_res < len) { |
1884 | 1884 | xlog_print_tic_res(mp, ticket); | |
1885 | partial_copy_len = partial_copy = 0; | ||
1886 | contwr = *start_lsn = 0; | ||
1887 | |||
1888 | len = xlog_write_calc_vec_length(ticket, reg, nentries); | ||
1889 | if (ticket->t_curr_res < len) { | ||
1890 | xlog_print_tic_res(mp, ticket); | ||
1891 | #ifdef DEBUG | 1885 | #ifdef DEBUG |
1892 | xlog_panic( | 1886 | xlog_panic( |
1893 | "xfs_log_write: reservation ran out. Need to up reservation"); | 1887 | "xfs_log_write: reservation ran out. Need to up reservation"); |
1894 | #else | 1888 | #else |
1895 | /* Customer configurable panic */ | 1889 | /* Customer configurable panic */ |
1896 | xfs_cmn_err(XFS_PTAG_LOGRES, CE_ALERT, mp, | 1890 | xfs_cmn_err(XFS_PTAG_LOGRES, CE_ALERT, mp, |
1897 | "xfs_log_write: reservation ran out. Need to up reservation"); | 1891 | "xfs_log_write: reservation ran out. Need to up reservation"); |
1898 | /* If we did not panic, shutdown the filesystem */ | 1892 | |
1899 | xfs_force_shutdown(mp, SHUTDOWN_CORRUPT_INCORE); | 1893 | /* If we did not panic, shutdown the filesystem */ |
1894 | xfs_force_shutdown(mp, SHUTDOWN_CORRUPT_INCORE); | ||
1900 | #endif | 1895 | #endif |
1901 | } else | 1896 | } |
1897 | |||
1902 | ticket->t_curr_res -= len; | 1898 | ticket->t_curr_res -= len; |
1903 | 1899 | ||
1904 | for (index = 0; index < nentries; ) { | 1900 | for (index = 0; index < nentries; ) { |
1905 | if ((error = xlog_state_get_iclog_space(log, len, &iclog, ticket, | 1901 | __psint_t ptr; |
1906 | &contwr, &log_offset))) | 1902 | int log_offset; |
1907 | return error; | ||
1908 | 1903 | ||
1909 | ASSERT(log_offset <= iclog->ic_size - 1); | 1904 | error = xlog_state_get_iclog_space(log, len, &iclog, ticket, |
1910 | ptr = (__psint_t) ((char *)iclog->ic_datap+log_offset); | 1905 | &contwr, &log_offset); |
1906 | if (error) | ||
1907 | return error; | ||
1911 | 1908 | ||
1912 | /* start_lsn is the first lsn written to. That's all we need. */ | 1909 | ASSERT(log_offset <= iclog->ic_size - 1); |
1913 | if (! *start_lsn) | 1910 | ptr = (__psint_t)((char *)iclog->ic_datap + log_offset); |
1914 | *start_lsn = be64_to_cpu(iclog->ic_header.h_lsn); | ||
1915 | 1911 | ||
1916 | /* This loop writes out as many regions as can fit in the amount | 1912 | /* start_lsn is the first lsn written to. That's all we need. */ |
1917 | * of space which was allocated by xlog_state_get_iclog_space(). | 1913 | if (!*start_lsn) |
1918 | */ | 1914 | *start_lsn = be64_to_cpu(iclog->ic_header.h_lsn); |
1919 | while (index < nentries) { | ||
1920 | ASSERT(reg[index].i_len % sizeof(__int32_t) == 0); | ||
1921 | ASSERT((__psint_t)ptr % sizeof(__int32_t) == 0); | ||
1922 | |||
1923 | start_rec_copy = xlog_write_start_rec(ptr, ticket); | ||
1924 | if (start_rec_copy) { | ||
1925 | record_cnt++; | ||
1926 | xlog_write_adv_cnt(ptr, len, log_offset, start_rec_copy); | ||
1927 | } | ||
1928 | 1915 | ||
1929 | logop_head = xlog_write_setup_ophdr(log, ptr, ticket, flags); | 1916 | /* |
1930 | if (!logop_head) | 1917 | * This loop writes out as many regions as can fit in the amount |
1931 | return XFS_ERROR(EIO); | 1918 | * of space which was allocated by xlog_state_get_iclog_space(). |
1932 | xlog_write_adv_cnt(ptr, len, log_offset, sizeof(xlog_op_header_t)); | 1919 | */ |
1933 | 1920 | while (index < nentries) { | |
1934 | len += xlog_write_setup_copy(ticket, logop_head, | 1921 | struct xlog_op_header *ophdr; |
1935 | iclog->ic_size - log_offset, | 1922 | int start_rec_copy; |
1936 | reg[index].i_len, ©_off, | 1923 | int copy_len; |
1937 | ©_len, &partial_copy, | 1924 | int copy_off; |
1938 | &partial_copy_len); | 1925 | |
1939 | xlog_verify_dest_ptr(log, ptr); | 1926 | ASSERT(reg[index].i_len % sizeof(__int32_t) == 0); |
1940 | 1927 | ASSERT((__psint_t)ptr % sizeof(__int32_t) == 0); | |
1941 | /* copy region */ | 1928 | |
1942 | ASSERT(copy_len >= 0); | 1929 | start_rec_copy = xlog_write_start_rec(ptr, ticket); |
1943 | memcpy((xfs_caddr_t)ptr, reg[index].i_addr + copy_off, copy_len); | 1930 | if (start_rec_copy) { |
1944 | xlog_write_adv_cnt(ptr, len, log_offset, copy_len); | 1931 | record_cnt++; |
1945 | 1932 | xlog_write_adv_cnt(ptr, len, log_offset, | |
1946 | /* make copy_len total bytes copied, including headers */ | 1933 | start_rec_copy); |
1947 | copy_len += start_rec_copy + sizeof(xlog_op_header_t); | 1934 | } |
1948 | record_cnt++; | ||
1949 | data_cnt += contwr ? copy_len : 0; | ||
1950 | |||
1951 | error = xlog_write_copy_finish(log, iclog, flags, | ||
1952 | &record_cnt, &data_cnt, | ||
1953 | &partial_copy, &partial_copy_len, | ||
1954 | log_offset, commit_iclog); | ||
1955 | if (error) | ||
1956 | return error; | ||
1957 | 1935 | ||
1958 | /* | 1936 | ophdr = xlog_write_setup_ophdr(log, ptr, ticket, flags); |
1959 | * if we had a partial copy, we need to get more iclog | 1937 | if (!ophdr) |
1960 | * space but we don't want to increment the region | 1938 | return XFS_ERROR(EIO); |
1961 | * index because there is still more is this region to write. | ||
1962 | * | ||
1963 | * If we completed writing this region, and we flushed | ||
1964 | * the iclog (indicated by resetting of the record | ||
1965 | * count), then we also need to get more log space. If | ||
1966 | * this was the last record, though, we are done and | ||
1967 | * can just return. | ||
1968 | */ | ||
1969 | if (partial_copy) | ||
1970 | break; | ||
1971 | 1939 | ||
1972 | index++; | 1940 | xlog_write_adv_cnt(ptr, len, log_offset, |
1973 | if (record_cnt == 0) { | 1941 | sizeof(struct xlog_op_header)); |
1974 | if (index == nentries) | 1942 | |
1975 | return 0; | 1943 | len += xlog_write_setup_copy(ticket, ophdr, |
1976 | break; | 1944 | iclog->ic_size-log_offset, |
1977 | } | 1945 | reg[index].i_len, |
1978 | } /* while (index < nentries) */ | 1946 | ©_off, ©_len, |
1979 | } /* for (index = 0; index < nentries; ) */ | 1947 | &partial_copy, |
1980 | ASSERT(len == 0); | 1948 | &partial_copy_len); |
1949 | xlog_verify_dest_ptr(log, ptr); | ||
1950 | |||
1951 | /* copy region */ | ||
1952 | ASSERT(copy_len >= 0); | ||
1953 | memcpy((xfs_caddr_t)ptr, reg[index].i_addr + copy_off, | ||
1954 | copy_len); | ||
1955 | xlog_write_adv_cnt(ptr, len, log_offset, copy_len); | ||
1956 | |||
1957 | copy_len += start_rec_copy + sizeof(xlog_op_header_t); | ||
1958 | record_cnt++; | ||
1959 | data_cnt += contwr ? copy_len : 0; | ||
1960 | |||
1961 | error = xlog_write_copy_finish(log, iclog, flags, | ||
1962 | &record_cnt, &data_cnt, | ||
1963 | &partial_copy, | ||
1964 | &partial_copy_len, | ||
1965 | log_offset, | ||
1966 | commit_iclog); | ||
1967 | if (error) | ||
1968 | return error; | ||
1969 | |||
1970 | /* | ||
1971 | * if we had a partial copy, we need to get more iclog | ||
1972 | * space but we don't want to increment the region | ||
1973 | * index because there is still more is this region to | ||
1974 | * write. | ||
1975 | * | ||
1976 | * If we completed writing this region, and we flushed | ||
1977 | * the iclog (indicated by resetting of the record | ||
1978 | * count), then we also need to get more log space. If | ||
1979 | * this was the last record, though, we are done and | ||
1980 | * can just return. | ||
1981 | */ | ||
1982 | if (partial_copy) | ||
1983 | break; | ||
1984 | |||
1985 | index++; | ||
1986 | if (record_cnt == 0) { | ||
1987 | if (index == nentries) | ||
1988 | return 0; | ||
1989 | break; | ||
1990 | } | ||
1991 | } | ||
1992 | } | ||
1993 | |||
1994 | ASSERT(len == 0); | ||
1995 | |||
1996 | xlog_state_finish_copy(log, iclog, record_cnt, data_cnt); | ||
1997 | if (!commit_iclog) | ||
1998 | return xlog_state_release_iclog(log, iclog); | ||
1981 | 1999 | ||
1982 | xlog_state_finish_copy(log, iclog, record_cnt, data_cnt); | ||
1983 | if (commit_iclog) { | ||
1984 | ASSERT(flags & XLOG_COMMIT_TRANS); | 2000 | ASSERT(flags & XLOG_COMMIT_TRANS); |
1985 | *commit_iclog = iclog; | 2001 | *commit_iclog = iclog; |
1986 | return 0; | 2002 | return 0; |
1987 | } | 2003 | } |
1988 | return xlog_state_release_iclog(log, iclog); | ||
1989 | } /* xlog_write */ | ||
1990 | 2004 | ||
1991 | 2005 | ||
1992 | /***************************************************************************** | 2006 | /***************************************************************************** |