]> git.kernelconcepts.de Git - karo-tx-linux.git/blob - fs/orangefs/namei.c
Merge remote-tracking branch 'orangefs/for-next'
[karo-tx-linux.git] / fs / orangefs / namei.c
1 /*
2  * (C) 2001 Clemson University and The University of Chicago
3  *
4  * See COPYING in top-level directory.
5  */
6
7 /*
8  *  Linux VFS namei operations.
9  */
10
11 #include "protocol.h"
12 #include "pvfs2-kernel.h"
13
14 /*
15  * Get a newly allocated inode to go with a negative dentry.
16  */
17 static int pvfs2_create(struct inode *dir,
18                         struct dentry *dentry,
19                         umode_t mode,
20                         bool exclusive)
21 {
22         struct pvfs2_inode_s *parent = PVFS2_I(dir);
23         struct pvfs2_kernel_op_s *new_op;
24         struct inode *inode;
25         int ret;
26
27         gossip_debug(GOSSIP_NAME_DEBUG, "%s: called\n", __func__);
28
29         new_op = op_alloc(PVFS2_VFS_OP_CREATE);
30         if (!new_op)
31                 return -ENOMEM;
32
33         new_op->upcall.req.create.parent_refn = parent->refn;
34
35         fill_default_sys_attrs(new_op->upcall.req.create.attributes,
36                                PVFS_TYPE_METAFILE, mode);
37
38         strncpy(new_op->upcall.req.create.d_name,
39                 dentry->d_name.name, PVFS2_NAME_LEN);
40
41         ret = service_operation(new_op, __func__, get_interruptible_flag(dir));
42
43         gossip_debug(GOSSIP_NAME_DEBUG,
44                      "Create Got PVFS2 handle %pU on fsid %d (ret=%d)\n",
45                      &new_op->downcall.resp.create.refn.khandle,
46                      new_op->downcall.resp.create.refn.fs_id, ret);
47
48         if (ret < 0) {
49                 gossip_debug(GOSSIP_NAME_DEBUG,
50                              "%s: failed with error code %d\n",
51                              __func__, ret);
52                 goto out;
53         }
54
55         inode = pvfs2_new_inode(dir->i_sb, dir, S_IFREG | mode, 0,
56                                 &new_op->downcall.resp.create.refn);
57         if (IS_ERR(inode)) {
58                 gossip_err("*** Failed to allocate pvfs2 file inode\n");
59                 ret = PTR_ERR(inode);
60                 goto out;
61         }
62
63         gossip_debug(GOSSIP_NAME_DEBUG,
64                      "Assigned file inode new number of %pU\n",
65                      get_khandle_from_ino(inode));
66
67         d_instantiate(dentry, inode);
68         unlock_new_inode(inode);
69
70         gossip_debug(GOSSIP_NAME_DEBUG,
71                      "Inode (Regular File) %pU -> %s\n",
72                      get_khandle_from_ino(inode),
73                      dentry->d_name.name);
74
75         SetMtimeFlag(parent);
76         dir->i_mtime = dir->i_ctime = current_fs_time(dir->i_sb);
77         mark_inode_dirty_sync(dir);
78         ret = 0;
79 out:
80         op_release(new_op);
81         gossip_debug(GOSSIP_NAME_DEBUG, "%s: returning %d\n", __func__, ret);
82         return ret;
83 }
84
85 /*
86  * Attempt to resolve an object name (dentry->d_name), parent handle, and
87  * fsid into a handle for the object.
88  */
89 static struct dentry *pvfs2_lookup(struct inode *dir, struct dentry *dentry,
90                                    unsigned int flags)
91 {
92         struct pvfs2_inode_s *parent = PVFS2_I(dir);
93         struct pvfs2_kernel_op_s *new_op;
94         struct inode *inode;
95         struct dentry *res;
96         int ret = -EINVAL;
97
98         /*
99          * in theory we could skip a lookup here (if the intent is to
100          * create) in order to avoid a potentially failed lookup, but
101          * leaving it in can skip a valid lookup and try to create a file
102          * that already exists (e.g. the vfs already handles checking for
103          * -EEXIST on O_EXCL opens, which is broken if we skip this lookup
104          * in the create path)
105          */
106         gossip_debug(GOSSIP_NAME_DEBUG, "%s called on %s\n",
107                      __func__, dentry->d_name.name);
108
109         if (dentry->d_name.len > (PVFS2_NAME_LEN - 1))
110                 return ERR_PTR(-ENAMETOOLONG);
111
112         new_op = op_alloc(PVFS2_VFS_OP_LOOKUP);
113         if (!new_op)
114                 return ERR_PTR(-ENOMEM);
115
116         new_op->upcall.req.lookup.sym_follow = flags & LOOKUP_FOLLOW;
117
118         gossip_debug(GOSSIP_NAME_DEBUG, "%s:%s:%d using parent %pU\n",
119                      __FILE__,
120                      __func__,
121                      __LINE__,
122                      &parent->refn.khandle);
123         new_op->upcall.req.lookup.parent_refn = parent->refn;
124
125         strncpy(new_op->upcall.req.lookup.d_name, dentry->d_name.name,
126                 PVFS2_NAME_LEN);
127
128         gossip_debug(GOSSIP_NAME_DEBUG,
129                      "%s: doing lookup on %s under %pU,%d (follow=%s)\n",
130                      __func__,
131                      new_op->upcall.req.lookup.d_name,
132                      &new_op->upcall.req.lookup.parent_refn.khandle,
133                      new_op->upcall.req.lookup.parent_refn.fs_id,
134                      ((new_op->upcall.req.lookup.sym_follow ==
135                        PVFS2_LOOKUP_LINK_FOLLOW) ? "yes" : "no"));
136
137         ret = service_operation(new_op, __func__, get_interruptible_flag(dir));
138
139         gossip_debug(GOSSIP_NAME_DEBUG,
140                      "Lookup Got %pU, fsid %d (ret=%d)\n",
141                      &new_op->downcall.resp.lookup.refn.khandle,
142                      new_op->downcall.resp.lookup.refn.fs_id,
143                      ret);
144
145         if (ret < 0) {
146                 if (ret == -ENOENT) {
147                         /*
148                          * if no inode was found, add a negative dentry to
149                          * dcache anyway; if we don't, we don't hold expected
150                          * lookup semantics and we most noticeably break
151                          * during directory renames.
152                          *
153                          * however, if the operation failed or exited, do not
154                          * add the dentry (e.g. in the case that a touch is
155                          * issued on a file that already exists that was
156                          * interrupted during this lookup -- no need to add
157                          * another negative dentry for an existing file)
158                          */
159
160                         gossip_debug(GOSSIP_NAME_DEBUG,
161                                      "pvfs2_lookup: Adding *negative* dentry "
162                                      "%p for %s\n",
163                                      dentry,
164                                      dentry->d_name.name);
165
166                         d_add(dentry, NULL);
167                         res = NULL;
168                         goto out;
169                 }
170
171                 /* must be a non-recoverable error */
172                 res = ERR_PTR(ret);
173                 goto out;
174         }
175
176         inode = pvfs2_iget(dir->i_sb, &new_op->downcall.resp.lookup.refn);
177         if (IS_ERR(inode)) {
178                 gossip_debug(GOSSIP_NAME_DEBUG,
179                         "error %ld from iget\n", PTR_ERR(inode));
180                 res = ERR_CAST(inode);
181                 goto out;
182         }
183
184         gossip_debug(GOSSIP_NAME_DEBUG,
185                      "%s:%s:%d "
186                      "Found good inode [%lu] with count [%d]\n",
187                      __FILE__,
188                      __func__,
189                      __LINE__,
190                      inode->i_ino,
191                      (int)atomic_read(&inode->i_count));
192
193         /* update dentry/inode pair into dcache */
194         res = d_splice_alias(inode, dentry);
195
196         gossip_debug(GOSSIP_NAME_DEBUG,
197                      "Lookup success (inode ct = %d)\n",
198                      (int)atomic_read(&inode->i_count));
199 out:
200         op_release(new_op);
201         return res;
202 }
203
204 /* return 0 on success; non-zero otherwise */
205 static int pvfs2_unlink(struct inode *dir, struct dentry *dentry)
206 {
207         struct inode *inode = dentry->d_inode;
208         struct pvfs2_inode_s *parent = PVFS2_I(dir);
209         struct pvfs2_kernel_op_s *new_op;
210         int ret;
211
212         gossip_debug(GOSSIP_NAME_DEBUG,
213                      "%s: called on %s\n"
214                      "  (inode %pU): Parent is %pU | fs_id %d\n",
215                      __func__,
216                      dentry->d_name.name,
217                      get_khandle_from_ino(inode),
218                      &parent->refn.khandle,
219                      parent->refn.fs_id);
220
221         new_op = op_alloc(PVFS2_VFS_OP_REMOVE);
222         if (!new_op)
223                 return -ENOMEM;
224
225         new_op->upcall.req.remove.parent_refn = parent->refn;
226         strncpy(new_op->upcall.req.remove.d_name, dentry->d_name.name,
227                 PVFS2_NAME_LEN);
228
229         ret = service_operation(new_op, "pvfs2_unlink",
230                                 get_interruptible_flag(inode));
231
232         /* when request is serviced properly, free req op struct */
233         op_release(new_op);
234
235         if (!ret) {
236                 drop_nlink(inode);
237
238                 SetMtimeFlag(parent);
239                 dir->i_mtime = dir->i_ctime = current_fs_time(dir->i_sb);
240                 mark_inode_dirty_sync(dir);
241         }
242         return ret;
243 }
244
245 /*
246  * PVFS2 does not support hard links.
247  */
248 static int pvfs2_link(struct dentry *old_dentry,
249                       struct inode *dir,
250                       struct dentry *dentry)
251 {
252         return -EPERM;
253 }
254
255 /*
256  * PVFS2 does not support special files.
257  */
258 static int pvfs2_mknod(struct inode *dir,
259                        struct dentry *dentry,
260                        umode_t mode,
261                        dev_t rdev)
262 {
263         return -EPERM;
264 }
265
266 static int pvfs2_symlink(struct inode *dir,
267                          struct dentry *dentry,
268                          const char *symname)
269 {
270         struct pvfs2_inode_s *parent = PVFS2_I(dir);
271         struct pvfs2_kernel_op_s *new_op;
272         struct inode *inode;
273         int mode = 755;
274         int ret;
275
276         gossip_debug(GOSSIP_NAME_DEBUG, "%s: called\n", __func__);
277
278         if (!symname)
279                 return -EINVAL;
280
281         new_op = op_alloc(PVFS2_VFS_OP_SYMLINK);
282         if (!new_op)
283                 return -ENOMEM;
284
285         new_op->upcall.req.sym.parent_refn = parent->refn;
286
287         fill_default_sys_attrs(new_op->upcall.req.sym.attributes,
288                                PVFS_TYPE_SYMLINK,
289                                mode);
290
291         strncpy(new_op->upcall.req.sym.entry_name,
292                 dentry->d_name.name,
293                 PVFS2_NAME_LEN);
294         strncpy(new_op->upcall.req.sym.target, symname, PVFS2_NAME_LEN);
295
296         ret = service_operation(new_op, __func__, get_interruptible_flag(dir));
297
298         gossip_debug(GOSSIP_NAME_DEBUG,
299                      "Symlink Got PVFS2 handle %pU on fsid %d (ret=%d)\n",
300                      &new_op->downcall.resp.sym.refn.khandle,
301                      new_op->downcall.resp.sym.refn.fs_id, ret);
302
303         if (ret < 0) {
304                 gossip_debug(GOSSIP_NAME_DEBUG,
305                             "%s: failed with error code %d\n",
306                             __func__, ret);
307                 goto out;
308         }
309
310         inode = pvfs2_new_inode(dir->i_sb, dir, S_IFLNK | mode, 0,
311                                 &new_op->downcall.resp.sym.refn);
312         if (IS_ERR(inode)) {
313                 gossip_err
314                     ("*** Failed to allocate pvfs2 symlink inode\n");
315                 ret = PTR_ERR(inode);
316                 goto out;
317         }
318
319         gossip_debug(GOSSIP_NAME_DEBUG,
320                      "Assigned symlink inode new number of %pU\n",
321                      get_khandle_from_ino(inode));
322
323         d_instantiate(dentry, inode);
324         unlock_new_inode(inode);
325
326         gossip_debug(GOSSIP_NAME_DEBUG,
327                      "Inode (Symlink) %pU -> %s\n",
328                      get_khandle_from_ino(inode),
329                      dentry->d_name.name);
330
331         SetMtimeFlag(parent);
332         dir->i_mtime = dir->i_ctime = current_fs_time(dir->i_sb);
333         mark_inode_dirty_sync(dir);
334         ret = 0;
335 out:
336         op_release(new_op);
337         return ret;
338 }
339
340 static int pvfs2_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
341 {
342         struct pvfs2_inode_s *parent = PVFS2_I(dir);
343         struct pvfs2_kernel_op_s *new_op;
344         struct inode *inode;
345         int ret;
346
347         new_op = op_alloc(PVFS2_VFS_OP_MKDIR);
348         if (!new_op)
349                 return -ENOMEM;
350
351         new_op->upcall.req.mkdir.parent_refn = parent->refn;
352
353         fill_default_sys_attrs(new_op->upcall.req.mkdir.attributes,
354                                PVFS_TYPE_DIRECTORY, mode);
355
356         strncpy(new_op->upcall.req.mkdir.d_name,
357                 dentry->d_name.name, PVFS2_NAME_LEN);
358
359         ret = service_operation(new_op, __func__, get_interruptible_flag(dir));
360
361         gossip_debug(GOSSIP_NAME_DEBUG,
362                      "Mkdir Got PVFS2 handle %pU on fsid %d\n",
363                      &new_op->downcall.resp.mkdir.refn.khandle,
364                      new_op->downcall.resp.mkdir.refn.fs_id);
365
366         if (ret < 0) {
367                 gossip_debug(GOSSIP_NAME_DEBUG,
368                              "%s: failed with error code %d\n",
369                              __func__, ret);
370                 goto out;
371         }
372
373         inode = pvfs2_new_inode(dir->i_sb, dir, S_IFDIR | mode, 0,
374                                 &new_op->downcall.resp.mkdir.refn);
375         if (IS_ERR(inode)) {
376                 gossip_err("*** Failed to allocate pvfs2 dir inode\n");
377                 ret = PTR_ERR(inode);
378                 goto out;
379         }
380
381         gossip_debug(GOSSIP_NAME_DEBUG,
382                      "Assigned dir inode new number of %pU\n",
383                      get_khandle_from_ino(inode));
384
385         d_instantiate(dentry, inode);
386         unlock_new_inode(inode);
387
388         gossip_debug(GOSSIP_NAME_DEBUG,
389                      "Inode (Directory) %pU -> %s\n",
390                      get_khandle_from_ino(inode),
391                      dentry->d_name.name);
392
393         /*
394          * NOTE: we have no good way to keep nlink consistent for directories
395          * across clients; keep constant at 1.
396          */
397         SetMtimeFlag(parent);
398         dir->i_mtime = dir->i_ctime = current_fs_time(dir->i_sb);
399         mark_inode_dirty_sync(dir);
400 out:
401         op_release(new_op);
402         return ret;
403 }
404
405 static int pvfs2_rename(struct inode *old_dir,
406                         struct dentry *old_dentry,
407                         struct inode *new_dir,
408                         struct dentry *new_dentry)
409 {
410         struct pvfs2_kernel_op_s *new_op;
411         int ret;
412
413         gossip_debug(GOSSIP_NAME_DEBUG,
414                      "pvfs2_rename: called (%s/%s => %s/%s) ct=%d\n",
415                      old_dentry->d_parent->d_name.name,
416                      old_dentry->d_name.name,
417                      new_dentry->d_parent->d_name.name,
418                      new_dentry->d_name.name,
419                      d_count(new_dentry));
420
421         new_op = op_alloc(PVFS2_VFS_OP_RENAME);
422         if (!new_op)
423                 return -EINVAL;
424
425         new_op->upcall.req.rename.old_parent_refn = PVFS2_I(old_dir)->refn;
426         new_op->upcall.req.rename.new_parent_refn = PVFS2_I(new_dir)->refn;
427
428         strncpy(new_op->upcall.req.rename.d_old_name,
429                 old_dentry->d_name.name,
430                 PVFS2_NAME_LEN);
431         strncpy(new_op->upcall.req.rename.d_new_name,
432                 new_dentry->d_name.name,
433                 PVFS2_NAME_LEN);
434
435         ret = service_operation(new_op,
436                                 "pvfs2_rename",
437                                 get_interruptible_flag(old_dentry->d_inode));
438
439         gossip_debug(GOSSIP_NAME_DEBUG,
440                      "pvfs2_rename: got downcall status %d\n",
441                      ret);
442
443         if (new_dentry->d_inode)
444                 new_dentry->d_inode->i_ctime = CURRENT_TIME;
445
446         op_release(new_op);
447         return ret;
448 }
449
450 /* PVFS2 implementation of VFS inode operations for directories */
451 struct inode_operations pvfs2_dir_inode_operations = {
452         .lookup = pvfs2_lookup,
453         .get_acl = pvfs2_get_acl,
454         .set_acl = pvfs2_set_acl,
455         .create = pvfs2_create,
456         .link = pvfs2_link,
457         .unlink = pvfs2_unlink,
458         .symlink = pvfs2_symlink,
459         .mkdir = pvfs2_mkdir,
460         .rmdir = pvfs2_unlink,
461         .mknod = pvfs2_mknod,
462         .rename = pvfs2_rename,
463         .setattr = pvfs2_setattr,
464         .getattr = pvfs2_getattr,
465         .setxattr = generic_setxattr,
466         .getxattr = generic_getxattr,
467         .removexattr = generic_removexattr,
468         .listxattr = pvfs2_listxattr,
469 };