xref: /openbmc/linux/fs/orangefs/orangefs-utils.c (revision 0971a799)
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 
fsid_of_op(struct orangefs_kernel_op_s * op)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 
orangefs_inode_flags(struct ORANGEFS_sys_attr_s * attrs)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 
orangefs_inode_perms(struct ORANGEFS_sys_attr_s * attrs)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  */
copy_attributes_from_inode(struct inode * inode,struct ORANGEFS_sys_attr_s * attrs)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 
orangefs_inode_type(enum orangefs_ds_type objtype)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 
orangefs_make_bad_inode(struct inode * inode)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 
orangefs_inode_is_stale(struct inode * inode,struct ORANGEFS_sys_attr_s * attrs,char * link_target)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 	 */
224e89f00d6SAl Viro 	if (type == -1 || inode_wrong_type(inode, 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 
orangefs_inode_getattr(struct inode * inode,int flags)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)) ||
25085ac799cSMartin Brandenburg 	    orangefs_inode->attr_valid || inode->i_state & I_DIRTY_PAGES) {
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)) ||
28485ac799cSMartin Brandenburg 	    orangefs_inode->attr_valid || inode->i_state & I_DIRTY_PAGES) {
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 		}
29085ac799cSMartin Brandenburg 		if (inode->i_state & I_DIRTY_PAGES) {
29185ac799cSMartin Brandenburg 			ret = 0;
29285ac799cSMartin Brandenburg 			goto out_unlock;
29385ac799cSMartin Brandenburg 		}
2945e4f606eSMartin Brandenburg 		gossip_debug(GOSSIP_UTILS_DEBUG, "%s: in cache or dirty\n",
2955e4f606eSMartin Brandenburg 		    __func__);
2965e4f606eSMartin Brandenburg 		ret = 0;
2975e4f606eSMartin Brandenburg 		goto out_unlock;
2985e4f606eSMartin Brandenburg 	}
2995e4f606eSMartin Brandenburg 
3008b60785cSMartin Brandenburg 	if (!(flags & ORANGEFS_GETATTR_NEW)) {
301480e5ae9SMartin Brandenburg 		ret = orangefs_inode_is_stale(inode,
30226662633SMartin Brandenburg 		    &new_op->downcall.resp.getattr.attributes,
30326662633SMartin Brandenburg 		    new_op->downcall.resp.getattr.link_target);
30426662633SMartin Brandenburg 		if (ret) {
3053c9cf98dSMartin Brandenburg 			ret = -ESTALE;
3065e4f606eSMartin Brandenburg 			goto out_unlock;
3073c9cf98dSMartin Brandenburg 		}
308480e5ae9SMartin Brandenburg 	}
3093c9cf98dSMartin Brandenburg 
310480e5ae9SMartin Brandenburg 	type = orangefs_inode_type(new_op->
311480e5ae9SMartin Brandenburg 	    downcall.resp.getattr.attributes.objtype);
31226662633SMartin Brandenburg 	switch (type) {
3133c9cf98dSMartin Brandenburg 	case S_IFREG:
3143c9cf98dSMartin Brandenburg 		inode->i_flags = orangefs_inode_flags(&new_op->
3153c9cf98dSMartin Brandenburg 		    downcall.resp.getattr.attributes);
3168b60785cSMartin Brandenburg 		if (flags) {
3173c9cf98dSMartin Brandenburg 			inode_size = (loff_t)new_op->
3183c9cf98dSMartin Brandenburg 			    downcall.resp.getattr.attributes.size;
3193c9cf98dSMartin Brandenburg 			inode->i_size = inode_size;
3209f8fd53cSMartin Brandenburg 			inode->i_blkbits = ffs(new_op->downcall.resp.getattr.
3219f8fd53cSMartin Brandenburg 			    attributes.blksize);
3223c9cf98dSMartin Brandenburg 			inode->i_bytes = inode_size;
3233c9cf98dSMartin Brandenburg 			inode->i_blocks =
3249f8fd53cSMartin Brandenburg 			    (inode_size + 512 - inode_size % 512)/512;
32568a24a6cSMartin Brandenburg 		}
3263c9cf98dSMartin Brandenburg 		break;
3273c9cf98dSMartin Brandenburg 	case S_IFDIR:
3288b60785cSMartin Brandenburg 		if (flags) {
32909cbfeafSKirill A. Shutemov 			inode->i_size = PAGE_SIZE;
3303c9cf98dSMartin Brandenburg 			inode_set_bytes(inode, inode->i_size);
33168a24a6cSMartin Brandenburg 		}
3323c9cf98dSMartin Brandenburg 		set_nlink(inode, 1);
3333c9cf98dSMartin Brandenburg 		break;
3343c9cf98dSMartin Brandenburg 	case S_IFLNK:
3358b60785cSMartin Brandenburg 		if (flags & ORANGEFS_GETATTR_NEW) {
3363c9cf98dSMartin Brandenburg 			inode->i_size = (loff_t)strlen(new_op->
3373c9cf98dSMartin Brandenburg 			    downcall.resp.getattr.link_target);
3382eacea74SMartin Brandenburg 			ret = strscpy(orangefs_inode->link_target,
3393c9cf98dSMartin Brandenburg 			    new_op->downcall.resp.getattr.link_target,
3403c9cf98dSMartin Brandenburg 			    ORANGEFS_NAME_MAX);
3412eacea74SMartin Brandenburg 			if (ret == -E2BIG) {
3422eacea74SMartin Brandenburg 				ret = -EIO;
3435e4f606eSMartin Brandenburg 				goto out_unlock;
3442eacea74SMartin Brandenburg 			}
345e8da254cSMartin Brandenburg 			inode->i_link = orangefs_inode->link_target;
3463c9cf98dSMartin Brandenburg 		}
3473c9cf98dSMartin Brandenburg 		break;
348480e5ae9SMartin Brandenburg 	/* i.e. -1 */
349480e5ae9SMartin Brandenburg 	default:
350480e5ae9SMartin Brandenburg 		/* XXX: ESTALE?  This is what is done if it is not new. */
351480e5ae9SMartin Brandenburg 		orangefs_make_bad_inode(inode);
352480e5ae9SMartin Brandenburg 		ret = -ESTALE;
3535e4f606eSMartin Brandenburg 		goto out_unlock;
3543c9cf98dSMartin Brandenburg 	}
3553c9cf98dSMartin Brandenburg 
3563c9cf98dSMartin Brandenburg 	inode->i_uid = make_kuid(&init_user_ns, new_op->
3573c9cf98dSMartin Brandenburg 	    downcall.resp.getattr.attributes.owner);
3583c9cf98dSMartin Brandenburg 	inode->i_gid = make_kgid(&init_user_ns, new_op->
3593c9cf98dSMartin Brandenburg 	    downcall.resp.getattr.attributes.group);
3603c9cf98dSMartin Brandenburg 	inode->i_atime.tv_sec = (time64_t)new_op->
3613c9cf98dSMartin Brandenburg 	    downcall.resp.getattr.attributes.atime;
3623c9cf98dSMartin Brandenburg 	inode->i_mtime.tv_sec = (time64_t)new_op->
3633c9cf98dSMartin Brandenburg 	    downcall.resp.getattr.attributes.mtime;
364*0971a799SJeff Layton 	inode_set_ctime(inode,
365*0971a799SJeff Layton 			(time64_t)new_op->downcall.resp.getattr.attributes.ctime,
366*0971a799SJeff Layton 			0);
3673c9cf98dSMartin Brandenburg 	inode->i_atime.tv_nsec = 0;
3683c9cf98dSMartin Brandenburg 	inode->i_mtime.tv_nsec = 0;
3693c9cf98dSMartin Brandenburg 
3703c9cf98dSMartin Brandenburg 	/* special case: mark the root inode as sticky */
37126662633SMartin Brandenburg 	inode->i_mode = type | (is_root_handle(inode) ? S_ISVTX : 0) |
3723c9cf98dSMartin Brandenburg 	    orangefs_inode_perms(&new_op->downcall.resp.getattr.attributes);
3733c9cf98dSMartin Brandenburg 
3741d503617SMartin Brandenburg 	orangefs_inode->getattr_time = jiffies +
3751d503617SMartin Brandenburg 	    orangefs_getattr_timeout_msecs*HZ/1000;
3763c9cf98dSMartin Brandenburg 	ret = 0;
3775e4f606eSMartin Brandenburg out_unlock:
3785e4f606eSMartin Brandenburg 	spin_unlock(&inode->i_lock);
3793c9cf98dSMartin Brandenburg out:
3803c9cf98dSMartin Brandenburg 	op_release(new_op);
3813c9cf98dSMartin Brandenburg 	return ret;
3823c9cf98dSMartin Brandenburg }
3833c9cf98dSMartin Brandenburg 
orangefs_inode_check_changed(struct inode * inode)3845859d77eSMartin Brandenburg int orangefs_inode_check_changed(struct inode *inode)
3855859d77eSMartin Brandenburg {
3865859d77eSMartin Brandenburg 	struct orangefs_inode_s *orangefs_inode = ORANGEFS_I(inode);
3875859d77eSMartin Brandenburg 	struct orangefs_kernel_op_s *new_op;
3885859d77eSMartin Brandenburg 	int ret;
3895859d77eSMartin Brandenburg 
3905859d77eSMartin Brandenburg 	gossip_debug(GOSSIP_UTILS_DEBUG, "%s: called on inode %pU\n", __func__,
3915859d77eSMartin Brandenburg 	    get_khandle_from_ino(inode));
3925859d77eSMartin Brandenburg 
3935859d77eSMartin Brandenburg 	new_op = op_alloc(ORANGEFS_VFS_OP_GETATTR);
3945859d77eSMartin Brandenburg 	if (!new_op)
3955859d77eSMartin Brandenburg 		return -ENOMEM;
3965859d77eSMartin Brandenburg 	new_op->upcall.req.getattr.refn = orangefs_inode->refn;
3975859d77eSMartin Brandenburg 	new_op->upcall.req.getattr.mask = ORANGEFS_ATTR_SYS_TYPE |
3985859d77eSMartin Brandenburg 	    ORANGEFS_ATTR_SYS_LNK_TARGET;
3995859d77eSMartin Brandenburg 
4005859d77eSMartin Brandenburg 	ret = service_operation(new_op, __func__,
4015859d77eSMartin Brandenburg 	    get_interruptible_flag(inode));
4025859d77eSMartin Brandenburg 	if (ret != 0)
4035859d77eSMartin Brandenburg 		goto out;
4045859d77eSMartin Brandenburg 
405480e5ae9SMartin Brandenburg 	ret = orangefs_inode_is_stale(inode,
40626662633SMartin Brandenburg 	    &new_op->downcall.resp.getattr.attributes,
40726662633SMartin Brandenburg 	    new_op->downcall.resp.getattr.link_target);
4085859d77eSMartin Brandenburg out:
4095859d77eSMartin Brandenburg 	op_release(new_op);
4105859d77eSMartin Brandenburg 	return ret;
4115859d77eSMartin Brandenburg }
4125859d77eSMartin Brandenburg 
413575e9461SMike Marshall /*
414575e9461SMike Marshall  * issues a orangefs setattr request to make sure the new attribute values
415575e9461SMike Marshall  * take effect if successful.  returns 0 on success; -errno otherwise
416575e9461SMike Marshall  */
orangefs_inode_setattr(struct inode * inode)417afd9fb2aSMartin Brandenburg int orangefs_inode_setattr(struct inode *inode)
418575e9461SMike Marshall {
419575e9461SMike Marshall 	struct orangefs_inode_s *orangefs_inode = ORANGEFS_I(inode);
420575e9461SMike Marshall 	struct orangefs_kernel_op_s *new_op;
421575e9461SMike Marshall 	int ret;
422575e9461SMike Marshall 
423575e9461SMike Marshall 	new_op = op_alloc(ORANGEFS_VFS_OP_SETATTR);
424575e9461SMike Marshall 	if (!new_op)
425575e9461SMike Marshall 		return -ENOMEM;
426575e9461SMike Marshall 
427afd9fb2aSMartin Brandenburg 	spin_lock(&inode->i_lock);
428afd9fb2aSMartin Brandenburg 	new_op->upcall.uid = from_kuid(&init_user_ns, orangefs_inode->attr_uid);
429afd9fb2aSMartin Brandenburg 	new_op->upcall.gid = from_kgid(&init_user_ns, orangefs_inode->attr_gid);
430575e9461SMike Marshall 	new_op->upcall.req.setattr.refn = orangefs_inode->refn;
431afd9fb2aSMartin Brandenburg 	copy_attributes_from_inode(inode,
432afd9fb2aSMartin Brandenburg 	    &new_op->upcall.req.setattr.attributes);
433afd9fb2aSMartin Brandenburg 	orangefs_inode->attr_valid = 0;
4348a88bbceSMartin Brandenburg 	if (!new_op->upcall.req.setattr.attributes.mask) {
4358a88bbceSMartin Brandenburg 		spin_unlock(&inode->i_lock);
4368a88bbceSMartin Brandenburg 		op_release(new_op);
4378a88bbceSMartin Brandenburg 		return 0;
4388a88bbceSMartin Brandenburg 	}
439afd9fb2aSMartin Brandenburg 	spin_unlock(&inode->i_lock);
440afd9fb2aSMartin Brandenburg 
441575e9461SMike Marshall 	ret = service_operation(new_op, __func__,
4420dcac0f7SMartin Brandenburg 	    get_interruptible_flag(inode) | ORANGEFS_OP_WRITEBACK);
443575e9461SMike Marshall 	gossip_debug(GOSSIP_UTILS_DEBUG,
444afd9fb2aSMartin Brandenburg 	    "orangefs_inode_setattr: returning %d\n", ret);
445afd9fb2aSMartin Brandenburg 	if (ret)
446afd9fb2aSMartin Brandenburg 		orangefs_make_bad_inode(inode);
447575e9461SMike Marshall 
448575e9461SMike Marshall 	op_release(new_op);
449575e9461SMike Marshall 
450a55f2d86SMartin Brandenburg 	if (ret == 0)
4518bbb20a8SMartin Brandenburg 		orangefs_inode->getattr_time = jiffies - 1;
452575e9461SMike Marshall 	return ret;
453575e9461SMike Marshall }
454575e9461SMike Marshall 
455575e9461SMike Marshall /*
456575e9461SMike Marshall  * The following is a very dirty hack that is now a permanent part of the
457575e9461SMike Marshall  * ORANGEFS protocol. See protocol.h for more error definitions.
458575e9461SMike Marshall  */
459575e9461SMike Marshall 
460575e9461SMike Marshall /* The order matches include/orangefs-types.h in the OrangeFS source. */
461575e9461SMike Marshall static int PINT_errno_mapping[] = {
462575e9461SMike Marshall 	0, EPERM, ENOENT, EINTR, EIO, ENXIO, EBADF, EAGAIN, ENOMEM,
463575e9461SMike Marshall 	EFAULT, EBUSY, EEXIST, ENODEV, ENOTDIR, EISDIR, EINVAL, EMFILE,
464575e9461SMike Marshall 	EFBIG, ENOSPC, EROFS, EMLINK, EPIPE, EDEADLK, ENAMETOOLONG,
465575e9461SMike Marshall 	ENOLCK, ENOSYS, ENOTEMPTY, ELOOP, EWOULDBLOCK, ENOMSG, EUNATCH,
466575e9461SMike Marshall 	EBADR, EDEADLOCK, ENODATA, ETIME, ENONET, EREMOTE, ECOMM,
467575e9461SMike Marshall 	EPROTO, EBADMSG, EOVERFLOW, ERESTART, EMSGSIZE, EPROTOTYPE,
468575e9461SMike Marshall 	ENOPROTOOPT, EPROTONOSUPPORT, EOPNOTSUPP, EADDRINUSE,
469575e9461SMike Marshall 	EADDRNOTAVAIL, ENETDOWN, ENETUNREACH, ENETRESET, ENOBUFS,
470575e9461SMike Marshall 	ETIMEDOUT, ECONNREFUSED, EHOSTDOWN, EHOSTUNREACH, EALREADY,
471575e9461SMike Marshall 	EACCES, ECONNRESET, ERANGE
472575e9461SMike Marshall };
473575e9461SMike Marshall 
orangefs_normalize_to_errno(__s32 error_code)474575e9461SMike Marshall int orangefs_normalize_to_errno(__s32 error_code)
475575e9461SMike Marshall {
476575e9461SMike Marshall 	__u32 i;
477575e9461SMike Marshall 
478575e9461SMike Marshall 	/* Success */
479575e9461SMike Marshall 	if (error_code == 0) {
480575e9461SMike Marshall 		return 0;
481575e9461SMike Marshall 	/*
482575e9461SMike Marshall 	 * This shouldn't ever happen. If it does it should be fixed on the
483575e9461SMike Marshall 	 * server.
484575e9461SMike Marshall 	 */
485575e9461SMike Marshall 	} else if (error_code > 0) {
486bc8282a7SMasanari Iida 		gossip_err("orangefs: error status received.\n");
487575e9461SMike Marshall 		gossip_err("orangefs: assuming error code is inverted.\n");
488575e9461SMike Marshall 		error_code = -error_code;
489575e9461SMike Marshall 	}
490575e9461SMike Marshall 
491575e9461SMike Marshall 	/*
492575e9461SMike Marshall 	 * XXX: This is very bad since error codes from ORANGEFS may not be
493575e9461SMike Marshall 	 * suitable for return into userspace.
494575e9461SMike Marshall 	 */
495575e9461SMike Marshall 
496575e9461SMike Marshall 	/*
497575e9461SMike Marshall 	 * Convert ORANGEFS error values into errno values suitable for return
498575e9461SMike Marshall 	 * from the kernel.
499575e9461SMike Marshall 	 */
500575e9461SMike Marshall 	if ((-error_code) & ORANGEFS_NON_ERRNO_ERROR_BIT) {
501575e9461SMike Marshall 		if (((-error_code) &
502575e9461SMike Marshall 		    (ORANGEFS_ERROR_NUMBER_BITS|ORANGEFS_NON_ERRNO_ERROR_BIT|
503575e9461SMike Marshall 		    ORANGEFS_ERROR_BIT)) == ORANGEFS_ECANCEL) {
504575e9461SMike Marshall 			/*
505575e9461SMike Marshall 			 * cancellation error codes generally correspond to
506575e9461SMike Marshall 			 * a timeout from the client's perspective
507575e9461SMike Marshall 			 */
508575e9461SMike Marshall 			error_code = -ETIMEDOUT;
509575e9461SMike Marshall 		} else {
510575e9461SMike Marshall 			/* assume a default error code */
51195f5f88fSMike Marshall 			gossip_err("%s: bad error code :%d:.\n",
51295f5f88fSMike Marshall 				__func__,
51395f5f88fSMike Marshall 				error_code);
514575e9461SMike Marshall 			error_code = -EINVAL;
515575e9461SMike Marshall 		}
516575e9461SMike Marshall 
517575e9461SMike Marshall 	/* Convert ORANGEFS encoded errno values into regular errno values. */
518575e9461SMike Marshall 	} else if ((-error_code) & ORANGEFS_ERROR_BIT) {
519575e9461SMike Marshall 		i = (-error_code) & ~(ORANGEFS_ERROR_BIT|ORANGEFS_ERROR_CLASS_BITS);
520296200d3SJérémy Lefaure 		if (i < ARRAY_SIZE(PINT_errno_mapping))
521575e9461SMike Marshall 			error_code = -PINT_errno_mapping[i];
522575e9461SMike Marshall 		else
523575e9461SMike Marshall 			error_code = -EINVAL;
524575e9461SMike Marshall 
525575e9461SMike Marshall 	/*
526575e9461SMike Marshall 	 * Only ORANGEFS protocol error codes should ever come here. Otherwise
527575e9461SMike Marshall 	 * there is a bug somewhere.
528575e9461SMike Marshall 	 */
529575e9461SMike Marshall 	} else {
53095f5f88fSMike Marshall 		gossip_err("%s: unknown error code.\n", __func__);
531cf546ab6SMike Marshall 		error_code = -EINVAL;
532575e9461SMike Marshall 	}
533575e9461SMike Marshall 	return error_code;
534575e9461SMike Marshall }
535575e9461SMike Marshall 
536575e9461SMike Marshall #define NUM_MODES 11
ORANGEFS_util_translate_mode(int mode)537575e9461SMike Marshall __s32 ORANGEFS_util_translate_mode(int mode)
538575e9461SMike Marshall {
539575e9461SMike Marshall 	int ret = 0;
540575e9461SMike Marshall 	int i = 0;
541575e9461SMike Marshall 	static int modes[NUM_MODES] = {
542575e9461SMike Marshall 		S_IXOTH, S_IWOTH, S_IROTH,
543575e9461SMike Marshall 		S_IXGRP, S_IWGRP, S_IRGRP,
544575e9461SMike Marshall 		S_IXUSR, S_IWUSR, S_IRUSR,
545575e9461SMike Marshall 		S_ISGID, S_ISUID
546575e9461SMike Marshall 	};
547575e9461SMike Marshall 	static int orangefs_modes[NUM_MODES] = {
548575e9461SMike Marshall 		ORANGEFS_O_EXECUTE, ORANGEFS_O_WRITE, ORANGEFS_O_READ,
549575e9461SMike Marshall 		ORANGEFS_G_EXECUTE, ORANGEFS_G_WRITE, ORANGEFS_G_READ,
550575e9461SMike Marshall 		ORANGEFS_U_EXECUTE, ORANGEFS_U_WRITE, ORANGEFS_U_READ,
551575e9461SMike Marshall 		ORANGEFS_G_SGID, ORANGEFS_U_SUID
552575e9461SMike Marshall 	};
553575e9461SMike Marshall 
554575e9461SMike Marshall 	for (i = 0; i < NUM_MODES; i++)
555575e9461SMike Marshall 		if (mode & modes[i])
556575e9461SMike Marshall 			ret |= orangefs_modes[i];
557575e9461SMike Marshall 
558575e9461SMike Marshall 	return ret;
559575e9461SMike Marshall }
560575e9461SMike Marshall #undef NUM_MODES
561