1 // SPDX-License-Identifier: GPL-2.0
3 * (C) 2001 Clemson University and The University of Chicago
5 * See COPYING in top-level directory.
9 * Linux VFS namei operations.
13 #include "orangefs-kernel.h"
16 * Get a newly allocated inode to go with a negative dentry.
18 static int orangefs_create(struct inode
*dir
,
19 struct dentry
*dentry
,
23 struct orangefs_inode_s
*parent
= ORANGEFS_I(dir
);
24 struct orangefs_kernel_op_s
*new_op
;
25 struct orangefs_object_kref ref
;
30 gossip_debug(GOSSIP_NAME_DEBUG
, "%s: %pd\n",
34 new_op
= op_alloc(ORANGEFS_VFS_OP_CREATE
);
38 new_op
->upcall
.req
.create
.parent_refn
= parent
->refn
;
40 fill_default_sys_attrs(new_op
->upcall
.req
.create
.attributes
,
41 ORANGEFS_TYPE_METAFILE
, mode
);
43 strncpy(new_op
->upcall
.req
.create
.d_name
,
44 dentry
->d_name
.name
, ORANGEFS_NAME_MAX
);
46 ret
= service_operation(new_op
, __func__
, get_interruptible_flag(dir
));
48 gossip_debug(GOSSIP_NAME_DEBUG
,
49 "%s: %pd: handle:%pU: fsid:%d: new_op:%p: ret:%d:\n",
52 &new_op
->downcall
.resp
.create
.refn
.khandle
,
53 new_op
->downcall
.resp
.create
.refn
.fs_id
,
60 ref
= new_op
->downcall
.resp
.create
.refn
;
63 inode
= orangefs_new_inode(dir
->i_sb
, dir
, S_IFREG
| mode
, 0, &ref
);
65 gossip_err("%s: Failed to allocate inode for file :%pd:\n",
72 gossip_debug(GOSSIP_NAME_DEBUG
,
73 "%s: Assigned inode :%pU: for file :%pd:\n",
75 get_khandle_from_ino(inode
),
78 d_instantiate(dentry
, inode
);
79 unlock_new_inode(inode
);
80 orangefs_set_timeout(dentry
);
81 ORANGEFS_I(inode
)->getattr_time
= jiffies
- 1;
82 ORANGEFS_I(inode
)->getattr_mask
= STATX_BASIC_STATS
;
84 gossip_debug(GOSSIP_NAME_DEBUG
,
85 "%s: dentry instantiated for %pd\n",
89 dir
->i_mtime
= dir
->i_ctime
= current_time(dir
);
90 memset(&iattr
, 0, sizeof iattr
);
91 iattr
.ia_valid
|= ATTR_MTIME
;
92 orangefs_inode_setattr(dir
, &iattr
);
93 mark_inode_dirty_sync(dir
);
96 gossip_debug(GOSSIP_NAME_DEBUG
,
97 "%s: %pd: returning %d\n",
105 * Attempt to resolve an object name (dentry->d_name), parent handle, and
106 * fsid into a handle for the object.
108 static struct dentry
*orangefs_lookup(struct inode
*dir
, struct dentry
*dentry
,
111 struct orangefs_inode_s
*parent
= ORANGEFS_I(dir
);
112 struct orangefs_kernel_op_s
*new_op
;
118 * in theory we could skip a lookup here (if the intent is to
119 * create) in order to avoid a potentially failed lookup, but
120 * leaving it in can skip a valid lookup and try to create a file
121 * that already exists (e.g. the vfs already handles checking for
122 * -EEXIST on O_EXCL opens, which is broken if we skip this lookup
123 * in the create path)
125 gossip_debug(GOSSIP_NAME_DEBUG
, "%s called on %pd\n",
128 if (dentry
->d_name
.len
> (ORANGEFS_NAME_MAX
- 1))
129 return ERR_PTR(-ENAMETOOLONG
);
131 new_op
= op_alloc(ORANGEFS_VFS_OP_LOOKUP
);
133 return ERR_PTR(-ENOMEM
);
135 new_op
->upcall
.req
.lookup
.sym_follow
= ORANGEFS_LOOKUP_LINK_NO_FOLLOW
;
137 gossip_debug(GOSSIP_NAME_DEBUG
, "%s:%s:%d using parent %pU\n",
141 &parent
->refn
.khandle
);
142 new_op
->upcall
.req
.lookup
.parent_refn
= parent
->refn
;
144 strncpy(new_op
->upcall
.req
.lookup
.d_name
, dentry
->d_name
.name
,
147 gossip_debug(GOSSIP_NAME_DEBUG
,
148 "%s: doing lookup on %s under %pU,%d\n",
150 new_op
->upcall
.req
.lookup
.d_name
,
151 &new_op
->upcall
.req
.lookup
.parent_refn
.khandle
,
152 new_op
->upcall
.req
.lookup
.parent_refn
.fs_id
);
154 ret
= service_operation(new_op
, __func__
, get_interruptible_flag(dir
));
156 gossip_debug(GOSSIP_NAME_DEBUG
,
157 "Lookup Got %pU, fsid %d (ret=%d)\n",
158 &new_op
->downcall
.resp
.lookup
.refn
.khandle
,
159 new_op
->downcall
.resp
.lookup
.refn
.fs_id
,
163 if (ret
== -ENOENT
) {
165 * if no inode was found, add a negative dentry to
166 * dcache anyway; if we don't, we don't hold expected
167 * lookup semantics and we most noticeably break
168 * during directory renames.
170 * however, if the operation failed or exited, do not
171 * add the dentry (e.g. in the case that a touch is
172 * issued on a file that already exists that was
173 * interrupted during this lookup -- no need to add
174 * another negative dentry for an existing file)
177 gossip_debug(GOSSIP_NAME_DEBUG
,
178 "orangefs_lookup: Adding *negative* dentry "
188 /* must be a non-recoverable error */
193 orangefs_set_timeout(dentry
);
195 inode
= orangefs_iget(dir
->i_sb
, &new_op
->downcall
.resp
.lookup
.refn
);
197 gossip_debug(GOSSIP_NAME_DEBUG
,
198 "error %ld from iget\n", PTR_ERR(inode
));
199 res
= ERR_CAST(inode
);
203 gossip_debug(GOSSIP_NAME_DEBUG
,
205 "Found good inode [%lu] with count [%d]\n",
210 (int)atomic_read(&inode
->i_count
));
212 /* update dentry/inode pair into dcache */
213 res
= d_splice_alias(inode
, dentry
);
215 gossip_debug(GOSSIP_NAME_DEBUG
,
216 "Lookup success (inode ct = %d)\n",
217 (int)atomic_read(&inode
->i_count
));
223 /* return 0 on success; non-zero otherwise */
224 static int orangefs_unlink(struct inode
*dir
, struct dentry
*dentry
)
226 struct inode
*inode
= dentry
->d_inode
;
227 struct orangefs_inode_s
*parent
= ORANGEFS_I(dir
);
228 struct orangefs_kernel_op_s
*new_op
;
232 gossip_debug(GOSSIP_NAME_DEBUG
,
233 "%s: called on %pd\n"
234 " (inode %pU): Parent is %pU | fs_id %d\n",
237 get_khandle_from_ino(inode
),
238 &parent
->refn
.khandle
,
241 new_op
= op_alloc(ORANGEFS_VFS_OP_REMOVE
);
245 new_op
->upcall
.req
.remove
.parent_refn
= parent
->refn
;
246 strncpy(new_op
->upcall
.req
.remove
.d_name
, dentry
->d_name
.name
,
249 ret
= service_operation(new_op
, "orangefs_unlink",
250 get_interruptible_flag(inode
));
252 gossip_debug(GOSSIP_NAME_DEBUG
,
253 "%s: service_operation returned:%d:\n",
262 dir
->i_mtime
= dir
->i_ctime
= current_time(dir
);
263 memset(&iattr
, 0, sizeof iattr
);
264 iattr
.ia_valid
|= ATTR_MTIME
;
265 orangefs_inode_setattr(dir
, &iattr
);
266 mark_inode_dirty_sync(dir
);
271 static int orangefs_symlink(struct inode
*dir
,
272 struct dentry
*dentry
,
275 struct orangefs_inode_s
*parent
= ORANGEFS_I(dir
);
276 struct orangefs_kernel_op_s
*new_op
;
277 struct orangefs_object_kref ref
;
283 gossip_debug(GOSSIP_NAME_DEBUG
, "%s: called\n", __func__
);
288 if (strlen(symname
)+1 > ORANGEFS_NAME_MAX
)
289 return -ENAMETOOLONG
;
291 new_op
= op_alloc(ORANGEFS_VFS_OP_SYMLINK
);
295 new_op
->upcall
.req
.sym
.parent_refn
= parent
->refn
;
297 fill_default_sys_attrs(new_op
->upcall
.req
.sym
.attributes
,
298 ORANGEFS_TYPE_SYMLINK
,
301 strncpy(new_op
->upcall
.req
.sym
.entry_name
,
304 strncpy(new_op
->upcall
.req
.sym
.target
, symname
, ORANGEFS_NAME_MAX
);
306 ret
= service_operation(new_op
, __func__
, get_interruptible_flag(dir
));
308 gossip_debug(GOSSIP_NAME_DEBUG
,
309 "Symlink Got ORANGEFS handle %pU on fsid %d (ret=%d)\n",
310 &new_op
->downcall
.resp
.sym
.refn
.khandle
,
311 new_op
->downcall
.resp
.sym
.refn
.fs_id
, ret
);
314 gossip_debug(GOSSIP_NAME_DEBUG
,
315 "%s: failed with error code %d\n",
320 ref
= new_op
->downcall
.resp
.sym
.refn
;
323 inode
= orangefs_new_inode(dir
->i_sb
, dir
, S_IFLNK
| mode
, 0, &ref
);
326 ("*** Failed to allocate orangefs symlink inode\n");
327 ret
= PTR_ERR(inode
);
331 gossip_debug(GOSSIP_NAME_DEBUG
,
332 "Assigned symlink inode new number of %pU\n",
333 get_khandle_from_ino(inode
));
335 d_instantiate(dentry
, inode
);
336 unlock_new_inode(inode
);
337 orangefs_set_timeout(dentry
);
338 ORANGEFS_I(inode
)->getattr_time
= jiffies
- 1;
339 ORANGEFS_I(inode
)->getattr_mask
= STATX_BASIC_STATS
;
341 gossip_debug(GOSSIP_NAME_DEBUG
,
342 "Inode (Symlink) %pU -> %pd\n",
343 get_khandle_from_ino(inode
),
346 dir
->i_mtime
= dir
->i_ctime
= current_time(dir
);
347 memset(&iattr
, 0, sizeof iattr
);
348 iattr
.ia_valid
|= ATTR_MTIME
;
349 orangefs_inode_setattr(dir
, &iattr
);
350 mark_inode_dirty_sync(dir
);
356 static int orangefs_mkdir(struct inode
*dir
, struct dentry
*dentry
, umode_t mode
)
358 struct orangefs_inode_s
*parent
= ORANGEFS_I(dir
);
359 struct orangefs_kernel_op_s
*new_op
;
360 struct orangefs_object_kref ref
;
365 new_op
= op_alloc(ORANGEFS_VFS_OP_MKDIR
);
369 new_op
->upcall
.req
.mkdir
.parent_refn
= parent
->refn
;
371 fill_default_sys_attrs(new_op
->upcall
.req
.mkdir
.attributes
,
372 ORANGEFS_TYPE_DIRECTORY
, mode
);
374 strncpy(new_op
->upcall
.req
.mkdir
.d_name
,
375 dentry
->d_name
.name
, ORANGEFS_NAME_MAX
);
377 ret
= service_operation(new_op
, __func__
, get_interruptible_flag(dir
));
379 gossip_debug(GOSSIP_NAME_DEBUG
,
380 "Mkdir Got ORANGEFS handle %pU on fsid %d\n",
381 &new_op
->downcall
.resp
.mkdir
.refn
.khandle
,
382 new_op
->downcall
.resp
.mkdir
.refn
.fs_id
);
385 gossip_debug(GOSSIP_NAME_DEBUG
,
386 "%s: failed with error code %d\n",
391 ref
= new_op
->downcall
.resp
.mkdir
.refn
;
394 inode
= orangefs_new_inode(dir
->i_sb
, dir
, S_IFDIR
| mode
, 0, &ref
);
396 gossip_err("*** Failed to allocate orangefs dir inode\n");
397 ret
= PTR_ERR(inode
);
401 gossip_debug(GOSSIP_NAME_DEBUG
,
402 "Assigned dir inode new number of %pU\n",
403 get_khandle_from_ino(inode
));
405 d_instantiate(dentry
, inode
);
406 unlock_new_inode(inode
);
407 orangefs_set_timeout(dentry
);
408 ORANGEFS_I(inode
)->getattr_time
= jiffies
- 1;
409 ORANGEFS_I(inode
)->getattr_mask
= STATX_BASIC_STATS
;
411 gossip_debug(GOSSIP_NAME_DEBUG
,
412 "Inode (Directory) %pU -> %pd\n",
413 get_khandle_from_ino(inode
),
417 * NOTE: we have no good way to keep nlink consistent for directories
418 * across clients; keep constant at 1.
420 dir
->i_mtime
= dir
->i_ctime
= current_time(dir
);
421 memset(&iattr
, 0, sizeof iattr
);
422 iattr
.ia_valid
|= ATTR_MTIME
;
423 orangefs_inode_setattr(dir
, &iattr
);
424 mark_inode_dirty_sync(dir
);
429 static int orangefs_rename(struct inode
*old_dir
,
430 struct dentry
*old_dentry
,
431 struct inode
*new_dir
,
432 struct dentry
*new_dentry
,
435 struct orangefs_kernel_op_s
*new_op
;
441 gossip_debug(GOSSIP_NAME_DEBUG
,
442 "orangefs_rename: called (%pd2 => %pd2) ct=%d\n",
443 old_dentry
, new_dentry
, d_count(new_dentry
));
445 ORANGEFS_I(new_dentry
->d_parent
->d_inode
)->getattr_time
= jiffies
- 1;
447 new_op
= op_alloc(ORANGEFS_VFS_OP_RENAME
);
451 new_op
->upcall
.req
.rename
.old_parent_refn
= ORANGEFS_I(old_dir
)->refn
;
452 new_op
->upcall
.req
.rename
.new_parent_refn
= ORANGEFS_I(new_dir
)->refn
;
454 strncpy(new_op
->upcall
.req
.rename
.d_old_name
,
455 old_dentry
->d_name
.name
,
457 strncpy(new_op
->upcall
.req
.rename
.d_new_name
,
458 new_dentry
->d_name
.name
,
461 ret
= service_operation(new_op
,
463 get_interruptible_flag(old_dentry
->d_inode
));
465 gossip_debug(GOSSIP_NAME_DEBUG
,
466 "orangefs_rename: got downcall status %d\n",
469 if (new_dentry
->d_inode
)
470 new_dentry
->d_inode
->i_ctime
= current_time(new_dentry
->d_inode
);
476 /* ORANGEFS implementation of VFS inode operations for directories */
477 const struct inode_operations orangefs_dir_inode_operations
= {
478 .lookup
= orangefs_lookup
,
479 .get_acl
= orangefs_get_acl
,
480 .set_acl
= orangefs_set_acl
,
481 .create
= orangefs_create
,
482 .unlink
= orangefs_unlink
,
483 .symlink
= orangefs_symlink
,
484 .mkdir
= orangefs_mkdir
,
485 .rmdir
= orangefs_unlink
,
486 .rename
= orangefs_rename
,
487 .setattr
= orangefs_setattr
,
488 .getattr
= orangefs_getattr
,
489 .listxattr
= orangefs_listxattr
,
490 .permission
= orangefs_permission
,
491 .update_time
= orangefs_update_time
,