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 inode *inode; 26 int ret; 27 28 gossip_debug(GOSSIP_NAME_DEBUG, "%s: %pd\n", 29 __func__, 30 dentry); 31 32 new_op = op_alloc(ORANGEFS_VFS_OP_CREATE); 33 if (!new_op) 34 return -ENOMEM; 35 36 new_op->upcall.req.create.parent_refn = parent->refn; 37 38 fill_default_sys_attrs(new_op->upcall.req.create.attributes, 39 ORANGEFS_TYPE_METAFILE, mode); 40 41 strncpy(new_op->upcall.req.create.d_name, 42 dentry->d_name.name, ORANGEFS_NAME_MAX); 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 inode = orangefs_new_inode(dir->i_sb, dir, S_IFREG | mode, 0, 59 &new_op->downcall.resp.create.refn); 60 if (IS_ERR(inode)) { 61 gossip_err("%s: Failed to allocate inode for file :%pd:\n", 62 __func__, 63 dentry); 64 ret = PTR_ERR(inode); 65 goto out; 66 } 67 68 gossip_debug(GOSSIP_NAME_DEBUG, 69 "%s: Assigned inode :%pU: for file :%pd:\n", 70 __func__, 71 get_khandle_from_ino(inode), 72 dentry); 73 74 d_instantiate(dentry, inode); 75 unlock_new_inode(inode); 76 orangefs_set_timeout(dentry); 77 ORANGEFS_I(inode)->getattr_time = jiffies - 1; 78 ORANGEFS_I(inode)->getattr_mask = STATX_BASIC_STATS; 79 80 gossip_debug(GOSSIP_NAME_DEBUG, 81 "%s: dentry instantiated for %pd\n", 82 __func__, 83 dentry); 84 85 SetMtimeFlag(parent); 86 dir->i_mtime = dir->i_ctime = current_time(dir); 87 mark_inode_dirty_sync(dir); 88 ret = 0; 89 out: 90 op_release(new_op); 91 gossip_debug(GOSSIP_NAME_DEBUG, 92 "%s: %pd: returning %d\n", 93 __func__, 94 dentry, 95 ret); 96 return ret; 97 } 98 99 /* 100 * Attempt to resolve an object name (dentry->d_name), parent handle, and 101 * fsid into a handle for the object. 102 */ 103 static struct dentry *orangefs_lookup(struct inode *dir, struct dentry *dentry, 104 unsigned int flags) 105 { 106 struct orangefs_inode_s *parent = ORANGEFS_I(dir); 107 struct orangefs_kernel_op_s *new_op; 108 struct inode *inode; 109 struct dentry *res; 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); 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 if (ret == -ENOENT) { 159 /* 160 * if no inode was found, add a negative dentry to 161 * dcache anyway; if we don't, we don't hold expected 162 * lookup semantics and we most noticeably break 163 * during directory renames. 164 * 165 * however, if the operation failed or exited, do not 166 * add the dentry (e.g. in the case that a touch is 167 * issued on a file that already exists that was 168 * interrupted during this lookup -- no need to add 169 * another negative dentry for an existing file) 170 */ 171 172 gossip_debug(GOSSIP_NAME_DEBUG, 173 "orangefs_lookup: Adding *negative* dentry " 174 "%p for %pd\n", 175 dentry, 176 dentry); 177 178 d_add(dentry, NULL); 179 res = NULL; 180 goto out; 181 } 182 183 /* must be a non-recoverable error */ 184 res = ERR_PTR(ret); 185 goto out; 186 } 187 188 orangefs_set_timeout(dentry); 189 190 inode = orangefs_iget(dir->i_sb, &new_op->downcall.resp.lookup.refn); 191 if (IS_ERR(inode)) { 192 gossip_debug(GOSSIP_NAME_DEBUG, 193 "error %ld from iget\n", PTR_ERR(inode)); 194 res = ERR_CAST(inode); 195 goto out; 196 } 197 198 gossip_debug(GOSSIP_NAME_DEBUG, 199 "%s:%s:%d " 200 "Found good inode [%lu] with count [%d]\n", 201 __FILE__, 202 __func__, 203 __LINE__, 204 inode->i_ino, 205 (int)atomic_read(&inode->i_count)); 206 207 /* update dentry/inode pair into dcache */ 208 res = d_splice_alias(inode, dentry); 209 210 gossip_debug(GOSSIP_NAME_DEBUG, 211 "Lookup success (inode ct = %d)\n", 212 (int)atomic_read(&inode->i_count)); 213 out: 214 op_release(new_op); 215 return res; 216 } 217 218 /* return 0 on success; non-zero otherwise */ 219 static int orangefs_unlink(struct inode *dir, struct dentry *dentry) 220 { 221 struct inode *inode = dentry->d_inode; 222 struct orangefs_inode_s *parent = ORANGEFS_I(dir); 223 struct orangefs_kernel_op_s *new_op; 224 int ret; 225 226 gossip_debug(GOSSIP_NAME_DEBUG, 227 "%s: called on %pd\n" 228 " (inode %pU): Parent is %pU | fs_id %d\n", 229 __func__, 230 dentry, 231 get_khandle_from_ino(inode), 232 &parent->refn.khandle, 233 parent->refn.fs_id); 234 235 new_op = op_alloc(ORANGEFS_VFS_OP_REMOVE); 236 if (!new_op) 237 return -ENOMEM; 238 239 new_op->upcall.req.remove.parent_refn = parent->refn; 240 strncpy(new_op->upcall.req.remove.d_name, dentry->d_name.name, 241 ORANGEFS_NAME_MAX); 242 243 ret = service_operation(new_op, "orangefs_unlink", 244 get_interruptible_flag(inode)); 245 246 gossip_debug(GOSSIP_NAME_DEBUG, 247 "%s: service_operation returned:%d:\n", 248 __func__, 249 ret); 250 251 op_release(new_op); 252 253 if (!ret) { 254 drop_nlink(inode); 255 256 SetMtimeFlag(parent); 257 dir->i_mtime = dir->i_ctime = current_time(dir); 258 mark_inode_dirty_sync(dir); 259 } 260 return ret; 261 } 262 263 static int orangefs_symlink(struct inode *dir, 264 struct dentry *dentry, 265 const char *symname) 266 { 267 struct orangefs_inode_s *parent = ORANGEFS_I(dir); 268 struct orangefs_kernel_op_s *new_op; 269 struct inode *inode; 270 int mode = 755; 271 int ret; 272 273 gossip_debug(GOSSIP_NAME_DEBUG, "%s: called\n", __func__); 274 275 if (!symname) 276 return -EINVAL; 277 278 if (strlen(symname)+1 > ORANGEFS_NAME_MAX) 279 return -ENAMETOOLONG; 280 281 new_op = op_alloc(ORANGEFS_VFS_OP_SYMLINK); 282 if (!new_op) 283 return -ENOMEM; 284 285 new_op->upcall.req.sym.parent_refn = parent->refn; 286 287 fill_default_sys_attrs(new_op->upcall.req.sym.attributes, 288 ORANGEFS_TYPE_SYMLINK, 289 mode); 290 291 strncpy(new_op->upcall.req.sym.entry_name, 292 dentry->d_name.name, 293 ORANGEFS_NAME_MAX); 294 strncpy(new_op->upcall.req.sym.target, symname, ORANGEFS_NAME_MAX); 295 296 ret = service_operation(new_op, __func__, get_interruptible_flag(dir)); 297 298 gossip_debug(GOSSIP_NAME_DEBUG, 299 "Symlink Got ORANGEFS handle %pU on fsid %d (ret=%d)\n", 300 &new_op->downcall.resp.sym.refn.khandle, 301 new_op->downcall.resp.sym.refn.fs_id, ret); 302 303 if (ret < 0) { 304 gossip_debug(GOSSIP_NAME_DEBUG, 305 "%s: failed with error code %d\n", 306 __func__, ret); 307 goto out; 308 } 309 310 inode = orangefs_new_inode(dir->i_sb, dir, S_IFLNK | mode, 0, 311 &new_op->downcall.resp.sym.refn); 312 if (IS_ERR(inode)) { 313 gossip_err 314 ("*** Failed to allocate orangefs symlink inode\n"); 315 ret = PTR_ERR(inode); 316 goto out; 317 } 318 319 gossip_debug(GOSSIP_NAME_DEBUG, 320 "Assigned symlink inode new number of %pU\n", 321 get_khandle_from_ino(inode)); 322 323 d_instantiate(dentry, inode); 324 unlock_new_inode(inode); 325 orangefs_set_timeout(dentry); 326 ORANGEFS_I(inode)->getattr_time = jiffies - 1; 327 ORANGEFS_I(inode)->getattr_mask = STATX_BASIC_STATS; 328 329 gossip_debug(GOSSIP_NAME_DEBUG, 330 "Inode (Symlink) %pU -> %pd\n", 331 get_khandle_from_ino(inode), 332 dentry); 333 334 SetMtimeFlag(parent); 335 dir->i_mtime = dir->i_ctime = current_time(dir); 336 mark_inode_dirty_sync(dir); 337 ret = 0; 338 out: 339 op_release(new_op); 340 return ret; 341 } 342 343 static int orangefs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode) 344 { 345 struct orangefs_inode_s *parent = ORANGEFS_I(dir); 346 struct orangefs_kernel_op_s *new_op; 347 struct inode *inode; 348 int ret; 349 350 new_op = op_alloc(ORANGEFS_VFS_OP_MKDIR); 351 if (!new_op) 352 return -ENOMEM; 353 354 new_op->upcall.req.mkdir.parent_refn = parent->refn; 355 356 fill_default_sys_attrs(new_op->upcall.req.mkdir.attributes, 357 ORANGEFS_TYPE_DIRECTORY, mode); 358 359 strncpy(new_op->upcall.req.mkdir.d_name, 360 dentry->d_name.name, ORANGEFS_NAME_MAX); 361 362 ret = service_operation(new_op, __func__, get_interruptible_flag(dir)); 363 364 gossip_debug(GOSSIP_NAME_DEBUG, 365 "Mkdir Got ORANGEFS handle %pU on fsid %d\n", 366 &new_op->downcall.resp.mkdir.refn.khandle, 367 new_op->downcall.resp.mkdir.refn.fs_id); 368 369 if (ret < 0) { 370 gossip_debug(GOSSIP_NAME_DEBUG, 371 "%s: failed with error code %d\n", 372 __func__, ret); 373 goto out; 374 } 375 376 inode = orangefs_new_inode(dir->i_sb, dir, S_IFDIR | mode, 0, 377 &new_op->downcall.resp.mkdir.refn); 378 if (IS_ERR(inode)) { 379 gossip_err("*** Failed to allocate orangefs dir inode\n"); 380 ret = PTR_ERR(inode); 381 goto out; 382 } 383 384 gossip_debug(GOSSIP_NAME_DEBUG, 385 "Assigned dir inode new number of %pU\n", 386 get_khandle_from_ino(inode)); 387 388 d_instantiate(dentry, inode); 389 unlock_new_inode(inode); 390 orangefs_set_timeout(dentry); 391 ORANGEFS_I(inode)->getattr_time = jiffies - 1; 392 ORANGEFS_I(inode)->getattr_mask = STATX_BASIC_STATS; 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 }; 474