Commit | Line | Data |
---|---|---|
d7e09d03 PT |
1 | /* |
2 | * GPL HEADER START | |
3 | * | |
4 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. | |
5 | * | |
6 | * This program is free software; you can redistribute it and/or modify | |
7 | * it under the terms of the GNU General Public License version 2 only, | |
8 | * as published by the Free Software Foundation. | |
9 | * | |
10 | * This program is distributed in the hope that it will be useful, but | |
11 | * WITHOUT ANY WARRANTY; without even the implied warranty of | |
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
13 | * General Public License version 2 for more details (a copy is included | |
14 | * in the LICENSE file that accompanied this code). | |
15 | * | |
16 | * You should have received a copy of the GNU General Public License | |
17 | * version 2 along with this program; If not, see | |
6a5b99a4 | 18 | * http://www.gnu.org/licenses/gpl-2.0.html |
d7e09d03 | 19 | * |
d7e09d03 PT |
20 | * GPL HEADER END |
21 | */ | |
22 | /* | |
23 | * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved. | |
24 | * Use is subject to license terms. | |
25 | * | |
1dc563a6 | 26 | * Copyright (c) 2011, 2015, Intel Corporation. |
d7e09d03 PT |
27 | */ |
28 | /* | |
29 | * This file is part of Lustre, http://www.lustre.org/ | |
30 | * Lustre is a trademark of Sun Microsystems, Inc. | |
31 | */ | |
32 | ||
33 | #include <linux/fs.h> | |
34 | #include <linux/sched.h> | |
35 | #include <linux/mm.h> | |
36 | #include <linux/quotaops.h> | |
37 | #include <linux/highmem.h> | |
38 | #include <linux/pagemap.h> | |
39 | #include <linux/security.h> | |
40 | ||
41 | #define DEBUG_SUBSYSTEM S_LLITE | |
42 | ||
67a235f5 GKH |
43 | #include "../include/obd_support.h" |
44 | #include "../include/lustre_fid.h" | |
45 | #include "../include/lustre_lite.h" | |
46 | #include "../include/lustre_dlm.h" | |
47 | #include "../include/lustre_ver.h" | |
d7e09d03 PT |
48 | #include "llite_internal.h" |
49 | ||
50 | static int ll_create_it(struct inode *, struct dentry *, | |
51 | int, struct lookup_intent *); | |
52 | ||
5a3cd992 | 53 | /* called from iget5_locked->find_inode() under inode_hash_lock spinlock */ |
d7e09d03 PT |
54 | static int ll_test_inode(struct inode *inode, void *opaque) |
55 | { | |
56 | struct ll_inode_info *lli = ll_i2info(inode); | |
57 | struct lustre_md *md = opaque; | |
58 | ||
59 | if (unlikely(!(md->body->valid & OBD_MD_FLID))) { | |
60 | CERROR("MDS body missing FID\n"); | |
61 | return 0; | |
62 | } | |
63 | ||
64 | if (!lu_fid_eq(&lli->lli_fid, &md->body->fid1)) | |
65 | return 0; | |
66 | ||
67 | return 1; | |
68 | } | |
69 | ||
70 | static int ll_set_inode(struct inode *inode, void *opaque) | |
71 | { | |
72 | struct ll_inode_info *lli = ll_i2info(inode); | |
73 | struct mdt_body *body = ((struct lustre_md *)opaque)->body; | |
74 | ||
75 | if (unlikely(!(body->valid & OBD_MD_FLID))) { | |
76 | CERROR("MDS body missing FID\n"); | |
77 | return -EINVAL; | |
78 | } | |
79 | ||
80 | lli->lli_fid = body->fid1; | |
81 | if (unlikely(!(body->valid & OBD_MD_FLTYPE))) { | |
267d9c8a LM |
82 | CERROR("Can not initialize inode " DFID |
83 | " without object type: valid = %#llx\n", | |
2d00bd17 | 84 | PFID(&lli->lli_fid), body->valid); |
d7e09d03 PT |
85 | return -EINVAL; |
86 | } | |
87 | ||
88 | inode->i_mode = (inode->i_mode & ~S_IFMT) | (body->mode & S_IFMT); | |
89 | if (unlikely(inode->i_mode == 0)) { | |
90 | CERROR("Invalid inode "DFID" type\n", PFID(&lli->lli_fid)); | |
91 | return -EINVAL; | |
92 | } | |
93 | ||
94 | ll_lli_init(lli); | |
95 | ||
96 | return 0; | |
97 | } | |
98 | ||
d7e09d03 PT |
99 | /* |
100 | * Get an inode by inode number (already instantiated by the intent lookup). | |
101 | * Returns inode or NULL | |
102 | */ | |
103 | struct inode *ll_iget(struct super_block *sb, ino_t hash, | |
104 | struct lustre_md *md) | |
105 | { | |
106 | struct inode *inode; | |
d7e09d03 PT |
107 | |
108 | LASSERT(hash != 0); | |
109 | inode = iget5_locked(sb, hash, ll_test_inode, ll_set_inode, md); | |
110 | ||
111 | if (inode) { | |
112 | if (inode->i_state & I_NEW) { | |
113 | int rc = 0; | |
114 | ||
115 | ll_read_inode2(inode, md); | |
116 | if (S_ISREG(inode->i_mode) && | |
6e16818b | 117 | !ll_i2info(inode)->lli_clob) { |
d7e09d03 | 118 | CDEBUG(D_INODE, |
e15ba45d OD |
119 | "%s: apply lsm %p to inode " DFID ".\n", |
120 | ll_get_fsname(sb, NULL, 0), md->lsm, | |
121 | PFID(ll_inode2fid(inode))); | |
d7e09d03 PT |
122 | rc = cl_file_inode_init(inode, md); |
123 | } | |
124 | if (rc != 0) { | |
0e81ba23 | 125 | iget_failed(inode); |
020ecc6f | 126 | inode = NULL; |
da5ecb4d | 127 | } else { |
d7e09d03 | 128 | unlock_new_inode(inode); |
da5ecb4d OD |
129 | } |
130 | } else if (!(inode->i_state & (I_FREEING | I_CLEAR))) { | |
d7e09d03 | 131 | ll_update_inode(inode, md); |
97a075cd JN |
132 | CDEBUG(D_VFSTRACE, "got inode: "DFID"(%p)\n", |
133 | PFID(&md->body->fid1), inode); | |
da5ecb4d | 134 | } |
d7e09d03 | 135 | } |
0a3bdb00 | 136 | return inode; |
d7e09d03 PT |
137 | } |
138 | ||
139 | static void ll_invalidate_negative_children(struct inode *dir) | |
140 | { | |
141 | struct dentry *dentry, *tmp_subdir; | |
d7e09d03 | 142 | |
2bbec0ed | 143 | spin_lock(&dir->i_lock); |
9d5be52f | 144 | hlist_for_each_entry(dentry, &dir->i_dentry, d_u.d_alias) { |
d7e09d03 PT |
145 | spin_lock(&dentry->d_lock); |
146 | if (!list_empty(&dentry->d_subdirs)) { | |
147 | struct dentry *child; | |
148 | ||
149 | list_for_each_entry_safe(child, tmp_subdir, | |
150 | &dentry->d_subdirs, | |
946e51f2 | 151 | d_child) { |
2b0143b5 | 152 | if (d_really_is_negative(child)) |
b1d2a127 | 153 | d_lustre_invalidate(child, 1); |
d7e09d03 PT |
154 | } |
155 | } | |
156 | spin_unlock(&dentry->d_lock); | |
157 | } | |
2bbec0ed | 158 | spin_unlock(&dir->i_lock); |
d7e09d03 PT |
159 | } |
160 | ||
161 | int ll_md_blocking_ast(struct ldlm_lock *lock, struct ldlm_lock_desc *desc, | |
162 | void *data, int flag) | |
163 | { | |
d7e09d03 | 164 | struct lustre_handle lockh; |
45b2a010 | 165 | int rc; |
d7e09d03 PT |
166 | |
167 | switch (flag) { | |
168 | case LDLM_CB_BLOCKING: | |
169 | ldlm_lock2handle(lock, &lockh); | |
170 | rc = ldlm_cli_cancel(&lockh, LCF_ASYNC); | |
171 | if (rc < 0) { | |
45b2a010 | 172 | CDEBUG(D_INODE, "ldlm_cli_cancel: rc = %d\n", rc); |
0a3bdb00 | 173 | return rc; |
d7e09d03 PT |
174 | } |
175 | break; | |
176 | case LDLM_CB_CANCELING: { | |
177 | struct inode *inode = ll_inode_from_resource_lock(lock); | |
d7e09d03 | 178 | __u64 bits = lock->l_policy_data.l_inodebits.bits; |
d7e09d03 PT |
179 | |
180 | /* Inode is set to lock->l_resource->lr_lvb_inode | |
c0894c6c OD |
181 | * for mdc - bug 24555 |
182 | */ | |
6e16818b | 183 | LASSERT(!lock->l_ast_data); |
d7e09d03 | 184 | |
6e16818b | 185 | if (!inode) |
d7e09d03 PT |
186 | break; |
187 | ||
45b2a010 | 188 | /* Invalidate all dentries associated with this inode */ |
5a9a80ba | 189 | LASSERT(ldlm_is_canceling(lock)); |
7fc1f831 | 190 | |
45b2a010 JH |
191 | if (!fid_res_name_eq(ll_inode2fid(inode), |
192 | &lock->l_resource->lr_name)) { | |
193 | LDLM_ERROR(lock, "data mismatch with object "DFID"(%p)", | |
194 | PFID(ll_inode2fid(inode)), inode); | |
195 | LBUG(); | |
196 | } | |
197 | ||
198 | if (bits & MDS_INODELOCK_XATTR) { | |
7fc1f831 | 199 | ll_xattr_cache_destroy(inode); |
45b2a010 JH |
200 | bits &= ~MDS_INODELOCK_XATTR; |
201 | } | |
7fc1f831 | 202 | |
d7e09d03 | 203 | /* For OPEN locks we differentiate between lock modes |
c0894c6c OD |
204 | * LCK_CR, LCK_CW, LCK_PR - bug 22891 |
205 | */ | |
d7e09d03 | 206 | if (bits & MDS_INODELOCK_OPEN) |
45b2a010 | 207 | ll_have_md_lock(inode, &bits, lock->l_req_mode); |
d7e09d03 PT |
208 | |
209 | if (bits & MDS_INODELOCK_OPEN) { | |
45b2a010 JH |
210 | fmode_t fmode; |
211 | ||
d7e09d03 PT |
212 | switch (lock->l_req_mode) { |
213 | case LCK_CW: | |
45b2a010 | 214 | fmode = FMODE_WRITE; |
d7e09d03 PT |
215 | break; |
216 | case LCK_PR: | |
45b2a010 | 217 | fmode = FMODE_EXEC; |
d7e09d03 PT |
218 | break; |
219 | case LCK_CR: | |
45b2a010 | 220 | fmode = FMODE_READ; |
d7e09d03 PT |
221 | break; |
222 | default: | |
45b2a010 JH |
223 | LDLM_ERROR(lock, "bad lock mode for OPEN lock"); |
224 | LBUG(); | |
d7e09d03 | 225 | } |
45b2a010 JH |
226 | |
227 | ll_md_real_close(inode, fmode); | |
d7e09d03 PT |
228 | } |
229 | ||
45b2a010 JH |
230 | if (bits & (MDS_INODELOCK_LOOKUP | MDS_INODELOCK_UPDATE | |
231 | MDS_INODELOCK_LAYOUT | MDS_INODELOCK_PERM)) | |
232 | ll_have_md_lock(inode, &bits, LCK_MINMODE); | |
233 | ||
d7e09d03 | 234 | if (bits & MDS_INODELOCK_LAYOUT) { |
45b2a010 JH |
235 | struct cl_object_conf conf = { |
236 | .coc_opc = OBJECT_CONF_INVALIDATE, | |
237 | .coc_inode = inode, | |
238 | }; | |
d7e09d03 | 239 | |
d7e09d03 | 240 | rc = ll_layout_conf(inode, &conf); |
45b2a010 JH |
241 | if (rc < 0) |
242 | CDEBUG(D_INODE, "cannot invalidate layout of " | |
243 | DFID": rc = %d\n", | |
244 | PFID(ll_inode2fid(inode)), rc); | |
d7e09d03 PT |
245 | } |
246 | ||
ae5ef67b | 247 | if (bits & MDS_INODELOCK_UPDATE) { |
45b2a010 JH |
248 | struct ll_inode_info *lli = ll_i2info(inode); |
249 | ||
ae5ef67b | 250 | spin_lock(&lli->lli_lock); |
d7e09d03 | 251 | lli->lli_flags &= ~LLIF_MDS_SIZE_LOCK; |
ae5ef67b SB |
252 | spin_unlock(&lli->lli_lock); |
253 | } | |
d7e09d03 | 254 | |
45b2a010 | 255 | if ((bits & MDS_INODELOCK_UPDATE) && S_ISDIR(inode->i_mode)) { |
97a075cd JN |
256 | CDEBUG(D_INODE, "invalidating inode "DFID"\n", |
257 | PFID(ll_inode2fid(inode))); | |
d7e09d03 PT |
258 | truncate_inode_pages(inode->i_mapping, 0); |
259 | ll_invalidate_negative_children(inode); | |
260 | } | |
261 | ||
45b2a010 | 262 | if ((bits & (MDS_INODELOCK_LOOKUP | MDS_INODELOCK_PERM)) && |
6e16818b | 263 | inode->i_sb->s_root && |
5242d422 | 264 | !is_root_inode(inode)) |
d7e09d03 | 265 | ll_invalidate_aliases(inode); |
45b2a010 | 266 | |
d7e09d03 PT |
267 | iput(inode); |
268 | break; | |
269 | } | |
270 | default: | |
271 | LBUG(); | |
272 | } | |
273 | ||
0a3bdb00 | 274 | return 0; |
d7e09d03 PT |
275 | } |
276 | ||
277 | __u32 ll_i2suppgid(struct inode *i) | |
278 | { | |
4b1a25f0 PT |
279 | if (in_group_p(i->i_gid)) |
280 | return (__u32)from_kgid(&init_user_ns, i->i_gid); | |
d7e09d03 PT |
281 | else |
282 | return (__u32)(-1); | |
283 | } | |
284 | ||
285 | /* Pack the required supplementary groups into the supplied groups array. | |
286 | * If we don't need to use the groups from the target inode(s) then we | |
287 | * instead pack one or more groups from the user's supplementary group | |
c0894c6c OD |
288 | * array in case it might be useful. Not needed if doing an MDS-side upcall. |
289 | */ | |
d7e09d03 PT |
290 | void ll_i2gids(__u32 *suppgids, struct inode *i1, struct inode *i2) |
291 | { | |
6e16818b | 292 | LASSERT(i1); |
d7e09d03 PT |
293 | |
294 | suppgids[0] = ll_i2suppgid(i1); | |
295 | ||
296 | if (i2) | |
297 | suppgids[1] = ll_i2suppgid(i2); | |
298 | else | |
299 | suppgids[1] = -1; | |
d7e09d03 PT |
300 | } |
301 | ||
302 | /* | |
303 | * try to reuse three types of dentry: | |
304 | * 1. unhashed alias, this one is unhashed by d_invalidate (but it may be valid | |
305 | * by concurrent .revalidate). | |
306 | * 2. INVALID alias (common case for no valid ldlm lock held, but this flag may | |
307 | * be cleared by others calling d_lustre_revalidate). | |
308 | * 3. DISCONNECTED alias. | |
309 | */ | |
310 | static struct dentry *ll_find_alias(struct inode *inode, struct dentry *dentry) | |
311 | { | |
312 | struct dentry *alias, *discon_alias, *invalid_alias; | |
d7e09d03 | 313 | |
9d5be52f | 314 | if (hlist_empty(&inode->i_dentry)) |
d7e09d03 PT |
315 | return NULL; |
316 | ||
7551b8b5 NC |
317 | discon_alias = NULL; |
318 | invalid_alias = NULL; | |
d7e09d03 | 319 | |
2bbec0ed | 320 | spin_lock(&inode->i_lock); |
9d5be52f | 321 | hlist_for_each_entry(alias, &inode->i_dentry, d_u.d_alias) { |
d7e09d03 PT |
322 | LASSERT(alias != dentry); |
323 | ||
324 | spin_lock(&alias->d_lock); | |
325 | if (alias->d_flags & DCACHE_DISCONNECTED) | |
326 | /* LASSERT(last_discon == NULL); LU-405, bz 20055 */ | |
327 | discon_alias = alias; | |
328 | else if (alias->d_parent == dentry->d_parent && | |
329 | alias->d_name.hash == dentry->d_name.hash && | |
330 | alias->d_name.len == dentry->d_name.len && | |
331 | memcmp(alias->d_name.name, dentry->d_name.name, | |
332 | dentry->d_name.len) == 0) | |
333 | invalid_alias = alias; | |
334 | spin_unlock(&alias->d_lock); | |
335 | ||
336 | if (invalid_alias) | |
337 | break; | |
338 | } | |
339 | alias = invalid_alias ?: discon_alias ?: NULL; | |
340 | if (alias) { | |
341 | spin_lock(&alias->d_lock); | |
342 | dget_dlock(alias); | |
343 | spin_unlock(&alias->d_lock); | |
344 | } | |
2bbec0ed | 345 | spin_unlock(&inode->i_lock); |
d7e09d03 PT |
346 | |
347 | return alias; | |
348 | } | |
349 | ||
350 | /* | |
351 | * Similar to d_splice_alias(), but lustre treats invalid alias | |
352 | * similar to DCACHE_DISCONNECTED, and tries to use it anyway. | |
353 | */ | |
354 | struct dentry *ll_splice_alias(struct inode *inode, struct dentry *de) | |
355 | { | |
356 | struct dentry *new; | |
3ea8f3bc | 357 | int rc; |
d7e09d03 PT |
358 | |
359 | if (inode) { | |
360 | new = ll_find_alias(inode, de); | |
361 | if (new) { | |
3ea8f3bc LS |
362 | rc = ll_d_init(new); |
363 | if (rc < 0) { | |
364 | dput(new); | |
365 | return ERR_PTR(rc); | |
366 | } | |
d7e09d03 PT |
367 | d_move(new, de); |
368 | iput(inode); | |
369 | CDEBUG(D_DENTRY, | |
370 | "Reuse dentry %p inode %p refc %d flags %#x\n", | |
2b0143b5 | 371 | new, d_inode(new), d_count(new), new->d_flags); |
d7e09d03 PT |
372 | return new; |
373 | } | |
374 | } | |
3ea8f3bc LS |
375 | rc = ll_d_init(de); |
376 | if (rc < 0) | |
377 | return ERR_PTR(rc); | |
d7e09d03 PT |
378 | d_add(de, inode); |
379 | CDEBUG(D_DENTRY, "Add dentry %p inode %p refc %d flags %#x\n", | |
2b0143b5 | 380 | de, d_inode(de), d_count(de), de->d_flags); |
d7e09d03 PT |
381 | return de; |
382 | } | |
383 | ||
2d95f10e JH |
384 | static int ll_lookup_it_finish(struct ptlrpc_request *request, |
385 | struct lookup_intent *it, | |
386 | struct inode *parent, struct dentry **de) | |
d7e09d03 | 387 | { |
d7e09d03 PT |
388 | struct inode *inode = NULL; |
389 | __u64 bits = 0; | |
44ecac68 | 390 | int rc = 0; |
99f1c013 | 391 | struct dentry *alias; |
d7e09d03 PT |
392 | |
393 | /* NB 1 request reference will be taken away by ll_intent_lock() | |
c0894c6c OD |
394 | * when I return |
395 | */ | |
d7e09d03 | 396 | CDEBUG(D_DENTRY, "it %p it_disposition %x\n", it, |
e476f2e5 | 397 | it->it_disposition); |
d7e09d03 PT |
398 | if (!it_disposition(it, DISP_LOOKUP_NEG)) { |
399 | rc = ll_prep_inode(&inode, request, (*de)->d_sb, it); | |
400 | if (rc) | |
0a3bdb00 | 401 | return rc; |
d7e09d03 PT |
402 | |
403 | ll_set_lock_data(ll_i2sbi(parent)->ll_md_exp, inode, it, &bits); | |
404 | ||
405 | /* We used to query real size from OSTs here, but actually | |
c0894c6c OD |
406 | * this is not needed. For stat() calls size would be updated |
407 | * from subsequent do_revalidate()->ll_inode_revalidate_it() in | |
408 | * 2.4 and | |
409 | * vfs_getattr_it->ll_getattr()->ll_inode_revalidate_it() in 2.6 | |
410 | * Everybody else who needs correct file size would call | |
411 | * ll_glimpse_size or some equivalent themselves anyway. | |
412 | * Also see bug 7198. | |
413 | */ | |
d7e09d03 PT |
414 | } |
415 | ||
99f1c013 OD |
416 | alias = ll_splice_alias(inode, *de); |
417 | if (IS_ERR(alias)) { | |
418 | rc = PTR_ERR(alias); | |
419 | goto out; | |
3ea8f3bc | 420 | } |
99f1c013 | 421 | *de = alias; |
d7e09d03 PT |
422 | |
423 | if (!it_disposition(it, DISP_LOOKUP_NEG)) { | |
424 | /* we have lookup look - unhide dentry */ | |
425 | if (bits & MDS_INODELOCK_LOOKUP) | |
426 | d_lustre_revalidate(*de); | |
427 | } else if (!it_disposition(it, DISP_OPEN_CREATE)) { | |
428 | /* If file created on server, don't depend on parent UPDATE | |
429 | * lock to unhide it. It is left hidden and next lookup can | |
430 | * find it in ll_splice_alias. | |
431 | */ | |
432 | /* Check that parent has UPDATE lock. */ | |
433 | struct lookup_intent parent_it = { | |
434 | .it_op = IT_GETATTR, | |
e476f2e5 | 435 | .it_lock_handle = 0 }; |
d7e09d03 PT |
436 | |
437 | if (md_revalidate_lock(ll_i2mdexp(parent), &parent_it, | |
438 | &ll_i2info(parent)->lli_fid, NULL)) { | |
439 | d_lustre_revalidate(*de); | |
440 | ll_intent_release(&parent_it); | |
441 | } | |
442 | } | |
443 | ||
44ecac68 FY |
444 | out: |
445 | if (rc != 0 && it->it_op & IT_OPEN) | |
446 | ll_open_cleanup((*de)->d_sb, request); | |
447 | ||
448 | return rc; | |
d7e09d03 PT |
449 | } |
450 | ||
451 | static struct dentry *ll_lookup_it(struct inode *parent, struct dentry *dentry, | |
452 | struct lookup_intent *it, int lookup_flags) | |
453 | { | |
454 | struct lookup_intent lookup_it = { .it_op = IT_LOOKUP }; | |
455 | struct dentry *save = dentry, *retval; | |
456 | struct ptlrpc_request *req = NULL; | |
dbca51dd | 457 | struct inode *inode; |
d7e09d03 | 458 | struct md_op_data *op_data; |
d7e09d03 PT |
459 | __u32 opc; |
460 | int rc; | |
d7e09d03 PT |
461 | |
462 | if (dentry->d_name.len > ll_i2sbi(parent)->ll_namelen) | |
0a3bdb00 | 463 | return ERR_PTR(-ENAMETOOLONG); |
d7e09d03 | 464 | |
97a075cd JN |
465 | CDEBUG(D_VFSTRACE, "VFS Op:name=%pd, dir="DFID"(%p),intent=%s\n", |
466 | dentry, PFID(ll_inode2fid(parent)), parent, LL_IT2STR(it)); | |
d7e09d03 PT |
467 | |
468 | if (d_mountpoint(dentry)) | |
469 | CERROR("Tell Peter, lookup on mtpt, it %s\n", LL_IT2STR(it)); | |
470 | ||
6e16818b | 471 | if (!it || it->it_op == IT_GETXATTR) |
2d95f10e | 472 | it = &lookup_it; |
d7e09d03 | 473 | |
d7e09d03 PT |
474 | if (it->it_op == IT_GETATTR) { |
475 | rc = ll_statahead_enter(parent, &dentry, 0); | |
476 | if (rc == 1) { | |
477 | if (dentry == save) | |
34e1f2bb JL |
478 | retval = NULL; |
479 | else | |
480 | retval = dentry; | |
481 | goto out; | |
d7e09d03 PT |
482 | } |
483 | } | |
484 | ||
1e8a576e | 485 | if (it->it_op & IT_CREAT) |
d7e09d03 PT |
486 | opc = LUSTRE_OPC_CREATE; |
487 | else | |
488 | opc = LUSTRE_OPC_ANY; | |
489 | ||
490 | op_data = ll_prep_md_op_data(NULL, parent, NULL, dentry->d_name.name, | |
491 | dentry->d_name.len, lookup_flags, opc, | |
492 | NULL); | |
493 | if (IS_ERR(op_data)) | |
0a3bdb00 | 494 | return (void *)op_data; |
d7e09d03 PT |
495 | |
496 | /* enforce umask if acl disabled or MDS doesn't support umask */ | |
497 | if (!IS_POSIXACL(parent) || !exp_connect_umask(ll_i2mdexp(parent))) | |
498 | it->it_create_mode &= ~current_umask(); | |
499 | ||
500 | rc = md_intent_lock(ll_i2mdexp(parent), op_data, NULL, 0, it, | |
501 | lookup_flags, &req, ll_md_blocking_ast, 0); | |
502 | ll_finish_md_op_data(op_data); | |
34e1f2bb JL |
503 | if (rc < 0) { |
504 | retval = ERR_PTR(rc); | |
505 | goto out; | |
506 | } | |
d7e09d03 | 507 | |
2d95f10e | 508 | rc = ll_lookup_it_finish(req, it, parent, &dentry); |
d7e09d03 PT |
509 | if (rc != 0) { |
510 | ll_intent_release(it); | |
34e1f2bb JL |
511 | retval = ERR_PTR(rc); |
512 | goto out; | |
d7e09d03 PT |
513 | } |
514 | ||
2b0143b5 | 515 | inode = d_inode(dentry); |
dbca51dd AV |
516 | if ((it->it_op & IT_OPEN) && inode && |
517 | !S_ISREG(inode->i_mode) && | |
518 | !S_ISDIR(inode->i_mode)) { | |
519 | ll_release_openhandle(inode, it); | |
d7e09d03 | 520 | } |
dbca51dd | 521 | ll_lookup_finish_locks(it, inode); |
d7e09d03 PT |
522 | |
523 | if (dentry == save) | |
34e1f2bb | 524 | retval = NULL; |
d7e09d03 | 525 | else |
34e1f2bb | 526 | retval = dentry; |
d7e09d03 PT |
527 | out: |
528 | if (req) | |
529 | ptlrpc_req_finished(req); | |
6e16818b | 530 | if (it->it_op == IT_GETATTR && (!retval || retval == dentry)) |
d7e09d03 PT |
531 | ll_statahead_mark(parent, dentry); |
532 | return retval; | |
533 | } | |
534 | ||
535 | static struct dentry *ll_lookup_nd(struct inode *parent, struct dentry *dentry, | |
536 | unsigned int flags) | |
537 | { | |
538 | struct lookup_intent *itp, it = { .it_op = IT_GETATTR }; | |
539 | struct dentry *de; | |
540 | ||
97a075cd JN |
541 | CDEBUG(D_VFSTRACE, "VFS Op:name=%pd, dir="DFID"(%p),flags=%u\n", |
542 | dentry, PFID(ll_inode2fid(parent)), parent, flags); | |
d7e09d03 PT |
543 | |
544 | /* Optimize away (CREATE && !OPEN). Let .create handle the race. */ | |
4f2fb455 | 545 | if ((flags & LOOKUP_CREATE) && !(flags & LOOKUP_OPEN)) |
d7e09d03 | 546 | return NULL; |
d7e09d03 PT |
547 | |
548 | if (flags & (LOOKUP_PARENT|LOOKUP_OPEN|LOOKUP_CREATE)) | |
549 | itp = NULL; | |
550 | else | |
551 | itp = ⁢ | |
552 | de = ll_lookup_it(parent, dentry, itp, 0); | |
553 | ||
6e16818b | 554 | if (itp) |
d7e09d03 PT |
555 | ll_intent_release(itp); |
556 | ||
557 | return de; | |
558 | } | |
559 | ||
560 | /* | |
561 | * For cached negative dentry and new dentry, handle lookup/create/open | |
562 | * together. | |
563 | */ | |
564 | static int ll_atomic_open(struct inode *dir, struct dentry *dentry, | |
565 | struct file *file, unsigned open_flags, | |
566 | umode_t mode, int *opened) | |
567 | { | |
568 | struct lookup_intent *it; | |
569 | struct dentry *de; | |
570 | long long lookup_flags = LOOKUP_OPEN; | |
571 | int rc = 0; | |
d7e09d03 | 572 | |
97a075cd JN |
573 | CDEBUG(D_VFSTRACE, "VFS Op:name=%pd, dir="DFID"(%p),file %p,open_flags %x,mode %x opened %d\n", |
574 | dentry, PFID(ll_inode2fid(dir)), dir, file, open_flags, mode, | |
575 | *opened); | |
d7e09d03 | 576 | |
99f1c013 OD |
577 | /* Only negative dentries enter here */ |
578 | LASSERT(!d_inode(dentry)); | |
579 | ||
580 | if (!d_in_lookup(dentry)) { | |
581 | /* A valid negative dentry that just passed revalidation, | |
582 | * there's little point to try and open it server-side, | |
583 | * even though there's a minuscle chance it might succeed. | |
584 | * Either way it's a valid race to just return -ENOENT here. | |
585 | */ | |
586 | if (!(open_flags & O_CREAT)) | |
587 | return -ENOENT; | |
588 | ||
589 | /* Otherwise we just unhash it to be rehashed afresh via | |
590 | * lookup if necessary | |
591 | */ | |
592 | d_drop(dentry); | |
593 | } | |
594 | ||
496a51bd | 595 | it = kzalloc(sizeof(*it), GFP_NOFS); |
d7e09d03 | 596 | if (!it) |
0a3bdb00 | 597 | return -ENOMEM; |
d7e09d03 PT |
598 | |
599 | it->it_op = IT_OPEN; | |
1e8a576e | 600 | if (open_flags & O_CREAT) { |
d7e09d03 PT |
601 | it->it_op |= IT_CREAT; |
602 | lookup_flags |= LOOKUP_CREATE; | |
603 | } | |
604 | it->it_create_mode = (mode & S_IALLUGO) | S_IFREG; | |
605 | it->it_flags = (open_flags & ~O_ACCMODE) | OPEN_FMODE(open_flags); | |
606 | ||
607 | /* Dentry added to dcache tree in ll_lookup_it */ | |
608 | de = ll_lookup_it(dir, dentry, it, lookup_flags); | |
609 | if (IS_ERR(de)) | |
610 | rc = PTR_ERR(de); | |
6e16818b | 611 | else if (de) |
d7e09d03 PT |
612 | dentry = de; |
613 | ||
614 | if (!rc) { | |
615 | if (it_disposition(it, DISP_OPEN_CREATE)) { | |
616 | /* Dentry instantiated in ll_create_it. */ | |
617 | rc = ll_create_it(dir, dentry, mode, it); | |
618 | if (rc) { | |
619 | /* We dget in ll_splice_alias. */ | |
6e16818b | 620 | if (de) |
d7e09d03 PT |
621 | dput(de); |
622 | goto out_release; | |
623 | } | |
624 | ||
625 | *opened |= FILE_CREATED; | |
626 | } | |
2b0143b5 | 627 | if (d_really_is_positive(dentry) && it_disposition(it, DISP_OPEN_OPEN)) { |
d7e09d03 | 628 | /* Open dentry. */ |
2b0143b5 | 629 | if (S_ISFIFO(d_inode(dentry)->i_mode)) { |
411c9699 JH |
630 | /* We cannot call open here as it might |
631 | * deadlock. This case is unreachable in | |
632 | * practice because of OBD_CONNECT_NODEVOH. | |
d7e09d03 | 633 | */ |
d7e09d03 PT |
634 | rc = finish_no_open(file, de); |
635 | } else { | |
636 | file->private_data = it; | |
637 | rc = finish_open(file, dentry, NULL, opened); | |
638 | /* We dget in ll_splice_alias. finish_open takes | |
639 | * care of dget for fd open. | |
640 | */ | |
6e16818b | 641 | if (de) |
d7e09d03 PT |
642 | dput(de); |
643 | } | |
644 | } else { | |
645 | rc = finish_no_open(file, de); | |
646 | } | |
647 | } | |
648 | ||
649 | out_release: | |
650 | ll_intent_release(it); | |
97903a26 | 651 | kfree(it); |
d7e09d03 | 652 | |
0a3bdb00 | 653 | return rc; |
d7e09d03 PT |
654 | } |
655 | ||
d7e09d03 | 656 | /* We depend on "mode" being set with the proper file type/umask by now */ |
2d95f10e | 657 | static struct inode *ll_create_node(struct inode *dir, struct lookup_intent *it) |
d7e09d03 PT |
658 | { |
659 | struct inode *inode = NULL; | |
660 | struct ptlrpc_request *request = NULL; | |
661 | struct ll_sb_info *sbi = ll_i2sbi(dir); | |
662 | int rc; | |
d7e09d03 | 663 | |
e476f2e5 | 664 | LASSERT(it && it->it_disposition); |
d7e09d03 PT |
665 | |
666 | LASSERT(it_disposition(it, DISP_ENQ_CREATE_REF)); | |
8bf86fd9 | 667 | request = it->it_request; |
d7e09d03 PT |
668 | it_clear_disposition(it, DISP_ENQ_CREATE_REF); |
669 | rc = ll_prep_inode(&inode, request, dir->i_sb, it); | |
34e1f2bb JL |
670 | if (rc) { |
671 | inode = ERR_PTR(rc); | |
672 | goto out; | |
673 | } | |
d7e09d03 | 674 | |
9d5be52f | 675 | LASSERT(hlist_empty(&inode->i_dentry)); |
d7e09d03 PT |
676 | |
677 | /* We asked for a lock on the directory, but were granted a | |
678 | * lock on the inode. Since we finally have an inode pointer, | |
c0894c6c OD |
679 | * stuff it in the lock. |
680 | */ | |
97a075cd JN |
681 | CDEBUG(D_DLMTRACE, "setting l_ast_data to inode "DFID"(%p)\n", |
682 | PFID(ll_inode2fid(dir)), inode); | |
d7e09d03 | 683 | ll_set_lock_data(sbi->ll_md_exp, inode, it, NULL); |
d7e09d03 PT |
684 | out: |
685 | ptlrpc_req_finished(request); | |
686 | return inode; | |
687 | } | |
688 | ||
689 | /* | |
690 | * By the time this is called, we already have created the directory cache | |
691 | * entry for the new file, but it is so far negative - it has no inode. | |
692 | * | |
693 | * We defer creating the OBD object(s) until open, to keep the intent and | |
694 | * non-intent code paths similar, and also because we do not have the MDS | |
695 | * inode number before calling ll_create_node() (which is needed for LOV), | |
696 | * so we would need to do yet another RPC to the MDS to store the LOV EA | |
697 | * data on the MDS. If needed, we would pass the PACKED lmm as data and | |
698 | * lmm_size in datalen (the MDS still has code which will handle that). | |
699 | * | |
700 | * If the create succeeds, we fill in the inode information | |
701 | * with d_instantiate(). | |
702 | */ | |
703 | static int ll_create_it(struct inode *dir, struct dentry *dentry, int mode, | |
704 | struct lookup_intent *it) | |
705 | { | |
706 | struct inode *inode; | |
707 | int rc = 0; | |
d7e09d03 | 708 | |
97a075cd JN |
709 | CDEBUG(D_VFSTRACE, "VFS Op:name=%pd, dir="DFID"(%p), intent=%s\n", |
710 | dentry, PFID(ll_inode2fid(dir)), dir, LL_IT2STR(it)); | |
d7e09d03 PT |
711 | |
712 | rc = it_open_error(DISP_OPEN_CREATE, it); | |
713 | if (rc) | |
0a3bdb00 | 714 | return rc; |
d7e09d03 | 715 | |
2d95f10e | 716 | inode = ll_create_node(dir, it); |
d7e09d03 | 717 | if (IS_ERR(inode)) |
0a3bdb00 | 718 | return PTR_ERR(inode); |
d7e09d03 | 719 | |
d7e09d03 | 720 | d_instantiate(dentry, inode); |
0a3bdb00 | 721 | return 0; |
d7e09d03 PT |
722 | } |
723 | ||
724 | static void ll_update_times(struct ptlrpc_request *request, | |
725 | struct inode *inode) | |
726 | { | |
727 | struct mdt_body *body = req_capsule_server_get(&request->rq_pill, | |
728 | &RMF_MDT_BODY); | |
729 | ||
730 | LASSERT(body); | |
731 | if (body->valid & OBD_MD_FLMTIME && | |
732 | body->mtime > LTIME_S(inode->i_mtime)) { | |
97a075cd JN |
733 | CDEBUG(D_INODE, "setting fid "DFID" mtime from %lu to %llu\n", |
734 | PFID(ll_inode2fid(inode)), LTIME_S(inode->i_mtime), | |
735 | body->mtime); | |
d7e09d03 PT |
736 | LTIME_S(inode->i_mtime) = body->mtime; |
737 | } | |
738 | if (body->valid & OBD_MD_FLCTIME && | |
739 | body->ctime > LTIME_S(inode->i_ctime)) | |
740 | LTIME_S(inode->i_ctime) = body->ctime; | |
741 | } | |
742 | ||
b2037bb6 | 743 | static int ll_new_node(struct inode *dir, struct dentry *dentry, |
d7e09d03 | 744 | const char *tgt, int mode, int rdev, |
b2037bb6 | 745 | __u32 opc) |
d7e09d03 PT |
746 | { |
747 | struct ptlrpc_request *request = NULL; | |
748 | struct md_op_data *op_data; | |
749 | struct inode *inode = NULL; | |
750 | struct ll_sb_info *sbi = ll_i2sbi(dir); | |
751 | int tgt_len = 0; | |
752 | int err; | |
753 | ||
6e16818b | 754 | if (unlikely(tgt)) |
d7e09d03 PT |
755 | tgt_len = strlen(tgt) + 1; |
756 | ||
b2037bb6 AV |
757 | op_data = ll_prep_md_op_data(NULL, dir, NULL, |
758 | dentry->d_name.name, | |
759 | dentry->d_name.len, | |
760 | 0, opc, NULL); | |
34e1f2bb JL |
761 | if (IS_ERR(op_data)) { |
762 | err = PTR_ERR(op_data); | |
763 | goto err_exit; | |
764 | } | |
d7e09d03 PT |
765 | |
766 | err = md_create(sbi->ll_md_exp, op_data, tgt, tgt_len, mode, | |
4b1a25f0 PT |
767 | from_kuid(&init_user_ns, current_fsuid()), |
768 | from_kgid(&init_user_ns, current_fsgid()), | |
d7e09d03 PT |
769 | cfs_curproc_cap_pack(), rdev, &request); |
770 | ll_finish_md_op_data(op_data); | |
771 | if (err) | |
34e1f2bb | 772 | goto err_exit; |
d7e09d03 PT |
773 | |
774 | ll_update_times(request, dir); | |
775 | ||
b2037bb6 AV |
776 | err = ll_prep_inode(&inode, request, dir->i_sb, NULL); |
777 | if (err) | |
778 | goto err_exit; | |
d7e09d03 | 779 | |
b2037bb6 | 780 | d_instantiate(dentry, inode); |
d7e09d03 PT |
781 | err_exit: |
782 | ptlrpc_req_finished(request); | |
783 | ||
784 | return err; | |
785 | } | |
786 | ||
d6689e5f AV |
787 | static int ll_mknod(struct inode *dir, struct dentry *dchild, |
788 | umode_t mode, dev_t rdev) | |
d7e09d03 PT |
789 | { |
790 | int err; | |
d7e09d03 | 791 | |
97a075cd JN |
792 | CDEBUG(D_VFSTRACE, "VFS Op:name=%pd, dir="DFID"(%p) mode %o dev %x\n", |
793 | dchild, PFID(ll_inode2fid(dir)), dir, mode, | |
794 | old_encode_dev(rdev)); | |
d7e09d03 PT |
795 | |
796 | if (!IS_POSIXACL(dir) || !exp_connect_umask(ll_i2mdexp(dir))) | |
797 | mode &= ~current_umask(); | |
798 | ||
799 | switch (mode & S_IFMT) { | |
800 | case 0: | |
801 | mode |= S_IFREG; /* for mode = 0 case, fallthrough */ | |
802 | case S_IFREG: | |
803 | case S_IFCHR: | |
804 | case S_IFBLK: | |
805 | case S_IFIFO: | |
806 | case S_IFSOCK: | |
b2037bb6 AV |
807 | err = ll_new_node(dir, dchild, NULL, mode, |
808 | old_encode_dev(rdev), | |
d7e09d03 PT |
809 | LUSTRE_OPC_MKNOD); |
810 | break; | |
811 | case S_IFDIR: | |
812 | err = -EPERM; | |
813 | break; | |
814 | default: | |
815 | err = -EINVAL; | |
816 | } | |
817 | ||
818 | if (!err) | |
819 | ll_stats_ops_tally(ll_i2sbi(dir), LPROC_LL_MKNOD, 1); | |
820 | ||
0a3bdb00 | 821 | return err; |
d7e09d03 PT |
822 | } |
823 | ||
824 | /* | |
825 | * Plain create. Intent create is handled in atomic_open. | |
826 | */ | |
827 | static int ll_create_nd(struct inode *dir, struct dentry *dentry, | |
828 | umode_t mode, bool want_excl) | |
829 | { | |
830 | int rc; | |
831 | ||
97a075cd JN |
832 | CDEBUG(D_VFSTRACE, "VFS Op:name=%pd, dir="DFID"(%p), flags=%u, excl=%d\n", |
833 | dentry, PFID(ll_inode2fid(dir)), dir, mode, want_excl); | |
d7e09d03 | 834 | |
d6689e5f | 835 | rc = ll_mknod(dir, dentry, mode, 0); |
d7e09d03 PT |
836 | |
837 | ll_stats_ops_tally(ll_i2sbi(dir), LPROC_LL_CREATE, 1); | |
838 | ||
09561a53 AV |
839 | CDEBUG(D_VFSTRACE, "VFS Op:name=%pd, unhashed %d\n", |
840 | dentry, d_unhashed(dentry)); | |
d7e09d03 PT |
841 | |
842 | return rc; | |
843 | } | |
844 | ||
d7e09d03 PT |
845 | int ll_objects_destroy(struct ptlrpc_request *request, struct inode *dir) |
846 | { | |
847 | struct mdt_body *body; | |
848 | struct lov_mds_md *eadata; | |
849 | struct lov_stripe_md *lsm = NULL; | |
850 | struct obd_trans_info oti = { 0 }; | |
851 | struct obdo *oa; | |
d7e09d03 | 852 | int rc; |
d7e09d03 PT |
853 | |
854 | /* req is swabbed so this is safe */ | |
855 | body = req_capsule_server_get(&request->rq_pill, &RMF_MDT_BODY); | |
856 | if (!(body->valid & OBD_MD_FLEASIZE)) | |
0a3bdb00 | 857 | return 0; |
d7e09d03 PT |
858 | |
859 | if (body->eadatasize == 0) { | |
860 | CERROR("OBD_MD_FLEASIZE set but eadatasize zero\n"); | |
34e1f2bb JL |
861 | rc = -EPROTO; |
862 | goto out; | |
d7e09d03 PT |
863 | } |
864 | ||
865 | /* The MDS sent back the EA because we unlinked the last reference | |
866 | * to this file. Use this EA to unlink the objects on the OST. | |
867 | * It's opaque so we don't swab here; we leave it to obd_unpackmd() to | |
c0894c6c OD |
868 | * check it is complete and sensible. |
869 | */ | |
d7e09d03 PT |
870 | eadata = req_capsule_server_sized_get(&request->rq_pill, &RMF_MDT_MD, |
871 | body->eadatasize); | |
6e16818b | 872 | LASSERT(eadata); |
d7e09d03 PT |
873 | |
874 | rc = obd_unpackmd(ll_i2dtexp(dir), &lsm, eadata, body->eadatasize); | |
875 | if (rc < 0) { | |
876 | CERROR("obd_unpackmd: %d\n", rc); | |
34e1f2bb | 877 | goto out; |
d7e09d03 PT |
878 | } |
879 | LASSERT(rc >= sizeof(*lsm)); | |
880 | ||
21068c46 | 881 | oa = kmem_cache_zalloc(obdo_cachep, GFP_NOFS); |
6e16818b | 882 | if (!oa) { |
34e1f2bb JL |
883 | rc = -ENOMEM; |
884 | goto out_free_memmd; | |
885 | } | |
d7e09d03 PT |
886 | |
887 | oa->o_oi = lsm->lsm_oi; | |
888 | oa->o_mode = body->mode & S_IFMT; | |
889 | oa->o_valid = OBD_MD_FLID | OBD_MD_FLTYPE | OBD_MD_FLGROUP; | |
890 | ||
891 | if (body->valid & OBD_MD_FLCOOKIE) { | |
892 | oa->o_valid |= OBD_MD_FLCOOKIE; | |
893 | oti.oti_logcookies = | |
894 | req_capsule_server_sized_get(&request->rq_pill, | |
895 | &RMF_LOGCOOKIES, | |
896 | sizeof(struct llog_cookie) * | |
897 | lsm->lsm_stripe_count); | |
6e16818b | 898 | if (!oti.oti_logcookies) { |
d7e09d03 PT |
899 | oa->o_valid &= ~OBD_MD_FLCOOKIE; |
900 | body->valid &= ~OBD_MD_FLCOOKIE; | |
901 | } | |
902 | } | |
903 | ||
d7e09d03 | 904 | rc = obd_destroy(NULL, ll_i2dtexp(dir), oa, lsm, &oti, |
ef2e0f55 | 905 | ll_i2mdexp(dir)); |
d7e09d03 PT |
906 | if (rc) |
907 | CERROR("obd destroy objid "DOSTID" error %d\n", | |
908 | POSTID(&lsm->lsm_oi), rc); | |
909 | out_free_memmd: | |
910 | obd_free_memmd(ll_i2dtexp(dir), &lsm); | |
2ba262fb | 911 | kmem_cache_free(obdo_cachep, oa); |
d7e09d03 PT |
912 | out: |
913 | return rc; | |
914 | } | |
915 | ||
521f2ad7 AV |
916 | /* ll_unlink() doesn't update the inode with the new link count. |
917 | * Instead, ll_ddelete() and ll_d_iput() will update it based upon if there | |
918 | * is any lock existing. They will recycle dentries and inodes based upon locks | |
c0894c6c OD |
919 | * too. b=20433 |
920 | */ | |
96d61c24 | 921 | static int ll_unlink(struct inode *dir, struct dentry *dchild) |
d7e09d03 | 922 | { |
521f2ad7 AV |
923 | struct ptlrpc_request *request = NULL; |
924 | struct md_op_data *op_data; | |
925 | int rc; | |
43550121 | 926 | |
521f2ad7 | 927 | CDEBUG(D_VFSTRACE, "VFS Op:name=%pd,dir=%lu/%u(%p)\n", |
96d61c24 | 928 | dchild, dir->i_ino, dir->i_generation, dir); |
521f2ad7 | 929 | |
521f2ad7 | 930 | op_data = ll_prep_md_op_data(NULL, dir, NULL, |
96d61c24 AP |
931 | dchild->d_name.name, |
932 | dchild->d_name.len, | |
521f2ad7 AV |
933 | 0, LUSTRE_OPC_ANY, NULL); |
934 | if (IS_ERR(op_data)) | |
935 | return PTR_ERR(op_data); | |
936 | ||
3c4b9d09 AP |
937 | if (dchild && dchild->d_inode) |
938 | op_data->op_fid3 = *ll_inode2fid(dchild->d_inode); | |
939 | ||
521f2ad7 AV |
940 | op_data->op_fid2 = op_data->op_fid3; |
941 | rc = md_unlink(ll_i2sbi(dir)->ll_md_exp, op_data, &request); | |
942 | ll_finish_md_op_data(op_data); | |
943 | if (rc) | |
944 | goto out; | |
945 | ||
946 | ll_update_times(request, dir); | |
947 | ll_stats_ops_tally(ll_i2sbi(dir), LPROC_LL_UNLINK, 1); | |
948 | ||
949 | rc = ll_objects_destroy(request, dir); | |
950 | out: | |
951 | ptlrpc_req_finished(request); | |
952 | return rc; | |
d7e09d03 PT |
953 | } |
954 | ||
e3befdc7 | 955 | static int ll_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode) |
d7e09d03 | 956 | { |
7c2f9094 AV |
957 | int err; |
958 | ||
97a075cd JN |
959 | CDEBUG(D_VFSTRACE, "VFS Op:name=%pd, dir"DFID"(%p)\n", |
960 | dentry, PFID(ll_inode2fid(dir)), dir); | |
7c2f9094 AV |
961 | |
962 | if (!IS_POSIXACL(dir) || !exp_connect_umask(ll_i2mdexp(dir))) | |
963 | mode &= ~current_umask(); | |
964 | mode = (mode & (S_IRWXUGO|S_ISVTX)) | S_IFDIR; | |
b2037bb6 | 965 | err = ll_new_node(dir, dentry, NULL, mode, 0, LUSTRE_OPC_MKDIR); |
7c2f9094 AV |
966 | |
967 | if (!err) | |
968 | ll_stats_ops_tally(ll_i2sbi(dir), LPROC_LL_MKDIR, 1); | |
969 | ||
970 | return err; | |
d7e09d03 PT |
971 | } |
972 | ||
96d61c24 | 973 | static int ll_rmdir(struct inode *dir, struct dentry *dchild) |
d7e09d03 | 974 | { |
55dec617 AV |
975 | struct ptlrpc_request *request = NULL; |
976 | struct md_op_data *op_data; | |
977 | int rc; | |
978 | ||
97a075cd JN |
979 | CDEBUG(D_VFSTRACE, "VFS Op:name=%pd, dir="DFID"(%p)\n", |
980 | dchild, PFID(ll_inode2fid(dir)), dir); | |
55dec617 | 981 | |
55dec617 | 982 | op_data = ll_prep_md_op_data(NULL, dir, NULL, |
96d61c24 AP |
983 | dchild->d_name.name, |
984 | dchild->d_name.len, | |
55dec617 AV |
985 | S_IFDIR, LUSTRE_OPC_ANY, NULL); |
986 | if (IS_ERR(op_data)) | |
987 | return PTR_ERR(op_data); | |
988 | ||
3c4b9d09 AP |
989 | if (dchild && dchild->d_inode) |
990 | op_data->op_fid3 = *ll_inode2fid(dchild->d_inode); | |
991 | ||
55dec617 AV |
992 | op_data->op_fid2 = op_data->op_fid3; |
993 | rc = md_unlink(ll_i2sbi(dir)->ll_md_exp, op_data, &request); | |
994 | ll_finish_md_op_data(op_data); | |
995 | if (rc == 0) { | |
996 | ll_update_times(request, dir); | |
997 | ll_stats_ops_tally(ll_i2sbi(dir), LPROC_LL_RMDIR, 1); | |
998 | } | |
999 | ||
1000 | ptlrpc_req_finished(request); | |
1001 | return rc; | |
d7e09d03 PT |
1002 | } |
1003 | ||
1004 | static int ll_symlink(struct inode *dir, struct dentry *dentry, | |
1005 | const char *oldname) | |
1006 | { | |
60dd654e AV |
1007 | int err; |
1008 | ||
97a075cd JN |
1009 | CDEBUG(D_VFSTRACE, "VFS Op:name=%pd, dir="DFID"(%p),target=%.*s\n", |
1010 | dentry, PFID(ll_inode2fid(dir)), dir, 3000, oldname); | |
60dd654e | 1011 | |
b2037bb6 | 1012 | err = ll_new_node(dir, dentry, oldname, S_IFLNK | S_IRWXUGO, |
e15ba45d | 1013 | 0, LUSTRE_OPC_SYMLINK); |
60dd654e AV |
1014 | |
1015 | if (!err) | |
1016 | ll_stats_ops_tally(ll_i2sbi(dir), LPROC_LL_SYMLINK, 1); | |
1017 | ||
1018 | return err; | |
d7e09d03 PT |
1019 | } |
1020 | ||
1021 | static int ll_link(struct dentry *old_dentry, struct inode *dir, | |
1022 | struct dentry *new_dentry) | |
1023 | { | |
2b0143b5 | 1024 | struct inode *src = d_inode(old_dentry); |
59cc93ef AV |
1025 | struct ll_sb_info *sbi = ll_i2sbi(dir); |
1026 | struct ptlrpc_request *request = NULL; | |
1027 | struct md_op_data *op_data; | |
1028 | int err; | |
1029 | ||
97a075cd JN |
1030 | CDEBUG(D_VFSTRACE, "VFS Op: inode="DFID"(%p), dir="DFID"(%p), target=%pd\n", |
1031 | PFID(ll_inode2fid(src)), src, PFID(ll_inode2fid(dir)), dir, | |
1032 | new_dentry); | |
59cc93ef AV |
1033 | |
1034 | op_data = ll_prep_md_op_data(NULL, src, dir, new_dentry->d_name.name, | |
1035 | new_dentry->d_name.len, | |
1036 | 0, LUSTRE_OPC_ANY, NULL); | |
1037 | if (IS_ERR(op_data)) | |
1038 | return PTR_ERR(op_data); | |
1039 | ||
1040 | err = md_link(sbi->ll_md_exp, op_data, &request); | |
1041 | ll_finish_md_op_data(op_data); | |
1042 | if (err) | |
1043 | goto out; | |
1044 | ||
1045 | ll_update_times(request, dir); | |
1046 | ll_stats_ops_tally(sbi, LPROC_LL_LINK, 1); | |
1047 | out: | |
1048 | ptlrpc_req_finished(request); | |
1049 | return err; | |
d7e09d03 PT |
1050 | } |
1051 | ||
96d61c24 | 1052 | static int ll_rename(struct inode *src, struct dentry *src_dchild, |
1423ecc0 MS |
1053 | struct inode *tgt, struct dentry *tgt_dchild, |
1054 | unsigned int flags) | |
d7e09d03 | 1055 | { |
78851093 | 1056 | struct ptlrpc_request *request = NULL; |
96d61c24 | 1057 | struct ll_sb_info *sbi = ll_i2sbi(src); |
78851093 | 1058 | struct md_op_data *op_data; |
d7e09d03 | 1059 | int err; |
78851093 | 1060 | |
1423ecc0 MS |
1061 | if (flags) |
1062 | return -EINVAL; | |
1063 | ||
78851093 | 1064 | CDEBUG(D_VFSTRACE, |
97a075cd JN |
1065 | "VFS Op:oldname=%pd, src_dir="DFID"(%p), newname=%pd, tgt_dir="DFID"(%p)\n", |
1066 | src_dchild, PFID(ll_inode2fid(src)), src, | |
1067 | tgt_dchild, PFID(ll_inode2fid(tgt)), tgt); | |
78851093 | 1068 | |
96d61c24 | 1069 | op_data = ll_prep_md_op_data(NULL, src, tgt, NULL, 0, 0, |
78851093 AV |
1070 | LUSTRE_OPC_ANY, NULL); |
1071 | if (IS_ERR(op_data)) | |
1072 | return PTR_ERR(op_data); | |
1073 | ||
3c4b9d09 AP |
1074 | if (src_dchild && src_dchild->d_inode) |
1075 | op_data->op_fid3 = *ll_inode2fid(src_dchild->d_inode); | |
1076 | if (tgt_dchild && tgt_dchild->d_inode) | |
1077 | op_data->op_fid4 = *ll_inode2fid(tgt_dchild->d_inode); | |
1078 | ||
78851093 | 1079 | err = md_rename(sbi->ll_md_exp, op_data, |
96d61c24 AP |
1080 | src_dchild->d_name.name, |
1081 | src_dchild->d_name.len, | |
1082 | tgt_dchild->d_name.name, | |
1083 | tgt_dchild->d_name.len, &request); | |
78851093 | 1084 | ll_finish_md_op_data(op_data); |
d7e09d03 | 1085 | if (!err) { |
96d61c24 AP |
1086 | ll_update_times(request, src); |
1087 | ll_update_times(request, tgt); | |
78851093 | 1088 | ll_stats_ops_tally(sbi, LPROC_LL_RENAME, 1); |
96d61c24 | 1089 | err = ll_objects_destroy(request, src); |
d7e09d03 | 1090 | } |
78851093 AV |
1091 | |
1092 | ptlrpc_req_finished(request); | |
1093 | if (!err) | |
96d61c24 | 1094 | d_move(src_dchild, tgt_dchild); |
d7e09d03 PT |
1095 | return err; |
1096 | } | |
1097 | ||
2d95f10e | 1098 | const struct inode_operations ll_dir_inode_operations = { |
d7e09d03 PT |
1099 | .mknod = ll_mknod, |
1100 | .atomic_open = ll_atomic_open, | |
1101 | .lookup = ll_lookup_nd, | |
1102 | .create = ll_create_nd, | |
1103 | /* We need all these non-raw things for NFSD, to not patch it. */ | |
1104 | .unlink = ll_unlink, | |
1105 | .mkdir = ll_mkdir, | |
1106 | .rmdir = ll_rmdir, | |
1107 | .symlink = ll_symlink, | |
1108 | .link = ll_link, | |
34332745 | 1109 | .rename = ll_rename, |
d7e09d03 PT |
1110 | .setattr = ll_setattr, |
1111 | .getattr = ll_getattr, | |
1112 | .permission = ll_inode_permission, | |
1113 | .setxattr = ll_setxattr, | |
1114 | .getxattr = ll_getxattr, | |
1115 | .listxattr = ll_listxattr, | |
1116 | .removexattr = ll_removexattr, | |
1117 | .get_acl = ll_get_acl, | |
1118 | }; | |
1119 | ||
2d95f10e | 1120 | const struct inode_operations ll_special_inode_operations = { |
d7e09d03 PT |
1121 | .setattr = ll_setattr, |
1122 | .getattr = ll_getattr, | |
1123 | .permission = ll_inode_permission, | |
1124 | .setxattr = ll_setxattr, | |
1125 | .getxattr = ll_getxattr, | |
1126 | .listxattr = ll_listxattr, | |
1127 | .removexattr = ll_removexattr, | |
1128 | .get_acl = ll_get_acl, | |
1129 | }; |