xref: /openbmc/linux/fs/orangefs/orangefs-utils.c (revision afd9fb2a)
1b2441318SGreg Kroah-Hartman // SPDX-License-Identifier: GPL-2.0
2575e9461SMike Marshall /*
3575e9461SMike Marshall  * (C) 2001 Clemson University and The University of Chicago
48b60785cSMartin Brandenburg  * Copyright 2018 Omnibond Systems, L.L.C.
5575e9461SMike Marshall  *
6575e9461SMike Marshall  * See COPYING in top-level directory.
7575e9461SMike Marshall  */
8296200d3SJérémy Lefaure #include <linux/kernel.h>
9575e9461SMike Marshall #include "protocol.h"
10575e9461SMike Marshall #include "orangefs-kernel.h"
11575e9461SMike Marshall #include "orangefs-dev-proto.h"
12575e9461SMike Marshall #include "orangefs-bufmap.h"
13575e9461SMike Marshall 
14575e9461SMike Marshall __s32 fsid_of_op(struct orangefs_kernel_op_s *op)
15575e9461SMike Marshall {
16575e9461SMike Marshall 	__s32 fsid = ORANGEFS_FS_ID_NULL;
17575e9461SMike Marshall 
18575e9461SMike Marshall 	if (op) {
19575e9461SMike Marshall 		switch (op->upcall.type) {
20575e9461SMike Marshall 		case ORANGEFS_VFS_OP_FILE_IO:
21575e9461SMike Marshall 			fsid = op->upcall.req.io.refn.fs_id;
22575e9461SMike Marshall 			break;
23575e9461SMike Marshall 		case ORANGEFS_VFS_OP_LOOKUP:
24575e9461SMike Marshall 			fsid = op->upcall.req.lookup.parent_refn.fs_id;
25575e9461SMike Marshall 			break;
26575e9461SMike Marshall 		case ORANGEFS_VFS_OP_CREATE:
27575e9461SMike Marshall 			fsid = op->upcall.req.create.parent_refn.fs_id;
28575e9461SMike Marshall 			break;
29575e9461SMike Marshall 		case ORANGEFS_VFS_OP_GETATTR:
30575e9461SMike Marshall 			fsid = op->upcall.req.getattr.refn.fs_id;
31575e9461SMike Marshall 			break;
32575e9461SMike Marshall 		case ORANGEFS_VFS_OP_REMOVE:
33575e9461SMike Marshall 			fsid = op->upcall.req.remove.parent_refn.fs_id;
34575e9461SMike Marshall 			break;
35575e9461SMike Marshall 		case ORANGEFS_VFS_OP_MKDIR:
36575e9461SMike Marshall 			fsid = op->upcall.req.mkdir.parent_refn.fs_id;
37575e9461SMike Marshall 			break;
38575e9461SMike Marshall 		case ORANGEFS_VFS_OP_READDIR:
39575e9461SMike Marshall 			fsid = op->upcall.req.readdir.refn.fs_id;
40575e9461SMike Marshall 			break;
41575e9461SMike Marshall 		case ORANGEFS_VFS_OP_SETATTR:
42575e9461SMike Marshall 			fsid = op->upcall.req.setattr.refn.fs_id;
43575e9461SMike Marshall 			break;
44575e9461SMike Marshall 		case ORANGEFS_VFS_OP_SYMLINK:
45575e9461SMike Marshall 			fsid = op->upcall.req.sym.parent_refn.fs_id;
46575e9461SMike Marshall 			break;
47575e9461SMike Marshall 		case ORANGEFS_VFS_OP_RENAME:
48575e9461SMike Marshall 			fsid = op->upcall.req.rename.old_parent_refn.fs_id;
49575e9461SMike Marshall 			break;
50575e9461SMike Marshall 		case ORANGEFS_VFS_OP_STATFS:
51575e9461SMike Marshall 			fsid = op->upcall.req.statfs.fs_id;
52575e9461SMike Marshall 			break;
53575e9461SMike Marshall 		case ORANGEFS_VFS_OP_TRUNCATE:
54575e9461SMike Marshall 			fsid = op->upcall.req.truncate.refn.fs_id;
55575e9461SMike Marshall 			break;
566eaff8c7SMartin Brandenburg 		case ORANGEFS_VFS_OP_RA_FLUSH:
57575e9461SMike Marshall 			fsid = op->upcall.req.ra_cache_flush.refn.fs_id;
58575e9461SMike Marshall 			break;
59575e9461SMike Marshall 		case ORANGEFS_VFS_OP_FS_UMOUNT:
60575e9461SMike Marshall 			fsid = op->upcall.req.fs_umount.fs_id;
61575e9461SMike Marshall 			break;
62575e9461SMike Marshall 		case ORANGEFS_VFS_OP_GETXATTR:
63575e9461SMike Marshall 			fsid = op->upcall.req.getxattr.refn.fs_id;
64575e9461SMike Marshall 			break;
65575e9461SMike Marshall 		case ORANGEFS_VFS_OP_SETXATTR:
66575e9461SMike Marshall 			fsid = op->upcall.req.setxattr.refn.fs_id;
67575e9461SMike Marshall 			break;
68575e9461SMike Marshall 		case ORANGEFS_VFS_OP_LISTXATTR:
69575e9461SMike Marshall 			fsid = op->upcall.req.listxattr.refn.fs_id;
70575e9461SMike Marshall 			break;
71575e9461SMike Marshall 		case ORANGEFS_VFS_OP_REMOVEXATTR:
72575e9461SMike Marshall 			fsid = op->upcall.req.removexattr.refn.fs_id;
73575e9461SMike Marshall 			break;
74575e9461SMike Marshall 		case ORANGEFS_VFS_OP_FSYNC:
75575e9461SMike Marshall 			fsid = op->upcall.req.fsync.refn.fs_id;
76575e9461SMike Marshall 			break;
77575e9461SMike Marshall 		default:
78575e9461SMike Marshall 			break;
79575e9461SMike Marshall 		}
80575e9461SMike Marshall 	}
81575e9461SMike Marshall 	return fsid;
82575e9461SMike Marshall }
83575e9461SMike Marshall 
84394f647eSMartin Brandenburg static int orangefs_inode_flags(struct ORANGEFS_sys_attr_s *attrs)
85575e9461SMike Marshall {
86394f647eSMartin Brandenburg 	int flags = 0;
87575e9461SMike Marshall 	if (attrs->flags & ORANGEFS_IMMUTABLE_FL)
88394f647eSMartin Brandenburg 		flags |= S_IMMUTABLE;
89575e9461SMike Marshall 	else
90394f647eSMartin Brandenburg 		flags &= ~S_IMMUTABLE;
91575e9461SMike Marshall 	if (attrs->flags & ORANGEFS_APPEND_FL)
92394f647eSMartin Brandenburg 		flags |= S_APPEND;
93575e9461SMike Marshall 	else
94394f647eSMartin Brandenburg 		flags &= ~S_APPEND;
95575e9461SMike Marshall 	if (attrs->flags & ORANGEFS_NOATIME_FL)
96394f647eSMartin Brandenburg 		flags |= S_NOATIME;
97575e9461SMike Marshall 	else
98394f647eSMartin Brandenburg 		flags &= ~S_NOATIME;
99394f647eSMartin Brandenburg 	return flags;
100394f647eSMartin Brandenburg }
101575e9461SMike Marshall 
102394f647eSMartin Brandenburg static int orangefs_inode_perms(struct ORANGEFS_sys_attr_s *attrs)
103394f647eSMartin Brandenburg {
104394f647eSMartin Brandenburg 	int perm_mode = 0;
105394f647eSMartin Brandenburg 
106394f647eSMartin Brandenburg 	if (attrs->perms & ORANGEFS_O_EXECUTE)
107394f647eSMartin Brandenburg 		perm_mode |= S_IXOTH;
108394f647eSMartin Brandenburg 	if (attrs->perms & ORANGEFS_O_WRITE)
109394f647eSMartin Brandenburg 		perm_mode |= S_IWOTH;
110394f647eSMartin Brandenburg 	if (attrs->perms & ORANGEFS_O_READ)
111394f647eSMartin Brandenburg 		perm_mode |= S_IROTH;
112394f647eSMartin Brandenburg 
113394f647eSMartin Brandenburg 	if (attrs->perms & ORANGEFS_G_EXECUTE)
114394f647eSMartin Brandenburg 		perm_mode |= S_IXGRP;
115394f647eSMartin Brandenburg 	if (attrs->perms & ORANGEFS_G_WRITE)
116394f647eSMartin Brandenburg 		perm_mode |= S_IWGRP;
117394f647eSMartin Brandenburg 	if (attrs->perms & ORANGEFS_G_READ)
118394f647eSMartin Brandenburg 		perm_mode |= S_IRGRP;
119394f647eSMartin Brandenburg 
120394f647eSMartin Brandenburg 	if (attrs->perms & ORANGEFS_U_EXECUTE)
121394f647eSMartin Brandenburg 		perm_mode |= S_IXUSR;
122394f647eSMartin Brandenburg 	if (attrs->perms & ORANGEFS_U_WRITE)
123394f647eSMartin Brandenburg 		perm_mode |= S_IWUSR;
124394f647eSMartin Brandenburg 	if (attrs->perms & ORANGEFS_U_READ)
125394f647eSMartin Brandenburg 		perm_mode |= S_IRUSR;
126394f647eSMartin Brandenburg 
127394f647eSMartin Brandenburg 	if (attrs->perms & ORANGEFS_G_SGID)
128394f647eSMartin Brandenburg 		perm_mode |= S_ISGID;
129394f647eSMartin Brandenburg 	if (attrs->perms & ORANGEFS_U_SUID)
130394f647eSMartin Brandenburg 		perm_mode |= S_ISUID;
131394f647eSMartin Brandenburg 
132394f647eSMartin Brandenburg 	return perm_mode;
133575e9461SMike Marshall }
134575e9461SMike Marshall 
135575e9461SMike Marshall /*
136575e9461SMike Marshall  * NOTE: in kernel land, we never use the sys_attr->link_target for
137575e9461SMike Marshall  * anything, so don't bother copying it into the sys_attr object here.
138575e9461SMike Marshall  */
139afd9fb2aSMartin Brandenburg static inline void copy_attributes_from_inode(struct inode *inode,
140afd9fb2aSMartin Brandenburg     struct ORANGEFS_sys_attr_s *attrs)
141575e9461SMike Marshall {
142afd9fb2aSMartin Brandenburg 	struct orangefs_inode_s *orangefs_inode = ORANGEFS_I(inode);
143575e9461SMike Marshall 	attrs->mask = 0;
144afd9fb2aSMartin Brandenburg 	if (orangefs_inode->attr_valid & ATTR_UID) {
145afd9fb2aSMartin Brandenburg 		attrs->owner = from_kuid(&init_user_ns, inode->i_uid);
146575e9461SMike Marshall 		attrs->mask |= ORANGEFS_ATTR_SYS_UID;
147575e9461SMike Marshall 		gossip_debug(GOSSIP_UTILS_DEBUG, "(UID) %d\n", attrs->owner);
148575e9461SMike Marshall 	}
149afd9fb2aSMartin Brandenburg 	if (orangefs_inode->attr_valid & ATTR_GID) {
150afd9fb2aSMartin Brandenburg 		attrs->group = from_kgid(&init_user_ns, inode->i_gid);
151575e9461SMike Marshall 		attrs->mask |= ORANGEFS_ATTR_SYS_GID;
152575e9461SMike Marshall 		gossip_debug(GOSSIP_UTILS_DEBUG, "(GID) %d\n", attrs->group);
153575e9461SMike Marshall 	}
154575e9461SMike Marshall 
155afd9fb2aSMartin Brandenburg 	if (orangefs_inode->attr_valid & ATTR_ATIME) {
156575e9461SMike Marshall 		attrs->mask |= ORANGEFS_ATTR_SYS_ATIME;
157afd9fb2aSMartin Brandenburg 		if (orangefs_inode->attr_valid & ATTR_ATIME_SET) {
158afd9fb2aSMartin Brandenburg 			attrs->atime = (time64_t)inode->i_atime.tv_sec;
159575e9461SMike Marshall 			attrs->mask |= ORANGEFS_ATTR_SYS_ATIME_SET;
160575e9461SMike Marshall 		}
161575e9461SMike Marshall 	}
162afd9fb2aSMartin Brandenburg 	if (orangefs_inode->attr_valid & ATTR_MTIME) {
163575e9461SMike Marshall 		attrs->mask |= ORANGEFS_ATTR_SYS_MTIME;
164afd9fb2aSMartin Brandenburg 		if (orangefs_inode->attr_valid & ATTR_MTIME_SET) {
165afd9fb2aSMartin Brandenburg 			attrs->mtime = (time64_t)inode->i_mtime.tv_sec;
166575e9461SMike Marshall 			attrs->mask |= ORANGEFS_ATTR_SYS_MTIME_SET;
167575e9461SMike Marshall 		}
168575e9461SMike Marshall 	}
169afd9fb2aSMartin Brandenburg 	if (orangefs_inode->attr_valid & ATTR_CTIME)
170575e9461SMike Marshall 		attrs->mask |= ORANGEFS_ATTR_SYS_CTIME;
171575e9461SMike Marshall 
172575e9461SMike Marshall 	/*
17395f5f88fSMike Marshall 	 * ORANGEFS cannot set size with a setattr operation. Probably not
17495f5f88fSMike Marshall 	 * likely to be requested through the VFS, but just in case, don't
17595f5f88fSMike Marshall 	 * worry about ATTR_SIZE
176575e9461SMike Marshall 	 */
177575e9461SMike Marshall 
178afd9fb2aSMartin Brandenburg 	if (orangefs_inode->attr_valid & ATTR_MODE) {
179afd9fb2aSMartin Brandenburg 		attrs->perms = ORANGEFS_util_translate_mode(inode->i_mode);
180575e9461SMike Marshall 		attrs->mask |= ORANGEFS_ATTR_SYS_PERM;
181575e9461SMike Marshall 	}
182575e9461SMike Marshall }
183575e9461SMike Marshall 
1843c9cf98dSMartin Brandenburg static int orangefs_inode_type(enum orangefs_ds_type objtype)
1853c9cf98dSMartin Brandenburg {
1863c9cf98dSMartin Brandenburg 	if (objtype == ORANGEFS_TYPE_METAFILE)
1873c9cf98dSMartin Brandenburg 		return S_IFREG;
1883c9cf98dSMartin Brandenburg 	else if (objtype == ORANGEFS_TYPE_DIRECTORY)
1893c9cf98dSMartin Brandenburg 		return S_IFDIR;
1903c9cf98dSMartin Brandenburg 	else if (objtype == ORANGEFS_TYPE_SYMLINK)
1913c9cf98dSMartin Brandenburg 		return S_IFLNK;
1923c9cf98dSMartin Brandenburg 	else
1933c9cf98dSMartin Brandenburg 		return -1;
1943c9cf98dSMartin Brandenburg }
1953c9cf98dSMartin Brandenburg 
1964d0cac7eSMartin Brandenburg static void orangefs_make_bad_inode(struct inode *inode)
1974d0cac7eSMartin Brandenburg {
1984d0cac7eSMartin Brandenburg 	if (is_root_handle(inode)) {
1994d0cac7eSMartin Brandenburg 		/*
2004d0cac7eSMartin Brandenburg 		 * if this occurs, the pvfs2-client-core was killed but we
2014d0cac7eSMartin Brandenburg 		 * can't afford to lose the inode operations and such
2024d0cac7eSMartin Brandenburg 		 * associated with the root handle in any case.
2034d0cac7eSMartin Brandenburg 		 */
2044d0cac7eSMartin Brandenburg 		gossip_debug(GOSSIP_UTILS_DEBUG,
2054d0cac7eSMartin Brandenburg 			     "*** NOT making bad root inode %pU\n",
2064d0cac7eSMartin Brandenburg 			     get_khandle_from_ino(inode));
2074d0cac7eSMartin Brandenburg 	} else {
2084d0cac7eSMartin Brandenburg 		gossip_debug(GOSSIP_UTILS_DEBUG,
2094d0cac7eSMartin Brandenburg 			     "*** making bad inode %pU\n",
2104d0cac7eSMartin Brandenburg 			     get_khandle_from_ino(inode));
2114d0cac7eSMartin Brandenburg 		make_bad_inode(inode);
2124d0cac7eSMartin Brandenburg 	}
2134d0cac7eSMartin Brandenburg }
2144d0cac7eSMartin Brandenburg 
215480e5ae9SMartin Brandenburg static int orangefs_inode_is_stale(struct inode *inode,
21626662633SMartin Brandenburg     struct ORANGEFS_sys_attr_s *attrs, char *link_target)
21726662633SMartin Brandenburg {
21826662633SMartin Brandenburg 	struct orangefs_inode_s *orangefs_inode = ORANGEFS_I(inode);
21926662633SMartin Brandenburg 	int type = orangefs_inode_type(attrs->objtype);
22026662633SMartin Brandenburg 	/*
22126662633SMartin Brandenburg 	 * If the inode type or symlink target have changed then this
22226662633SMartin Brandenburg 	 * inode is stale.
22326662633SMartin Brandenburg 	 */
22426662633SMartin Brandenburg 	if (type == -1 || !(inode->i_mode & type)) {
22526662633SMartin Brandenburg 		orangefs_make_bad_inode(inode);
22626662633SMartin Brandenburg 		return 1;
22726662633SMartin Brandenburg 	}
22826662633SMartin Brandenburg 	if (type == S_IFLNK && strncmp(orangefs_inode->link_target,
22926662633SMartin Brandenburg 	    link_target, ORANGEFS_NAME_MAX)) {
23026662633SMartin Brandenburg 		orangefs_make_bad_inode(inode);
23126662633SMartin Brandenburg 		return 1;
23226662633SMartin Brandenburg 	}
23326662633SMartin Brandenburg 	return 0;
23426662633SMartin Brandenburg }
23526662633SMartin Brandenburg 
2368b60785cSMartin Brandenburg int orangefs_inode_getattr(struct inode *inode, int flags)
2373c9cf98dSMartin Brandenburg {
2383c9cf98dSMartin Brandenburg 	struct orangefs_inode_s *orangefs_inode = ORANGEFS_I(inode);
2393c9cf98dSMartin Brandenburg 	struct orangefs_kernel_op_s *new_op;
2409f8fd53cSMartin Brandenburg 	loff_t inode_size;
24126662633SMartin Brandenburg 	int ret, type;
2423c9cf98dSMartin Brandenburg 
2435e4f606eSMartin Brandenburg 	gossip_debug(GOSSIP_UTILS_DEBUG, "%s: called on inode %pU flags %d\n",
2445e4f606eSMartin Brandenburg 	    __func__, get_khandle_from_ino(inode), flags);
2453c9cf98dSMartin Brandenburg 
246afd9fb2aSMartin Brandenburg again:
2475e4f606eSMartin Brandenburg 	spin_lock(&inode->i_lock);
2488b60785cSMartin Brandenburg 	/* Must have all the attributes in the mask and be within cache time. */
2495e4f606eSMartin Brandenburg 	if ((!flags && time_before(jiffies, orangefs_inode->getattr_time)) ||
250afd9fb2aSMartin Brandenburg 	    orangefs_inode->attr_valid) {
251afd9fb2aSMartin Brandenburg 		if (orangefs_inode->attr_valid) {
252afd9fb2aSMartin Brandenburg 			spin_unlock(&inode->i_lock);
253afd9fb2aSMartin Brandenburg 			write_inode_now(inode, 1);
254afd9fb2aSMartin Brandenburg 			goto again;
255afd9fb2aSMartin Brandenburg 		}
2565e4f606eSMartin Brandenburg 		spin_unlock(&inode->i_lock);
25771680c18SMartin Brandenburg 		return 0;
2585e4f606eSMartin Brandenburg 	}
2595e4f606eSMartin Brandenburg 	spin_unlock(&inode->i_lock);
26071680c18SMartin Brandenburg 
2613c9cf98dSMartin Brandenburg 	new_op = op_alloc(ORANGEFS_VFS_OP_GETATTR);
2623c9cf98dSMartin Brandenburg 	if (!new_op)
2633c9cf98dSMartin Brandenburg 		return -ENOMEM;
2643c9cf98dSMartin Brandenburg 	new_op->upcall.req.getattr.refn = orangefs_inode->refn;
26568a24a6cSMartin Brandenburg 	/*
26668a24a6cSMartin Brandenburg 	 * Size is the hardest attribute to get.  The incremental cost of any
26768a24a6cSMartin Brandenburg 	 * other attribute is essentially zero.
26868a24a6cSMartin Brandenburg 	 */
2698b60785cSMartin Brandenburg 	if (flags)
27071680c18SMartin Brandenburg 		new_op->upcall.req.getattr.mask = ORANGEFS_ATTR_SYS_ALL_NOHINT;
27168a24a6cSMartin Brandenburg 	else
27268a24a6cSMartin Brandenburg 		new_op->upcall.req.getattr.mask =
27368a24a6cSMartin Brandenburg 		    ORANGEFS_ATTR_SYS_ALL_NOHINT & ~ORANGEFS_ATTR_SYS_SIZE;
2743c9cf98dSMartin Brandenburg 
2753c9cf98dSMartin Brandenburg 	ret = service_operation(new_op, __func__,
2763c9cf98dSMartin Brandenburg 	    get_interruptible_flag(inode));
2773c9cf98dSMartin Brandenburg 	if (ret != 0)
2783c9cf98dSMartin Brandenburg 		goto out;
2793c9cf98dSMartin Brandenburg 
280afd9fb2aSMartin Brandenburg again2:
2815e4f606eSMartin Brandenburg 	spin_lock(&inode->i_lock);
2825e4f606eSMartin Brandenburg 	/* Must have all the attributes in the mask and be within cache time. */
2835e4f606eSMartin Brandenburg 	if ((!flags && time_before(jiffies, orangefs_inode->getattr_time)) ||
284afd9fb2aSMartin Brandenburg 	    orangefs_inode->attr_valid) {
285afd9fb2aSMartin Brandenburg 		if (orangefs_inode->attr_valid) {
286afd9fb2aSMartin Brandenburg 			spin_unlock(&inode->i_lock);
287afd9fb2aSMartin Brandenburg 			write_inode_now(inode, 1);
288afd9fb2aSMartin Brandenburg 			goto again2;
289afd9fb2aSMartin Brandenburg 		}
2905e4f606eSMartin Brandenburg 		gossip_debug(GOSSIP_UTILS_DEBUG, "%s: in cache or dirty\n",
2915e4f606eSMartin Brandenburg 		    __func__);
2925e4f606eSMartin Brandenburg 		ret = 0;
2935e4f606eSMartin Brandenburg 		goto out_unlock;
2945e4f606eSMartin Brandenburg 	}
2955e4f606eSMartin Brandenburg 
2968b60785cSMartin Brandenburg 	if (!(flags & ORANGEFS_GETATTR_NEW)) {
297480e5ae9SMartin Brandenburg 		ret = orangefs_inode_is_stale(inode,
29826662633SMartin Brandenburg 		    &new_op->downcall.resp.getattr.attributes,
29926662633SMartin Brandenburg 		    new_op->downcall.resp.getattr.link_target);
30026662633SMartin Brandenburg 		if (ret) {
3013c9cf98dSMartin Brandenburg 			ret = -ESTALE;
3025e4f606eSMartin Brandenburg 			goto out_unlock;
3033c9cf98dSMartin Brandenburg 		}
304480e5ae9SMartin Brandenburg 	}
3053c9cf98dSMartin Brandenburg 
306480e5ae9SMartin Brandenburg 	type = orangefs_inode_type(new_op->
307480e5ae9SMartin Brandenburg 	    downcall.resp.getattr.attributes.objtype);
30826662633SMartin Brandenburg 	switch (type) {
3093c9cf98dSMartin Brandenburg 	case S_IFREG:
3103c9cf98dSMartin Brandenburg 		inode->i_flags = orangefs_inode_flags(&new_op->
3113c9cf98dSMartin Brandenburg 		    downcall.resp.getattr.attributes);
3128b60785cSMartin Brandenburg 		if (flags) {
3133c9cf98dSMartin Brandenburg 			inode_size = (loff_t)new_op->
3143c9cf98dSMartin Brandenburg 			    downcall.resp.getattr.attributes.size;
3153c9cf98dSMartin Brandenburg 			inode->i_size = inode_size;
3169f8fd53cSMartin Brandenburg 			inode->i_blkbits = ffs(new_op->downcall.resp.getattr.
3179f8fd53cSMartin Brandenburg 			    attributes.blksize);
3183c9cf98dSMartin Brandenburg 			inode->i_bytes = inode_size;
3193c9cf98dSMartin Brandenburg 			inode->i_blocks =
3209f8fd53cSMartin Brandenburg 			    (inode_size + 512 - inode_size % 512)/512;
32168a24a6cSMartin Brandenburg 		}
3223c9cf98dSMartin Brandenburg 		break;
3233c9cf98dSMartin Brandenburg 	case S_IFDIR:
3248b60785cSMartin Brandenburg 		if (flags) {
32509cbfeafSKirill A. Shutemov 			inode->i_size = PAGE_SIZE;
3263c9cf98dSMartin Brandenburg 			inode_set_bytes(inode, inode->i_size);
32768a24a6cSMartin Brandenburg 		}
3283c9cf98dSMartin Brandenburg 		set_nlink(inode, 1);
3293c9cf98dSMartin Brandenburg 		break;
3303c9cf98dSMartin Brandenburg 	case S_IFLNK:
3318b60785cSMartin Brandenburg 		if (flags & ORANGEFS_GETATTR_NEW) {
3323c9cf98dSMartin Brandenburg 			inode->i_size = (loff_t)strlen(new_op->
3333c9cf98dSMartin Brandenburg 			    downcall.resp.getattr.link_target);
3342eacea74SMartin Brandenburg 			ret = strscpy(orangefs_inode->link_target,
3353c9cf98dSMartin Brandenburg 			    new_op->downcall.resp.getattr.link_target,
3363c9cf98dSMartin Brandenburg 			    ORANGEFS_NAME_MAX);
3372eacea74SMartin Brandenburg 			if (ret == -E2BIG) {
3382eacea74SMartin Brandenburg 				ret = -EIO;
3395e4f606eSMartin Brandenburg 				goto out_unlock;
3402eacea74SMartin Brandenburg 			}
341e8da254cSMartin Brandenburg 			inode->i_link = orangefs_inode->link_target;
3423c9cf98dSMartin Brandenburg 		}
3433c9cf98dSMartin Brandenburg 		break;
344480e5ae9SMartin Brandenburg 	/* i.e. -1 */
345480e5ae9SMartin Brandenburg 	default:
346480e5ae9SMartin Brandenburg 		/* XXX: ESTALE?  This is what is done if it is not new. */
347480e5ae9SMartin Brandenburg 		orangefs_make_bad_inode(inode);
348480e5ae9SMartin Brandenburg 		ret = -ESTALE;
3495e4f606eSMartin Brandenburg 		goto out_unlock;
3503c9cf98dSMartin Brandenburg 	}
3513c9cf98dSMartin Brandenburg 
3523c9cf98dSMartin Brandenburg 	inode->i_uid = make_kuid(&init_user_ns, new_op->
3533c9cf98dSMartin Brandenburg 	    downcall.resp.getattr.attributes.owner);
3543c9cf98dSMartin Brandenburg 	inode->i_gid = make_kgid(&init_user_ns, new_op->
3553c9cf98dSMartin Brandenburg 	    downcall.resp.getattr.attributes.group);
3563c9cf98dSMartin Brandenburg 	inode->i_atime.tv_sec = (time64_t)new_op->
3573c9cf98dSMartin Brandenburg 	    downcall.resp.getattr.attributes.atime;
3583c9cf98dSMartin Brandenburg 	inode->i_mtime.tv_sec = (time64_t)new_op->
3593c9cf98dSMartin Brandenburg 	    downcall.resp.getattr.attributes.mtime;
3603c9cf98dSMartin Brandenburg 	inode->i_ctime.tv_sec = (time64_t)new_op->
3613c9cf98dSMartin Brandenburg 	    downcall.resp.getattr.attributes.ctime;
3623c9cf98dSMartin Brandenburg 	inode->i_atime.tv_nsec = 0;
3633c9cf98dSMartin Brandenburg 	inode->i_mtime.tv_nsec = 0;
3643c9cf98dSMartin Brandenburg 	inode->i_ctime.tv_nsec = 0;
3653c9cf98dSMartin Brandenburg 
3663c9cf98dSMartin Brandenburg 	/* special case: mark the root inode as sticky */
36726662633SMartin Brandenburg 	inode->i_mode = type | (is_root_handle(inode) ? S_ISVTX : 0) |
3683c9cf98dSMartin Brandenburg 	    orangefs_inode_perms(&new_op->downcall.resp.getattr.attributes);
3693c9cf98dSMartin Brandenburg 
3701d503617SMartin Brandenburg 	orangefs_inode->getattr_time = jiffies +
3711d503617SMartin Brandenburg 	    orangefs_getattr_timeout_msecs*HZ/1000;
3723c9cf98dSMartin Brandenburg 	ret = 0;
3735e4f606eSMartin Brandenburg out_unlock:
3745e4f606eSMartin Brandenburg 	spin_unlock(&inode->i_lock);
3753c9cf98dSMartin Brandenburg out:
3763c9cf98dSMartin Brandenburg 	op_release(new_op);
3773c9cf98dSMartin Brandenburg 	return ret;
3783c9cf98dSMartin Brandenburg }
3793c9cf98dSMartin Brandenburg 
3805859d77eSMartin Brandenburg int orangefs_inode_check_changed(struct inode *inode)
3815859d77eSMartin Brandenburg {
3825859d77eSMartin Brandenburg 	struct orangefs_inode_s *orangefs_inode = ORANGEFS_I(inode);
3835859d77eSMartin Brandenburg 	struct orangefs_kernel_op_s *new_op;
3845859d77eSMartin Brandenburg 	int ret;
3855859d77eSMartin Brandenburg 
3865859d77eSMartin Brandenburg 	gossip_debug(GOSSIP_UTILS_DEBUG, "%s: called on inode %pU\n", __func__,
3875859d77eSMartin Brandenburg 	    get_khandle_from_ino(inode));
3885859d77eSMartin Brandenburg 
3895859d77eSMartin Brandenburg 	new_op = op_alloc(ORANGEFS_VFS_OP_GETATTR);
3905859d77eSMartin Brandenburg 	if (!new_op)
3915859d77eSMartin Brandenburg 		return -ENOMEM;
3925859d77eSMartin Brandenburg 	new_op->upcall.req.getattr.refn = orangefs_inode->refn;
3935859d77eSMartin Brandenburg 	new_op->upcall.req.getattr.mask = ORANGEFS_ATTR_SYS_TYPE |
3945859d77eSMartin Brandenburg 	    ORANGEFS_ATTR_SYS_LNK_TARGET;
3955859d77eSMartin Brandenburg 
3965859d77eSMartin Brandenburg 	ret = service_operation(new_op, __func__,
3975859d77eSMartin Brandenburg 	    get_interruptible_flag(inode));
3985859d77eSMartin Brandenburg 	if (ret != 0)
3995859d77eSMartin Brandenburg 		goto out;
4005859d77eSMartin Brandenburg 
401480e5ae9SMartin Brandenburg 	ret = orangefs_inode_is_stale(inode,
40226662633SMartin Brandenburg 	    &new_op->downcall.resp.getattr.attributes,
40326662633SMartin Brandenburg 	    new_op->downcall.resp.getattr.link_target);
4045859d77eSMartin Brandenburg out:
4055859d77eSMartin Brandenburg 	op_release(new_op);
4065859d77eSMartin Brandenburg 	return ret;
4075859d77eSMartin Brandenburg }
4085859d77eSMartin Brandenburg 
409575e9461SMike Marshall /*
410575e9461SMike Marshall  * issues a orangefs setattr request to make sure the new attribute values
411575e9461SMike Marshall  * take effect if successful.  returns 0 on success; -errno otherwise
412575e9461SMike Marshall  */
413afd9fb2aSMartin Brandenburg int orangefs_inode_setattr(struct inode *inode)
414575e9461SMike Marshall {
415575e9461SMike Marshall 	struct orangefs_inode_s *orangefs_inode = ORANGEFS_I(inode);
416575e9461SMike Marshall 	struct orangefs_kernel_op_s *new_op;
417575e9461SMike Marshall 	int ret;
418575e9461SMike Marshall 
419575e9461SMike Marshall 	new_op = op_alloc(ORANGEFS_VFS_OP_SETATTR);
420575e9461SMike Marshall 	if (!new_op)
421575e9461SMike Marshall 		return -ENOMEM;
422575e9461SMike Marshall 
423afd9fb2aSMartin Brandenburg 	spin_lock(&inode->i_lock);
424afd9fb2aSMartin Brandenburg 	new_op->upcall.uid = from_kuid(&init_user_ns, orangefs_inode->attr_uid);
425afd9fb2aSMartin Brandenburg 	new_op->upcall.gid = from_kgid(&init_user_ns, orangefs_inode->attr_gid);
426575e9461SMike Marshall 	new_op->upcall.req.setattr.refn = orangefs_inode->refn;
427afd9fb2aSMartin Brandenburg 	copy_attributes_from_inode(inode,
428afd9fb2aSMartin Brandenburg 	    &new_op->upcall.req.setattr.attributes);
429afd9fb2aSMartin Brandenburg 	orangefs_inode->attr_valid = 0;
430afd9fb2aSMartin Brandenburg 	spin_unlock(&inode->i_lock);
431afd9fb2aSMartin Brandenburg 
432575e9461SMike Marshall 	ret = service_operation(new_op, __func__,
433575e9461SMike Marshall 	    get_interruptible_flag(inode));
434575e9461SMike Marshall 	gossip_debug(GOSSIP_UTILS_DEBUG,
435afd9fb2aSMartin Brandenburg 	    "orangefs_inode_setattr: returning %d\n", ret);
436afd9fb2aSMartin Brandenburg 	if (ret)
437afd9fb2aSMartin Brandenburg 		orangefs_make_bad_inode(inode);
438575e9461SMike Marshall 
439575e9461SMike Marshall 	op_release(new_op);
440575e9461SMike Marshall 
441a55f2d86SMartin Brandenburg 	if (ret == 0)
4428bbb20a8SMartin Brandenburg 		orangefs_inode->getattr_time = jiffies - 1;
443575e9461SMike Marshall 	return ret;
444575e9461SMike Marshall }
445575e9461SMike Marshall 
446575e9461SMike Marshall /*
447575e9461SMike Marshall  * The following is a very dirty hack that is now a permanent part of the
448575e9461SMike Marshall  * ORANGEFS protocol. See protocol.h for more error definitions.
449575e9461SMike Marshall  */
450575e9461SMike Marshall 
451575e9461SMike Marshall /* The order matches include/orangefs-types.h in the OrangeFS source. */
452575e9461SMike Marshall static int PINT_errno_mapping[] = {
453575e9461SMike Marshall 	0, EPERM, ENOENT, EINTR, EIO, ENXIO, EBADF, EAGAIN, ENOMEM,
454575e9461SMike Marshall 	EFAULT, EBUSY, EEXIST, ENODEV, ENOTDIR, EISDIR, EINVAL, EMFILE,
455575e9461SMike Marshall 	EFBIG, ENOSPC, EROFS, EMLINK, EPIPE, EDEADLK, ENAMETOOLONG,
456575e9461SMike Marshall 	ENOLCK, ENOSYS, ENOTEMPTY, ELOOP, EWOULDBLOCK, ENOMSG, EUNATCH,
457575e9461SMike Marshall 	EBADR, EDEADLOCK, ENODATA, ETIME, ENONET, EREMOTE, ECOMM,
458575e9461SMike Marshall 	EPROTO, EBADMSG, EOVERFLOW, ERESTART, EMSGSIZE, EPROTOTYPE,
459575e9461SMike Marshall 	ENOPROTOOPT, EPROTONOSUPPORT, EOPNOTSUPP, EADDRINUSE,
460575e9461SMike Marshall 	EADDRNOTAVAIL, ENETDOWN, ENETUNREACH, ENETRESET, ENOBUFS,
461575e9461SMike Marshall 	ETIMEDOUT, ECONNREFUSED, EHOSTDOWN, EHOSTUNREACH, EALREADY,
462575e9461SMike Marshall 	EACCES, ECONNRESET, ERANGE
463575e9461SMike Marshall };
464575e9461SMike Marshall 
465575e9461SMike Marshall int orangefs_normalize_to_errno(__s32 error_code)
466575e9461SMike Marshall {
467575e9461SMike Marshall 	__u32 i;
468575e9461SMike Marshall 
469575e9461SMike Marshall 	/* Success */
470575e9461SMike Marshall 	if (error_code == 0) {
471575e9461SMike Marshall 		return 0;
472575e9461SMike Marshall 	/*
473575e9461SMike Marshall 	 * This shouldn't ever happen. If it does it should be fixed on the
474575e9461SMike Marshall 	 * server.
475575e9461SMike Marshall 	 */
476575e9461SMike Marshall 	} else if (error_code > 0) {
477bc8282a7SMasanari Iida 		gossip_err("orangefs: error status received.\n");
478575e9461SMike Marshall 		gossip_err("orangefs: assuming error code is inverted.\n");
479575e9461SMike Marshall 		error_code = -error_code;
480575e9461SMike Marshall 	}
481575e9461SMike Marshall 
482575e9461SMike Marshall 	/*
483575e9461SMike Marshall 	 * XXX: This is very bad since error codes from ORANGEFS may not be
484575e9461SMike Marshall 	 * suitable for return into userspace.
485575e9461SMike Marshall 	 */
486575e9461SMike Marshall 
487575e9461SMike Marshall 	/*
488575e9461SMike Marshall 	 * Convert ORANGEFS error values into errno values suitable for return
489575e9461SMike Marshall 	 * from the kernel.
490575e9461SMike Marshall 	 */
491575e9461SMike Marshall 	if ((-error_code) & ORANGEFS_NON_ERRNO_ERROR_BIT) {
492575e9461SMike Marshall 		if (((-error_code) &
493575e9461SMike Marshall 		    (ORANGEFS_ERROR_NUMBER_BITS|ORANGEFS_NON_ERRNO_ERROR_BIT|
494575e9461SMike Marshall 		    ORANGEFS_ERROR_BIT)) == ORANGEFS_ECANCEL) {
495575e9461SMike Marshall 			/*
496575e9461SMike Marshall 			 * cancellation error codes generally correspond to
497575e9461SMike Marshall 			 * a timeout from the client's perspective
498575e9461SMike Marshall 			 */
499575e9461SMike Marshall 			error_code = -ETIMEDOUT;
500575e9461SMike Marshall 		} else {
501575e9461SMike Marshall 			/* assume a default error code */
50295f5f88fSMike Marshall 			gossip_err("%s: bad error code :%d:.\n",
50395f5f88fSMike Marshall 				__func__,
50495f5f88fSMike Marshall 				error_code);
505575e9461SMike Marshall 			error_code = -EINVAL;
506575e9461SMike Marshall 		}
507575e9461SMike Marshall 
508575e9461SMike Marshall 	/* Convert ORANGEFS encoded errno values into regular errno values. */
509575e9461SMike Marshall 	} else if ((-error_code) & ORANGEFS_ERROR_BIT) {
510575e9461SMike Marshall 		i = (-error_code) & ~(ORANGEFS_ERROR_BIT|ORANGEFS_ERROR_CLASS_BITS);
511296200d3SJérémy Lefaure 		if (i < ARRAY_SIZE(PINT_errno_mapping))
512575e9461SMike Marshall 			error_code = -PINT_errno_mapping[i];
513575e9461SMike Marshall 		else
514575e9461SMike Marshall 			error_code = -EINVAL;
515575e9461SMike Marshall 
516575e9461SMike Marshall 	/*
517575e9461SMike Marshall 	 * Only ORANGEFS protocol error codes should ever come here. Otherwise
518575e9461SMike Marshall 	 * there is a bug somewhere.
519575e9461SMike Marshall 	 */
520575e9461SMike Marshall 	} else {
52195f5f88fSMike Marshall 		gossip_err("%s: unknown error code.\n", __func__);
522cf546ab6SMike Marshall 		error_code = -EINVAL;
523575e9461SMike Marshall 	}
524575e9461SMike Marshall 	return error_code;
525575e9461SMike Marshall }
526575e9461SMike Marshall 
527575e9461SMike Marshall #define NUM_MODES 11
528575e9461SMike Marshall __s32 ORANGEFS_util_translate_mode(int mode)
529575e9461SMike Marshall {
530575e9461SMike Marshall 	int ret = 0;
531575e9461SMike Marshall 	int i = 0;
532575e9461SMike Marshall 	static int modes[NUM_MODES] = {
533575e9461SMike Marshall 		S_IXOTH, S_IWOTH, S_IROTH,
534575e9461SMike Marshall 		S_IXGRP, S_IWGRP, S_IRGRP,
535575e9461SMike Marshall 		S_IXUSR, S_IWUSR, S_IRUSR,
536575e9461SMike Marshall 		S_ISGID, S_ISUID
537575e9461SMike Marshall 	};
538575e9461SMike Marshall 	static int orangefs_modes[NUM_MODES] = {
539575e9461SMike Marshall 		ORANGEFS_O_EXECUTE, ORANGEFS_O_WRITE, ORANGEFS_O_READ,
540575e9461SMike Marshall 		ORANGEFS_G_EXECUTE, ORANGEFS_G_WRITE, ORANGEFS_G_READ,
541575e9461SMike Marshall 		ORANGEFS_U_EXECUTE, ORANGEFS_U_WRITE, ORANGEFS_U_READ,
542575e9461SMike Marshall 		ORANGEFS_G_SGID, ORANGEFS_U_SUID
543575e9461SMike Marshall 	};
544575e9461SMike Marshall 
545575e9461SMike Marshall 	for (i = 0; i < NUM_MODES; i++)
546575e9461SMike Marshall 		if (mode & modes[i])
547575e9461SMike Marshall 			ret |= orangefs_modes[i];
548575e9461SMike Marshall 
549575e9461SMike Marshall 	return ret;
550575e9461SMike Marshall }
551575e9461SMike Marshall #undef NUM_MODES
552