xref: /openbmc/linux/fs/orangefs/orangefs-utils.c (revision 4d0cac7e)
1b2441318SGreg Kroah-Hartman // SPDX-License-Identifier: GPL-2.0
2575e9461SMike Marshall /*
3575e9461SMike Marshall  * (C) 2001 Clemson University and The University of Chicago
4575e9461SMike Marshall  *
5575e9461SMike Marshall  * See COPYING in top-level directory.
6575e9461SMike Marshall  */
7296200d3SJérémy Lefaure #include <linux/kernel.h>
8575e9461SMike Marshall #include "protocol.h"
9575e9461SMike Marshall #include "orangefs-kernel.h"
10575e9461SMike Marshall #include "orangefs-dev-proto.h"
11575e9461SMike Marshall #include "orangefs-bufmap.h"
12575e9461SMike Marshall 
13575e9461SMike Marshall __s32 fsid_of_op(struct orangefs_kernel_op_s *op)
14575e9461SMike Marshall {
15575e9461SMike Marshall 	__s32 fsid = ORANGEFS_FS_ID_NULL;
16575e9461SMike Marshall 
17575e9461SMike Marshall 	if (op) {
18575e9461SMike Marshall 		switch (op->upcall.type) {
19575e9461SMike Marshall 		case ORANGEFS_VFS_OP_FILE_IO:
20575e9461SMike Marshall 			fsid = op->upcall.req.io.refn.fs_id;
21575e9461SMike Marshall 			break;
22575e9461SMike Marshall 		case ORANGEFS_VFS_OP_LOOKUP:
23575e9461SMike Marshall 			fsid = op->upcall.req.lookup.parent_refn.fs_id;
24575e9461SMike Marshall 			break;
25575e9461SMike Marshall 		case ORANGEFS_VFS_OP_CREATE:
26575e9461SMike Marshall 			fsid = op->upcall.req.create.parent_refn.fs_id;
27575e9461SMike Marshall 			break;
28575e9461SMike Marshall 		case ORANGEFS_VFS_OP_GETATTR:
29575e9461SMike Marshall 			fsid = op->upcall.req.getattr.refn.fs_id;
30575e9461SMike Marshall 			break;
31575e9461SMike Marshall 		case ORANGEFS_VFS_OP_REMOVE:
32575e9461SMike Marshall 			fsid = op->upcall.req.remove.parent_refn.fs_id;
33575e9461SMike Marshall 			break;
34575e9461SMike Marshall 		case ORANGEFS_VFS_OP_MKDIR:
35575e9461SMike Marshall 			fsid = op->upcall.req.mkdir.parent_refn.fs_id;
36575e9461SMike Marshall 			break;
37575e9461SMike Marshall 		case ORANGEFS_VFS_OP_READDIR:
38575e9461SMike Marshall 			fsid = op->upcall.req.readdir.refn.fs_id;
39575e9461SMike Marshall 			break;
40575e9461SMike Marshall 		case ORANGEFS_VFS_OP_SETATTR:
41575e9461SMike Marshall 			fsid = op->upcall.req.setattr.refn.fs_id;
42575e9461SMike Marshall 			break;
43575e9461SMike Marshall 		case ORANGEFS_VFS_OP_SYMLINK:
44575e9461SMike Marshall 			fsid = op->upcall.req.sym.parent_refn.fs_id;
45575e9461SMike Marshall 			break;
46575e9461SMike Marshall 		case ORANGEFS_VFS_OP_RENAME:
47575e9461SMike Marshall 			fsid = op->upcall.req.rename.old_parent_refn.fs_id;
48575e9461SMike Marshall 			break;
49575e9461SMike Marshall 		case ORANGEFS_VFS_OP_STATFS:
50575e9461SMike Marshall 			fsid = op->upcall.req.statfs.fs_id;
51575e9461SMike Marshall 			break;
52575e9461SMike Marshall 		case ORANGEFS_VFS_OP_TRUNCATE:
53575e9461SMike Marshall 			fsid = op->upcall.req.truncate.refn.fs_id;
54575e9461SMike Marshall 			break;
556eaff8c7SMartin Brandenburg 		case ORANGEFS_VFS_OP_RA_FLUSH:
56575e9461SMike Marshall 			fsid = op->upcall.req.ra_cache_flush.refn.fs_id;
57575e9461SMike Marshall 			break;
58575e9461SMike Marshall 		case ORANGEFS_VFS_OP_FS_UMOUNT:
59575e9461SMike Marshall 			fsid = op->upcall.req.fs_umount.fs_id;
60575e9461SMike Marshall 			break;
61575e9461SMike Marshall 		case ORANGEFS_VFS_OP_GETXATTR:
62575e9461SMike Marshall 			fsid = op->upcall.req.getxattr.refn.fs_id;
63575e9461SMike Marshall 			break;
64575e9461SMike Marshall 		case ORANGEFS_VFS_OP_SETXATTR:
65575e9461SMike Marshall 			fsid = op->upcall.req.setxattr.refn.fs_id;
66575e9461SMike Marshall 			break;
67575e9461SMike Marshall 		case ORANGEFS_VFS_OP_LISTXATTR:
68575e9461SMike Marshall 			fsid = op->upcall.req.listxattr.refn.fs_id;
69575e9461SMike Marshall 			break;
70575e9461SMike Marshall 		case ORANGEFS_VFS_OP_REMOVEXATTR:
71575e9461SMike Marshall 			fsid = op->upcall.req.removexattr.refn.fs_id;
72575e9461SMike Marshall 			break;
73575e9461SMike Marshall 		case ORANGEFS_VFS_OP_FSYNC:
74575e9461SMike Marshall 			fsid = op->upcall.req.fsync.refn.fs_id;
75575e9461SMike Marshall 			break;
76575e9461SMike Marshall 		default:
77575e9461SMike Marshall 			break;
78575e9461SMike Marshall 		}
79575e9461SMike Marshall 	}
80575e9461SMike Marshall 	return fsid;
81575e9461SMike Marshall }
82575e9461SMike Marshall 
83394f647eSMartin Brandenburg static int orangefs_inode_flags(struct ORANGEFS_sys_attr_s *attrs)
84575e9461SMike Marshall {
85394f647eSMartin Brandenburg 	int flags = 0;
86575e9461SMike Marshall 	if (attrs->flags & ORANGEFS_IMMUTABLE_FL)
87394f647eSMartin Brandenburg 		flags |= S_IMMUTABLE;
88575e9461SMike Marshall 	else
89394f647eSMartin Brandenburg 		flags &= ~S_IMMUTABLE;
90575e9461SMike Marshall 	if (attrs->flags & ORANGEFS_APPEND_FL)
91394f647eSMartin Brandenburg 		flags |= S_APPEND;
92575e9461SMike Marshall 	else
93394f647eSMartin Brandenburg 		flags &= ~S_APPEND;
94575e9461SMike Marshall 	if (attrs->flags & ORANGEFS_NOATIME_FL)
95394f647eSMartin Brandenburg 		flags |= S_NOATIME;
96575e9461SMike Marshall 	else
97394f647eSMartin Brandenburg 		flags &= ~S_NOATIME;
98394f647eSMartin Brandenburg 	return flags;
99394f647eSMartin Brandenburg }
100575e9461SMike Marshall 
101394f647eSMartin Brandenburg static int orangefs_inode_perms(struct ORANGEFS_sys_attr_s *attrs)
102394f647eSMartin Brandenburg {
103394f647eSMartin Brandenburg 	int perm_mode = 0;
104394f647eSMartin Brandenburg 
105394f647eSMartin Brandenburg 	if (attrs->perms & ORANGEFS_O_EXECUTE)
106394f647eSMartin Brandenburg 		perm_mode |= S_IXOTH;
107394f647eSMartin Brandenburg 	if (attrs->perms & ORANGEFS_O_WRITE)
108394f647eSMartin Brandenburg 		perm_mode |= S_IWOTH;
109394f647eSMartin Brandenburg 	if (attrs->perms & ORANGEFS_O_READ)
110394f647eSMartin Brandenburg 		perm_mode |= S_IROTH;
111394f647eSMartin Brandenburg 
112394f647eSMartin Brandenburg 	if (attrs->perms & ORANGEFS_G_EXECUTE)
113394f647eSMartin Brandenburg 		perm_mode |= S_IXGRP;
114394f647eSMartin Brandenburg 	if (attrs->perms & ORANGEFS_G_WRITE)
115394f647eSMartin Brandenburg 		perm_mode |= S_IWGRP;
116394f647eSMartin Brandenburg 	if (attrs->perms & ORANGEFS_G_READ)
117394f647eSMartin Brandenburg 		perm_mode |= S_IRGRP;
118394f647eSMartin Brandenburg 
119394f647eSMartin Brandenburg 	if (attrs->perms & ORANGEFS_U_EXECUTE)
120394f647eSMartin Brandenburg 		perm_mode |= S_IXUSR;
121394f647eSMartin Brandenburg 	if (attrs->perms & ORANGEFS_U_WRITE)
122394f647eSMartin Brandenburg 		perm_mode |= S_IWUSR;
123394f647eSMartin Brandenburg 	if (attrs->perms & ORANGEFS_U_READ)
124394f647eSMartin Brandenburg 		perm_mode |= S_IRUSR;
125394f647eSMartin Brandenburg 
126394f647eSMartin Brandenburg 	if (attrs->perms & ORANGEFS_G_SGID)
127394f647eSMartin Brandenburg 		perm_mode |= S_ISGID;
128394f647eSMartin Brandenburg 	if (attrs->perms & ORANGEFS_U_SUID)
129394f647eSMartin Brandenburg 		perm_mode |= S_ISUID;
130394f647eSMartin Brandenburg 
131394f647eSMartin Brandenburg 	return perm_mode;
132575e9461SMike Marshall }
133575e9461SMike Marshall 
134575e9461SMike Marshall /*
135575e9461SMike Marshall  * NOTE: in kernel land, we never use the sys_attr->link_target for
136575e9461SMike Marshall  * anything, so don't bother copying it into the sys_attr object here.
137575e9461SMike Marshall  */
138575e9461SMike Marshall static inline int copy_attributes_from_inode(struct inode *inode,
139575e9461SMike Marshall 					     struct ORANGEFS_sys_attr_s *attrs,
140575e9461SMike Marshall 					     struct iattr *iattr)
141575e9461SMike Marshall {
142575e9461SMike Marshall 	umode_t tmp_mode;
143575e9461SMike Marshall 
144575e9461SMike Marshall 	if (!iattr || !inode || !attrs) {
145575e9461SMike Marshall 		gossip_err("NULL iattr (%p), inode (%p), attrs (%p) "
146575e9461SMike Marshall 			   "in copy_attributes_from_inode!\n",
147575e9461SMike Marshall 			   iattr,
148575e9461SMike Marshall 			   inode,
149575e9461SMike Marshall 			   attrs);
150575e9461SMike Marshall 		return -EINVAL;
151575e9461SMike Marshall 	}
152575e9461SMike Marshall 	/*
153575e9461SMike Marshall 	 * We need to be careful to only copy the attributes out of the
154575e9461SMike Marshall 	 * iattr object that we know are valid.
155575e9461SMike Marshall 	 */
156575e9461SMike Marshall 	attrs->mask = 0;
157575e9461SMike Marshall 	if (iattr->ia_valid & ATTR_UID) {
15878fee0b6SJann Horn 		attrs->owner = from_kuid(&init_user_ns, iattr->ia_uid);
159575e9461SMike Marshall 		attrs->mask |= ORANGEFS_ATTR_SYS_UID;
160575e9461SMike Marshall 		gossip_debug(GOSSIP_UTILS_DEBUG, "(UID) %d\n", attrs->owner);
161575e9461SMike Marshall 	}
162575e9461SMike Marshall 	if (iattr->ia_valid & ATTR_GID) {
16378fee0b6SJann Horn 		attrs->group = from_kgid(&init_user_ns, iattr->ia_gid);
164575e9461SMike Marshall 		attrs->mask |= ORANGEFS_ATTR_SYS_GID;
165575e9461SMike Marshall 		gossip_debug(GOSSIP_UTILS_DEBUG, "(GID) %d\n", attrs->group);
166575e9461SMike Marshall 	}
167575e9461SMike Marshall 
168575e9461SMike Marshall 	if (iattr->ia_valid & ATTR_ATIME) {
169575e9461SMike Marshall 		attrs->mask |= ORANGEFS_ATTR_SYS_ATIME;
170575e9461SMike Marshall 		if (iattr->ia_valid & ATTR_ATIME_SET) {
171be81ce48SArnd Bergmann 			attrs->atime = (time64_t)iattr->ia_atime.tv_sec;
172575e9461SMike Marshall 			attrs->mask |= ORANGEFS_ATTR_SYS_ATIME_SET;
173575e9461SMike Marshall 		}
174575e9461SMike Marshall 	}
175575e9461SMike Marshall 	if (iattr->ia_valid & ATTR_MTIME) {
176575e9461SMike Marshall 		attrs->mask |= ORANGEFS_ATTR_SYS_MTIME;
177575e9461SMike Marshall 		if (iattr->ia_valid & ATTR_MTIME_SET) {
178be81ce48SArnd Bergmann 			attrs->mtime = (time64_t)iattr->ia_mtime.tv_sec;
179575e9461SMike Marshall 			attrs->mask |= ORANGEFS_ATTR_SYS_MTIME_SET;
180575e9461SMike Marshall 		}
181575e9461SMike Marshall 	}
182575e9461SMike Marshall 	if (iattr->ia_valid & ATTR_CTIME)
183575e9461SMike Marshall 		attrs->mask |= ORANGEFS_ATTR_SYS_CTIME;
184575e9461SMike Marshall 
185575e9461SMike Marshall 	/*
186575e9461SMike Marshall 	 * ORANGEFS cannot set size with a setattr operation.  Probably not likely
187575e9461SMike Marshall 	 * to be requested through the VFS, but just in case, don't worry about
188575e9461SMike Marshall 	 * ATTR_SIZE
189575e9461SMike Marshall 	 */
190575e9461SMike Marshall 
191575e9461SMike Marshall 	if (iattr->ia_valid & ATTR_MODE) {
192575e9461SMike Marshall 		tmp_mode = iattr->ia_mode;
193575e9461SMike Marshall 		if (tmp_mode & (S_ISVTX)) {
194575e9461SMike Marshall 			if (is_root_handle(inode)) {
195575e9461SMike Marshall 				/*
196575e9461SMike Marshall 				 * allow sticky bit to be set on root (since
197575e9461SMike Marshall 				 * it shows up that way by default anyhow),
198575e9461SMike Marshall 				 * but don't show it to the server
199575e9461SMike Marshall 				 */
200575e9461SMike Marshall 				tmp_mode -= S_ISVTX;
201575e9461SMike Marshall 			} else {
202575e9461SMike Marshall 				gossip_debug(GOSSIP_UTILS_DEBUG,
203575e9461SMike Marshall 					     "User attempted to set sticky bit on non-root directory; returning EINVAL.\n");
204575e9461SMike Marshall 				return -EINVAL;
205575e9461SMike Marshall 			}
206575e9461SMike Marshall 		}
207575e9461SMike Marshall 
208575e9461SMike Marshall 		if (tmp_mode & (S_ISUID)) {
209575e9461SMike Marshall 			gossip_debug(GOSSIP_UTILS_DEBUG,
210575e9461SMike Marshall 				     "Attempting to set setuid bit (not supported); returning EINVAL.\n");
211575e9461SMike Marshall 			return -EINVAL;
212575e9461SMike Marshall 		}
213575e9461SMike Marshall 
214575e9461SMike Marshall 		attrs->perms = ORANGEFS_util_translate_mode(tmp_mode);
215575e9461SMike Marshall 		attrs->mask |= ORANGEFS_ATTR_SYS_PERM;
216575e9461SMike Marshall 	}
217575e9461SMike Marshall 
218575e9461SMike Marshall 	return 0;
219575e9461SMike Marshall }
220575e9461SMike Marshall 
2213c9cf98dSMartin Brandenburg static int orangefs_inode_type(enum orangefs_ds_type objtype)
2223c9cf98dSMartin Brandenburg {
2233c9cf98dSMartin Brandenburg 	if (objtype == ORANGEFS_TYPE_METAFILE)
2243c9cf98dSMartin Brandenburg 		return S_IFREG;
2253c9cf98dSMartin Brandenburg 	else if (objtype == ORANGEFS_TYPE_DIRECTORY)
2263c9cf98dSMartin Brandenburg 		return S_IFDIR;
2273c9cf98dSMartin Brandenburg 	else if (objtype == ORANGEFS_TYPE_SYMLINK)
2283c9cf98dSMartin Brandenburg 		return S_IFLNK;
2293c9cf98dSMartin Brandenburg 	else
2303c9cf98dSMartin Brandenburg 		return -1;
2313c9cf98dSMartin Brandenburg }
2323c9cf98dSMartin Brandenburg 
2334d0cac7eSMartin Brandenburg static void orangefs_make_bad_inode(struct inode *inode)
2344d0cac7eSMartin Brandenburg {
2354d0cac7eSMartin Brandenburg 	if (is_root_handle(inode)) {
2364d0cac7eSMartin Brandenburg 		/*
2374d0cac7eSMartin Brandenburg 		 * if this occurs, the pvfs2-client-core was killed but we
2384d0cac7eSMartin Brandenburg 		 * can't afford to lose the inode operations and such
2394d0cac7eSMartin Brandenburg 		 * associated with the root handle in any case.
2404d0cac7eSMartin Brandenburg 		 */
2414d0cac7eSMartin Brandenburg 		gossip_debug(GOSSIP_UTILS_DEBUG,
2424d0cac7eSMartin Brandenburg 			     "*** NOT making bad root inode %pU\n",
2434d0cac7eSMartin Brandenburg 			     get_khandle_from_ino(inode));
2444d0cac7eSMartin Brandenburg 	} else {
2454d0cac7eSMartin Brandenburg 		gossip_debug(GOSSIP_UTILS_DEBUG,
2464d0cac7eSMartin Brandenburg 			     "*** making bad inode %pU\n",
2474d0cac7eSMartin Brandenburg 			     get_khandle_from_ino(inode));
2484d0cac7eSMartin Brandenburg 		make_bad_inode(inode);
2494d0cac7eSMartin Brandenburg 	}
2504d0cac7eSMartin Brandenburg }
2514d0cac7eSMartin Brandenburg 
25226662633SMartin Brandenburg static int orangefs_inode_is_stale(struct inode *inode, int new,
25326662633SMartin Brandenburg     struct ORANGEFS_sys_attr_s *attrs, char *link_target)
25426662633SMartin Brandenburg {
25526662633SMartin Brandenburg 	struct orangefs_inode_s *orangefs_inode = ORANGEFS_I(inode);
25626662633SMartin Brandenburg 	int type = orangefs_inode_type(attrs->objtype);
25726662633SMartin Brandenburg 	if (!new) {
25826662633SMartin Brandenburg 		/*
25926662633SMartin Brandenburg 		 * If the inode type or symlink target have changed then this
26026662633SMartin Brandenburg 		 * inode is stale.
26126662633SMartin Brandenburg 		 */
26226662633SMartin Brandenburg 		if (type == -1 || !(inode->i_mode & type)) {
26326662633SMartin Brandenburg 			orangefs_make_bad_inode(inode);
26426662633SMartin Brandenburg 			return 1;
26526662633SMartin Brandenburg 		}
26626662633SMartin Brandenburg 		if (type == S_IFLNK && strncmp(orangefs_inode->link_target,
26726662633SMartin Brandenburg 		    link_target, ORANGEFS_NAME_MAX)) {
26826662633SMartin Brandenburg 			orangefs_make_bad_inode(inode);
26926662633SMartin Brandenburg 			return 1;
27026662633SMartin Brandenburg 		}
27126662633SMartin Brandenburg 	}
27226662633SMartin Brandenburg 	return 0;
27326662633SMartin Brandenburg }
27426662633SMartin Brandenburg 
27568a24a6cSMartin Brandenburg int orangefs_inode_getattr(struct inode *inode, int new, int bypass,
27668a24a6cSMartin Brandenburg     u32 request_mask)
2773c9cf98dSMartin Brandenburg {
2783c9cf98dSMartin Brandenburg 	struct orangefs_inode_s *orangefs_inode = ORANGEFS_I(inode);
2793c9cf98dSMartin Brandenburg 	struct orangefs_kernel_op_s *new_op;
2803c9cf98dSMartin Brandenburg 	loff_t inode_size, rounded_up_size;
28126662633SMartin Brandenburg 	int ret, type;
2823c9cf98dSMartin Brandenburg 
2833c9cf98dSMartin Brandenburg 	gossip_debug(GOSSIP_UTILS_DEBUG, "%s: called on inode %pU\n", __func__,
2843c9cf98dSMartin Brandenburg 	    get_khandle_from_ino(inode));
2853c9cf98dSMartin Brandenburg 
28671680c18SMartin Brandenburg 	if (!new && !bypass) {
28768a24a6cSMartin Brandenburg 		/*
28868a24a6cSMartin Brandenburg 		 * Must have all the attributes in the mask and be within cache
28968a24a6cSMartin Brandenburg 		 * time.
29068a24a6cSMartin Brandenburg 		 */
29168a24a6cSMartin Brandenburg 		if ((request_mask & orangefs_inode->getattr_mask) ==
29268a24a6cSMartin Brandenburg 		    request_mask &&
29368a24a6cSMartin Brandenburg 		    time_before(jiffies, orangefs_inode->getattr_time))
29471680c18SMartin Brandenburg 			return 0;
29571680c18SMartin Brandenburg 	}
29671680c18SMartin Brandenburg 
2973c9cf98dSMartin Brandenburg 	new_op = op_alloc(ORANGEFS_VFS_OP_GETATTR);
2983c9cf98dSMartin Brandenburg 	if (!new_op)
2993c9cf98dSMartin Brandenburg 		return -ENOMEM;
3003c9cf98dSMartin Brandenburg 	new_op->upcall.req.getattr.refn = orangefs_inode->refn;
30168a24a6cSMartin Brandenburg 	/*
30268a24a6cSMartin Brandenburg 	 * Size is the hardest attribute to get.  The incremental cost of any
30368a24a6cSMartin Brandenburg 	 * other attribute is essentially zero.
30468a24a6cSMartin Brandenburg 	 */
30568a24a6cSMartin Brandenburg 	if (request_mask & STATX_SIZE || new)
30671680c18SMartin Brandenburg 		new_op->upcall.req.getattr.mask = ORANGEFS_ATTR_SYS_ALL_NOHINT;
30768a24a6cSMartin Brandenburg 	else
30868a24a6cSMartin Brandenburg 		new_op->upcall.req.getattr.mask =
30968a24a6cSMartin Brandenburg 		    ORANGEFS_ATTR_SYS_ALL_NOHINT & ~ORANGEFS_ATTR_SYS_SIZE;
3103c9cf98dSMartin Brandenburg 
3113c9cf98dSMartin Brandenburg 	ret = service_operation(new_op, __func__,
3123c9cf98dSMartin Brandenburg 	    get_interruptible_flag(inode));
3133c9cf98dSMartin Brandenburg 	if (ret != 0)
3143c9cf98dSMartin Brandenburg 		goto out;
3153c9cf98dSMartin Brandenburg 
31626662633SMartin Brandenburg 	type = orangefs_inode_type(new_op->
3173c9cf98dSMartin Brandenburg 	    downcall.resp.getattr.attributes.objtype);
31826662633SMartin Brandenburg 	ret = orangefs_inode_is_stale(inode, new,
31926662633SMartin Brandenburg 	    &new_op->downcall.resp.getattr.attributes,
32026662633SMartin Brandenburg 	    new_op->downcall.resp.getattr.link_target);
32126662633SMartin Brandenburg 	if (ret) {
3223c9cf98dSMartin Brandenburg 		ret = -ESTALE;
3233c9cf98dSMartin Brandenburg 		goto out;
3243c9cf98dSMartin Brandenburg 	}
3253c9cf98dSMartin Brandenburg 
32626662633SMartin Brandenburg 	switch (type) {
3273c9cf98dSMartin Brandenburg 	case S_IFREG:
3283c9cf98dSMartin Brandenburg 		inode->i_flags = orangefs_inode_flags(&new_op->
3293c9cf98dSMartin Brandenburg 		    downcall.resp.getattr.attributes);
33068a24a6cSMartin Brandenburg 		if (request_mask & STATX_SIZE || new) {
3313c9cf98dSMartin Brandenburg 			inode_size = (loff_t)new_op->
3323c9cf98dSMartin Brandenburg 			    downcall.resp.getattr.attributes.size;
3333c9cf98dSMartin Brandenburg 			rounded_up_size =
3343c9cf98dSMartin Brandenburg 			    (inode_size + (4096 - (inode_size % 4096)));
3353c9cf98dSMartin Brandenburg 			inode->i_size = inode_size;
3363c9cf98dSMartin Brandenburg 			orangefs_inode->blksize =
3373c9cf98dSMartin Brandenburg 			    new_op->downcall.resp.getattr.attributes.blksize;
3383c9cf98dSMartin Brandenburg 			spin_lock(&inode->i_lock);
3393c9cf98dSMartin Brandenburg 			inode->i_bytes = inode_size;
3403c9cf98dSMartin Brandenburg 			inode->i_blocks =
3413c9cf98dSMartin Brandenburg 			    (unsigned long)(rounded_up_size / 512);
3423c9cf98dSMartin Brandenburg 			spin_unlock(&inode->i_lock);
34368a24a6cSMartin Brandenburg 		}
3443c9cf98dSMartin Brandenburg 		break;
3453c9cf98dSMartin Brandenburg 	case S_IFDIR:
34668a24a6cSMartin Brandenburg 		if (request_mask & STATX_SIZE || new) {
34709cbfeafSKirill A. Shutemov 			inode->i_size = PAGE_SIZE;
34893407472SFabian Frederick 			orangefs_inode->blksize = i_blocksize(inode);
3493c9cf98dSMartin Brandenburg 			spin_lock(&inode->i_lock);
3503c9cf98dSMartin Brandenburg 			inode_set_bytes(inode, inode->i_size);
3513c9cf98dSMartin Brandenburg 			spin_unlock(&inode->i_lock);
35268a24a6cSMartin Brandenburg 		}
3533c9cf98dSMartin Brandenburg 		set_nlink(inode, 1);
3543c9cf98dSMartin Brandenburg 		break;
3553c9cf98dSMartin Brandenburg 	case S_IFLNK:
3563c9cf98dSMartin Brandenburg 		if (new) {
3573c9cf98dSMartin Brandenburg 			inode->i_size = (loff_t)strlen(new_op->
3583c9cf98dSMartin Brandenburg 			    downcall.resp.getattr.link_target);
35993407472SFabian Frederick 			orangefs_inode->blksize = i_blocksize(inode);
3602eacea74SMartin Brandenburg 			ret = strscpy(orangefs_inode->link_target,
3613c9cf98dSMartin Brandenburg 			    new_op->downcall.resp.getattr.link_target,
3623c9cf98dSMartin Brandenburg 			    ORANGEFS_NAME_MAX);
3632eacea74SMartin Brandenburg 			if (ret == -E2BIG) {
3642eacea74SMartin Brandenburg 				ret = -EIO;
3652eacea74SMartin Brandenburg 				goto out;
3662eacea74SMartin Brandenburg 			}
367e8da254cSMartin Brandenburg 			inode->i_link = orangefs_inode->link_target;
3683c9cf98dSMartin Brandenburg 		}
3693c9cf98dSMartin Brandenburg 		break;
3703c9cf98dSMartin Brandenburg 	}
3713c9cf98dSMartin Brandenburg 
3723c9cf98dSMartin Brandenburg 	inode->i_uid = make_kuid(&init_user_ns, new_op->
3733c9cf98dSMartin Brandenburg 	    downcall.resp.getattr.attributes.owner);
3743c9cf98dSMartin Brandenburg 	inode->i_gid = make_kgid(&init_user_ns, new_op->
3753c9cf98dSMartin Brandenburg 	    downcall.resp.getattr.attributes.group);
3763c9cf98dSMartin Brandenburg 	inode->i_atime.tv_sec = (time64_t)new_op->
3773c9cf98dSMartin Brandenburg 	    downcall.resp.getattr.attributes.atime;
3783c9cf98dSMartin Brandenburg 	inode->i_mtime.tv_sec = (time64_t)new_op->
3793c9cf98dSMartin Brandenburg 	    downcall.resp.getattr.attributes.mtime;
3803c9cf98dSMartin Brandenburg 	inode->i_ctime.tv_sec = (time64_t)new_op->
3813c9cf98dSMartin Brandenburg 	    downcall.resp.getattr.attributes.ctime;
3823c9cf98dSMartin Brandenburg 	inode->i_atime.tv_nsec = 0;
3833c9cf98dSMartin Brandenburg 	inode->i_mtime.tv_nsec = 0;
3843c9cf98dSMartin Brandenburg 	inode->i_ctime.tv_nsec = 0;
3853c9cf98dSMartin Brandenburg 
3863c9cf98dSMartin Brandenburg 	/* special case: mark the root inode as sticky */
38726662633SMartin Brandenburg 	inode->i_mode = type | (is_root_handle(inode) ? S_ISVTX : 0) |
3883c9cf98dSMartin Brandenburg 	    orangefs_inode_perms(&new_op->downcall.resp.getattr.attributes);
3893c9cf98dSMartin Brandenburg 
3901d503617SMartin Brandenburg 	orangefs_inode->getattr_time = jiffies +
3911d503617SMartin Brandenburg 	    orangefs_getattr_timeout_msecs*HZ/1000;
39268a24a6cSMartin Brandenburg 	if (request_mask & STATX_SIZE || new)
39368a24a6cSMartin Brandenburg 		orangefs_inode->getattr_mask = STATX_BASIC_STATS;
39468a24a6cSMartin Brandenburg 	else
39568a24a6cSMartin Brandenburg 		orangefs_inode->getattr_mask = STATX_BASIC_STATS & ~STATX_SIZE;
3963c9cf98dSMartin Brandenburg 	ret = 0;
3973c9cf98dSMartin Brandenburg out:
3983c9cf98dSMartin Brandenburg 	op_release(new_op);
3993c9cf98dSMartin Brandenburg 	return ret;
4003c9cf98dSMartin Brandenburg }
4013c9cf98dSMartin Brandenburg 
4025859d77eSMartin Brandenburg int orangefs_inode_check_changed(struct inode *inode)
4035859d77eSMartin Brandenburg {
4045859d77eSMartin Brandenburg 	struct orangefs_inode_s *orangefs_inode = ORANGEFS_I(inode);
4055859d77eSMartin Brandenburg 	struct orangefs_kernel_op_s *new_op;
4065859d77eSMartin Brandenburg 	int ret;
4075859d77eSMartin Brandenburg 
4085859d77eSMartin Brandenburg 	gossip_debug(GOSSIP_UTILS_DEBUG, "%s: called on inode %pU\n", __func__,
4095859d77eSMartin Brandenburg 	    get_khandle_from_ino(inode));
4105859d77eSMartin Brandenburg 
4115859d77eSMartin Brandenburg 	new_op = op_alloc(ORANGEFS_VFS_OP_GETATTR);
4125859d77eSMartin Brandenburg 	if (!new_op)
4135859d77eSMartin Brandenburg 		return -ENOMEM;
4145859d77eSMartin Brandenburg 	new_op->upcall.req.getattr.refn = orangefs_inode->refn;
4155859d77eSMartin Brandenburg 	new_op->upcall.req.getattr.mask = ORANGEFS_ATTR_SYS_TYPE |
4165859d77eSMartin Brandenburg 	    ORANGEFS_ATTR_SYS_LNK_TARGET;
4175859d77eSMartin Brandenburg 
4185859d77eSMartin Brandenburg 	ret = service_operation(new_op, __func__,
4195859d77eSMartin Brandenburg 	    get_interruptible_flag(inode));
4205859d77eSMartin Brandenburg 	if (ret != 0)
4215859d77eSMartin Brandenburg 		goto out;
4225859d77eSMartin Brandenburg 
42326662633SMartin Brandenburg 	ret = orangefs_inode_is_stale(inode, 0,
42426662633SMartin Brandenburg 	    &new_op->downcall.resp.getattr.attributes,
42526662633SMartin Brandenburg 	    new_op->downcall.resp.getattr.link_target);
4265859d77eSMartin Brandenburg out:
4275859d77eSMartin Brandenburg 	op_release(new_op);
4285859d77eSMartin Brandenburg 	return ret;
4295859d77eSMartin Brandenburg }
4305859d77eSMartin Brandenburg 
431575e9461SMike Marshall /*
432575e9461SMike Marshall  * issues a orangefs setattr request to make sure the new attribute values
433575e9461SMike Marshall  * take effect if successful.  returns 0 on success; -errno otherwise
434575e9461SMike Marshall  */
435575e9461SMike Marshall int orangefs_inode_setattr(struct inode *inode, struct iattr *iattr)
436575e9461SMike Marshall {
437575e9461SMike Marshall 	struct orangefs_inode_s *orangefs_inode = ORANGEFS_I(inode);
438575e9461SMike Marshall 	struct orangefs_kernel_op_s *new_op;
439575e9461SMike Marshall 	int ret;
440575e9461SMike Marshall 
441575e9461SMike Marshall 	new_op = op_alloc(ORANGEFS_VFS_OP_SETATTR);
442575e9461SMike Marshall 	if (!new_op)
443575e9461SMike Marshall 		return -ENOMEM;
444575e9461SMike Marshall 
445575e9461SMike Marshall 	new_op->upcall.req.setattr.refn = orangefs_inode->refn;
446575e9461SMike Marshall 	ret = copy_attributes_from_inode(inode,
447575e9461SMike Marshall 		       &new_op->upcall.req.setattr.attributes,
448575e9461SMike Marshall 		       iattr);
449ed42fe05SAl Viro 	if (ret >= 0) {
450575e9461SMike Marshall 		ret = service_operation(new_op, __func__,
451575e9461SMike Marshall 				get_interruptible_flag(inode));
452575e9461SMike Marshall 
453575e9461SMike Marshall 		gossip_debug(GOSSIP_UTILS_DEBUG,
454575e9461SMike Marshall 			     "orangefs_inode_setattr: returning %d\n",
455575e9461SMike Marshall 			     ret);
456ed42fe05SAl Viro 	}
457575e9461SMike Marshall 
458575e9461SMike Marshall 	op_release(new_op);
459575e9461SMike Marshall 
460a55f2d86SMartin Brandenburg 	if (ret == 0)
4618bbb20a8SMartin Brandenburg 		orangefs_inode->getattr_time = jiffies - 1;
462575e9461SMike Marshall 
463575e9461SMike Marshall 	return ret;
464575e9461SMike Marshall }
465575e9461SMike Marshall 
466575e9461SMike Marshall /*
467575e9461SMike Marshall  * The following is a very dirty hack that is now a permanent part of the
468575e9461SMike Marshall  * ORANGEFS protocol. See protocol.h for more error definitions.
469575e9461SMike Marshall  */
470575e9461SMike Marshall 
471575e9461SMike Marshall /* The order matches include/orangefs-types.h in the OrangeFS source. */
472575e9461SMike Marshall static int PINT_errno_mapping[] = {
473575e9461SMike Marshall 	0, EPERM, ENOENT, EINTR, EIO, ENXIO, EBADF, EAGAIN, ENOMEM,
474575e9461SMike Marshall 	EFAULT, EBUSY, EEXIST, ENODEV, ENOTDIR, EISDIR, EINVAL, EMFILE,
475575e9461SMike Marshall 	EFBIG, ENOSPC, EROFS, EMLINK, EPIPE, EDEADLK, ENAMETOOLONG,
476575e9461SMike Marshall 	ENOLCK, ENOSYS, ENOTEMPTY, ELOOP, EWOULDBLOCK, ENOMSG, EUNATCH,
477575e9461SMike Marshall 	EBADR, EDEADLOCK, ENODATA, ETIME, ENONET, EREMOTE, ECOMM,
478575e9461SMike Marshall 	EPROTO, EBADMSG, EOVERFLOW, ERESTART, EMSGSIZE, EPROTOTYPE,
479575e9461SMike Marshall 	ENOPROTOOPT, EPROTONOSUPPORT, EOPNOTSUPP, EADDRINUSE,
480575e9461SMike Marshall 	EADDRNOTAVAIL, ENETDOWN, ENETUNREACH, ENETRESET, ENOBUFS,
481575e9461SMike Marshall 	ETIMEDOUT, ECONNREFUSED, EHOSTDOWN, EHOSTUNREACH, EALREADY,
482575e9461SMike Marshall 	EACCES, ECONNRESET, ERANGE
483575e9461SMike Marshall };
484575e9461SMike Marshall 
485575e9461SMike Marshall int orangefs_normalize_to_errno(__s32 error_code)
486575e9461SMike Marshall {
487575e9461SMike Marshall 	__u32 i;
488575e9461SMike Marshall 
489575e9461SMike Marshall 	/* Success */
490575e9461SMike Marshall 	if (error_code == 0) {
491575e9461SMike Marshall 		return 0;
492575e9461SMike Marshall 	/*
493575e9461SMike Marshall 	 * This shouldn't ever happen. If it does it should be fixed on the
494575e9461SMike Marshall 	 * server.
495575e9461SMike Marshall 	 */
496575e9461SMike Marshall 	} else if (error_code > 0) {
497575e9461SMike Marshall 		gossip_err("orangefs: error status receieved.\n");
498575e9461SMike Marshall 		gossip_err("orangefs: assuming error code is inverted.\n");
499575e9461SMike Marshall 		error_code = -error_code;
500575e9461SMike Marshall 	}
501575e9461SMike Marshall 
502575e9461SMike Marshall 	/*
503575e9461SMike Marshall 	 * XXX: This is very bad since error codes from ORANGEFS may not be
504575e9461SMike Marshall 	 * suitable for return into userspace.
505575e9461SMike Marshall 	 */
506575e9461SMike Marshall 
507575e9461SMike Marshall 	/*
508575e9461SMike Marshall 	 * Convert ORANGEFS error values into errno values suitable for return
509575e9461SMike Marshall 	 * from the kernel.
510575e9461SMike Marshall 	 */
511575e9461SMike Marshall 	if ((-error_code) & ORANGEFS_NON_ERRNO_ERROR_BIT) {
512575e9461SMike Marshall 		if (((-error_code) &
513575e9461SMike Marshall 		    (ORANGEFS_ERROR_NUMBER_BITS|ORANGEFS_NON_ERRNO_ERROR_BIT|
514575e9461SMike Marshall 		    ORANGEFS_ERROR_BIT)) == ORANGEFS_ECANCEL) {
515575e9461SMike Marshall 			/*
516575e9461SMike Marshall 			 * cancellation error codes generally correspond to
517575e9461SMike Marshall 			 * a timeout from the client's perspective
518575e9461SMike Marshall 			 */
519575e9461SMike Marshall 			error_code = -ETIMEDOUT;
520575e9461SMike Marshall 		} else {
521575e9461SMike Marshall 			/* assume a default error code */
522575e9461SMike Marshall 			gossip_err("orangefs: warning: got error code without errno equivalent: %d.\n", error_code);
523575e9461SMike Marshall 			error_code = -EINVAL;
524575e9461SMike Marshall 		}
525575e9461SMike Marshall 
526575e9461SMike Marshall 	/* Convert ORANGEFS encoded errno values into regular errno values. */
527575e9461SMike Marshall 	} else if ((-error_code) & ORANGEFS_ERROR_BIT) {
528575e9461SMike Marshall 		i = (-error_code) & ~(ORANGEFS_ERROR_BIT|ORANGEFS_ERROR_CLASS_BITS);
529296200d3SJérémy Lefaure 		if (i < ARRAY_SIZE(PINT_errno_mapping))
530575e9461SMike Marshall 			error_code = -PINT_errno_mapping[i];
531575e9461SMike Marshall 		else
532575e9461SMike Marshall 			error_code = -EINVAL;
533575e9461SMike Marshall 
534575e9461SMike Marshall 	/*
535575e9461SMike Marshall 	 * Only ORANGEFS protocol error codes should ever come here. Otherwise
536575e9461SMike Marshall 	 * there is a bug somewhere.
537575e9461SMike Marshall 	 */
538575e9461SMike Marshall 	} else {
539575e9461SMike Marshall 		gossip_err("orangefs: orangefs_normalize_to_errno: got error code which is not from ORANGEFS.\n");
540575e9461SMike Marshall 	}
541575e9461SMike Marshall 	return error_code;
542575e9461SMike Marshall }
543575e9461SMike Marshall 
544575e9461SMike Marshall #define NUM_MODES 11
545575e9461SMike Marshall __s32 ORANGEFS_util_translate_mode(int mode)
546575e9461SMike Marshall {
547575e9461SMike Marshall 	int ret = 0;
548575e9461SMike Marshall 	int i = 0;
549575e9461SMike Marshall 	static int modes[NUM_MODES] = {
550575e9461SMike Marshall 		S_IXOTH, S_IWOTH, S_IROTH,
551575e9461SMike Marshall 		S_IXGRP, S_IWGRP, S_IRGRP,
552575e9461SMike Marshall 		S_IXUSR, S_IWUSR, S_IRUSR,
553575e9461SMike Marshall 		S_ISGID, S_ISUID
554575e9461SMike Marshall 	};
555575e9461SMike Marshall 	static int orangefs_modes[NUM_MODES] = {
556575e9461SMike Marshall 		ORANGEFS_O_EXECUTE, ORANGEFS_O_WRITE, ORANGEFS_O_READ,
557575e9461SMike Marshall 		ORANGEFS_G_EXECUTE, ORANGEFS_G_WRITE, ORANGEFS_G_READ,
558575e9461SMike Marshall 		ORANGEFS_U_EXECUTE, ORANGEFS_U_WRITE, ORANGEFS_U_READ,
559575e9461SMike Marshall 		ORANGEFS_G_SGID, ORANGEFS_U_SUID
560575e9461SMike Marshall 	};
561575e9461SMike Marshall 
562575e9461SMike Marshall 	for (i = 0; i < NUM_MODES; i++)
563575e9461SMike Marshall 		if (mode & modes[i])
564575e9461SMike Marshall 			ret |= orangefs_modes[i];
565575e9461SMike Marshall 
566575e9461SMike Marshall 	return ret;
567575e9461SMike Marshall }
568575e9461SMike Marshall #undef NUM_MODES
569