162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * (C) 2001 Clemson University and The University of Chicago
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci * See COPYING in top-level directory.
662306a36Sopenharmony_ci */
762306a36Sopenharmony_ci
862306a36Sopenharmony_ci/*
962306a36Sopenharmony_ci *  Linux VFS namei operations.
1062306a36Sopenharmony_ci */
1162306a36Sopenharmony_ci
1262306a36Sopenharmony_ci#include "protocol.h"
1362306a36Sopenharmony_ci#include "orangefs-kernel.h"
1462306a36Sopenharmony_ci
1562306a36Sopenharmony_ci/*
1662306a36Sopenharmony_ci * Get a newly allocated inode to go with a negative dentry.
1762306a36Sopenharmony_ci */
1862306a36Sopenharmony_cistatic int orangefs_create(struct mnt_idmap *idmap,
1962306a36Sopenharmony_ci			struct inode *dir,
2062306a36Sopenharmony_ci			struct dentry *dentry,
2162306a36Sopenharmony_ci			umode_t mode,
2262306a36Sopenharmony_ci			bool exclusive)
2362306a36Sopenharmony_ci{
2462306a36Sopenharmony_ci	struct orangefs_inode_s *parent = ORANGEFS_I(dir);
2562306a36Sopenharmony_ci	struct orangefs_kernel_op_s *new_op;
2662306a36Sopenharmony_ci	struct orangefs_object_kref ref;
2762306a36Sopenharmony_ci	struct inode *inode;
2862306a36Sopenharmony_ci	struct iattr iattr;
2962306a36Sopenharmony_ci	int ret;
3062306a36Sopenharmony_ci
3162306a36Sopenharmony_ci	gossip_debug(GOSSIP_NAME_DEBUG, "%s: %pd\n",
3262306a36Sopenharmony_ci		     __func__,
3362306a36Sopenharmony_ci		     dentry);
3462306a36Sopenharmony_ci
3562306a36Sopenharmony_ci	new_op = op_alloc(ORANGEFS_VFS_OP_CREATE);
3662306a36Sopenharmony_ci	if (!new_op)
3762306a36Sopenharmony_ci		return -ENOMEM;
3862306a36Sopenharmony_ci
3962306a36Sopenharmony_ci	new_op->upcall.req.create.parent_refn = parent->refn;
4062306a36Sopenharmony_ci
4162306a36Sopenharmony_ci	fill_default_sys_attrs(new_op->upcall.req.create.attributes,
4262306a36Sopenharmony_ci			       ORANGEFS_TYPE_METAFILE, mode);
4362306a36Sopenharmony_ci
4462306a36Sopenharmony_ci	strncpy(new_op->upcall.req.create.d_name,
4562306a36Sopenharmony_ci		dentry->d_name.name, ORANGEFS_NAME_MAX - 1);
4662306a36Sopenharmony_ci
4762306a36Sopenharmony_ci	ret = service_operation(new_op, __func__, get_interruptible_flag(dir));
4862306a36Sopenharmony_ci
4962306a36Sopenharmony_ci	gossip_debug(GOSSIP_NAME_DEBUG,
5062306a36Sopenharmony_ci		     "%s: %pd: handle:%pU: fsid:%d: new_op:%p: ret:%d:\n",
5162306a36Sopenharmony_ci		     __func__,
5262306a36Sopenharmony_ci		     dentry,
5362306a36Sopenharmony_ci		     &new_op->downcall.resp.create.refn.khandle,
5462306a36Sopenharmony_ci		     new_op->downcall.resp.create.refn.fs_id,
5562306a36Sopenharmony_ci		     new_op,
5662306a36Sopenharmony_ci		     ret);
5762306a36Sopenharmony_ci
5862306a36Sopenharmony_ci	if (ret < 0)
5962306a36Sopenharmony_ci		goto out;
6062306a36Sopenharmony_ci
6162306a36Sopenharmony_ci	ref = new_op->downcall.resp.create.refn;
6262306a36Sopenharmony_ci
6362306a36Sopenharmony_ci	inode = orangefs_new_inode(dir->i_sb, dir, S_IFREG | mode, 0, &ref);
6462306a36Sopenharmony_ci	if (IS_ERR(inode)) {
6562306a36Sopenharmony_ci		gossip_err("%s: Failed to allocate inode for file :%pd:\n",
6662306a36Sopenharmony_ci			   __func__,
6762306a36Sopenharmony_ci			   dentry);
6862306a36Sopenharmony_ci		ret = PTR_ERR(inode);
6962306a36Sopenharmony_ci		goto out;
7062306a36Sopenharmony_ci	}
7162306a36Sopenharmony_ci
7262306a36Sopenharmony_ci	gossip_debug(GOSSIP_NAME_DEBUG,
7362306a36Sopenharmony_ci		     "%s: Assigned inode :%pU: for file :%pd:\n",
7462306a36Sopenharmony_ci		     __func__,
7562306a36Sopenharmony_ci		     get_khandle_from_ino(inode),
7662306a36Sopenharmony_ci		     dentry);
7762306a36Sopenharmony_ci
7862306a36Sopenharmony_ci	d_instantiate_new(dentry, inode);
7962306a36Sopenharmony_ci	orangefs_set_timeout(dentry);
8062306a36Sopenharmony_ci
8162306a36Sopenharmony_ci	gossip_debug(GOSSIP_NAME_DEBUG,
8262306a36Sopenharmony_ci		     "%s: dentry instantiated for %pd\n",
8362306a36Sopenharmony_ci		     __func__,
8462306a36Sopenharmony_ci		     dentry);
8562306a36Sopenharmony_ci
8662306a36Sopenharmony_ci	memset(&iattr, 0, sizeof iattr);
8762306a36Sopenharmony_ci	iattr.ia_valid |= ATTR_MTIME | ATTR_CTIME;
8862306a36Sopenharmony_ci	iattr.ia_mtime = iattr.ia_ctime = current_time(dir);
8962306a36Sopenharmony_ci	__orangefs_setattr(dir, &iattr);
9062306a36Sopenharmony_ci	ret = 0;
9162306a36Sopenharmony_ciout:
9262306a36Sopenharmony_ci	op_release(new_op);
9362306a36Sopenharmony_ci	gossip_debug(GOSSIP_NAME_DEBUG,
9462306a36Sopenharmony_ci		     "%s: %pd: returning %d\n",
9562306a36Sopenharmony_ci		     __func__,
9662306a36Sopenharmony_ci		     dentry,
9762306a36Sopenharmony_ci		     ret);
9862306a36Sopenharmony_ci	return ret;
9962306a36Sopenharmony_ci}
10062306a36Sopenharmony_ci
10162306a36Sopenharmony_ci/*
10262306a36Sopenharmony_ci * Attempt to resolve an object name (dentry->d_name), parent handle, and
10362306a36Sopenharmony_ci * fsid into a handle for the object.
10462306a36Sopenharmony_ci */
10562306a36Sopenharmony_cistatic struct dentry *orangefs_lookup(struct inode *dir, struct dentry *dentry,
10662306a36Sopenharmony_ci				   unsigned int flags)
10762306a36Sopenharmony_ci{
10862306a36Sopenharmony_ci	struct orangefs_inode_s *parent = ORANGEFS_I(dir);
10962306a36Sopenharmony_ci	struct orangefs_kernel_op_s *new_op;
11062306a36Sopenharmony_ci	struct inode *inode;
11162306a36Sopenharmony_ci	int ret = -EINVAL;
11262306a36Sopenharmony_ci
11362306a36Sopenharmony_ci	/*
11462306a36Sopenharmony_ci	 * in theory we could skip a lookup here (if the intent is to
11562306a36Sopenharmony_ci	 * create) in order to avoid a potentially failed lookup, but
11662306a36Sopenharmony_ci	 * leaving it in can skip a valid lookup and try to create a file
11762306a36Sopenharmony_ci	 * that already exists (e.g. the vfs already handles checking for
11862306a36Sopenharmony_ci	 * -EEXIST on O_EXCL opens, which is broken if we skip this lookup
11962306a36Sopenharmony_ci	 * in the create path)
12062306a36Sopenharmony_ci	 */
12162306a36Sopenharmony_ci	gossip_debug(GOSSIP_NAME_DEBUG, "%s called on %pd\n",
12262306a36Sopenharmony_ci		     __func__, dentry);
12362306a36Sopenharmony_ci
12462306a36Sopenharmony_ci	if (dentry->d_name.len > (ORANGEFS_NAME_MAX - 1))
12562306a36Sopenharmony_ci		return ERR_PTR(-ENAMETOOLONG);
12662306a36Sopenharmony_ci
12762306a36Sopenharmony_ci	new_op = op_alloc(ORANGEFS_VFS_OP_LOOKUP);
12862306a36Sopenharmony_ci	if (!new_op)
12962306a36Sopenharmony_ci		return ERR_PTR(-ENOMEM);
13062306a36Sopenharmony_ci
13162306a36Sopenharmony_ci	new_op->upcall.req.lookup.sym_follow = ORANGEFS_LOOKUP_LINK_NO_FOLLOW;
13262306a36Sopenharmony_ci
13362306a36Sopenharmony_ci	gossip_debug(GOSSIP_NAME_DEBUG, "%s:%s:%d using parent %pU\n",
13462306a36Sopenharmony_ci		     __FILE__,
13562306a36Sopenharmony_ci		     __func__,
13662306a36Sopenharmony_ci		     __LINE__,
13762306a36Sopenharmony_ci		     &parent->refn.khandle);
13862306a36Sopenharmony_ci	new_op->upcall.req.lookup.parent_refn = parent->refn;
13962306a36Sopenharmony_ci
14062306a36Sopenharmony_ci	strncpy(new_op->upcall.req.lookup.d_name, dentry->d_name.name,
14162306a36Sopenharmony_ci		ORANGEFS_NAME_MAX - 1);
14262306a36Sopenharmony_ci
14362306a36Sopenharmony_ci	gossip_debug(GOSSIP_NAME_DEBUG,
14462306a36Sopenharmony_ci		     "%s: doing lookup on %s under %pU,%d\n",
14562306a36Sopenharmony_ci		     __func__,
14662306a36Sopenharmony_ci		     new_op->upcall.req.lookup.d_name,
14762306a36Sopenharmony_ci		     &new_op->upcall.req.lookup.parent_refn.khandle,
14862306a36Sopenharmony_ci		     new_op->upcall.req.lookup.parent_refn.fs_id);
14962306a36Sopenharmony_ci
15062306a36Sopenharmony_ci	ret = service_operation(new_op, __func__, get_interruptible_flag(dir));
15162306a36Sopenharmony_ci
15262306a36Sopenharmony_ci	gossip_debug(GOSSIP_NAME_DEBUG,
15362306a36Sopenharmony_ci		     "Lookup Got %pU, fsid %d (ret=%d)\n",
15462306a36Sopenharmony_ci		     &new_op->downcall.resp.lookup.refn.khandle,
15562306a36Sopenharmony_ci		     new_op->downcall.resp.lookup.refn.fs_id,
15662306a36Sopenharmony_ci		     ret);
15762306a36Sopenharmony_ci
15862306a36Sopenharmony_ci	if (ret == 0) {
15962306a36Sopenharmony_ci		orangefs_set_timeout(dentry);
16062306a36Sopenharmony_ci		inode = orangefs_iget(dir->i_sb, &new_op->downcall.resp.lookup.refn);
16162306a36Sopenharmony_ci	} else if (ret == -ENOENT) {
16262306a36Sopenharmony_ci		inode = NULL;
16362306a36Sopenharmony_ci	} else {
16462306a36Sopenharmony_ci		/* must be a non-recoverable error */
16562306a36Sopenharmony_ci		inode = ERR_PTR(ret);
16662306a36Sopenharmony_ci	}
16762306a36Sopenharmony_ci
16862306a36Sopenharmony_ci	op_release(new_op);
16962306a36Sopenharmony_ci	return d_splice_alias(inode, dentry);
17062306a36Sopenharmony_ci}
17162306a36Sopenharmony_ci
17262306a36Sopenharmony_ci/* return 0 on success; non-zero otherwise */
17362306a36Sopenharmony_cistatic int orangefs_unlink(struct inode *dir, struct dentry *dentry)
17462306a36Sopenharmony_ci{
17562306a36Sopenharmony_ci	struct inode *inode = dentry->d_inode;
17662306a36Sopenharmony_ci	struct orangefs_inode_s *parent = ORANGEFS_I(dir);
17762306a36Sopenharmony_ci	struct orangefs_kernel_op_s *new_op;
17862306a36Sopenharmony_ci	struct iattr iattr;
17962306a36Sopenharmony_ci	int ret;
18062306a36Sopenharmony_ci
18162306a36Sopenharmony_ci	gossip_debug(GOSSIP_NAME_DEBUG,
18262306a36Sopenharmony_ci		     "%s: called on %pd\n"
18362306a36Sopenharmony_ci		     "  (inode %pU): Parent is %pU | fs_id %d\n",
18462306a36Sopenharmony_ci		     __func__,
18562306a36Sopenharmony_ci		     dentry,
18662306a36Sopenharmony_ci		     get_khandle_from_ino(inode),
18762306a36Sopenharmony_ci		     &parent->refn.khandle,
18862306a36Sopenharmony_ci		     parent->refn.fs_id);
18962306a36Sopenharmony_ci
19062306a36Sopenharmony_ci	new_op = op_alloc(ORANGEFS_VFS_OP_REMOVE);
19162306a36Sopenharmony_ci	if (!new_op)
19262306a36Sopenharmony_ci		return -ENOMEM;
19362306a36Sopenharmony_ci
19462306a36Sopenharmony_ci	new_op->upcall.req.remove.parent_refn = parent->refn;
19562306a36Sopenharmony_ci	strncpy(new_op->upcall.req.remove.d_name, dentry->d_name.name,
19662306a36Sopenharmony_ci		ORANGEFS_NAME_MAX - 1);
19762306a36Sopenharmony_ci
19862306a36Sopenharmony_ci	ret = service_operation(new_op, "orangefs_unlink",
19962306a36Sopenharmony_ci				get_interruptible_flag(inode));
20062306a36Sopenharmony_ci
20162306a36Sopenharmony_ci	gossip_debug(GOSSIP_NAME_DEBUG,
20262306a36Sopenharmony_ci		     "%s: service_operation returned:%d:\n",
20362306a36Sopenharmony_ci		     __func__,
20462306a36Sopenharmony_ci		     ret);
20562306a36Sopenharmony_ci
20662306a36Sopenharmony_ci	op_release(new_op);
20762306a36Sopenharmony_ci
20862306a36Sopenharmony_ci	if (!ret) {
20962306a36Sopenharmony_ci		drop_nlink(inode);
21062306a36Sopenharmony_ci
21162306a36Sopenharmony_ci		memset(&iattr, 0, sizeof iattr);
21262306a36Sopenharmony_ci		iattr.ia_valid |= ATTR_MTIME | ATTR_CTIME;
21362306a36Sopenharmony_ci		iattr.ia_mtime = iattr.ia_ctime = current_time(dir);
21462306a36Sopenharmony_ci		__orangefs_setattr(dir, &iattr);
21562306a36Sopenharmony_ci	}
21662306a36Sopenharmony_ci	return ret;
21762306a36Sopenharmony_ci}
21862306a36Sopenharmony_ci
21962306a36Sopenharmony_cistatic int orangefs_symlink(struct mnt_idmap *idmap,
22062306a36Sopenharmony_ci		         struct inode *dir,
22162306a36Sopenharmony_ci			 struct dentry *dentry,
22262306a36Sopenharmony_ci			 const char *symname)
22362306a36Sopenharmony_ci{
22462306a36Sopenharmony_ci	struct orangefs_inode_s *parent = ORANGEFS_I(dir);
22562306a36Sopenharmony_ci	struct orangefs_kernel_op_s *new_op;
22662306a36Sopenharmony_ci	struct orangefs_object_kref ref;
22762306a36Sopenharmony_ci	struct inode *inode;
22862306a36Sopenharmony_ci	struct iattr iattr;
22962306a36Sopenharmony_ci	int mode = 0755;
23062306a36Sopenharmony_ci	int ret;
23162306a36Sopenharmony_ci
23262306a36Sopenharmony_ci	gossip_debug(GOSSIP_NAME_DEBUG, "%s: called\n", __func__);
23362306a36Sopenharmony_ci
23462306a36Sopenharmony_ci	if (!symname)
23562306a36Sopenharmony_ci		return -EINVAL;
23662306a36Sopenharmony_ci
23762306a36Sopenharmony_ci	if (strlen(symname)+1 > ORANGEFS_NAME_MAX)
23862306a36Sopenharmony_ci		return -ENAMETOOLONG;
23962306a36Sopenharmony_ci
24062306a36Sopenharmony_ci	new_op = op_alloc(ORANGEFS_VFS_OP_SYMLINK);
24162306a36Sopenharmony_ci	if (!new_op)
24262306a36Sopenharmony_ci		return -ENOMEM;
24362306a36Sopenharmony_ci
24462306a36Sopenharmony_ci	new_op->upcall.req.sym.parent_refn = parent->refn;
24562306a36Sopenharmony_ci
24662306a36Sopenharmony_ci	fill_default_sys_attrs(new_op->upcall.req.sym.attributes,
24762306a36Sopenharmony_ci			       ORANGEFS_TYPE_SYMLINK,
24862306a36Sopenharmony_ci			       mode);
24962306a36Sopenharmony_ci
25062306a36Sopenharmony_ci	strncpy(new_op->upcall.req.sym.entry_name,
25162306a36Sopenharmony_ci		dentry->d_name.name,
25262306a36Sopenharmony_ci		ORANGEFS_NAME_MAX - 1);
25362306a36Sopenharmony_ci	strncpy(new_op->upcall.req.sym.target, symname, ORANGEFS_NAME_MAX - 1);
25462306a36Sopenharmony_ci
25562306a36Sopenharmony_ci	ret = service_operation(new_op, __func__, get_interruptible_flag(dir));
25662306a36Sopenharmony_ci
25762306a36Sopenharmony_ci	gossip_debug(GOSSIP_NAME_DEBUG,
25862306a36Sopenharmony_ci		     "Symlink Got ORANGEFS handle %pU on fsid %d (ret=%d)\n",
25962306a36Sopenharmony_ci		     &new_op->downcall.resp.sym.refn.khandle,
26062306a36Sopenharmony_ci		     new_op->downcall.resp.sym.refn.fs_id, ret);
26162306a36Sopenharmony_ci
26262306a36Sopenharmony_ci	if (ret < 0) {
26362306a36Sopenharmony_ci		gossip_debug(GOSSIP_NAME_DEBUG,
26462306a36Sopenharmony_ci			    "%s: failed with error code %d\n",
26562306a36Sopenharmony_ci			    __func__, ret);
26662306a36Sopenharmony_ci		goto out;
26762306a36Sopenharmony_ci	}
26862306a36Sopenharmony_ci
26962306a36Sopenharmony_ci	ref = new_op->downcall.resp.sym.refn;
27062306a36Sopenharmony_ci
27162306a36Sopenharmony_ci	inode = orangefs_new_inode(dir->i_sb, dir, S_IFLNK | mode, 0, &ref);
27262306a36Sopenharmony_ci	if (IS_ERR(inode)) {
27362306a36Sopenharmony_ci		gossip_err
27462306a36Sopenharmony_ci		    ("*** Failed to allocate orangefs symlink inode\n");
27562306a36Sopenharmony_ci		ret = PTR_ERR(inode);
27662306a36Sopenharmony_ci		goto out;
27762306a36Sopenharmony_ci	}
27862306a36Sopenharmony_ci	/*
27962306a36Sopenharmony_ci	 * This is necessary because orangefs_inode_getattr will not
28062306a36Sopenharmony_ci	 * re-read symlink size as it is impossible for it to change.
28162306a36Sopenharmony_ci	 * Invalidating the cache does not help.  orangefs_new_inode
28262306a36Sopenharmony_ci	 * does not set the correct size (it does not know symname).
28362306a36Sopenharmony_ci	 */
28462306a36Sopenharmony_ci	inode->i_size = strlen(symname);
28562306a36Sopenharmony_ci
28662306a36Sopenharmony_ci	gossip_debug(GOSSIP_NAME_DEBUG,
28762306a36Sopenharmony_ci		     "Assigned symlink inode new number of %pU\n",
28862306a36Sopenharmony_ci		     get_khandle_from_ino(inode));
28962306a36Sopenharmony_ci
29062306a36Sopenharmony_ci	d_instantiate_new(dentry, inode);
29162306a36Sopenharmony_ci	orangefs_set_timeout(dentry);
29262306a36Sopenharmony_ci
29362306a36Sopenharmony_ci	gossip_debug(GOSSIP_NAME_DEBUG,
29462306a36Sopenharmony_ci		     "Inode (Symlink) %pU -> %pd\n",
29562306a36Sopenharmony_ci		     get_khandle_from_ino(inode),
29662306a36Sopenharmony_ci		     dentry);
29762306a36Sopenharmony_ci
29862306a36Sopenharmony_ci	memset(&iattr, 0, sizeof iattr);
29962306a36Sopenharmony_ci	iattr.ia_valid |= ATTR_MTIME | ATTR_CTIME;
30062306a36Sopenharmony_ci	iattr.ia_mtime = iattr.ia_ctime = current_time(dir);
30162306a36Sopenharmony_ci	__orangefs_setattr(dir, &iattr);
30262306a36Sopenharmony_ci	ret = 0;
30362306a36Sopenharmony_ciout:
30462306a36Sopenharmony_ci	op_release(new_op);
30562306a36Sopenharmony_ci	return ret;
30662306a36Sopenharmony_ci}
30762306a36Sopenharmony_ci
30862306a36Sopenharmony_cistatic int orangefs_mkdir(struct mnt_idmap *idmap, struct inode *dir,
30962306a36Sopenharmony_ci			  struct dentry *dentry, umode_t mode)
31062306a36Sopenharmony_ci{
31162306a36Sopenharmony_ci	struct orangefs_inode_s *parent = ORANGEFS_I(dir);
31262306a36Sopenharmony_ci	struct orangefs_kernel_op_s *new_op;
31362306a36Sopenharmony_ci	struct orangefs_object_kref ref;
31462306a36Sopenharmony_ci	struct inode *inode;
31562306a36Sopenharmony_ci	struct iattr iattr;
31662306a36Sopenharmony_ci	int ret;
31762306a36Sopenharmony_ci
31862306a36Sopenharmony_ci	new_op = op_alloc(ORANGEFS_VFS_OP_MKDIR);
31962306a36Sopenharmony_ci	if (!new_op)
32062306a36Sopenharmony_ci		return -ENOMEM;
32162306a36Sopenharmony_ci
32262306a36Sopenharmony_ci	new_op->upcall.req.mkdir.parent_refn = parent->refn;
32362306a36Sopenharmony_ci
32462306a36Sopenharmony_ci	fill_default_sys_attrs(new_op->upcall.req.mkdir.attributes,
32562306a36Sopenharmony_ci			      ORANGEFS_TYPE_DIRECTORY, mode);
32662306a36Sopenharmony_ci
32762306a36Sopenharmony_ci	strncpy(new_op->upcall.req.mkdir.d_name,
32862306a36Sopenharmony_ci		dentry->d_name.name, ORANGEFS_NAME_MAX - 1);
32962306a36Sopenharmony_ci
33062306a36Sopenharmony_ci	ret = service_operation(new_op, __func__, get_interruptible_flag(dir));
33162306a36Sopenharmony_ci
33262306a36Sopenharmony_ci	gossip_debug(GOSSIP_NAME_DEBUG,
33362306a36Sopenharmony_ci		     "Mkdir Got ORANGEFS handle %pU on fsid %d\n",
33462306a36Sopenharmony_ci		     &new_op->downcall.resp.mkdir.refn.khandle,
33562306a36Sopenharmony_ci		     new_op->downcall.resp.mkdir.refn.fs_id);
33662306a36Sopenharmony_ci
33762306a36Sopenharmony_ci	if (ret < 0) {
33862306a36Sopenharmony_ci		gossip_debug(GOSSIP_NAME_DEBUG,
33962306a36Sopenharmony_ci			     "%s: failed with error code %d\n",
34062306a36Sopenharmony_ci			     __func__, ret);
34162306a36Sopenharmony_ci		goto out;
34262306a36Sopenharmony_ci	}
34362306a36Sopenharmony_ci
34462306a36Sopenharmony_ci	ref = new_op->downcall.resp.mkdir.refn;
34562306a36Sopenharmony_ci
34662306a36Sopenharmony_ci	inode = orangefs_new_inode(dir->i_sb, dir, S_IFDIR | mode, 0, &ref);
34762306a36Sopenharmony_ci	if (IS_ERR(inode)) {
34862306a36Sopenharmony_ci		gossip_err("*** Failed to allocate orangefs dir inode\n");
34962306a36Sopenharmony_ci		ret = PTR_ERR(inode);
35062306a36Sopenharmony_ci		goto out;
35162306a36Sopenharmony_ci	}
35262306a36Sopenharmony_ci
35362306a36Sopenharmony_ci	gossip_debug(GOSSIP_NAME_DEBUG,
35462306a36Sopenharmony_ci		     "Assigned dir inode new number of %pU\n",
35562306a36Sopenharmony_ci		     get_khandle_from_ino(inode));
35662306a36Sopenharmony_ci
35762306a36Sopenharmony_ci	d_instantiate_new(dentry, inode);
35862306a36Sopenharmony_ci	orangefs_set_timeout(dentry);
35962306a36Sopenharmony_ci
36062306a36Sopenharmony_ci	gossip_debug(GOSSIP_NAME_DEBUG,
36162306a36Sopenharmony_ci		     "Inode (Directory) %pU -> %pd\n",
36262306a36Sopenharmony_ci		     get_khandle_from_ino(inode),
36362306a36Sopenharmony_ci		     dentry);
36462306a36Sopenharmony_ci
36562306a36Sopenharmony_ci	/*
36662306a36Sopenharmony_ci	 * NOTE: we have no good way to keep nlink consistent for directories
36762306a36Sopenharmony_ci	 * across clients; keep constant at 1.
36862306a36Sopenharmony_ci	 */
36962306a36Sopenharmony_ci	memset(&iattr, 0, sizeof iattr);
37062306a36Sopenharmony_ci	iattr.ia_valid |= ATTR_MTIME | ATTR_CTIME;
37162306a36Sopenharmony_ci	iattr.ia_mtime = iattr.ia_ctime = current_time(dir);
37262306a36Sopenharmony_ci	__orangefs_setattr(dir, &iattr);
37362306a36Sopenharmony_ciout:
37462306a36Sopenharmony_ci	op_release(new_op);
37562306a36Sopenharmony_ci	return ret;
37662306a36Sopenharmony_ci}
37762306a36Sopenharmony_ci
37862306a36Sopenharmony_cistatic int orangefs_rename(struct mnt_idmap *idmap,
37962306a36Sopenharmony_ci			struct inode *old_dir,
38062306a36Sopenharmony_ci			struct dentry *old_dentry,
38162306a36Sopenharmony_ci			struct inode *new_dir,
38262306a36Sopenharmony_ci			struct dentry *new_dentry,
38362306a36Sopenharmony_ci			unsigned int flags)
38462306a36Sopenharmony_ci{
38562306a36Sopenharmony_ci	struct orangefs_kernel_op_s *new_op;
38662306a36Sopenharmony_ci	struct iattr iattr;
38762306a36Sopenharmony_ci	int ret;
38862306a36Sopenharmony_ci
38962306a36Sopenharmony_ci	if (flags)
39062306a36Sopenharmony_ci		return -EINVAL;
39162306a36Sopenharmony_ci
39262306a36Sopenharmony_ci	gossip_debug(GOSSIP_NAME_DEBUG,
39362306a36Sopenharmony_ci		     "orangefs_rename: called (%pd2 => %pd2) ct=%d\n",
39462306a36Sopenharmony_ci		     old_dentry, new_dentry, d_count(new_dentry));
39562306a36Sopenharmony_ci
39662306a36Sopenharmony_ci	memset(&iattr, 0, sizeof iattr);
39762306a36Sopenharmony_ci	iattr.ia_valid |= ATTR_MTIME | ATTR_CTIME;
39862306a36Sopenharmony_ci	iattr.ia_mtime = iattr.ia_ctime = current_time(new_dir);
39962306a36Sopenharmony_ci	__orangefs_setattr(new_dir, &iattr);
40062306a36Sopenharmony_ci
40162306a36Sopenharmony_ci	new_op = op_alloc(ORANGEFS_VFS_OP_RENAME);
40262306a36Sopenharmony_ci	if (!new_op)
40362306a36Sopenharmony_ci		return -EINVAL;
40462306a36Sopenharmony_ci
40562306a36Sopenharmony_ci	new_op->upcall.req.rename.old_parent_refn = ORANGEFS_I(old_dir)->refn;
40662306a36Sopenharmony_ci	new_op->upcall.req.rename.new_parent_refn = ORANGEFS_I(new_dir)->refn;
40762306a36Sopenharmony_ci
40862306a36Sopenharmony_ci	strncpy(new_op->upcall.req.rename.d_old_name,
40962306a36Sopenharmony_ci		old_dentry->d_name.name,
41062306a36Sopenharmony_ci		ORANGEFS_NAME_MAX - 1);
41162306a36Sopenharmony_ci	strncpy(new_op->upcall.req.rename.d_new_name,
41262306a36Sopenharmony_ci		new_dentry->d_name.name,
41362306a36Sopenharmony_ci		ORANGEFS_NAME_MAX - 1);
41462306a36Sopenharmony_ci
41562306a36Sopenharmony_ci	ret = service_operation(new_op,
41662306a36Sopenharmony_ci				"orangefs_rename",
41762306a36Sopenharmony_ci				get_interruptible_flag(old_dentry->d_inode));
41862306a36Sopenharmony_ci
41962306a36Sopenharmony_ci	gossip_debug(GOSSIP_NAME_DEBUG,
42062306a36Sopenharmony_ci		     "orangefs_rename: got downcall status %d\n",
42162306a36Sopenharmony_ci		     ret);
42262306a36Sopenharmony_ci
42362306a36Sopenharmony_ci	if (new_dentry->d_inode)
42462306a36Sopenharmony_ci		inode_set_ctime_current(d_inode(new_dentry));
42562306a36Sopenharmony_ci
42662306a36Sopenharmony_ci	op_release(new_op);
42762306a36Sopenharmony_ci	return ret;
42862306a36Sopenharmony_ci}
42962306a36Sopenharmony_ci
43062306a36Sopenharmony_ci/* ORANGEFS implementation of VFS inode operations for directories */
43162306a36Sopenharmony_ciconst struct inode_operations orangefs_dir_inode_operations = {
43262306a36Sopenharmony_ci	.lookup = orangefs_lookup,
43362306a36Sopenharmony_ci	.get_inode_acl = orangefs_get_acl,
43462306a36Sopenharmony_ci	.set_acl = orangefs_set_acl,
43562306a36Sopenharmony_ci	.create = orangefs_create,
43662306a36Sopenharmony_ci	.unlink = orangefs_unlink,
43762306a36Sopenharmony_ci	.symlink = orangefs_symlink,
43862306a36Sopenharmony_ci	.mkdir = orangefs_mkdir,
43962306a36Sopenharmony_ci	.rmdir = orangefs_unlink,
44062306a36Sopenharmony_ci	.rename = orangefs_rename,
44162306a36Sopenharmony_ci	.setattr = orangefs_setattr,
44262306a36Sopenharmony_ci	.getattr = orangefs_getattr,
44362306a36Sopenharmony_ci	.listxattr = orangefs_listxattr,
44462306a36Sopenharmony_ci	.permission = orangefs_permission,
44562306a36Sopenharmony_ci	.update_time = orangefs_update_time,
44662306a36Sopenharmony_ci};
447