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 mnt_idmap *idmap, 19 struct inode *dir, 20 struct dentry *dentry, 21 umode_t mode, 22 bool exclusive) 23 { 24 struct orangefs_inode_s *parent = ORANGEFS_I(dir); 25 struct orangefs_kernel_op_s *new_op; 26 struct orangefs_object_kref ref; 27 struct inode *inode; 28 struct iattr iattr; 29 int ret; 30 31 gossip_debug(GOSSIP_NAME_DEBUG, "%s: %pd\n", 32 __func__, 33 dentry); 34 35 new_op = op_alloc(ORANGEFS_VFS_OP_CREATE); 36 if (!new_op) 37 return -ENOMEM; 38 39 new_op->upcall.req.create.parent_refn = parent->refn; 40 41 fill_default_sys_attrs(new_op->upcall.req.create.attributes, 42 ORANGEFS_TYPE_METAFILE, mode); 43 44 strscpy(new_op->upcall.req.create.d_name, dentry->d_name.name); 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 strscpy(new_op->upcall.req.lookup.d_name, dentry->d_name.name); 140 141 gossip_debug(GOSSIP_NAME_DEBUG, 142 "%s: doing lookup on %s under %pU,%d\n", 143 __func__, 144 new_op->upcall.req.lookup.d_name, 145 &new_op->upcall.req.lookup.parent_refn.khandle, 146 new_op->upcall.req.lookup.parent_refn.fs_id); 147 148 ret = service_operation(new_op, __func__, get_interruptible_flag(dir)); 149 150 gossip_debug(GOSSIP_NAME_DEBUG, 151 "Lookup Got %pU, fsid %d (ret=%d)\n", 152 &new_op->downcall.resp.lookup.refn.khandle, 153 new_op->downcall.resp.lookup.refn.fs_id, 154 ret); 155 156 if (ret == 0) { 157 orangefs_set_timeout(dentry); 158 inode = orangefs_iget(dir->i_sb, &new_op->downcall.resp.lookup.refn); 159 } else if (ret == -ENOENT) { 160 inode = NULL; 161 } else { 162 /* must be a non-recoverable error */ 163 inode = ERR_PTR(ret); 164 } 165 166 op_release(new_op); 167 return d_splice_alias(inode, dentry); 168 } 169 170 /* return 0 on success; non-zero otherwise */ 171 static int orangefs_unlink(struct inode *dir, struct dentry *dentry) 172 { 173 struct inode *inode = dentry->d_inode; 174 struct orangefs_inode_s *parent = ORANGEFS_I(dir); 175 struct orangefs_kernel_op_s *new_op; 176 struct iattr iattr; 177 int ret; 178 179 gossip_debug(GOSSIP_NAME_DEBUG, 180 "%s: called on %pd\n" 181 " (inode %pU): Parent is %pU | fs_id %d\n", 182 __func__, 183 dentry, 184 get_khandle_from_ino(inode), 185 &parent->refn.khandle, 186 parent->refn.fs_id); 187 188 new_op = op_alloc(ORANGEFS_VFS_OP_REMOVE); 189 if (!new_op) 190 return -ENOMEM; 191 192 new_op->upcall.req.remove.parent_refn = parent->refn; 193 strscpy(new_op->upcall.req.remove.d_name, dentry->d_name.name); 194 195 ret = service_operation(new_op, "orangefs_unlink", 196 get_interruptible_flag(inode)); 197 198 gossip_debug(GOSSIP_NAME_DEBUG, 199 "%s: service_operation returned:%d:\n", 200 __func__, 201 ret); 202 203 op_release(new_op); 204 205 if (!ret) { 206 drop_nlink(inode); 207 208 memset(&iattr, 0, sizeof iattr); 209 iattr.ia_valid |= ATTR_MTIME | ATTR_CTIME; 210 iattr.ia_mtime = iattr.ia_ctime = current_time(dir); 211 __orangefs_setattr(dir, &iattr); 212 } 213 return ret; 214 } 215 216 static int orangefs_symlink(struct mnt_idmap *idmap, 217 struct inode *dir, 218 struct dentry *dentry, 219 const char *symname) 220 { 221 struct orangefs_inode_s *parent = ORANGEFS_I(dir); 222 struct orangefs_kernel_op_s *new_op; 223 struct orangefs_object_kref ref; 224 struct inode *inode; 225 struct iattr iattr; 226 int mode = 0755; 227 int ret; 228 229 gossip_debug(GOSSIP_NAME_DEBUG, "%s: called\n", __func__); 230 231 if (!symname) 232 return -EINVAL; 233 234 if (strlen(symname)+1 > ORANGEFS_NAME_MAX) 235 return -ENAMETOOLONG; 236 237 new_op = op_alloc(ORANGEFS_VFS_OP_SYMLINK); 238 if (!new_op) 239 return -ENOMEM; 240 241 new_op->upcall.req.sym.parent_refn = parent->refn; 242 243 fill_default_sys_attrs(new_op->upcall.req.sym.attributes, 244 ORANGEFS_TYPE_SYMLINK, 245 mode); 246 247 strscpy(new_op->upcall.req.sym.entry_name, dentry->d_name.name); 248 strscpy(new_op->upcall.req.sym.target, symname); 249 250 ret = service_operation(new_op, __func__, get_interruptible_flag(dir)); 251 252 gossip_debug(GOSSIP_NAME_DEBUG, 253 "Symlink Got ORANGEFS handle %pU on fsid %d (ret=%d)\n", 254 &new_op->downcall.resp.sym.refn.khandle, 255 new_op->downcall.resp.sym.refn.fs_id, ret); 256 257 if (ret < 0) { 258 gossip_debug(GOSSIP_NAME_DEBUG, 259 "%s: failed with error code %d\n", 260 __func__, ret); 261 goto out; 262 } 263 264 ref = new_op->downcall.resp.sym.refn; 265 266 inode = orangefs_new_inode(dir->i_sb, dir, S_IFLNK | mode, 0, &ref); 267 if (IS_ERR(inode)) { 268 gossip_err 269 ("*** Failed to allocate orangefs symlink inode\n"); 270 ret = PTR_ERR(inode); 271 goto out; 272 } 273 /* 274 * This is necessary because orangefs_inode_getattr will not 275 * re-read symlink size as it is impossible for it to change. 276 * Invalidating the cache does not help. orangefs_new_inode 277 * does not set the correct size (it does not know symname). 278 */ 279 inode->i_size = strlen(symname); 280 281 gossip_debug(GOSSIP_NAME_DEBUG, 282 "Assigned symlink inode new number of %pU\n", 283 get_khandle_from_ino(inode)); 284 285 d_instantiate_new(dentry, inode); 286 orangefs_set_timeout(dentry); 287 288 gossip_debug(GOSSIP_NAME_DEBUG, 289 "Inode (Symlink) %pU -> %pd\n", 290 get_khandle_from_ino(inode), 291 dentry); 292 293 memset(&iattr, 0, sizeof iattr); 294 iattr.ia_valid |= ATTR_MTIME | ATTR_CTIME; 295 iattr.ia_mtime = iattr.ia_ctime = current_time(dir); 296 __orangefs_setattr(dir, &iattr); 297 ret = 0; 298 out: 299 op_release(new_op); 300 return ret; 301 } 302 303 static int orangefs_mkdir(struct mnt_idmap *idmap, struct inode *dir, 304 struct dentry *dentry, umode_t mode) 305 { 306 struct orangefs_inode_s *parent = ORANGEFS_I(dir); 307 struct orangefs_kernel_op_s *new_op; 308 struct orangefs_object_kref ref; 309 struct inode *inode; 310 struct iattr iattr; 311 int ret; 312 313 new_op = op_alloc(ORANGEFS_VFS_OP_MKDIR); 314 if (!new_op) 315 return -ENOMEM; 316 317 new_op->upcall.req.mkdir.parent_refn = parent->refn; 318 319 fill_default_sys_attrs(new_op->upcall.req.mkdir.attributes, 320 ORANGEFS_TYPE_DIRECTORY, mode); 321 322 strscpy(new_op->upcall.req.mkdir.d_name, dentry->d_name.name); 323 324 ret = service_operation(new_op, __func__, get_interruptible_flag(dir)); 325 326 gossip_debug(GOSSIP_NAME_DEBUG, 327 "Mkdir Got ORANGEFS handle %pU on fsid %d\n", 328 &new_op->downcall.resp.mkdir.refn.khandle, 329 new_op->downcall.resp.mkdir.refn.fs_id); 330 331 if (ret < 0) { 332 gossip_debug(GOSSIP_NAME_DEBUG, 333 "%s: failed with error code %d\n", 334 __func__, ret); 335 goto out; 336 } 337 338 ref = new_op->downcall.resp.mkdir.refn; 339 340 inode = orangefs_new_inode(dir->i_sb, dir, S_IFDIR | mode, 0, &ref); 341 if (IS_ERR(inode)) { 342 gossip_err("*** Failed to allocate orangefs dir inode\n"); 343 ret = PTR_ERR(inode); 344 goto out; 345 } 346 347 gossip_debug(GOSSIP_NAME_DEBUG, 348 "Assigned dir inode new number of %pU\n", 349 get_khandle_from_ino(inode)); 350 351 d_instantiate_new(dentry, inode); 352 orangefs_set_timeout(dentry); 353 354 gossip_debug(GOSSIP_NAME_DEBUG, 355 "Inode (Directory) %pU -> %pd\n", 356 get_khandle_from_ino(inode), 357 dentry); 358 359 /* 360 * NOTE: we have no good way to keep nlink consistent for directories 361 * across clients; keep constant at 1. 362 */ 363 memset(&iattr, 0, sizeof iattr); 364 iattr.ia_valid |= ATTR_MTIME | ATTR_CTIME; 365 iattr.ia_mtime = iattr.ia_ctime = current_time(dir); 366 __orangefs_setattr(dir, &iattr); 367 out: 368 op_release(new_op); 369 return ret; 370 } 371 372 static int orangefs_rename(struct mnt_idmap *idmap, 373 struct inode *old_dir, 374 struct dentry *old_dentry, 375 struct inode *new_dir, 376 struct dentry *new_dentry, 377 unsigned int flags) 378 { 379 struct orangefs_kernel_op_s *new_op; 380 struct iattr iattr; 381 int ret; 382 383 if (flags) 384 return -EINVAL; 385 386 gossip_debug(GOSSIP_NAME_DEBUG, 387 "orangefs_rename: called (%pd2 => %pd2) ct=%d\n", 388 old_dentry, new_dentry, d_count(new_dentry)); 389 390 memset(&iattr, 0, sizeof iattr); 391 iattr.ia_valid |= ATTR_MTIME | ATTR_CTIME; 392 iattr.ia_mtime = iattr.ia_ctime = current_time(new_dir); 393 __orangefs_setattr(new_dir, &iattr); 394 395 new_op = op_alloc(ORANGEFS_VFS_OP_RENAME); 396 if (!new_op) 397 return -EINVAL; 398 399 new_op->upcall.req.rename.old_parent_refn = ORANGEFS_I(old_dir)->refn; 400 new_op->upcall.req.rename.new_parent_refn = ORANGEFS_I(new_dir)->refn; 401 402 strscpy(new_op->upcall.req.rename.d_old_name, old_dentry->d_name.name); 403 strscpy(new_op->upcall.req.rename.d_new_name, new_dentry->d_name.name); 404 405 ret = service_operation(new_op, 406 "orangefs_rename", 407 get_interruptible_flag(old_dentry->d_inode)); 408 409 gossip_debug(GOSSIP_NAME_DEBUG, 410 "orangefs_rename: got downcall status %d\n", 411 ret); 412 413 if (new_dentry->d_inode) 414 inode_set_ctime_current(d_inode(new_dentry)); 415 416 op_release(new_op); 417 return ret; 418 } 419 420 /* ORANGEFS implementation of VFS inode operations for directories */ 421 const struct inode_operations orangefs_dir_inode_operations = { 422 .lookup = orangefs_lookup, 423 .get_inode_acl = orangefs_get_acl, 424 .set_acl = orangefs_set_acl, 425 .create = orangefs_create, 426 .unlink = orangefs_unlink, 427 .symlink = orangefs_symlink, 428 .mkdir = orangefs_mkdir, 429 .rmdir = orangefs_unlink, 430 .rename = orangefs_rename, 431 .setattr = orangefs_setattr, 432 .getattr = orangefs_getattr, 433 .listxattr = orangefs_listxattr, 434 .permission = orangefs_permission, 435 .update_time = orangefs_update_time, 436 }; 437