]> git.proxmox.com Git - mirror_zfs-debian.git/blame - module/zfs/zpl_inode.c
Improve 'zpool import' safety
[mirror_zfs-debian.git] / module / zfs / zpl_inode.c
CommitLineData
ee154f01
BB
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
32static struct dentry *
33zpl_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
54static int
55zpl_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);
76out:
77 kmem_free(vap, sizeof(vattr_t));
78 put_cred(cred);
79 ASSERT3S(error, <=, 0);
80
81 return (error);
82}
83
84static int
85zpl_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);
106out:
107 kmem_free(vap, sizeof(vattr_t));
108 put_cred(cred);
109 ASSERT3S(error, <=, 0);
110
111 return (-error);
112}
113
114static int
115zpl_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
128static int
129zpl_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);
148out:
149 kmem_free(vap, sizeof(vattr_t));
150 put_cred(cr);
151 ASSERT3S(error, <=, 0);
152
153 return (error);
154}
155
156static int
157zpl_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
170static int
171zpl_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
184static int
185zpl_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
202static int
203zpl_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
217static int
218zpl_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);
237out:
238 kmem_free(vap, sizeof(vattr_t));
239 put_cred(cr);
240 ASSERT3S(error, <=, 0);
241
242 return (error);
243}
244
245static void *
246zpl_follow_link(struct dentry *dentry, struct nameidata *nd)
247{
8b4f9a2d
BB
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);
ee154f01
BB
275}
276
277static void
278zpl_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))
8b4f9a2d 284 kmem_free(link, MAXPATHLEN);
ee154f01
BB
285}
286
287static int
288zpl_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);
308out:
309 put_cred(cr);
310 ASSERT3S(error, <=, 0);
311
312 return (error);
313}
314
315const struct inode_operations zpl_inode_operations = {
ee154f01
BB
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
332const struct inode_operations zpl_dir_inode_operations = {
ee154f01
BB
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,
a6695d83
BB
343 .getattr = zpl_getattr,
344 .setxattr = generic_setxattr,
345 .getxattr = generic_getxattr,
346 .removexattr = generic_removexattr,
347 .listxattr = zpl_xattr_list,
ee154f01
BB
348};
349
350const struct inode_operations zpl_symlink_inode_operations = {
ee154f01
BB
351 .readlink = generic_readlink,
352 .follow_link = zpl_follow_link,
353 .put_link = zpl_put_link,
354};
355
356const struct inode_operations zpl_special_inode_operations = {
a6695d83
BB
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,
ee154f01 363};