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