1 /* 2 * (C) 2001 Clemson University and The University of Chicago 3 * 4 * See COPYING in top-level directory. 5 */ 6 7 /* 8 * Linux VFS namei operations. 9 */ 10 11 #include "protocol.h" 12 #include "orangefs-kernel.h" 13 14 /* 15 * Get a newly allocated inode to go with a negative dentry. 16 */ 17 static int orangefs_create(struct inode *dir, 18 struct dentry *dentry, 19 umode_t mode, 20 bool exclusive) 21 { 22 struct orangefs_inode_s *parent = ORANGEFS_I(dir); 23 struct orangefs_kernel_op_s *new_op; 24 struct inode *inode; 25 int ret; 26 27 gossip_debug(GOSSIP_NAME_DEBUG, "%s: %pd\n", 28 __func__, 29 dentry); 30 31 new_op = op_alloc(ORANGEFS_VFS_OP_CREATE); 32 if (!new_op) 33 return -ENOMEM; 34 35 new_op->upcall.req.create.parent_refn = parent->refn; 36 37 fill_default_sys_attrs(new_op->upcall.req.create.attributes, 38 ORANGEFS_TYPE_METAFILE, mode); 39 40 strncpy(new_op->upcall.req.create.d_name, 41 dentry->d_name.name, ORANGEFS_NAME_MAX); 42 43 ret = service_operation(new_op, __func__, get_interruptible_flag(dir)); 44 45 gossip_debug(GOSSIP_NAME_DEBUG, 46 "%s: %pd: handle:%pU: fsid:%d: new_op:%p: ret:%d:\n", 47 __func__, 48 dentry, 49 &new_op->downcall.resp.create.refn.khandle, 50 new_op->downcall.resp.create.refn.fs_id, 51 new_op, 52 ret); 53 54 if (ret < 0) 55 goto out; 56 57 inode = orangefs_new_inode(dir->i_sb, dir, S_IFREG | mode, 0, 58 &new_op->downcall.resp.create.refn); 59 if (IS_ERR(inode)) { 60 gossip_err("%s: Failed to allocate inode for file :%pd:\n", 61 __func__, 62 dentry); 63 ret = PTR_ERR(inode); 64 goto out; 65 } 66 67 gossip_debug(GOSSIP_NAME_DEBUG, 68 "%s: Assigned inode :%pU: for file :%pd:\n", 69 __func__, 70 get_khandle_from_ino(inode), 71 dentry); 72 73 d_instantiate(dentry, inode); 74 unlock_new_inode(inode); 75 orangefs_set_timeout(dentry); 76 ORANGEFS_I(inode)->getattr_time = jiffies - 1; 77 ORANGEFS_I(inode)->getattr_mask = STATX_BASIC_STATS; 78 79 gossip_debug(GOSSIP_NAME_DEBUG, 80 "%s: dentry instantiated for %pd\n", 81 __func__, 82 dentry); 83 84 SetMtimeFlag(parent); 85 dir->i_mtime = dir->i_ctime = current_time(dir); 86 mark_inode_dirty_sync(dir); 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 struct dentry *res; 109 int ret = -EINVAL; 110 111 /* 112 * in theory we could skip a lookup here (if the intent is to 113 * create) in order to avoid a potentially failed lookup, but 114 * leaving it in can skip a valid lookup and try to create a file 115 * that already exists (e.g. the vfs already handles checking for 116 * -EEXIST on O_EXCL opens, which is broken if we skip this lookup 117 * in the create path) 118 */ 119 gossip_debug(GOSSIP_NAME_DEBUG, "%s called on %pd\n", 120 __func__, dentry); 121 122 if (dentry->d_name.len > (ORANGEFS_NAME_MAX - 1)) 123 return ERR_PTR(-ENAMETOOLONG); 124 125 new_op = op_alloc(ORANGEFS_VFS_OP_LOOKUP); 126 if (!new_op) 127 return ERR_PTR(-ENOMEM); 128 129 new_op->upcall.req.lookup.sym_follow = ORANGEFS_LOOKUP_LINK_NO_FOLLOW; 130 131 gossip_debug(GOSSIP_NAME_DEBUG, "%s:%s:%d using parent %pU\n", 132 __FILE__, 133 __func__, 134 __LINE__, 135 &parent->refn.khandle); 136 new_op->upcall.req.lookup.parent_refn = parent->refn; 137 138 strncpy(new_op->upcall.req.lookup.d_name, dentry->d_name.name, 139 ORANGEFS_NAME_MAX); 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 if (ret == -ENOENT) { 158 /* 159 * if no inode was found, add a negative dentry to 160 * dcache anyway; if we don't, we don't hold expected 161 * lookup semantics and we most noticeably break 162 * during directory renames. 163 * 164 * however, if the operation failed or exited, do not 165 * add the dentry (e.g. in the case that a touch is 166 * issued on a file that already exists that was 167 * interrupted during this lookup -- no need to add 168 * another negative dentry for an existing file) 169 */ 170 171 gossip_debug(GOSSIP_NAME_DEBUG, 172 "orangefs_lookup: Adding *negative* dentry " 173 "%p for %pd\n", 174 dentry, 175 dentry); 176 177 d_add(dentry, NULL); 178 res = NULL; 179 goto out; 180 } 181 182 /* must be a non-recoverable error */ 183 res = ERR_PTR(ret); 184 goto out; 185 } 186 187 orangefs_set_timeout(dentry); 188 189 inode = orangefs_iget(dir->i_sb, &new_op->downcall.resp.lookup.refn); 190 if (IS_ERR(inode)) { 191 gossip_debug(GOSSIP_NAME_DEBUG, 192 "error %ld from iget\n", PTR_ERR(inode)); 193 res = ERR_CAST(inode); 194 goto out; 195 } 196 197 gossip_debug(GOSSIP_NAME_DEBUG, 198 "%s:%s:%d " 199 "Found good inode [%lu] with count [%d]\n", 200 __FILE__, 201 __func__, 202 __LINE__, 203 inode->i_ino, 204 (int)atomic_read(&inode->i_count)); 205 206 /* update dentry/inode pair into dcache */ 207 res = d_splice_alias(inode, dentry); 208 209 gossip_debug(GOSSIP_NAME_DEBUG, 210 "Lookup success (inode ct = %d)\n", 211 (int)atomic_read(&inode->i_count)); 212 out: 213 op_release(new_op); 214 return res; 215 } 216 217 /* return 0 on success; non-zero otherwise */ 218 static int orangefs_unlink(struct inode *dir, struct dentry *dentry) 219 { 220 struct inode *inode = dentry->d_inode; 221 struct orangefs_inode_s *parent = ORANGEFS_I(dir); 222 struct orangefs_kernel_op_s *new_op; 223 int ret; 224 225 gossip_debug(GOSSIP_NAME_DEBUG, 226 "%s: called on %pd\n" 227 " (inode %pU): Parent is %pU | fs_id %d\n", 228 __func__, 229 dentry, 230 get_khandle_from_ino(inode), 231 &parent->refn.khandle, 232 parent->refn.fs_id); 233 234 new_op = op_alloc(ORANGEFS_VFS_OP_REMOVE); 235 if (!new_op) 236 return -ENOMEM; 237 238 new_op->upcall.req.remove.parent_refn = parent->refn; 239 strncpy(new_op->upcall.req.remove.d_name, dentry->d_name.name, 240 ORANGEFS_NAME_MAX); 241 242 ret = service_operation(new_op, "orangefs_unlink", 243 get_interruptible_flag(inode)); 244 245 gossip_debug(GOSSIP_NAME_DEBUG, 246 "%s: service_operation returned:%d:\n", 247 __func__, 248 ret); 249 250 op_release(new_op); 251 252 if (!ret) { 253 drop_nlink(inode); 254 255 SetMtimeFlag(parent); 256 dir->i_mtime = dir->i_ctime = current_time(dir); 257 mark_inode_dirty_sync(dir); 258 } 259 return ret; 260 } 261 262 static int orangefs_symlink(struct inode *dir, 263 struct dentry *dentry, 264 const char *symname) 265 { 266 struct orangefs_inode_s *parent = ORANGEFS_I(dir); 267 struct orangefs_kernel_op_s *new_op; 268 struct inode *inode; 269 int mode = 755; 270 int ret; 271 272 gossip_debug(GOSSIP_NAME_DEBUG, "%s: called\n", __func__); 273 274 if (!symname) 275 return -EINVAL; 276 277 if (strlen(symname)+1 > ORANGEFS_NAME_MAX) 278 return -ENAMETOOLONG; 279 280 new_op = op_alloc(ORANGEFS_VFS_OP_SYMLINK); 281 if (!new_op) 282 return -ENOMEM; 283 284 new_op->upcall.req.sym.parent_refn = parent->refn; 285 286 fill_default_sys_attrs(new_op->upcall.req.sym.attributes, 287 ORANGEFS_TYPE_SYMLINK, 288 mode); 289 290 strncpy(new_op->upcall.req.sym.entry_name, 291 dentry->d_name.name, 292 ORANGEFS_NAME_MAX); 293 strncpy(new_op->upcall.req.sym.target, symname, ORANGEFS_NAME_MAX); 294 295 ret = service_operation(new_op, __func__, get_interruptible_flag(dir)); 296 297 gossip_debug(GOSSIP_NAME_DEBUG, 298 "Symlink Got ORANGEFS handle %pU on fsid %d (ret=%d)\n", 299 &new_op->downcall.resp.sym.refn.khandle, 300 new_op->downcall.resp.sym.refn.fs_id, ret); 301 302 if (ret < 0) { 303 gossip_debug(GOSSIP_NAME_DEBUG, 304 "%s: failed with error code %d\n", 305 __func__, ret); 306 goto out; 307 } 308 309 inode = orangefs_new_inode(dir->i_sb, dir, S_IFLNK | mode, 0, 310 &new_op->downcall.resp.sym.refn); 311 if (IS_ERR(inode)) { 312 gossip_err 313 ("*** Failed to allocate orangefs symlink inode\n"); 314 ret = PTR_ERR(inode); 315 goto out; 316 } 317 318 gossip_debug(GOSSIP_NAME_DEBUG, 319 "Assigned symlink inode new number of %pU\n", 320 get_khandle_from_ino(inode)); 321 322 d_instantiate(dentry, inode); 323 unlock_new_inode(inode); 324 orangefs_set_timeout(dentry); 325 ORANGEFS_I(inode)->getattr_time = jiffies - 1; 326 ORANGEFS_I(inode)->getattr_mask = STATX_BASIC_STATS; 327 328 gossip_debug(GOSSIP_NAME_DEBUG, 329 "Inode (Symlink) %pU -> %pd\n", 330 get_khandle_from_ino(inode), 331 dentry); 332 333 SetMtimeFlag(parent); 334 dir->i_mtime = dir->i_ctime = current_time(dir); 335 mark_inode_dirty_sync(dir); 336 ret = 0; 337 out: 338 op_release(new_op); 339 return ret; 340 } 341 342 static int orangefs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode) 343 { 344 struct orangefs_inode_s *parent = ORANGEFS_I(dir); 345 struct orangefs_kernel_op_s *new_op; 346 struct inode *inode; 347 int ret; 348 349 new_op = op_alloc(ORANGEFS_VFS_OP_MKDIR); 350 if (!new_op) 351 return -ENOMEM; 352 353 new_op->upcall.req.mkdir.parent_refn = parent->refn; 354 355 fill_default_sys_attrs(new_op->upcall.req.mkdir.attributes, 356 ORANGEFS_TYPE_DIRECTORY, mode); 357 358 strncpy(new_op->upcall.req.mkdir.d_name, 359 dentry->d_name.name, ORANGEFS_NAME_MAX); 360 361 ret = service_operation(new_op, __func__, get_interruptible_flag(dir)); 362 363 gossip_debug(GOSSIP_NAME_DEBUG, 364 "Mkdir Got ORANGEFS handle %pU on fsid %d\n", 365 &new_op->downcall.resp.mkdir.refn.khandle, 366 new_op->downcall.resp.mkdir.refn.fs_id); 367 368 if (ret < 0) { 369 gossip_debug(GOSSIP_NAME_DEBUG, 370 "%s: failed with error code %d\n", 371 __func__, ret); 372 goto out; 373 } 374 375 inode = orangefs_new_inode(dir->i_sb, dir, S_IFDIR | mode, 0, 376 &new_op->downcall.resp.mkdir.refn); 377 if (IS_ERR(inode)) { 378 gossip_err("*** Failed to allocate orangefs dir inode\n"); 379 ret = PTR_ERR(inode); 380 goto out; 381 } 382 383 gossip_debug(GOSSIP_NAME_DEBUG, 384 "Assigned dir inode new number of %pU\n", 385 get_khandle_from_ino(inode)); 386 387 d_instantiate(dentry, inode); 388 unlock_new_inode(inode); 389 orangefs_set_timeout(dentry); 390 ORANGEFS_I(inode)->getattr_time = jiffies - 1; 391 ORANGEFS_I(inode)->getattr_mask = STATX_BASIC_STATS; 392 393 gossip_debug(GOSSIP_NAME_DEBUG, 394 "Inode (Directory) %pU -> %pd\n", 395 get_khandle_from_ino(inode), 396 dentry); 397 398 /* 399 * NOTE: we have no good way to keep nlink consistent for directories 400 * across clients; keep constant at 1. 401 */ 402 SetMtimeFlag(parent); 403 dir->i_mtime = dir->i_ctime = current_time(dir); 404 mark_inode_dirty_sync(dir); 405 out: 406 op_release(new_op); 407 return ret; 408 } 409 410 static int orangefs_rename(struct inode *old_dir, 411 struct dentry *old_dentry, 412 struct inode *new_dir, 413 struct dentry *new_dentry, 414 unsigned int flags) 415 { 416 struct orangefs_kernel_op_s *new_op; 417 int ret; 418 419 if (flags) 420 return -EINVAL; 421 422 gossip_debug(GOSSIP_NAME_DEBUG, 423 "orangefs_rename: called (%pd2 => %pd2) ct=%d\n", 424 old_dentry, new_dentry, d_count(new_dentry)); 425 426 ORANGEFS_I(new_dentry->d_parent->d_inode)->getattr_time = jiffies - 1; 427 428 new_op = op_alloc(ORANGEFS_VFS_OP_RENAME); 429 if (!new_op) 430 return -EINVAL; 431 432 new_op->upcall.req.rename.old_parent_refn = ORANGEFS_I(old_dir)->refn; 433 new_op->upcall.req.rename.new_parent_refn = ORANGEFS_I(new_dir)->refn; 434 435 strncpy(new_op->upcall.req.rename.d_old_name, 436 old_dentry->d_name.name, 437 ORANGEFS_NAME_MAX); 438 strncpy(new_op->upcall.req.rename.d_new_name, 439 new_dentry->d_name.name, 440 ORANGEFS_NAME_MAX); 441 442 ret = service_operation(new_op, 443 "orangefs_rename", 444 get_interruptible_flag(old_dentry->d_inode)); 445 446 gossip_debug(GOSSIP_NAME_DEBUG, 447 "orangefs_rename: got downcall status %d\n", 448 ret); 449 450 if (new_dentry->d_inode) 451 new_dentry->d_inode->i_ctime = current_time(new_dentry->d_inode); 452 453 op_release(new_op); 454 return ret; 455 } 456 457 /* ORANGEFS implementation of VFS inode operations for directories */ 458 const struct inode_operations orangefs_dir_inode_operations = { 459 .lookup = orangefs_lookup, 460 .get_acl = orangefs_get_acl, 461 .set_acl = orangefs_set_acl, 462 .create = orangefs_create, 463 .unlink = orangefs_unlink, 464 .symlink = orangefs_symlink, 465 .mkdir = orangefs_mkdir, 466 .rmdir = orangefs_unlink, 467 .rename = orangefs_rename, 468 .setattr = orangefs_setattr, 469 .getattr = orangefs_getattr, 470 .listxattr = orangefs_listxattr, 471 .permission = orangefs_permission, 472 }; 473