~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/fs/orangefs/namei.c

Version: ~ [ linux-5.5-rc7 ] ~ [ linux-5.4.13 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.97 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.166 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.210 ] ~ [ linux-4.8.17 ] ~ [ linux-4.7.10 ] ~ [ linux-4.6.7 ] ~ [ linux-4.5.7 ] ~ [ linux-4.4.210 ] ~ [ linux-4.3.6 ] ~ [ linux-4.2.8 ] ~ [ linux-4.1.52 ] ~ [ linux-4.0.9 ] ~ [ linux-3.19.8 ] ~ [ linux-3.18.140 ] ~ [ linux-3.17.8 ] ~ [ linux-3.16.81 ] ~ [ linux-3.15.10 ] ~ [ linux-3.14.79 ] ~ [ linux-3.13.11 ] ~ [ linux-3.12.74 ] ~ [ linux-3.11.10 ] ~ [ linux-3.10.108 ] ~ [ linux-3.9.11 ] ~ [ linux-3.8.13 ] ~ [ linux-3.7.10 ] ~ [ linux-3.6.11 ] ~ [ linux-3.5.7 ] ~ [ linux-3.4.113 ] ~ [ linux-3.3.8 ] ~ [ linux-3.2.102 ] ~ [ linux-3.1.10 ] ~ [ linux-3.0.101 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.5 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  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 
 62         inode = orangefs_new_inode(dir->i_sb, dir, S_IFREG | mode, 0, &ref);
 63         if (IS_ERR(inode)) {
 64                 gossip_err("%s: Failed to allocate inode for file :%pd:\n",
 65                            __func__,
 66                            dentry);
 67                 ret = PTR_ERR(inode);
 68                 goto out;
 69         }
 70 
 71         gossip_debug(GOSSIP_NAME_DEBUG,
 72                      "%s: Assigned inode :%pU: for file :%pd:\n",
 73                      __func__,
 74                      get_khandle_from_ino(inode),
 75                      dentry);
 76 
 77         d_instantiate_new(dentry, inode);
 78         orangefs_set_timeout(dentry);
 79         ORANGEFS_I(inode)->getattr_time = jiffies - 1;
 80         ORANGEFS_I(inode)->getattr_mask = STATX_BASIC_STATS;
 81 
 82         gossip_debug(GOSSIP_NAME_DEBUG,
 83                      "%s: dentry instantiated for %pd\n",
 84                      __func__,
 85                      dentry);
 86 
 87         dir->i_mtime = dir->i_ctime = current_time(dir);
 88         memset(&iattr, 0, sizeof iattr);
 89         iattr.ia_valid |= ATTR_MTIME;
 90         orangefs_inode_setattr(dir, &iattr);
 91         mark_inode_dirty_sync(dir);
 92         ret = 0;
 93 out:
 94         op_release(new_op);
 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         int ret = -EINVAL;
114 
115         /*
116          * in theory we could skip a lookup here (if the intent is to
117          * create) in order to avoid a potentially failed lookup, but
118          * leaving it in can skip a valid lookup and try to create a file
119          * that already exists (e.g. the vfs already handles checking for
120          * -EEXIST on O_EXCL opens, which is broken if we skip this lookup
121          * in the create path)
122          */
123         gossip_debug(GOSSIP_NAME_DEBUG, "%s called on %pd\n",
124                      __func__, dentry);
125 
126         if (dentry->d_name.len > (ORANGEFS_NAME_MAX - 1))
127                 return ERR_PTR(-ENAMETOOLONG);
128 
129         new_op = op_alloc(ORANGEFS_VFS_OP_LOOKUP);
130         if (!new_op)
131                 return ERR_PTR(-ENOMEM);
132 
133         new_op->upcall.req.lookup.sym_follow = ORANGEFS_LOOKUP_LINK_NO_FOLLOW;
134 
135         gossip_debug(GOSSIP_NAME_DEBUG, "%s:%s:%d using parent %pU\n",
136                      __FILE__,
137                      __func__,
138                      __LINE__,
139                      &parent->refn.khandle);
140         new_op->upcall.req.lookup.parent_refn = parent->refn;
141 
142         strncpy(new_op->upcall.req.lookup.d_name, dentry->d_name.name,
143                 ORANGEFS_NAME_MAX - 1);
144 
145         gossip_debug(GOSSIP_NAME_DEBUG,
146                      "%s: doing lookup on %s under %pU,%d\n",
147                      __func__,
148                      new_op->upcall.req.lookup.d_name,
149                      &new_op->upcall.req.lookup.parent_refn.khandle,
150                      new_op->upcall.req.lookup.parent_refn.fs_id);
151 
152         ret = service_operation(new_op, __func__, get_interruptible_flag(dir));
153 
154         gossip_debug(GOSSIP_NAME_DEBUG,
155                      "Lookup Got %pU, fsid %d (ret=%d)\n",
156                      &new_op->downcall.resp.lookup.refn.khandle,
157                      new_op->downcall.resp.lookup.refn.fs_id,
158                      ret);
159 
160         if (ret == 0) {
161                 orangefs_set_timeout(dentry);
162                 inode = orangefs_iget(dir->i_sb, &new_op->downcall.resp.lookup.refn);
163         } else if (ret == -ENOENT) {
164                 inode = NULL;
165         } else {
166                 /* must be a non-recoverable error */
167                 inode = ERR_PTR(ret);
168         }
169 
170         op_release(new_op);
171         return d_splice_alias(inode, dentry);
172 }
173 
174 /* return 0 on success; non-zero otherwise */
175 static int orangefs_unlink(struct inode *dir, struct dentry *dentry)
176 {
177         struct inode *inode = dentry->d_inode;
178         struct orangefs_inode_s *parent = ORANGEFS_I(dir);
179         struct orangefs_kernel_op_s *new_op;
180         struct iattr iattr;
181         int ret;
182 
183         gossip_debug(GOSSIP_NAME_DEBUG,
184                      "%s: called on %pd\n"
185                      "  (inode %pU): Parent is %pU | fs_id %d\n",
186                      __func__,
187                      dentry,
188                      get_khandle_from_ino(inode),
189                      &parent->refn.khandle,
190                      parent->refn.fs_id);
191 
192         new_op = op_alloc(ORANGEFS_VFS_OP_REMOVE);
193         if (!new_op)
194                 return -ENOMEM;
195 
196         new_op->upcall.req.remove.parent_refn = parent->refn;
197         strncpy(new_op->upcall.req.remove.d_name, dentry->d_name.name,
198                 ORANGEFS_NAME_MAX - 1);
199 
200         ret = service_operation(new_op, "orangefs_unlink",
201                                 get_interruptible_flag(inode));
202 
203         gossip_debug(GOSSIP_NAME_DEBUG,
204                      "%s: service_operation returned:%d:\n",
205                      __func__,
206                      ret);
207 
208         op_release(new_op);
209 
210         if (!ret) {
211                 drop_nlink(inode);
212 
213                 dir->i_mtime = dir->i_ctime = current_time(dir);
214                 memset(&iattr, 0, sizeof iattr);
215                 iattr.ia_valid |= ATTR_MTIME;
216                 orangefs_inode_setattr(dir, &iattr);
217                 mark_inode_dirty_sync(dir);
218         }
219         return ret;
220 }
221 
222 static int orangefs_symlink(struct inode *dir,
223                          struct dentry *dentry,
224                          const char *symname)
225 {
226         struct orangefs_inode_s *parent = ORANGEFS_I(dir);
227         struct orangefs_kernel_op_s *new_op;
228         struct orangefs_object_kref ref;
229         struct inode *inode;
230         struct iattr iattr;
231         int mode = 755;
232         int ret;
233 
234         gossip_debug(GOSSIP_NAME_DEBUG, "%s: called\n", __func__);
235 
236         if (!symname)
237                 return -EINVAL;
238 
239         if (strlen(symname)+1 > ORANGEFS_NAME_MAX)
240                 return -ENAMETOOLONG;
241 
242         new_op = op_alloc(ORANGEFS_VFS_OP_SYMLINK);
243         if (!new_op)
244                 return -ENOMEM;
245 
246         new_op->upcall.req.sym.parent_refn = parent->refn;
247 
248         fill_default_sys_attrs(new_op->upcall.req.sym.attributes,
249                                ORANGEFS_TYPE_SYMLINK,
250                                mode);
251 
252         strncpy(new_op->upcall.req.sym.entry_name,
253                 dentry->d_name.name,
254                 ORANGEFS_NAME_MAX - 1);
255         strncpy(new_op->upcall.req.sym.target, symname, ORANGEFS_NAME_MAX - 1);
256 
257         ret = service_operation(new_op, __func__, get_interruptible_flag(dir));
258 
259         gossip_debug(GOSSIP_NAME_DEBUG,
260                      "Symlink Got ORANGEFS handle %pU on fsid %d (ret=%d)\n",
261                      &new_op->downcall.resp.sym.refn.khandle,
262                      new_op->downcall.resp.sym.refn.fs_id, ret);
263 
264         if (ret < 0) {
265                 gossip_debug(GOSSIP_NAME_DEBUG,
266                             "%s: failed with error code %d\n",
267                             __func__, ret);
268                 goto out;
269         }
270 
271         ref = new_op->downcall.resp.sym.refn;
272 
273         inode = orangefs_new_inode(dir->i_sb, dir, S_IFLNK | mode, 0, &ref);
274         if (IS_ERR(inode)) {
275                 gossip_err
276                     ("*** Failed to allocate orangefs symlink inode\n");
277                 ret = PTR_ERR(inode);
278                 goto out;
279         }
280         /*
281          * This is necessary because orangefs_inode_getattr will not
282          * re-read symlink size as it is impossible for it to change.
283          * Invalidating the cache does not help.  orangefs_new_inode
284          * does not set the correct size (it does not know symname).
285          */
286         inode->i_size = strlen(symname);
287 
288         gossip_debug(GOSSIP_NAME_DEBUG,
289                      "Assigned symlink inode new number of %pU\n",
290                      get_khandle_from_ino(inode));
291 
292         d_instantiate_new(dentry, inode);
293         orangefs_set_timeout(dentry);
294         ORANGEFS_I(inode)->getattr_time = jiffies - 1;
295         ORANGEFS_I(inode)->getattr_mask = STATX_BASIC_STATS;
296 
297         gossip_debug(GOSSIP_NAME_DEBUG,
298                      "Inode (Symlink) %pU -> %pd\n",
299                      get_khandle_from_ino(inode),
300                      dentry);
301 
302         dir->i_mtime = dir->i_ctime = current_time(dir);
303         memset(&iattr, 0, sizeof iattr);
304         iattr.ia_valid |= ATTR_MTIME;
305         orangefs_inode_setattr(dir, &iattr);
306         mark_inode_dirty_sync(dir);
307         ret = 0;
308 out:
309         op_release(new_op);
310         return ret;
311 }
312 
313 static int orangefs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
314 {
315         struct orangefs_inode_s *parent = ORANGEFS_I(dir);
316         struct orangefs_kernel_op_s *new_op;
317         struct orangefs_object_kref ref;
318         struct inode *inode;
319         struct iattr iattr;
320         int ret;
321 
322         new_op = op_alloc(ORANGEFS_VFS_OP_MKDIR);
323         if (!new_op)
324                 return -ENOMEM;
325 
326         new_op->upcall.req.mkdir.parent_refn = parent->refn;
327 
328         fill_default_sys_attrs(new_op->upcall.req.mkdir.attributes,
329                               ORANGEFS_TYPE_DIRECTORY, mode);
330 
331         strncpy(new_op->upcall.req.mkdir.d_name,
332                 dentry->d_name.name, ORANGEFS_NAME_MAX - 1);
333 
334         ret = service_operation(new_op, __func__, get_interruptible_flag(dir));
335 
336         gossip_debug(GOSSIP_NAME_DEBUG,
337                      "Mkdir Got ORANGEFS handle %pU on fsid %d\n",
338                      &new_op->downcall.resp.mkdir.refn.khandle,
339                      new_op->downcall.resp.mkdir.refn.fs_id);
340 
341         if (ret < 0) {
342                 gossip_debug(GOSSIP_NAME_DEBUG,
343                              "%s: failed with error code %d\n",
344                              __func__, ret);
345                 goto out;
346         }
347 
348         ref = new_op->downcall.resp.mkdir.refn;
349 
350         inode = orangefs_new_inode(dir->i_sb, dir, S_IFDIR | mode, 0, &ref);
351         if (IS_ERR(inode)) {
352                 gossip_err("*** Failed to allocate orangefs dir inode\n");
353                 ret = PTR_ERR(inode);
354                 goto out;
355         }
356 
357         gossip_debug(GOSSIP_NAME_DEBUG,
358                      "Assigned dir inode new number of %pU\n",
359                      get_khandle_from_ino(inode));
360 
361         d_instantiate_new(dentry, inode);
362         orangefs_set_timeout(dentry);
363         ORANGEFS_I(inode)->getattr_time = jiffies - 1;
364         ORANGEFS_I(inode)->getattr_mask = STATX_BASIC_STATS;
365 
366         gossip_debug(GOSSIP_NAME_DEBUG,
367                      "Inode (Directory) %pU -> %pd\n",
368                      get_khandle_from_ino(inode),
369                      dentry);
370 
371         /*
372          * NOTE: we have no good way to keep nlink consistent for directories
373          * across clients; keep constant at 1.
374          */
375         dir->i_mtime = dir->i_ctime = current_time(dir);
376         memset(&iattr, 0, sizeof iattr);
377         iattr.ia_valid |= ATTR_MTIME;
378         orangefs_inode_setattr(dir, &iattr);
379         mark_inode_dirty_sync(dir);
380 out:
381         op_release(new_op);
382         return ret;
383 }
384 
385 static int orangefs_rename(struct inode *old_dir,
386                         struct dentry *old_dentry,
387                         struct inode *new_dir,
388                         struct dentry *new_dentry,
389                         unsigned int flags)
390 {
391         struct orangefs_kernel_op_s *new_op;
392         int ret;
393 
394         if (flags)
395                 return -EINVAL;
396 
397         gossip_debug(GOSSIP_NAME_DEBUG,
398                      "orangefs_rename: called (%pd2 => %pd2) ct=%d\n",
399                      old_dentry, new_dentry, d_count(new_dentry));
400 
401         ORANGEFS_I(new_dentry->d_parent->d_inode)->getattr_time = jiffies - 1;
402 
403         new_op = op_alloc(ORANGEFS_VFS_OP_RENAME);
404         if (!new_op)
405                 return -EINVAL;
406 
407         new_op->upcall.req.rename.old_parent_refn = ORANGEFS_I(old_dir)->refn;
408         new_op->upcall.req.rename.new_parent_refn = ORANGEFS_I(new_dir)->refn;
409 
410         strncpy(new_op->upcall.req.rename.d_old_name,
411                 old_dentry->d_name.name,
412                 ORANGEFS_NAME_MAX - 1);
413         strncpy(new_op->upcall.req.rename.d_new_name,
414                 new_dentry->d_name.name,
415                 ORANGEFS_NAME_MAX - 1);
416 
417         ret = service_operation(new_op,
418                                 "orangefs_rename",
419                                 get_interruptible_flag(old_dentry->d_inode));
420 
421         gossip_debug(GOSSIP_NAME_DEBUG,
422                      "orangefs_rename: got downcall status %d\n",
423                      ret);
424 
425         if (new_dentry->d_inode)
426                 new_dentry->d_inode->i_ctime = current_time(new_dentry->d_inode);
427 
428         op_release(new_op);
429         return ret;
430 }
431 
432 /* ORANGEFS implementation of VFS inode operations for directories */
433 const struct inode_operations orangefs_dir_inode_operations = {
434         .lookup = orangefs_lookup,
435         .get_acl = orangefs_get_acl,
436         .set_acl = orangefs_set_acl,
437         .create = orangefs_create,
438         .unlink = orangefs_unlink,
439         .symlink = orangefs_symlink,
440         .mkdir = orangefs_mkdir,
441         .rmdir = orangefs_unlink,
442         .rename = orangefs_rename,
443         .setattr = orangefs_setattr,
444         .getattr = orangefs_getattr,
445         .listxattr = orangefs_listxattr,
446         .permission = orangefs_permission,
447         .update_time = orangefs_update_time,
448 };
449 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | Wiki (Japanese) | Wiki (English) | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

osdn.jp