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