]>
Commit | Line | Data |
---|---|---|
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 | ||
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 | { | |
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 | ||
50950001 | 265 | error = -zfs_readlink(ip, &uio, cr); |
8b4f9a2d BB |
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 | ||
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)) | |
8b4f9a2d | 284 | kmem_free(link, MAXPATHLEN); |
ee154f01 BB |
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 = { | |
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 | ||
332 | const 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 | ||
350 | const 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 | ||
356 | const 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 | }; |