Linux 2.6.35 compat, fops->fsync()
[zfs.git] / module / zfs / zpl_file.c
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 /*
22  * Copyright (c) 2011, Lawrence Livermore National Security, LLC.
23  */
24
25
26 #include <sys/zfs_vfsops.h>
27 #include <sys/zfs_vnops.h>
28 #include <sys/zfs_znode.h>
29 #include <sys/zpl.h>
30
31
32 static int
33 zpl_readdir(struct file *filp, void *dirent, filldir_t filldir)
34 {
35         struct dentry *dentry = filp->f_path.dentry;
36         cred_t *cr;
37         int error;
38
39         cr = (cred_t *)get_current_cred();
40         error = -zfs_readdir(dentry->d_inode, dirent, filldir,
41             &filp->f_pos, cr);
42         put_cred(cr);
43         ASSERT3S(error, <=, 0);
44
45         return (error);
46 }
47
48 ZPL_FSYNC_PROTO(zpl_fsync, filp, unused_dentry, datasync)
49 {
50         cred_t *cr;
51         int error;
52
53         cr = (cred_t *)get_current_cred();
54         error = -zfs_fsync(filp->f_path.dentry->d_inode, datasync, cr);
55         put_cred(cr);
56         ASSERT3S(error, <=, 0);
57
58         return (error);
59 }
60
61 ssize_t
62 zpl_read_common(struct inode *ip, const char *buf, size_t len, loff_t pos,
63      uio_seg_t segment, int flags, cred_t *cr)
64 {
65         int error;
66         struct iovec iov;
67         uio_t uio;
68
69         iov.iov_base = (void *)buf;
70         iov.iov_len = len;
71
72         uio.uio_iov = &iov;
73         uio.uio_resid = len;
74         uio.uio_iovcnt = 1;
75         uio.uio_loffset = pos;
76         uio.uio_limit = MAXOFFSET_T;
77         uio.uio_segflg = segment;
78
79         error = -zfs_read(ip, &uio, flags, cr);
80         if (error < 0)
81                 return (error);
82
83         return (len - uio.uio_resid);
84 }
85
86 static ssize_t
87 zpl_read(struct file *filp, char __user *buf, size_t len, loff_t *ppos)
88 {
89         cred_t *cr;
90         ssize_t read;
91
92         cr = (cred_t *)get_current_cred();
93         read = zpl_read_common(filp->f_mapping->host, buf, len, *ppos,
94             UIO_USERSPACE, filp->f_flags, cr);
95         put_cred(cr);
96
97         if (read < 0)
98                 return (read);
99
100         *ppos += read;
101         return (read);
102 }
103
104 ssize_t
105 zpl_write_common(struct inode *ip, const char *buf, size_t len, loff_t pos,
106     uio_seg_t segment, int flags, cred_t *cr)
107 {
108         int error;
109         struct iovec iov;
110         uio_t uio;
111
112         iov.iov_base = (void *)buf;
113         iov.iov_len = len;
114
115         uio.uio_iov = &iov;
116         uio.uio_resid = len,
117         uio.uio_iovcnt = 1;
118         uio.uio_loffset = pos;
119         uio.uio_limit = MAXOFFSET_T;
120         uio.uio_segflg = segment;
121
122         error = -zfs_write(ip, &uio, flags, cr);
123         if (error < 0)
124                 return (error);
125
126         return (len - uio.uio_resid);
127 }
128
129 static ssize_t
130 zpl_write(struct file *filp, const char __user *buf, size_t len, loff_t *ppos)
131 {
132         cred_t *cr;
133         ssize_t wrote;
134
135         cr = (cred_t *)get_current_cred();
136         wrote = zpl_write_common(filp->f_mapping->host, buf, len, *ppos,
137             UIO_USERSPACE, filp->f_flags, cr);
138         put_cred(cr);
139
140         if (wrote < 0)
141                 return (wrote);
142
143         *ppos += wrote;
144         return (wrote);
145 }
146
147 /*
148  * It's worth taking a moment to describe how mmap is implemented
149  * for zfs because it differs considerably from other Linux filesystems.
150  * However, this issue is handled the same way under OpenSolaris.
151  *
152  * The issue is that by design zfs bypasses the Linux page cache and
153  * leaves all caching up to the ARC.  This has been shown to work
154  * well for the common read(2)/write(2) case.  However, mmap(2)
155  * is problem because it relies on being tightly integrated with the
156  * page cache.  To handle this we cache mmap'ed files twice, once in
157  * the ARC and a second time in the page cache.  The code is careful
158  * to keep both copies synchronized.
159  *
160  * When a file with an mmap'ed region is written to using write(2)
161  * both the data in the ARC and existing pages in the page cache
162  * are updated.  For a read(2) data will be read first from the page
163  * cache then the ARC if needed.  Neither a write(2) or read(2) will
164  * will ever result in new pages being added to the page cache.
165  *
166  * New pages are added to the page cache only via .readpage() which
167  * is called when the vfs needs to read a page off disk to back the
168  * virtual memory region.  These pages may be modified without
169  * notifying the ARC and will be written out periodically via
170  * .writepage().  This will occur due to either a sync or the usual
171  * page aging behavior.  Note because a read(2) of a mmap'ed file
172  * will always check the page cache first even when the ARC is out
173  * of date correct data will still be returned.
174  *
175  * While this implementation ensures correct behavior it does have
176  * have some drawbacks.  The most obvious of which is that it
177  * increases the required memory footprint when access mmap'ed
178  * files.  It also adds additional complexity to the code keeping
179  * both caches synchronized.
180  *
181  * Longer term it may be possible to cleanly resolve this wart by
182  * mapping page cache pages directly on to the ARC buffers.  The
183  * Linux address space operations are flexible enough to allow
184  * selection of which pages back a particular index.  The trick
185  * would be working out the details of which subsystem is in
186  * charge, the ARC, the page cache, or both.  It may also prove
187  * helpful to move the ARC buffers to a scatter-gather lists
188  * rather than a vmalloc'ed region.
189  */
190 static int
191 zpl_mmap(struct file *filp, struct vm_area_struct *vma)
192 {
193         znode_t *zp = ITOZ(filp->f_mapping->host);
194         int error;
195
196         error = generic_file_mmap(filp, vma);
197         if (error)
198                 return (error);
199
200         mutex_enter(&zp->z_lock);
201         zp->z_is_mapped = 1;
202         mutex_exit(&zp->z_lock);
203
204         return (error);
205 }
206
207 /*
208  * Populate a page with data for the Linux page cache.  This function is
209  * only used to support mmap(2).  There will be an identical copy of the
210  * data in the ARC which is kept up to date via .write() and .writepage().
211  *
212  * Current this function relies on zpl_read_common() and the O_DIRECT
213  * flag to read in a page.  This works but the more correct way is to
214  * update zfs_fillpage() to be Linux friendly and use that interface.
215  */
216 static int
217 zpl_readpage(struct file *filp, struct page *pp)
218 {
219         struct inode *ip;
220         loff_t off, i_size;
221         size_t len, wrote;
222         cred_t *cr;
223         void *pb;
224         int error = 0;
225
226         ASSERT(PageLocked(pp));
227         ip = pp->mapping->host;
228         off = page_offset(pp);
229         i_size = i_size_read(ip);
230         ASSERT3S(off, <, i_size);
231
232         cr = (cred_t *)get_current_cred();
233         len = MIN(PAGE_CACHE_SIZE, i_size - off);
234
235         pb = kmap(pp);
236
237         /* O_DIRECT is passed to bypass the page cache and avoid deadlock. */
238         wrote = zpl_read_common(ip, pb, len, off, UIO_SYSSPACE, O_DIRECT, cr);
239         if (wrote != len)
240                 error = -EIO;
241
242         if (!error && (len < PAGE_CACHE_SIZE))
243                 memset(pb + len, 0, PAGE_CACHE_SIZE - len);
244
245         kunmap(pp);
246         put_cred(cr);
247
248         if (error) {
249                 SetPageError(pp);
250                 ClearPageUptodate(pp);
251         } else {
252                 ClearPageError(pp);
253                 SetPageUptodate(pp);
254                 flush_dcache_page(pp);
255         }
256
257         unlock_page(pp);
258
259         return (error);
260 }
261
262 /*
263  * Write out dirty pages to the ARC, this function is only required to
264  * support mmap(2).  Mapped pages may be dirtied by memory operations
265  * which never call .write().  These dirty pages are kept in sync with
266  * the ARC buffers via this hook.
267  *
268  * Currently this function relies on zpl_write_common() and the O_DIRECT
269  * flag to push out the page.  This works but the more correct way is
270  * to update zfs_putapage() to be Linux friendly and use that interface.
271  */
272 static int
273 zpl_writepage(struct page *pp, struct writeback_control *wbc)
274 {
275         struct inode *ip;
276         loff_t off, i_size;
277         size_t len, read;
278         cred_t *cr;
279         void *pb;
280         int error = 0;
281
282         ASSERT(PageLocked(pp));
283         ip = pp->mapping->host;
284         off = page_offset(pp);
285         i_size = i_size_read(ip);
286
287         cr = (cred_t *)get_current_cred();
288         len = MIN(PAGE_CACHE_SIZE, i_size - off);
289
290         pb = kmap(pp);
291
292         /* O_DIRECT is passed to bypass the page cache and avoid deadlock. */
293         read = zpl_write_common(ip, pb, len, off, UIO_SYSSPACE, O_DIRECT, cr);
294         if (read != len)
295                 error = -EIO;
296
297         kunmap(pp);
298         put_cred(cr);
299
300         if (error) {
301                 SetPageError(pp);
302                 ClearPageUptodate(pp);
303         } else {
304                 ClearPageError(pp);
305                 SetPageUptodate(pp);
306         }
307
308         unlock_page(pp);
309
310         return (error);
311 }
312
313 const struct address_space_operations zpl_address_space_operations = {
314         .readpage       = zpl_readpage,
315         .writepage      = zpl_writepage,
316 };
317
318 const struct file_operations zpl_file_operations = {
319         .open           = generic_file_open,
320         .llseek         = generic_file_llseek,
321         .read           = zpl_read,
322         .write          = zpl_write,
323         .readdir        = zpl_readdir,
324         .mmap           = zpl_mmap,
325         .fsync          = zpl_fsync,
326 };
327
328 const struct file_operations zpl_dir_file_operations = {
329         .llseek         = generic_file_llseek,
330         .read           = generic_read_dir,
331         .readdir        = zpl_readdir,
332         .fsync          = zpl_fsync,
333 };