root/fs/orangefs/namei.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. orangefs_create
  2. orangefs_lookup
  3. orangefs_unlink
  4. orangefs_symlink
  5. orangefs_mkdir
  6. orangefs_rename

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

/* [<][>][^][v][top][bottom][index][help] */