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