Fix readlink(2)
[zfs.git] / module / zfs / zpl_inode.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/vfs.h>
29 #include <sys/zpl.h>
30
31
32 static struct dentry *
33 zpl_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
34 {
35         struct inode *ip;
36         cred_t *cr;
37         int error;
38
39         cr = (cred_t *)get_current_cred();
40         error = -zfs_lookup(dir, dname(dentry), &ip, 0, cr, NULL, NULL);
41         ASSERT3S(error, <=, 0);
42         put_cred(cr);
43
44         if (error) {
45                 if (error == -ENOENT)
46                         return d_splice_alias(NULL, dentry);
47                 else
48                         return ERR_PTR(error);
49         }
50
51         return d_splice_alias(ip, dentry);
52 }
53
54 static int
55 zpl_create(struct inode *dir, struct dentry *dentry, int mode,
56     struct nameidata *nd)
57 {
58         const struct cred *cred;
59         struct inode *ip;
60         vattr_t *vap;
61         int error;
62
63         cred = get_current_cred();
64         vap = kmem_zalloc(sizeof(vattr_t), KM_SLEEP);
65         vap->va_mode = mode;
66         vap->va_mask = ATTR_MODE;
67         vap->va_uid = current_fsuid();
68         vap->va_gid = current_fsgid();
69
70         error = -zfs_create(dir, (char *)dentry->d_name.name,
71             vap, 0, mode, &ip, (struct cred *)cred, 0, NULL);
72         if (error)
73                 goto out;
74
75         d_instantiate(dentry, ip);
76 out:
77         kmem_free(vap, sizeof(vattr_t));
78         put_cred(cred);
79         ASSERT3S(error, <=, 0);
80
81         return (error);
82 }
83
84 static int
85 zpl_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t rdev)
86 {
87         const struct cred *cred;
88         struct inode *ip;
89         vattr_t *vap;
90         int error;
91
92         cred = get_current_cred();
93         vap = kmem_zalloc(sizeof(vattr_t), KM_SLEEP);
94         vap->va_mode = mode;
95         vap->va_mask = ATTR_MODE;
96         vap->va_rdev = rdev;
97         vap->va_uid = current_fsuid();
98         vap->va_gid = current_fsgid();
99
100         error = -zfs_create(dir, (char *)dentry->d_name.name,
101             vap, 0, mode, &ip, (struct cred *)cred, 0, NULL);
102         if (error)
103                 goto out;
104
105         d_instantiate(dentry, ip);
106 out:
107         kmem_free(vap, sizeof(vattr_t));
108         put_cred(cred);
109         ASSERT3S(error, <=, 0);
110
111         return (-error);
112 }
113
114 static int
115 zpl_unlink(struct inode *dir, struct dentry *dentry)
116 {
117         cred_t *cr;
118         int error;
119
120         cr = (cred_t *)get_current_cred();
121         error = -zfs_remove(dir, dname(dentry), cr);
122         put_cred(cr);
123         ASSERT3S(error, <=, 0);
124
125         return (error);
126 }
127
128 static int
129 zpl_mkdir(struct inode *dir, struct dentry *dentry, int mode)
130 {
131         cred_t *cr;
132         vattr_t *vap;
133         struct inode *ip;
134         int error;
135
136         cr = (cred_t *)get_current_cred();
137         vap = kmem_zalloc(sizeof(vattr_t), KM_SLEEP);
138         vap->va_mode = S_IFDIR | mode;
139         vap->va_mask = ATTR_MODE;
140         vap->va_uid = current_fsuid();
141         vap->va_gid = current_fsgid();
142
143         error = -zfs_mkdir(dir, dname(dentry), vap, &ip, cr, 0, NULL);
144         if (error)
145                 goto out;
146
147         d_instantiate(dentry, ip);
148 out:
149         kmem_free(vap, sizeof(vattr_t));
150         put_cred(cr);
151         ASSERT3S(error, <=, 0);
152
153         return (error);
154 }
155
156 static int
157 zpl_rmdir(struct inode * dir, struct dentry *dentry)
158 {
159         cred_t *cr;
160         int error;
161
162         cr = (cred_t *)get_current_cred();
163         error = -zfs_rmdir(dir, dname(dentry), NULL, cr, 0);
164         put_cred(cr);
165         ASSERT3S(error, <=, 0);
166
167         return (error);
168 }
169
170 static int
171 zpl_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat)
172 {
173         cred_t *cr;
174         int error;
175
176         cr = (cred_t *)get_current_cred();
177         error = -zfs_getattr(dentry->d_inode, stat, 0, cr);
178         put_cred(cr);
179         ASSERT3S(error, <=, 0);
180
181         return (error);
182 }
183
184 static int
185 zpl_setattr(struct dentry *dentry, struct iattr *attr)
186 {
187         cred_t *cr;
188         int error;
189
190         error = inode_change_ok(dentry->d_inode, attr);
191         if (error)
192                 return (error);
193
194         cr = (cred_t *)get_current_cred();
195         error = -zfs_setattr(dentry->d_inode, attr, 0, cr);
196         put_cred(cr);
197         ASSERT3S(error, <=, 0);
198
199         return (-error);
200 }
201
202 static int
203 zpl_rename(struct inode *sdip, struct dentry *sdentry,
204     struct inode *tdip, struct dentry *tdentry)
205 {
206         cred_t *cr;
207         int error;
208
209         cr = (cred_t *)get_current_cred();
210         error = -zfs_rename(sdip, dname(sdentry), tdip, dname(tdentry), cr, 0);
211         put_cred(cr);
212         ASSERT3S(error, <=, 0);
213
214         return (error);
215 }
216
217 static int
218 zpl_symlink(struct inode *dir, struct dentry *dentry, const char *name)
219 {
220         cred_t *cr;
221         vattr_t *vap;
222         struct inode *ip;
223         int error;
224
225         cr = (cred_t *)get_current_cred();
226         vap = kmem_zalloc(sizeof(vattr_t), KM_SLEEP);
227         vap->va_mode = S_IFLNK | S_IRWXUGO;
228         vap->va_mask = ATTR_MODE;
229         vap->va_uid = current_fsuid();
230         vap->va_gid = current_fsgid();
231
232         error = -zfs_symlink(dir, dname(dentry), vap, (char *)name, &ip, cr, 0);
233         if (error)
234                 goto out;
235
236         d_instantiate(dentry, ip);
237 out:
238         kmem_free(vap, sizeof(vattr_t));
239         put_cred(cr);
240         ASSERT3S(error, <=, 0);
241
242         return (error);
243 }
244
245 static void *
246 zpl_follow_link(struct dentry *dentry, struct nameidata *nd)
247 {
248         struct inode *ip = dentry->d_inode;
249         struct iovec iov;
250         uio_t uio;
251         char *link;
252         cred_t *cr;
253         int error;
254
255         cr = (cred_t *)get_current_cred();
256
257         iov.iov_len = MAXPATHLEN;
258         iov.iov_base = link = kmem_zalloc(MAXPATHLEN, KM_SLEEP);
259
260         uio.uio_iov = &iov;
261         uio.uio_iovcnt = 1;
262         uio.uio_resid = (MAXPATHLEN - 1);
263         uio.uio_segflg = UIO_SYSSPACE;
264
265         error = zfs_readlink(ip, &uio, cr);
266         if (error) {
267                 kmem_free(link, MAXPATHLEN);
268                 nd_set_link(nd, ERR_PTR(error));
269         } else {
270                 nd_set_link(nd, link);
271         }
272
273         put_cred(cr);
274         return (NULL);
275 }
276
277 static void
278 zpl_put_link(struct dentry *dentry, struct nameidata *nd, void *ptr)
279 {
280         char *link;
281
282         link = nd_get_link(nd);
283         if (!IS_ERR(link))
284                 kmem_free(link, MAXPATHLEN);
285 }
286
287 static int
288 zpl_link(struct dentry *old_dentry, struct inode *dir, struct dentry *dentry)
289 {
290         struct inode *ip = old_dentry->d_inode;
291         cred_t *cr;
292         int error;
293
294         if (ip->i_nlink >= ZFS_LINK_MAX)
295                 return -EMLINK;
296
297         cr = (cred_t *)get_current_cred();
298         ip->i_ctime = CURRENT_TIME_SEC;
299         igrab(ip); /* Use ihold() if available */
300
301         error = -zfs_link(dir, ip, dname(dentry), cr);
302         if (error) {
303                 iput(ip);
304                 goto out;
305         }
306
307         d_instantiate(dentry, ip);
308 out:
309         put_cred(cr);
310         ASSERT3S(error, <=, 0);
311
312         return (error);
313 }
314
315 const struct inode_operations zpl_inode_operations = {
316         .create         = zpl_create,
317         .link           = zpl_link,
318         .unlink         = zpl_unlink,
319         .symlink        = zpl_symlink,
320         .mkdir          = zpl_mkdir,
321         .rmdir          = zpl_rmdir,
322         .mknod          = zpl_mknod,
323         .rename         = zpl_rename,
324         .setattr        = zpl_setattr,
325         .getattr        = zpl_getattr,
326         .setxattr       = generic_setxattr,
327         .getxattr       = generic_getxattr,
328         .removexattr    = generic_removexattr,
329         .listxattr      = zpl_xattr_list,
330 };
331
332 const struct inode_operations zpl_dir_inode_operations = {
333         .create         = zpl_create,
334         .lookup         = zpl_lookup,
335         .link           = zpl_link,
336         .unlink         = zpl_unlink,
337         .symlink        = zpl_symlink,
338         .mkdir          = zpl_mkdir,
339         .rmdir          = zpl_rmdir,
340         .mknod          = zpl_mknod,
341         .rename         = zpl_rename,
342         .setattr        = zpl_setattr,
343         .getattr        = zpl_getattr,
344         .setxattr       = generic_setxattr,
345         .getxattr       = generic_getxattr,
346         .removexattr    = generic_removexattr,
347         .listxattr      = zpl_xattr_list,
348 };
349
350 const struct inode_operations zpl_symlink_inode_operations = {
351         .readlink       = generic_readlink,
352         .follow_link    = zpl_follow_link,
353         .put_link       = zpl_put_link,
354 };
355
356 const struct inode_operations zpl_special_inode_operations = {
357         .setattr        = zpl_setattr,
358         .getattr        = zpl_getattr,
359         .setxattr       = generic_setxattr,
360         .getxattr       = generic_getxattr,
361         .removexattr    = generic_removexattr,
362         .listxattr      = zpl_xattr_list,
363 };