]> git.proxmox.com Git - mirror_zfs.git/blob - module/zfs/zpl_inode.c
Fix build failures on PaX/GRSecurity patched kernels
[mirror_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/zfs_znode.h>
29 #include <sys/vfs.h>
30 #include <sys/zpl.h>
31
32
33 static struct dentry *
34 zpl_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
35 {
36 cred_t *cr = CRED();
37 struct inode *ip;
38 int error;
39
40 crhold(cr);
41 error = -zfs_lookup(dir, dname(dentry), &ip, 0, cr, NULL, NULL);
42 ASSERT3S(error, <=, 0);
43 crfree(cr);
44
45 if (error) {
46 if (error == -ENOENT)
47 return d_splice_alias(NULL, dentry);
48 else
49 return ERR_PTR(error);
50 }
51
52 return d_splice_alias(ip, dentry);
53 }
54
55 void
56 zpl_vap_init(vattr_t *vap, struct inode *dir, struct dentry *dentry,
57 zpl_umode_t mode, cred_t *cr)
58 {
59 vap->va_mask = ATTR_MODE;
60 vap->va_mode = mode;
61 vap->va_dentry = dentry;
62 vap->va_uid = crgetfsuid(cr);
63
64 if (dir && dir->i_mode & S_ISGID) {
65 vap->va_gid = dir->i_gid;
66 if (S_ISDIR(mode))
67 vap->va_mode |= S_ISGID;
68 } else {
69 vap->va_gid = crgetfsgid(cr);
70 }
71 }
72
73 static int
74 zpl_create(struct inode *dir, struct dentry *dentry, zpl_umode_t mode,
75 struct nameidata *nd)
76 {
77 cred_t *cr = CRED();
78 struct inode *ip;
79 vattr_t *vap;
80 int error;
81
82 crhold(cr);
83 vap = kmem_zalloc(sizeof(vattr_t), KM_SLEEP);
84 zpl_vap_init(vap, dir, dentry, mode, cr);
85
86 error = -zfs_create(dir, (char *)dentry->d_name.name,
87 vap, 0, mode, &ip, cr, 0, NULL);
88 kmem_free(vap, sizeof(vattr_t));
89 crfree(cr);
90 ASSERT3S(error, <=, 0);
91
92 return (error);
93 }
94
95 static int
96 zpl_mknod(struct inode *dir, struct dentry *dentry, zpl_umode_t mode,
97 dev_t rdev)
98 {
99 cred_t *cr = CRED();
100 struct inode *ip;
101 vattr_t *vap;
102 int error;
103
104 /*
105 * We currently expect Linux to supply rdev=0 for all sockets
106 * and fifos, but we want to know if this behavior ever changes.
107 */
108 if (S_ISSOCK(mode) || S_ISFIFO(mode))
109 ASSERT(rdev == 0);
110
111 crhold(cr);
112 vap = kmem_zalloc(sizeof(vattr_t), KM_SLEEP);
113 zpl_vap_init(vap, dir, dentry, mode, cr);
114 vap->va_rdev = rdev;
115
116 error = -zfs_create(dir, (char *)dentry->d_name.name,
117 vap, 0, mode, &ip, cr, 0, NULL);
118 kmem_free(vap, sizeof(vattr_t));
119 crfree(cr);
120 ASSERT3S(error, <=, 0);
121
122 return (-error);
123 }
124
125 static int
126 zpl_unlink(struct inode *dir, struct dentry *dentry)
127 {
128 cred_t *cr = CRED();
129 int error;
130
131 crhold(cr);
132 error = -zfs_remove(dir, dname(dentry), cr);
133 crfree(cr);
134 ASSERT3S(error, <=, 0);
135
136 return (error);
137 }
138
139 static int
140 zpl_mkdir(struct inode *dir, struct dentry *dentry, zpl_umode_t mode)
141 {
142 cred_t *cr = CRED();
143 vattr_t *vap;
144 struct inode *ip;
145 int error;
146
147 crhold(cr);
148 vap = kmem_zalloc(sizeof(vattr_t), KM_SLEEP);
149 zpl_vap_init(vap, dir, dentry, mode | S_IFDIR, cr);
150
151 error = -zfs_mkdir(dir, dname(dentry), vap, &ip, cr, 0, NULL);
152 kmem_free(vap, sizeof(vattr_t));
153 crfree(cr);
154 ASSERT3S(error, <=, 0);
155
156 return (error);
157 }
158
159 static int
160 zpl_rmdir(struct inode * dir, struct dentry *dentry)
161 {
162 cred_t *cr = CRED();
163 int error;
164
165 crhold(cr);
166 error = -zfs_rmdir(dir, dname(dentry), NULL, cr, 0);
167 crfree(cr);
168 ASSERT3S(error, <=, 0);
169
170 return (error);
171 }
172
173 static int
174 zpl_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat)
175 {
176 boolean_t issnap = ITOZSB(dentry->d_inode)->z_issnap;
177 int error;
178
179 /*
180 * Ensure MNT_SHRINKABLE is set on snapshots to ensure they are
181 * unmounted automatically with the parent file system. This
182 * is done on the first getattr because it's not easy to get the
183 * vfsmount structure at mount time. This call path is explicitly
184 * marked unlikely to avoid any performance impact. FWIW, ext4
185 * resorts to a similar trick for sysadmin convenience.
186 */
187 if (unlikely(issnap && !(mnt->mnt_flags & MNT_SHRINKABLE)))
188 mnt->mnt_flags |= MNT_SHRINKABLE;
189
190 error = -zfs_getattr_fast(dentry->d_inode, stat);
191 ASSERT3S(error, <=, 0);
192
193 return (error);
194 }
195
196 static int
197 zpl_setattr(struct dentry *dentry, struct iattr *ia)
198 {
199 cred_t *cr = CRED();
200 vattr_t *vap;
201 int error;
202
203 error = inode_change_ok(dentry->d_inode, ia);
204 if (error)
205 return (error);
206
207 crhold(cr);
208 vap = kmem_zalloc(sizeof(vattr_t), KM_SLEEP);
209 vap->va_mask = ia->ia_valid & ATTR_IATTR_MASK;
210 vap->va_mode = ia->ia_mode;
211 vap->va_uid = ia->ia_uid;
212 vap->va_gid = ia->ia_gid;
213 vap->va_size = ia->ia_size;
214 vap->va_atime = ia->ia_atime;
215 vap->va_mtime = ia->ia_mtime;
216 vap->va_ctime = ia->ia_ctime;
217
218 error = -zfs_setattr(dentry->d_inode, vap, 0, cr);
219
220 kmem_free(vap, sizeof(vattr_t));
221 crfree(cr);
222 ASSERT3S(error, <=, 0);
223
224 return (error);
225 }
226
227 static int
228 zpl_rename(struct inode *sdip, struct dentry *sdentry,
229 struct inode *tdip, struct dentry *tdentry)
230 {
231 cred_t *cr = CRED();
232 int error;
233
234 crhold(cr);
235 error = -zfs_rename(sdip, dname(sdentry), tdip, dname(tdentry), cr, 0);
236 crfree(cr);
237 ASSERT3S(error, <=, 0);
238
239 return (error);
240 }
241
242 static int
243 zpl_symlink(struct inode *dir, struct dentry *dentry, const char *name)
244 {
245 cred_t *cr = CRED();
246 vattr_t *vap;
247 struct inode *ip;
248 int error;
249
250 crhold(cr);
251 vap = kmem_zalloc(sizeof(vattr_t), KM_SLEEP);
252 zpl_vap_init(vap, dir, dentry, S_IFLNK | S_IRWXUGO, cr);
253
254 error = -zfs_symlink(dir, dname(dentry), vap, (char *)name, &ip, cr, 0);
255 kmem_free(vap, sizeof(vattr_t));
256 crfree(cr);
257 ASSERT3S(error, <=, 0);
258
259 return (error);
260 }
261
262 static void *
263 zpl_follow_link(struct dentry *dentry, struct nameidata *nd)
264 {
265 cred_t *cr = CRED();
266 struct inode *ip = dentry->d_inode;
267 struct iovec iov;
268 uio_t uio;
269 char *link;
270 int error;
271
272 crhold(cr);
273
274 iov.iov_len = MAXPATHLEN;
275 iov.iov_base = link = kmem_zalloc(MAXPATHLEN, KM_SLEEP);
276
277 uio.uio_iov = &iov;
278 uio.uio_iovcnt = 1;
279 uio.uio_resid = (MAXPATHLEN - 1);
280 uio.uio_segflg = UIO_SYSSPACE;
281
282 error = -zfs_readlink(ip, &uio, cr);
283 if (error) {
284 kmem_free(link, MAXPATHLEN);
285 nd_set_link(nd, ERR_PTR(error));
286 } else {
287 nd_set_link(nd, link);
288 }
289
290 crfree(cr);
291 return (NULL);
292 }
293
294 static void
295 zpl_put_link(struct dentry *dentry, struct nameidata *nd, void *ptr)
296 {
297 const char *link = nd_get_link(nd);
298
299 if (!IS_ERR(link))
300 kmem_free(link, MAXPATHLEN);
301 }
302
303 static int
304 zpl_link(struct dentry *old_dentry, struct inode *dir, struct dentry *dentry)
305 {
306 cred_t *cr = CRED();
307 struct inode *ip = old_dentry->d_inode;
308 int error;
309
310 if (ip->i_nlink >= ZFS_LINK_MAX)
311 return -EMLINK;
312
313 crhold(cr);
314 ip->i_ctime = CURRENT_TIME_SEC;
315 igrab(ip); /* Use ihold() if available */
316
317 error = -zfs_link(dir, ip, dname(dentry), cr);
318 if (error) {
319 iput(ip);
320 goto out;
321 }
322
323 d_instantiate(dentry, ip);
324 out:
325 crfree(cr);
326 ASSERT3S(error, <=, 0);
327
328 return (error);
329 }
330
331 static void
332 zpl_truncate_range(struct inode* ip, loff_t start, loff_t end)
333 {
334 cred_t *cr = CRED();
335 flock64_t bf;
336
337 ASSERT3S(start, <=, end);
338
339 /*
340 * zfs_freesp() will interpret (len == 0) as meaning "truncate until
341 * the end of the file". We don't want that.
342 */
343 if (start == end)
344 return;
345
346 crhold(cr);
347
348 bf.l_type = F_WRLCK;
349 bf.l_whence = 0;
350 bf.l_start = start;
351 bf.l_len = end - start;
352 bf.l_pid = 0;
353 zfs_space(ip, F_FREESP, &bf, FWRITE, start, cr);
354
355 crfree(cr);
356 }
357
358 #ifdef HAVE_INODE_FALLOCATE
359 static long
360 zpl_fallocate(struct inode *ip, int mode, loff_t offset, loff_t len)
361 {
362 return zpl_fallocate_common(ip, mode, offset, len);
363 }
364 #endif /* HAVE_INODE_FALLOCATE */
365
366
367 const struct inode_operations zpl_inode_operations = {
368 .create = zpl_create,
369 .link = zpl_link,
370 .unlink = zpl_unlink,
371 .symlink = zpl_symlink,
372 .mkdir = zpl_mkdir,
373 .rmdir = zpl_rmdir,
374 .mknod = zpl_mknod,
375 .rename = zpl_rename,
376 .setattr = zpl_setattr,
377 .getattr = zpl_getattr,
378 .setxattr = generic_setxattr,
379 .getxattr = generic_getxattr,
380 .removexattr = generic_removexattr,
381 .listxattr = zpl_xattr_list,
382 .truncate_range = zpl_truncate_range,
383 #ifdef HAVE_INODE_FALLOCATE
384 .fallocate = zpl_fallocate,
385 #endif /* HAVE_INODE_FALLOCATE */
386 };
387
388 const struct inode_operations zpl_dir_inode_operations = {
389 .create = zpl_create,
390 .lookup = zpl_lookup,
391 .link = zpl_link,
392 .unlink = zpl_unlink,
393 .symlink = zpl_symlink,
394 .mkdir = zpl_mkdir,
395 .rmdir = zpl_rmdir,
396 .mknod = zpl_mknod,
397 .rename = zpl_rename,
398 .setattr = zpl_setattr,
399 .getattr = zpl_getattr,
400 .setxattr = generic_setxattr,
401 .getxattr = generic_getxattr,
402 .removexattr = generic_removexattr,
403 .listxattr = zpl_xattr_list,
404 };
405
406 const struct inode_operations zpl_symlink_inode_operations = {
407 .readlink = generic_readlink,
408 .follow_link = zpl_follow_link,
409 .put_link = zpl_put_link,
410 .setattr = zpl_setattr,
411 .getattr = zpl_getattr,
412 .setxattr = generic_setxattr,
413 .getxattr = generic_getxattr,
414 .removexattr = generic_removexattr,
415 .listxattr = zpl_xattr_list,
416 };
417
418 const struct inode_operations zpl_special_inode_operations = {
419 .setattr = zpl_setattr,
420 .getattr = zpl_getattr,
421 .setxattr = generic_setxattr,
422 .getxattr = generic_getxattr,
423 .removexattr = generic_removexattr,
424 .listxattr = zpl_xattr_list,
425 };