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 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 op_release(new_op); 273 274 inode = orangefs_new_inode(dir->i_sb, dir, S_IFLNK | mode, 0, &ref); 275 if (IS_ERR(inode)) { 276 gossip_err 277 ("*** Failed to allocate orangefs symlink inode\n"); 278 ret = PTR_ERR(inode); 279 goto out; 280 } 281 /* 282 * This is necessary because orangefs_inode_getattr will not 283 * re-read symlink size as it is impossible for it to change. 284 * Invalidating the cache does not help. orangefs_new_inode 285 * does not set the correct size (it does not know symname). 286 */ 287 inode->i_size = strlen(symname); 288 289 gossip_debug(GOSSIP_NAME_DEBUG, 290 "Assigned symlink inode new number of %pU\n", 291 get_khandle_from_ino(inode)); 292 293 d_instantiate_new(dentry, inode); 294 orangefs_set_timeout(dentry); 295 ORANGEFS_I(inode)->getattr_time = jiffies - 1; 296 ORANGEFS_I(inode)->getattr_mask = STATX_BASIC_STATS; 297 298 gossip_debug(GOSSIP_NAME_DEBUG, 299 "Inode (Symlink) %pU -> %pd\n", 300 get_khandle_from_ino(inode), 301 dentry); 302 303 dir->i_mtime = dir->i_ctime = current_time(dir); 304 memset(&iattr, 0, sizeof iattr); 305 iattr.ia_valid |= ATTR_MTIME; 306 orangefs_inode_setattr(dir, &iattr); 307 mark_inode_dirty_sync(dir); 308 ret = 0; 309 out: 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 op_release(new_op); 350 351 inode = orangefs_new_inode(dir->i_sb, dir, S_IFDIR | mode, 0, &ref); 352 if (IS_ERR(inode)) { 353 gossip_err("*** Failed to allocate orangefs dir inode\n"); 354 ret = PTR_ERR(inode); 355 goto out; 356 } 357 358 gossip_debug(GOSSIP_NAME_DEBUG, 359 "Assigned dir inode new number of %pU\n", 360 get_khandle_from_ino(inode)); 361 362 d_instantiate_new(dentry, inode); 363 orangefs_set_timeout(dentry); 364 ORANGEFS_I(inode)->getattr_time = jiffies - 1; 365 ORANGEFS_I(inode)->getattr_mask = STATX_BASIC_STATS; 366 367 gossip_debug(GOSSIP_NAME_DEBUG, 368 "Inode (Directory) %pU -> %pd\n", 369 get_khandle_from_ino(inode), 370 dentry); 371 372 /* 373 * NOTE: we have no good way to keep nlink consistent for directories 374 * across clients; keep constant at 1. 375 */ 376 dir->i_mtime = dir->i_ctime = current_time(dir); 377 memset(&iattr, 0, sizeof iattr); 378 iattr.ia_valid |= ATTR_MTIME; 379 orangefs_inode_setattr(dir, &iattr); 380 mark_inode_dirty_sync(dir); 381 out: 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