]>
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 | { | |
248 | (void) zfs_follow_link(dentry, nd); | |
249 | return NULL; | |
250 | } | |
251 | ||
252 | static void | |
253 | zpl_put_link(struct dentry *dentry, struct nameidata *nd, void *ptr) | |
254 | { | |
255 | char *link; | |
256 | ||
257 | link = nd_get_link(nd); | |
258 | if (!IS_ERR(link)) | |
259 | kmem_free(link, MAXPATHLEN + 1); | |
260 | } | |
261 | ||
262 | static int | |
263 | zpl_link(struct dentry *old_dentry, struct inode *dir, struct dentry *dentry) | |
264 | { | |
265 | struct inode *ip = old_dentry->d_inode; | |
266 | cred_t *cr; | |
267 | int error; | |
268 | ||
269 | if (ip->i_nlink >= ZFS_LINK_MAX) | |
270 | return -EMLINK; | |
271 | ||
272 | cr = (cred_t *)get_current_cred(); | |
273 | ip->i_ctime = CURRENT_TIME_SEC; | |
274 | igrab(ip); /* Use ihold() if available */ | |
275 | ||
276 | error = -zfs_link(dir, ip, dname(dentry), cr); | |
277 | if (error) { | |
278 | iput(ip); | |
279 | goto out; | |
280 | } | |
281 | ||
282 | d_instantiate(dentry, ip); | |
283 | out: | |
284 | put_cred(cr); | |
285 | ASSERT3S(error, <=, 0); | |
286 | ||
287 | return (error); | |
288 | } | |
289 | ||
290 | const struct inode_operations zpl_inode_operations = { | |
291 | .check_acl = NULL, | |
292 | .create = zpl_create, | |
293 | .link = zpl_link, | |
294 | .unlink = zpl_unlink, | |
295 | .symlink = zpl_symlink, | |
296 | .mkdir = zpl_mkdir, | |
297 | .rmdir = zpl_rmdir, | |
298 | .mknod = zpl_mknod, | |
299 | .rename = zpl_rename, | |
300 | .setattr = zpl_setattr, | |
301 | .getattr = zpl_getattr, | |
302 | .setxattr = generic_setxattr, | |
303 | .getxattr = generic_getxattr, | |
304 | .removexattr = generic_removexattr, | |
305 | .listxattr = zpl_xattr_list, | |
306 | }; | |
307 | ||
308 | const struct inode_operations zpl_dir_inode_operations = { | |
309 | .check_acl = NULL, | |
310 | .create = zpl_create, | |
311 | .lookup = zpl_lookup, | |
312 | .link = zpl_link, | |
313 | .unlink = zpl_unlink, | |
314 | .symlink = zpl_symlink, | |
315 | .mkdir = zpl_mkdir, | |
316 | .rmdir = zpl_rmdir, | |
317 | .mknod = zpl_mknod, | |
318 | .rename = zpl_rename, | |
319 | .setattr = zpl_setattr, | |
320 | }; | |
321 | ||
322 | const struct inode_operations zpl_symlink_inode_operations = { | |
323 | .check_acl = NULL, | |
324 | .readlink = generic_readlink, | |
325 | .follow_link = zpl_follow_link, | |
326 | .put_link = zpl_put_link, | |
327 | }; | |
328 | ||
329 | const struct inode_operations zpl_special_inode_operations = { | |
330 | .check_acl = NULL, | |
331 | }; |