diff options
author | Nick Piggin <npiggin@suse.de> | 2007-10-16 04:25:24 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-10-16 12:42:58 -0400 |
commit | b6af1bcd8720cb3062c8c4d4c8ba02bee10ff03f (patch) | |
tree | e6cb27498f649dd3addc48fb4d92ac20ae8de7cb | |
parent | f2b6a16eb8f5b4851b01625a21e0c71207c2ce77 (diff) |
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>
-rw-r--r-- | fs/ocfs2/aops.c | 14 | ||||
-rw-r--r-- | fs/ocfs2/aops.h | 8 | ||||
-rw-r--r-- | fs/ocfs2/file.c | 266 |
3 files changed, 22 insertions, 266 deletions
diff --git a/fs/ocfs2/aops.c b/fs/ocfs2/aops.c index 34d10452c56d..c69c1b300155 100644 --- a/fs/ocfs2/aops.c +++ b/fs/ocfs2/aops.c | |||
@@ -1724,9 +1724,9 @@ out: | |||
1724 | return ret; | 1724 | return ret; |
1725 | } | 1725 | } |
1726 | 1726 | ||
1727 | int ocfs2_write_begin(struct file *file, struct address_space *mapping, | 1727 | static int ocfs2_write_begin(struct file *file, struct address_space *mapping, |
1728 | loff_t pos, unsigned len, unsigned flags, | 1728 | loff_t pos, unsigned len, unsigned flags, |
1729 | struct page **pagep, void **fsdata) | 1729 | struct page **pagep, void **fsdata) |
1730 | { | 1730 | { |
1731 | int ret; | 1731 | int ret; |
1732 | struct buffer_head *di_bh = NULL; | 1732 | struct buffer_head *di_bh = NULL; |
@@ -1877,9 +1877,9 @@ out_write_size: | |||
1877 | return copied; | 1877 | return copied; |
1878 | } | 1878 | } |
1879 | 1879 | ||
1880 | int ocfs2_write_end(struct file *file, struct address_space *mapping, | 1880 | static int ocfs2_write_end(struct file *file, struct address_space *mapping, |
1881 | loff_t pos, unsigned len, unsigned copied, | 1881 | loff_t pos, unsigned len, unsigned copied, |
1882 | struct page *page, void *fsdata) | 1882 | struct page *page, void *fsdata) |
1883 | { | 1883 | { |
1884 | int ret; | 1884 | int ret; |
1885 | struct inode *inode = mapping->host; | 1885 | struct inode *inode = mapping->host; |
@@ -1896,6 +1896,8 @@ int ocfs2_write_end(struct file *file, struct address_space *mapping, | |||
1896 | const struct address_space_operations ocfs2_aops = { | 1896 | const struct address_space_operations ocfs2_aops = { |
1897 | .readpage = ocfs2_readpage, | 1897 | .readpage = ocfs2_readpage, |
1898 | .writepage = ocfs2_writepage, | 1898 | .writepage = ocfs2_writepage, |
1899 | .write_begin = ocfs2_write_begin, | ||
1900 | .write_end = ocfs2_write_end, | ||
1899 | .bmap = ocfs2_bmap, | 1901 | .bmap = ocfs2_bmap, |
1900 | .sync_page = block_sync_page, | 1902 | .sync_page = block_sync_page, |
1901 | .direct_IO = ocfs2_direct_IO, | 1903 | .direct_IO = ocfs2_direct_IO, |
diff --git a/fs/ocfs2/aops.h b/fs/ocfs2/aops.h index 113560877dbb..503e49232e11 100644 --- a/fs/ocfs2/aops.h +++ b/fs/ocfs2/aops.h | |||
@@ -44,14 +44,6 @@ int walk_page_buffers( handle_t *handle, | |||
44 | int (*fn)( handle_t *handle, | 44 | int (*fn)( handle_t *handle, |
45 | struct buffer_head *bh)); | 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 | int ocfs2_write_end_nolock(struct address_space *mapping, | 47 | int ocfs2_write_end_nolock(struct address_space *mapping, |
56 | loff_t pos, unsigned len, unsigned copied, | 48 | loff_t pos, unsigned len, unsigned copied, |
57 | struct page *page, void *fsdata); | 49 | struct page *page, void *fsdata); |
diff --git a/fs/ocfs2/file.c b/fs/ocfs2/file.c index a62b14eb4065..f92fe91ff260 100644 --- a/fs/ocfs2/file.c +++ b/fs/ocfs2/file.c | |||
@@ -1881,143 +1881,13 @@ out: | |||
1881 | return ret; | 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 | static ssize_t ocfs2_file_aio_write(struct kiocb *iocb, | 1884 | static ssize_t ocfs2_file_aio_write(struct kiocb *iocb, |
2015 | const struct iovec *iov, | 1885 | const struct iovec *iov, |
2016 | unsigned long nr_segs, | 1886 | unsigned long nr_segs, |
2017 | loff_t pos) | 1887 | loff_t pos) |
2018 | { | 1888 | { |
2019 | int ret, direct_io, appending, rw_level, have_alloc_sem = 0; | 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 | ssize_t written = 0; | 1891 | ssize_t written = 0; |
2022 | size_t ocount; /* original count */ | 1892 | size_t ocount; /* original count */ |
2023 | size_t count; /* after file limit checks */ | 1893 | size_t count; /* after file limit checks */ |
@@ -2033,12 +1903,6 @@ static ssize_t ocfs2_file_aio_write(struct kiocb *iocb, | |||
2033 | if (iocb->ki_left == 0) | 1903 | if (iocb->ki_left == 0) |
2034 | return 0; | 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 | vfs_check_frozen(inode->i_sb, SB_FREEZE_WRITE); | 1906 | vfs_check_frozen(inode->i_sb, SB_FREEZE_WRITE); |
2043 | 1907 | ||
2044 | appending = file->f_flags & O_APPEND ? 1 : 0; | 1908 | appending = file->f_flags & O_APPEND ? 1 : 0; |
@@ -2082,33 +1946,23 @@ relock: | |||
2082 | rw_level = -1; | 1946 | rw_level = -1; |
2083 | 1947 | ||
2084 | direct_io = 0; | 1948 | direct_io = 0; |
2085 | sync = 1; | ||
2086 | goto relock; | 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 | /* communicate with ocfs2_dio_end_io */ | 1952 | /* communicate with ocfs2_dio_end_io */ |
2109 | ocfs2_iocb_set_rw_locked(iocb, rw_level); | 1953 | ocfs2_iocb_set_rw_locked(iocb, rw_level); |
2110 | 1954 | ||
2111 | if (direct_io) { | 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 | written = generic_file_direct_write(iocb, iov, &nr_segs, *ppos, | 1966 | written = generic_file_direct_write(iocb, iov, &nr_segs, *ppos, |
2113 | ppos, count, ocount); | 1967 | ppos, count, ocount); |
2114 | if (written < 0) { | 1968 | if (written < 0) { |
@@ -2116,14 +1970,8 @@ relock: | |||
2116 | goto out_dio; | 1970 | goto out_dio; |
2117 | } | 1971 | } |
2118 | } else { | 1972 | } else { |
2119 | written = ocfs2_file_buffered_write(file, ppos, iov, nr_segs, | 1973 | written = generic_file_aio_write_nolock(iocb, iov, nr_segs, |
2120 | count, written); | 1974 | *ppos); |
2121 | if (written < 0) { | ||
2122 | ret = written; | ||
2123 | if (ret != -EFAULT || ret != -ENOSPC) | ||
2124 | mlog_errno(ret); | ||
2125 | goto out; | ||
2126 | } | ||
2127 | } | 1975 | } |
2128 | 1976 | ||
2129 | out_dio: | 1977 | out_dio: |
@@ -2153,97 +2001,12 @@ out_sems: | |||
2153 | if (have_alloc_sem) | 2001 | if (have_alloc_sem) |
2154 | up_read(&inode->i_alloc_sem); | 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 | mutex_unlock(&inode->i_mutex); | 2004 | mutex_unlock(&inode->i_mutex); |
2165 | 2005 | ||
2166 | mlog_exit(ret); | 2006 | mlog_exit(ret); |
2167 | return written ? written : ret; | 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 | static ssize_t ocfs2_file_splice_write(struct pipe_inode_info *pipe, | 2010 | static ssize_t ocfs2_file_splice_write(struct pipe_inode_info *pipe, |
2248 | struct file *out, | 2011 | struct file *out, |
2249 | loff_t *ppos, | 2012 | loff_t *ppos, |
@@ -2273,8 +2036,7 @@ static ssize_t ocfs2_file_splice_write(struct pipe_inode_info *pipe, | |||
2273 | goto out_unlock; | 2036 | goto out_unlock; |
2274 | } | 2037 | } |
2275 | 2038 | ||
2276 | /* ok, we're done with i_size and alloc work */ | 2039 | ret = generic_file_splice_write_nolock(pipe, out, ppos, len, flags); |
2277 | ret = __ocfs2_file_splice_write(pipe, out, ppos, len, flags); | ||
2278 | 2040 | ||
2279 | out_unlock: | 2041 | out_unlock: |
2280 | ocfs2_rw_unlock(inode, 1); | 2042 | ocfs2_rw_unlock(inode, 1); |