Commit b6af1bcd8720cb3062c8c4d4c8ba02bee10ff03f
Committed by
Linus Torvalds
1 parent
f2b6a16eb8
ocfs2: convert to new aops
Plug ocfs2 into the ->write_begin and ->write_end aops. A bunch of custom code is now gone - the iovec iteration stuff during write and the ocfs2 splice write actor. Signed-off-by: Mark Fasheh <mark.fasheh@oracle.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Showing 3 changed files with 22 additions and 266 deletions Side-by-side Diff
fs/ocfs2/aops.c
... | ... | @@ -1724,9 +1724,9 @@ |
1724 | 1724 | return ret; |
1725 | 1725 | } |
1726 | 1726 | |
1727 | -int ocfs2_write_begin(struct file *file, struct address_space *mapping, | |
1728 | - loff_t pos, unsigned len, unsigned flags, | |
1729 | - struct page **pagep, void **fsdata) | |
1727 | +static int ocfs2_write_begin(struct file *file, struct address_space *mapping, | |
1728 | + loff_t pos, unsigned len, unsigned flags, | |
1729 | + struct page **pagep, void **fsdata) | |
1730 | 1730 | { |
1731 | 1731 | int ret; |
1732 | 1732 | struct buffer_head *di_bh = NULL; |
... | ... | @@ -1877,9 +1877,9 @@ |
1877 | 1877 | return copied; |
1878 | 1878 | } |
1879 | 1879 | |
1880 | -int ocfs2_write_end(struct file *file, struct address_space *mapping, | |
1881 | - loff_t pos, unsigned len, unsigned copied, | |
1882 | - struct page *page, void *fsdata) | |
1880 | +static int ocfs2_write_end(struct file *file, struct address_space *mapping, | |
1881 | + loff_t pos, unsigned len, unsigned copied, | |
1882 | + struct page *page, void *fsdata) | |
1883 | 1883 | { |
1884 | 1884 | int ret; |
1885 | 1885 | struct inode *inode = mapping->host; |
... | ... | @@ -1896,6 +1896,8 @@ |
1896 | 1896 | const struct address_space_operations ocfs2_aops = { |
1897 | 1897 | .readpage = ocfs2_readpage, |
1898 | 1898 | .writepage = ocfs2_writepage, |
1899 | + .write_begin = ocfs2_write_begin, | |
1900 | + .write_end = ocfs2_write_end, | |
1899 | 1901 | .bmap = ocfs2_bmap, |
1900 | 1902 | .sync_page = block_sync_page, |
1901 | 1903 | .direct_IO = ocfs2_direct_IO, |
fs/ocfs2/aops.h
... | ... | @@ -44,14 +44,6 @@ |
44 | 44 | int (*fn)( handle_t *handle, |
45 | 45 | struct buffer_head *bh)); |
46 | 46 | |
47 | -int ocfs2_write_begin(struct file *file, struct address_space *mapping, | |
48 | - loff_t pos, unsigned len, unsigned flags, | |
49 | - struct page **pagep, void **fsdata); | |
50 | - | |
51 | -int ocfs2_write_end(struct file *file, struct address_space *mapping, | |
52 | - loff_t pos, unsigned len, unsigned copied, | |
53 | - struct page *page, void *fsdata); | |
54 | - | |
55 | 47 | int ocfs2_write_end_nolock(struct address_space *mapping, |
56 | 48 | loff_t pos, unsigned len, unsigned copied, |
57 | 49 | struct page *page, void *fsdata); |
fs/ocfs2/file.c
... | ... | @@ -1881,143 +1881,13 @@ |
1881 | 1881 | return ret; |
1882 | 1882 | } |
1883 | 1883 | |
1884 | -static inline void | |
1885 | -ocfs2_set_next_iovec(const struct iovec **iovp, size_t *basep, size_t bytes) | |
1886 | -{ | |
1887 | - const struct iovec *iov = *iovp; | |
1888 | - size_t base = *basep; | |
1889 | - | |
1890 | - do { | |
1891 | - int copy = min(bytes, iov->iov_len - base); | |
1892 | - | |
1893 | - bytes -= copy; | |
1894 | - base += copy; | |
1895 | - if (iov->iov_len == base) { | |
1896 | - iov++; | |
1897 | - base = 0; | |
1898 | - } | |
1899 | - } while (bytes); | |
1900 | - *iovp = iov; | |
1901 | - *basep = base; | |
1902 | -} | |
1903 | - | |
1904 | -static struct page * ocfs2_get_write_source(char **ret_src_buf, | |
1905 | - const struct iovec *cur_iov, | |
1906 | - size_t iov_offset) | |
1907 | -{ | |
1908 | - int ret; | |
1909 | - char *buf = cur_iov->iov_base + iov_offset; | |
1910 | - struct page *src_page = NULL; | |
1911 | - unsigned long off; | |
1912 | - | |
1913 | - off = (unsigned long)(buf) & ~PAGE_CACHE_MASK; | |
1914 | - | |
1915 | - if (!segment_eq(get_fs(), KERNEL_DS)) { | |
1916 | - /* | |
1917 | - * Pull in the user page. We want to do this outside | |
1918 | - * of the meta data locks in order to preserve locking | |
1919 | - * order in case of page fault. | |
1920 | - */ | |
1921 | - ret = get_user_pages(current, current->mm, | |
1922 | - (unsigned long)buf & PAGE_CACHE_MASK, 1, | |
1923 | - 0, 0, &src_page, NULL); | |
1924 | - if (ret == 1) | |
1925 | - *ret_src_buf = kmap(src_page) + off; | |
1926 | - else | |
1927 | - src_page = ERR_PTR(-EFAULT); | |
1928 | - } else { | |
1929 | - *ret_src_buf = buf; | |
1930 | - } | |
1931 | - | |
1932 | - return src_page; | |
1933 | -} | |
1934 | - | |
1935 | -static void ocfs2_put_write_source(struct page *page) | |
1936 | -{ | |
1937 | - if (page) { | |
1938 | - kunmap(page); | |
1939 | - page_cache_release(page); | |
1940 | - } | |
1941 | -} | |
1942 | - | |
1943 | -static ssize_t ocfs2_file_buffered_write(struct file *file, loff_t *ppos, | |
1944 | - const struct iovec *iov, | |
1945 | - unsigned long nr_segs, | |
1946 | - size_t count, | |
1947 | - ssize_t o_direct_written) | |
1948 | -{ | |
1949 | - int ret = 0; | |
1950 | - ssize_t copied, total = 0; | |
1951 | - size_t iov_offset = 0, bytes; | |
1952 | - loff_t pos; | |
1953 | - const struct iovec *cur_iov = iov; | |
1954 | - struct page *user_page, *page; | |
1955 | - char * uninitialized_var(buf); | |
1956 | - char *dst; | |
1957 | - void *fsdata; | |
1958 | - | |
1959 | - /* | |
1960 | - * handle partial DIO write. Adjust cur_iov if needed. | |
1961 | - */ | |
1962 | - ocfs2_set_next_iovec(&cur_iov, &iov_offset, o_direct_written); | |
1963 | - | |
1964 | - do { | |
1965 | - pos = *ppos; | |
1966 | - | |
1967 | - user_page = ocfs2_get_write_source(&buf, cur_iov, iov_offset); | |
1968 | - if (IS_ERR(user_page)) { | |
1969 | - ret = PTR_ERR(user_page); | |
1970 | - goto out; | |
1971 | - } | |
1972 | - | |
1973 | - /* Stay within our page boundaries */ | |
1974 | - bytes = min((PAGE_CACHE_SIZE - ((unsigned long)pos & ~PAGE_CACHE_MASK)), | |
1975 | - (PAGE_CACHE_SIZE - ((unsigned long)buf & ~PAGE_CACHE_MASK))); | |
1976 | - /* Stay within the vector boundary */ | |
1977 | - bytes = min_t(size_t, bytes, cur_iov->iov_len - iov_offset); | |
1978 | - /* Stay within count */ | |
1979 | - bytes = min(bytes, count); | |
1980 | - | |
1981 | - page = NULL; | |
1982 | - ret = ocfs2_write_begin(file, file->f_mapping, pos, bytes, 0, | |
1983 | - &page, &fsdata); | |
1984 | - if (ret) { | |
1985 | - mlog_errno(ret); | |
1986 | - goto out; | |
1987 | - } | |
1988 | - | |
1989 | - dst = kmap_atomic(page, KM_USER0); | |
1990 | - memcpy(dst + (pos & (loff_t)(PAGE_CACHE_SIZE - 1)), buf, bytes); | |
1991 | - kunmap_atomic(dst, KM_USER0); | |
1992 | - flush_dcache_page(page); | |
1993 | - ocfs2_put_write_source(user_page); | |
1994 | - | |
1995 | - copied = ocfs2_write_end(file, file->f_mapping, pos, bytes, | |
1996 | - bytes, page, fsdata); | |
1997 | - if (copied < 0) { | |
1998 | - mlog_errno(copied); | |
1999 | - ret = copied; | |
2000 | - goto out; | |
2001 | - } | |
2002 | - | |
2003 | - total += copied; | |
2004 | - *ppos = pos + copied; | |
2005 | - count -= copied; | |
2006 | - | |
2007 | - ocfs2_set_next_iovec(&cur_iov, &iov_offset, copied); | |
2008 | - } while(count); | |
2009 | - | |
2010 | -out: | |
2011 | - return total ? total : ret; | |
2012 | -} | |
2013 | - | |
2014 | 1884 | static ssize_t ocfs2_file_aio_write(struct kiocb *iocb, |
2015 | 1885 | const struct iovec *iov, |
2016 | 1886 | unsigned long nr_segs, |
2017 | 1887 | loff_t pos) |
2018 | 1888 | { |
2019 | 1889 | int ret, direct_io, appending, rw_level, have_alloc_sem = 0; |
2020 | - int can_do_direct, sync = 0; | |
1890 | + int can_do_direct; | |
2021 | 1891 | ssize_t written = 0; |
2022 | 1892 | size_t ocount; /* original count */ |
2023 | 1893 | size_t count; /* after file limit checks */ |
... | ... | @@ -2033,12 +1903,6 @@ |
2033 | 1903 | if (iocb->ki_left == 0) |
2034 | 1904 | return 0; |
2035 | 1905 | |
2036 | - ret = generic_segment_checks(iov, &nr_segs, &ocount, VERIFY_READ); | |
2037 | - if (ret) | |
2038 | - return ret; | |
2039 | - | |
2040 | - count = ocount; | |
2041 | - | |
2042 | 1906 | vfs_check_frozen(inode->i_sb, SB_FREEZE_WRITE); |
2043 | 1907 | |
2044 | 1908 | appending = file->f_flags & O_APPEND ? 1 : 0; |
2045 | 1909 | |
2046 | 1910 | |
... | ... | @@ -2082,33 +1946,23 @@ |
2082 | 1946 | rw_level = -1; |
2083 | 1947 | |
2084 | 1948 | direct_io = 0; |
2085 | - sync = 1; | |
2086 | 1949 | goto relock; |
2087 | 1950 | } |
2088 | 1951 | |
2089 | - if (!sync && ((file->f_flags & O_SYNC) || IS_SYNC(inode))) | |
2090 | - sync = 1; | |
2091 | - | |
2092 | - /* | |
2093 | - * XXX: Is it ok to execute these checks a second time? | |
2094 | - */ | |
2095 | - ret = generic_write_checks(file, ppos, &count, S_ISBLK(inode->i_mode)); | |
2096 | - if (ret) | |
2097 | - goto out; | |
2098 | - | |
2099 | - /* | |
2100 | - * Set pos so that sync_page_range_nolock() below understands | |
2101 | - * where to start from. We might've moved it around via the | |
2102 | - * calls above. The range we want to actually sync starts from | |
2103 | - * *ppos here. | |
2104 | - * | |
2105 | - */ | |
2106 | - pos = *ppos; | |
2107 | - | |
2108 | 1952 | /* communicate with ocfs2_dio_end_io */ |
2109 | 1953 | ocfs2_iocb_set_rw_locked(iocb, rw_level); |
2110 | 1954 | |
2111 | 1955 | if (direct_io) { |
1956 | + ret = generic_segment_checks(iov, &nr_segs, &ocount, | |
1957 | + VERIFY_READ); | |
1958 | + if (ret) | |
1959 | + goto out_dio; | |
1960 | + | |
1961 | + ret = generic_write_checks(file, ppos, &count, | |
1962 | + S_ISBLK(inode->i_mode)); | |
1963 | + if (ret) | |
1964 | + goto out_dio; | |
1965 | + | |
2112 | 1966 | written = generic_file_direct_write(iocb, iov, &nr_segs, *ppos, |
2113 | 1967 | ppos, count, ocount); |
2114 | 1968 | if (written < 0) { |
... | ... | @@ -2116,14 +1970,8 @@ |
2116 | 1970 | goto out_dio; |
2117 | 1971 | } |
2118 | 1972 | } else { |
2119 | - written = ocfs2_file_buffered_write(file, ppos, iov, nr_segs, | |
2120 | - count, written); | |
2121 | - if (written < 0) { | |
2122 | - ret = written; | |
2123 | - if (ret != -EFAULT || ret != -ENOSPC) | |
2124 | - mlog_errno(ret); | |
2125 | - goto out; | |
2126 | - } | |
1973 | + written = generic_file_aio_write_nolock(iocb, iov, nr_segs, | |
1974 | + *ppos); | |
2127 | 1975 | } |
2128 | 1976 | |
2129 | 1977 | out_dio: |
2130 | 1978 | |
... | ... | @@ -2153,97 +2001,12 @@ |
2153 | 2001 | if (have_alloc_sem) |
2154 | 2002 | up_read(&inode->i_alloc_sem); |
2155 | 2003 | |
2156 | - if (written > 0 && sync) { | |
2157 | - ssize_t err; | |
2158 | - | |
2159 | - err = sync_page_range_nolock(inode, file->f_mapping, pos, count); | |
2160 | - if (err < 0) | |
2161 | - written = err; | |
2162 | - } | |
2163 | - | |
2164 | 2004 | mutex_unlock(&inode->i_mutex); |
2165 | 2005 | |
2166 | 2006 | mlog_exit(ret); |
2167 | 2007 | return written ? written : ret; |
2168 | 2008 | } |
2169 | 2009 | |
2170 | -static int ocfs2_splice_write_actor(struct pipe_inode_info *pipe, | |
2171 | - struct pipe_buffer *buf, | |
2172 | - struct splice_desc *sd) | |
2173 | -{ | |
2174 | - int ret, count; | |
2175 | - ssize_t copied = 0; | |
2176 | - struct file *file = sd->u.file; | |
2177 | - unsigned int offset; | |
2178 | - struct page *page = NULL; | |
2179 | - void *fsdata; | |
2180 | - char *src, *dst; | |
2181 | - | |
2182 | - ret = buf->ops->confirm(pipe, buf); | |
2183 | - if (ret) | |
2184 | - goto out; | |
2185 | - | |
2186 | - offset = sd->pos & ~PAGE_CACHE_MASK; | |
2187 | - count = sd->len; | |
2188 | - if (count + offset > PAGE_CACHE_SIZE) | |
2189 | - count = PAGE_CACHE_SIZE - offset; | |
2190 | - | |
2191 | - ret = ocfs2_write_begin(file, file->f_mapping, sd->pos, count, 0, | |
2192 | - &page, &fsdata); | |
2193 | - if (ret) { | |
2194 | - mlog_errno(ret); | |
2195 | - goto out; | |
2196 | - } | |
2197 | - | |
2198 | - src = buf->ops->map(pipe, buf, 1); | |
2199 | - dst = kmap_atomic(page, KM_USER1); | |
2200 | - memcpy(dst + offset, src + buf->offset, count); | |
2201 | - kunmap_atomic(dst, KM_USER1); | |
2202 | - buf->ops->unmap(pipe, buf, src); | |
2203 | - | |
2204 | - copied = ocfs2_write_end(file, file->f_mapping, sd->pos, count, count, | |
2205 | - page, fsdata); | |
2206 | - if (copied < 0) { | |
2207 | - mlog_errno(copied); | |
2208 | - ret = copied; | |
2209 | - goto out; | |
2210 | - } | |
2211 | -out: | |
2212 | - | |
2213 | - return copied ? copied : ret; | |
2214 | -} | |
2215 | - | |
2216 | -static ssize_t __ocfs2_file_splice_write(struct pipe_inode_info *pipe, | |
2217 | - struct file *out, | |
2218 | - loff_t *ppos, | |
2219 | - size_t len, | |
2220 | - unsigned int flags) | |
2221 | -{ | |
2222 | - int ret, err; | |
2223 | - struct address_space *mapping = out->f_mapping; | |
2224 | - struct inode *inode = mapping->host; | |
2225 | - struct splice_desc sd = { | |
2226 | - .total_len = len, | |
2227 | - .flags = flags, | |
2228 | - .pos = *ppos, | |
2229 | - .u.file = out, | |
2230 | - }; | |
2231 | - | |
2232 | - ret = __splice_from_pipe(pipe, &sd, ocfs2_splice_write_actor); | |
2233 | - if (ret > 0) { | |
2234 | - *ppos += ret; | |
2235 | - | |
2236 | - if (unlikely((out->f_flags & O_SYNC) || IS_SYNC(inode))) { | |
2237 | - err = generic_osync_inode(inode, mapping, | |
2238 | - OSYNC_METADATA|OSYNC_DATA); | |
2239 | - if (err) | |
2240 | - ret = err; | |
2241 | - } | |
2242 | - } | |
2243 | - | |
2244 | - return ret; | |
2245 | -} | |
2246 | - | |
2247 | 2010 | static ssize_t ocfs2_file_splice_write(struct pipe_inode_info *pipe, |
2248 | 2011 | struct file *out, |
2249 | 2012 | loff_t *ppos, |
... | ... | @@ -2273,8 +2036,7 @@ |
2273 | 2036 | goto out_unlock; |
2274 | 2037 | } |
2275 | 2038 | |
2276 | - /* ok, we're done with i_size and alloc work */ | |
2277 | - ret = __ocfs2_file_splice_write(pipe, out, ppos, len, flags); | |
2039 | + ret = generic_file_splice_write_nolock(pipe, out, ppos, len, flags); | |
2278 | 2040 | |
2279 | 2041 | out_unlock: |
2280 | 2042 | ocfs2_rw_unlock(inode, 1); |