Add Hooks for Linux File Operations
[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 static int
49 zpl_fsync(struct file *filp, struct dentry *dentry, int datasync)
50 {
51         cred_t *cr;
52         int error;
53
54         cr = (cred_t *)get_current_cred();
55         error = -zfs_fsync(filp->f_path.dentry->d_inode, datasync, cr);
56         put_cred(cr);
57         ASSERT3S(error, <=, 0);
58
59         return (error);
60 }
61
62 ssize_t
63 zpl_read_common(struct inode *ip, const char *buf, size_t len, loff_t pos,
64      uio_seg_t segment, int flags, cred_t *cr)
65 {
66         int error;
67         struct iovec iov;
68         uio_t uio;
69
70         iov.iov_base = (void *)buf;
71         iov.iov_len = len;
72
73         uio.uio_iov = &iov;
74         uio.uio_resid = len;
75         uio.uio_iovcnt = 1;
76         uio.uio_loffset = pos;
77         uio.uio_limit = MAXOFFSET_T;
78         uio.uio_segflg = segment;
79
80         error = -zfs_read(ip, &uio, flags, cr);
81         if (error < 0)
82                 return (error);
83
84         return (len - uio.uio_resid);
85 }
86
87 static ssize_t
88 zpl_read(struct file *filp, char __user *buf, size_t len, loff_t *ppos)
89 {
90         cred_t *cr;
91         ssize_t read;
92
93         cr = (cred_t *)get_current_cred();
94         read = zpl_read_common(filp->f_mapping->host, buf, len, *ppos,
95             UIO_USERSPACE, filp->f_flags, cr);
96         put_cred(cr);
97
98         if (read < 0)
99                 return (read);
100
101         *ppos += read;
102         return (read);
103 }
104
105 ssize_t
106 zpl_write_common(struct inode *ip, const char *buf, size_t len, loff_t pos,
107     uio_seg_t segment, int flags, cred_t *cr)
108 {
109         int error;
110         struct iovec iov;
111         uio_t uio;
112
113         iov.iov_base = (void *)buf;
114         iov.iov_len = len;
115
116         uio.uio_iov = &iov;
117         uio.uio_resid = len,
118         uio.uio_iovcnt = 1;
119         uio.uio_loffset = pos;
120         uio.uio_limit = MAXOFFSET_T;
121         uio.uio_segflg = segment;
122
123         error = -zfs_write(ip, &uio, flags, cr);
124         if (error < 0)
125                 return (error);
126
127         return (len - uio.uio_resid);
128 }
129
130 static ssize_t
131 zpl_write(struct file *filp, const char __user *buf, size_t len, loff_t *ppos)
132 {
133         cred_t *cr;
134         ssize_t wrote;
135
136         cr = (cred_t *)get_current_cred();
137         wrote = zpl_write_common(filp->f_mapping->host, buf, len, *ppos,
138             UIO_USERSPACE, filp->f_flags, cr);
139         put_cred(cr);
140
141         if (wrote < 0)
142                 return (wrote);
143
144         *ppos += wrote;
145         return (wrote);
146 }
147
148 const struct address_space_operations zpl_address_space_operations = {
149 #if 0
150         .readpage       = zpl_readpage,
151         .writepage      = zpl_writepage,
152         .direct_IO      = zpl_direct_IO,
153 #endif
154 };
155
156 const struct file_operations zpl_file_operations = {
157         .open           = generic_file_open,
158         .llseek         = generic_file_llseek,
159         .read           = zpl_read,     /* do_sync_read */
160         .write          = zpl_write,    /* do_sync_write */
161         .readdir        = zpl_readdir,
162         .mmap           = generic_file_mmap,
163         .fsync          = zpl_fsync,
164         .aio_read       = NULL,         /* generic_file_aio_read */
165         .aio_write      = NULL,         /* generic_file_aio_write */
166 };
167
168 const struct file_operations zpl_dir_file_operations = {
169         .llseek         = generic_file_llseek,
170         .read           = generic_read_dir,
171         .readdir        = zpl_readdir,
172         .fsync          = zpl_fsync,
173 };