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