xref: /OK3568_Linux_fs/kernel/fs/orangefs/orangefs-utils.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun  * (C) 2001 Clemson University and The University of Chicago
4*4882a593Smuzhiyun  * Copyright 2018 Omnibond Systems, L.L.C.
5*4882a593Smuzhiyun  *
6*4882a593Smuzhiyun  * See COPYING in top-level directory.
7*4882a593Smuzhiyun  */
8*4882a593Smuzhiyun #include <linux/kernel.h>
9*4882a593Smuzhiyun #include "protocol.h"
10*4882a593Smuzhiyun #include "orangefs-kernel.h"
11*4882a593Smuzhiyun #include "orangefs-dev-proto.h"
12*4882a593Smuzhiyun #include "orangefs-bufmap.h"
13*4882a593Smuzhiyun 
fsid_of_op(struct orangefs_kernel_op_s * op)14*4882a593Smuzhiyun __s32 fsid_of_op(struct orangefs_kernel_op_s *op)
15*4882a593Smuzhiyun {
16*4882a593Smuzhiyun 	__s32 fsid = ORANGEFS_FS_ID_NULL;
17*4882a593Smuzhiyun 
18*4882a593Smuzhiyun 	if (op) {
19*4882a593Smuzhiyun 		switch (op->upcall.type) {
20*4882a593Smuzhiyun 		case ORANGEFS_VFS_OP_FILE_IO:
21*4882a593Smuzhiyun 			fsid = op->upcall.req.io.refn.fs_id;
22*4882a593Smuzhiyun 			break;
23*4882a593Smuzhiyun 		case ORANGEFS_VFS_OP_LOOKUP:
24*4882a593Smuzhiyun 			fsid = op->upcall.req.lookup.parent_refn.fs_id;
25*4882a593Smuzhiyun 			break;
26*4882a593Smuzhiyun 		case ORANGEFS_VFS_OP_CREATE:
27*4882a593Smuzhiyun 			fsid = op->upcall.req.create.parent_refn.fs_id;
28*4882a593Smuzhiyun 			break;
29*4882a593Smuzhiyun 		case ORANGEFS_VFS_OP_GETATTR:
30*4882a593Smuzhiyun 			fsid = op->upcall.req.getattr.refn.fs_id;
31*4882a593Smuzhiyun 			break;
32*4882a593Smuzhiyun 		case ORANGEFS_VFS_OP_REMOVE:
33*4882a593Smuzhiyun 			fsid = op->upcall.req.remove.parent_refn.fs_id;
34*4882a593Smuzhiyun 			break;
35*4882a593Smuzhiyun 		case ORANGEFS_VFS_OP_MKDIR:
36*4882a593Smuzhiyun 			fsid = op->upcall.req.mkdir.parent_refn.fs_id;
37*4882a593Smuzhiyun 			break;
38*4882a593Smuzhiyun 		case ORANGEFS_VFS_OP_READDIR:
39*4882a593Smuzhiyun 			fsid = op->upcall.req.readdir.refn.fs_id;
40*4882a593Smuzhiyun 			break;
41*4882a593Smuzhiyun 		case ORANGEFS_VFS_OP_SETATTR:
42*4882a593Smuzhiyun 			fsid = op->upcall.req.setattr.refn.fs_id;
43*4882a593Smuzhiyun 			break;
44*4882a593Smuzhiyun 		case ORANGEFS_VFS_OP_SYMLINK:
45*4882a593Smuzhiyun 			fsid = op->upcall.req.sym.parent_refn.fs_id;
46*4882a593Smuzhiyun 			break;
47*4882a593Smuzhiyun 		case ORANGEFS_VFS_OP_RENAME:
48*4882a593Smuzhiyun 			fsid = op->upcall.req.rename.old_parent_refn.fs_id;
49*4882a593Smuzhiyun 			break;
50*4882a593Smuzhiyun 		case ORANGEFS_VFS_OP_STATFS:
51*4882a593Smuzhiyun 			fsid = op->upcall.req.statfs.fs_id;
52*4882a593Smuzhiyun 			break;
53*4882a593Smuzhiyun 		case ORANGEFS_VFS_OP_TRUNCATE:
54*4882a593Smuzhiyun 			fsid = op->upcall.req.truncate.refn.fs_id;
55*4882a593Smuzhiyun 			break;
56*4882a593Smuzhiyun 		case ORANGEFS_VFS_OP_RA_FLUSH:
57*4882a593Smuzhiyun 			fsid = op->upcall.req.ra_cache_flush.refn.fs_id;
58*4882a593Smuzhiyun 			break;
59*4882a593Smuzhiyun 		case ORANGEFS_VFS_OP_FS_UMOUNT:
60*4882a593Smuzhiyun 			fsid = op->upcall.req.fs_umount.fs_id;
61*4882a593Smuzhiyun 			break;
62*4882a593Smuzhiyun 		case ORANGEFS_VFS_OP_GETXATTR:
63*4882a593Smuzhiyun 			fsid = op->upcall.req.getxattr.refn.fs_id;
64*4882a593Smuzhiyun 			break;
65*4882a593Smuzhiyun 		case ORANGEFS_VFS_OP_SETXATTR:
66*4882a593Smuzhiyun 			fsid = op->upcall.req.setxattr.refn.fs_id;
67*4882a593Smuzhiyun 			break;
68*4882a593Smuzhiyun 		case ORANGEFS_VFS_OP_LISTXATTR:
69*4882a593Smuzhiyun 			fsid = op->upcall.req.listxattr.refn.fs_id;
70*4882a593Smuzhiyun 			break;
71*4882a593Smuzhiyun 		case ORANGEFS_VFS_OP_REMOVEXATTR:
72*4882a593Smuzhiyun 			fsid = op->upcall.req.removexattr.refn.fs_id;
73*4882a593Smuzhiyun 			break;
74*4882a593Smuzhiyun 		case ORANGEFS_VFS_OP_FSYNC:
75*4882a593Smuzhiyun 			fsid = op->upcall.req.fsync.refn.fs_id;
76*4882a593Smuzhiyun 			break;
77*4882a593Smuzhiyun 		default:
78*4882a593Smuzhiyun 			break;
79*4882a593Smuzhiyun 		}
80*4882a593Smuzhiyun 	}
81*4882a593Smuzhiyun 	return fsid;
82*4882a593Smuzhiyun }
83*4882a593Smuzhiyun 
orangefs_inode_flags(struct ORANGEFS_sys_attr_s * attrs)84*4882a593Smuzhiyun static int orangefs_inode_flags(struct ORANGEFS_sys_attr_s *attrs)
85*4882a593Smuzhiyun {
86*4882a593Smuzhiyun 	int flags = 0;
87*4882a593Smuzhiyun 	if (attrs->flags & ORANGEFS_IMMUTABLE_FL)
88*4882a593Smuzhiyun 		flags |= S_IMMUTABLE;
89*4882a593Smuzhiyun 	else
90*4882a593Smuzhiyun 		flags &= ~S_IMMUTABLE;
91*4882a593Smuzhiyun 	if (attrs->flags & ORANGEFS_APPEND_FL)
92*4882a593Smuzhiyun 		flags |= S_APPEND;
93*4882a593Smuzhiyun 	else
94*4882a593Smuzhiyun 		flags &= ~S_APPEND;
95*4882a593Smuzhiyun 	if (attrs->flags & ORANGEFS_NOATIME_FL)
96*4882a593Smuzhiyun 		flags |= S_NOATIME;
97*4882a593Smuzhiyun 	else
98*4882a593Smuzhiyun 		flags &= ~S_NOATIME;
99*4882a593Smuzhiyun 	return flags;
100*4882a593Smuzhiyun }
101*4882a593Smuzhiyun 
orangefs_inode_perms(struct ORANGEFS_sys_attr_s * attrs)102*4882a593Smuzhiyun static int orangefs_inode_perms(struct ORANGEFS_sys_attr_s *attrs)
103*4882a593Smuzhiyun {
104*4882a593Smuzhiyun 	int perm_mode = 0;
105*4882a593Smuzhiyun 
106*4882a593Smuzhiyun 	if (attrs->perms & ORANGEFS_O_EXECUTE)
107*4882a593Smuzhiyun 		perm_mode |= S_IXOTH;
108*4882a593Smuzhiyun 	if (attrs->perms & ORANGEFS_O_WRITE)
109*4882a593Smuzhiyun 		perm_mode |= S_IWOTH;
110*4882a593Smuzhiyun 	if (attrs->perms & ORANGEFS_O_READ)
111*4882a593Smuzhiyun 		perm_mode |= S_IROTH;
112*4882a593Smuzhiyun 
113*4882a593Smuzhiyun 	if (attrs->perms & ORANGEFS_G_EXECUTE)
114*4882a593Smuzhiyun 		perm_mode |= S_IXGRP;
115*4882a593Smuzhiyun 	if (attrs->perms & ORANGEFS_G_WRITE)
116*4882a593Smuzhiyun 		perm_mode |= S_IWGRP;
117*4882a593Smuzhiyun 	if (attrs->perms & ORANGEFS_G_READ)
118*4882a593Smuzhiyun 		perm_mode |= S_IRGRP;
119*4882a593Smuzhiyun 
120*4882a593Smuzhiyun 	if (attrs->perms & ORANGEFS_U_EXECUTE)
121*4882a593Smuzhiyun 		perm_mode |= S_IXUSR;
122*4882a593Smuzhiyun 	if (attrs->perms & ORANGEFS_U_WRITE)
123*4882a593Smuzhiyun 		perm_mode |= S_IWUSR;
124*4882a593Smuzhiyun 	if (attrs->perms & ORANGEFS_U_READ)
125*4882a593Smuzhiyun 		perm_mode |= S_IRUSR;
126*4882a593Smuzhiyun 
127*4882a593Smuzhiyun 	if (attrs->perms & ORANGEFS_G_SGID)
128*4882a593Smuzhiyun 		perm_mode |= S_ISGID;
129*4882a593Smuzhiyun 	if (attrs->perms & ORANGEFS_U_SUID)
130*4882a593Smuzhiyun 		perm_mode |= S_ISUID;
131*4882a593Smuzhiyun 
132*4882a593Smuzhiyun 	return perm_mode;
133*4882a593Smuzhiyun }
134*4882a593Smuzhiyun 
135*4882a593Smuzhiyun /*
136*4882a593Smuzhiyun  * NOTE: in kernel land, we never use the sys_attr->link_target for
137*4882a593Smuzhiyun  * anything, so don't bother copying it into the sys_attr object here.
138*4882a593Smuzhiyun  */
copy_attributes_from_inode(struct inode * inode,struct ORANGEFS_sys_attr_s * attrs)139*4882a593Smuzhiyun static inline void copy_attributes_from_inode(struct inode *inode,
140*4882a593Smuzhiyun     struct ORANGEFS_sys_attr_s *attrs)
141*4882a593Smuzhiyun {
142*4882a593Smuzhiyun 	struct orangefs_inode_s *orangefs_inode = ORANGEFS_I(inode);
143*4882a593Smuzhiyun 	attrs->mask = 0;
144*4882a593Smuzhiyun 	if (orangefs_inode->attr_valid & ATTR_UID) {
145*4882a593Smuzhiyun 		attrs->owner = from_kuid(&init_user_ns, inode->i_uid);
146*4882a593Smuzhiyun 		attrs->mask |= ORANGEFS_ATTR_SYS_UID;
147*4882a593Smuzhiyun 		gossip_debug(GOSSIP_UTILS_DEBUG, "(UID) %d\n", attrs->owner);
148*4882a593Smuzhiyun 	}
149*4882a593Smuzhiyun 	if (orangefs_inode->attr_valid & ATTR_GID) {
150*4882a593Smuzhiyun 		attrs->group = from_kgid(&init_user_ns, inode->i_gid);
151*4882a593Smuzhiyun 		attrs->mask |= ORANGEFS_ATTR_SYS_GID;
152*4882a593Smuzhiyun 		gossip_debug(GOSSIP_UTILS_DEBUG, "(GID) %d\n", attrs->group);
153*4882a593Smuzhiyun 	}
154*4882a593Smuzhiyun 
155*4882a593Smuzhiyun 	if (orangefs_inode->attr_valid & ATTR_ATIME) {
156*4882a593Smuzhiyun 		attrs->mask |= ORANGEFS_ATTR_SYS_ATIME;
157*4882a593Smuzhiyun 		if (orangefs_inode->attr_valid & ATTR_ATIME_SET) {
158*4882a593Smuzhiyun 			attrs->atime = (time64_t)inode->i_atime.tv_sec;
159*4882a593Smuzhiyun 			attrs->mask |= ORANGEFS_ATTR_SYS_ATIME_SET;
160*4882a593Smuzhiyun 		}
161*4882a593Smuzhiyun 	}
162*4882a593Smuzhiyun 	if (orangefs_inode->attr_valid & ATTR_MTIME) {
163*4882a593Smuzhiyun 		attrs->mask |= ORANGEFS_ATTR_SYS_MTIME;
164*4882a593Smuzhiyun 		if (orangefs_inode->attr_valid & ATTR_MTIME_SET) {
165*4882a593Smuzhiyun 			attrs->mtime = (time64_t)inode->i_mtime.tv_sec;
166*4882a593Smuzhiyun 			attrs->mask |= ORANGEFS_ATTR_SYS_MTIME_SET;
167*4882a593Smuzhiyun 		}
168*4882a593Smuzhiyun 	}
169*4882a593Smuzhiyun 	if (orangefs_inode->attr_valid & ATTR_CTIME)
170*4882a593Smuzhiyun 		attrs->mask |= ORANGEFS_ATTR_SYS_CTIME;
171*4882a593Smuzhiyun 
172*4882a593Smuzhiyun 	/*
173*4882a593Smuzhiyun 	 * ORANGEFS cannot set size with a setattr operation. Probably not
174*4882a593Smuzhiyun 	 * likely to be requested through the VFS, but just in case, don't
175*4882a593Smuzhiyun 	 * worry about ATTR_SIZE
176*4882a593Smuzhiyun 	 */
177*4882a593Smuzhiyun 
178*4882a593Smuzhiyun 	if (orangefs_inode->attr_valid & ATTR_MODE) {
179*4882a593Smuzhiyun 		attrs->perms = ORANGEFS_util_translate_mode(inode->i_mode);
180*4882a593Smuzhiyun 		attrs->mask |= ORANGEFS_ATTR_SYS_PERM;
181*4882a593Smuzhiyun 	}
182*4882a593Smuzhiyun }
183*4882a593Smuzhiyun 
orangefs_inode_type(enum orangefs_ds_type objtype)184*4882a593Smuzhiyun static int orangefs_inode_type(enum orangefs_ds_type objtype)
185*4882a593Smuzhiyun {
186*4882a593Smuzhiyun 	if (objtype == ORANGEFS_TYPE_METAFILE)
187*4882a593Smuzhiyun 		return S_IFREG;
188*4882a593Smuzhiyun 	else if (objtype == ORANGEFS_TYPE_DIRECTORY)
189*4882a593Smuzhiyun 		return S_IFDIR;
190*4882a593Smuzhiyun 	else if (objtype == ORANGEFS_TYPE_SYMLINK)
191*4882a593Smuzhiyun 		return S_IFLNK;
192*4882a593Smuzhiyun 	else
193*4882a593Smuzhiyun 		return -1;
194*4882a593Smuzhiyun }
195*4882a593Smuzhiyun 
orangefs_make_bad_inode(struct inode * inode)196*4882a593Smuzhiyun static void orangefs_make_bad_inode(struct inode *inode)
197*4882a593Smuzhiyun {
198*4882a593Smuzhiyun 	if (is_root_handle(inode)) {
199*4882a593Smuzhiyun 		/*
200*4882a593Smuzhiyun 		 * if this occurs, the pvfs2-client-core was killed but we
201*4882a593Smuzhiyun 		 * can't afford to lose the inode operations and such
202*4882a593Smuzhiyun 		 * associated with the root handle in any case.
203*4882a593Smuzhiyun 		 */
204*4882a593Smuzhiyun 		gossip_debug(GOSSIP_UTILS_DEBUG,
205*4882a593Smuzhiyun 			     "*** NOT making bad root inode %pU\n",
206*4882a593Smuzhiyun 			     get_khandle_from_ino(inode));
207*4882a593Smuzhiyun 	} else {
208*4882a593Smuzhiyun 		gossip_debug(GOSSIP_UTILS_DEBUG,
209*4882a593Smuzhiyun 			     "*** making bad inode %pU\n",
210*4882a593Smuzhiyun 			     get_khandle_from_ino(inode));
211*4882a593Smuzhiyun 		make_bad_inode(inode);
212*4882a593Smuzhiyun 	}
213*4882a593Smuzhiyun }
214*4882a593Smuzhiyun 
orangefs_inode_is_stale(struct inode * inode,struct ORANGEFS_sys_attr_s * attrs,char * link_target)215*4882a593Smuzhiyun static int orangefs_inode_is_stale(struct inode *inode,
216*4882a593Smuzhiyun     struct ORANGEFS_sys_attr_s *attrs, char *link_target)
217*4882a593Smuzhiyun {
218*4882a593Smuzhiyun 	struct orangefs_inode_s *orangefs_inode = ORANGEFS_I(inode);
219*4882a593Smuzhiyun 	int type = orangefs_inode_type(attrs->objtype);
220*4882a593Smuzhiyun 	/*
221*4882a593Smuzhiyun 	 * If the inode type or symlink target have changed then this
222*4882a593Smuzhiyun 	 * inode is stale.
223*4882a593Smuzhiyun 	 */
224*4882a593Smuzhiyun 	if (type == -1 || !(inode->i_mode & type)) {
225*4882a593Smuzhiyun 		orangefs_make_bad_inode(inode);
226*4882a593Smuzhiyun 		return 1;
227*4882a593Smuzhiyun 	}
228*4882a593Smuzhiyun 	if (type == S_IFLNK && strncmp(orangefs_inode->link_target,
229*4882a593Smuzhiyun 	    link_target, ORANGEFS_NAME_MAX)) {
230*4882a593Smuzhiyun 		orangefs_make_bad_inode(inode);
231*4882a593Smuzhiyun 		return 1;
232*4882a593Smuzhiyun 	}
233*4882a593Smuzhiyun 	return 0;
234*4882a593Smuzhiyun }
235*4882a593Smuzhiyun 
orangefs_inode_getattr(struct inode * inode,int flags)236*4882a593Smuzhiyun int orangefs_inode_getattr(struct inode *inode, int flags)
237*4882a593Smuzhiyun {
238*4882a593Smuzhiyun 	struct orangefs_inode_s *orangefs_inode = ORANGEFS_I(inode);
239*4882a593Smuzhiyun 	struct orangefs_kernel_op_s *new_op;
240*4882a593Smuzhiyun 	loff_t inode_size;
241*4882a593Smuzhiyun 	int ret, type;
242*4882a593Smuzhiyun 
243*4882a593Smuzhiyun 	gossip_debug(GOSSIP_UTILS_DEBUG, "%s: called on inode %pU flags %d\n",
244*4882a593Smuzhiyun 	    __func__, get_khandle_from_ino(inode), flags);
245*4882a593Smuzhiyun 
246*4882a593Smuzhiyun again:
247*4882a593Smuzhiyun 	spin_lock(&inode->i_lock);
248*4882a593Smuzhiyun 	/* Must have all the attributes in the mask and be within cache time. */
249*4882a593Smuzhiyun 	if ((!flags && time_before(jiffies, orangefs_inode->getattr_time)) ||
250*4882a593Smuzhiyun 	    orangefs_inode->attr_valid || inode->i_state & I_DIRTY_PAGES) {
251*4882a593Smuzhiyun 		if (orangefs_inode->attr_valid) {
252*4882a593Smuzhiyun 			spin_unlock(&inode->i_lock);
253*4882a593Smuzhiyun 			write_inode_now(inode, 1);
254*4882a593Smuzhiyun 			goto again;
255*4882a593Smuzhiyun 		}
256*4882a593Smuzhiyun 		spin_unlock(&inode->i_lock);
257*4882a593Smuzhiyun 		return 0;
258*4882a593Smuzhiyun 	}
259*4882a593Smuzhiyun 	spin_unlock(&inode->i_lock);
260*4882a593Smuzhiyun 
261*4882a593Smuzhiyun 	new_op = op_alloc(ORANGEFS_VFS_OP_GETATTR);
262*4882a593Smuzhiyun 	if (!new_op)
263*4882a593Smuzhiyun 		return -ENOMEM;
264*4882a593Smuzhiyun 	new_op->upcall.req.getattr.refn = orangefs_inode->refn;
265*4882a593Smuzhiyun 	/*
266*4882a593Smuzhiyun 	 * Size is the hardest attribute to get.  The incremental cost of any
267*4882a593Smuzhiyun 	 * other attribute is essentially zero.
268*4882a593Smuzhiyun 	 */
269*4882a593Smuzhiyun 	if (flags)
270*4882a593Smuzhiyun 		new_op->upcall.req.getattr.mask = ORANGEFS_ATTR_SYS_ALL_NOHINT;
271*4882a593Smuzhiyun 	else
272*4882a593Smuzhiyun 		new_op->upcall.req.getattr.mask =
273*4882a593Smuzhiyun 		    ORANGEFS_ATTR_SYS_ALL_NOHINT & ~ORANGEFS_ATTR_SYS_SIZE;
274*4882a593Smuzhiyun 
275*4882a593Smuzhiyun 	ret = service_operation(new_op, __func__,
276*4882a593Smuzhiyun 	    get_interruptible_flag(inode));
277*4882a593Smuzhiyun 	if (ret != 0)
278*4882a593Smuzhiyun 		goto out;
279*4882a593Smuzhiyun 
280*4882a593Smuzhiyun again2:
281*4882a593Smuzhiyun 	spin_lock(&inode->i_lock);
282*4882a593Smuzhiyun 	/* Must have all the attributes in the mask and be within cache time. */
283*4882a593Smuzhiyun 	if ((!flags && time_before(jiffies, orangefs_inode->getattr_time)) ||
284*4882a593Smuzhiyun 	    orangefs_inode->attr_valid || inode->i_state & I_DIRTY_PAGES) {
285*4882a593Smuzhiyun 		if (orangefs_inode->attr_valid) {
286*4882a593Smuzhiyun 			spin_unlock(&inode->i_lock);
287*4882a593Smuzhiyun 			write_inode_now(inode, 1);
288*4882a593Smuzhiyun 			goto again2;
289*4882a593Smuzhiyun 		}
290*4882a593Smuzhiyun 		if (inode->i_state & I_DIRTY_PAGES) {
291*4882a593Smuzhiyun 			ret = 0;
292*4882a593Smuzhiyun 			goto out_unlock;
293*4882a593Smuzhiyun 		}
294*4882a593Smuzhiyun 		gossip_debug(GOSSIP_UTILS_DEBUG, "%s: in cache or dirty\n",
295*4882a593Smuzhiyun 		    __func__);
296*4882a593Smuzhiyun 		ret = 0;
297*4882a593Smuzhiyun 		goto out_unlock;
298*4882a593Smuzhiyun 	}
299*4882a593Smuzhiyun 
300*4882a593Smuzhiyun 	if (!(flags & ORANGEFS_GETATTR_NEW)) {
301*4882a593Smuzhiyun 		ret = orangefs_inode_is_stale(inode,
302*4882a593Smuzhiyun 		    &new_op->downcall.resp.getattr.attributes,
303*4882a593Smuzhiyun 		    new_op->downcall.resp.getattr.link_target);
304*4882a593Smuzhiyun 		if (ret) {
305*4882a593Smuzhiyun 			ret = -ESTALE;
306*4882a593Smuzhiyun 			goto out_unlock;
307*4882a593Smuzhiyun 		}
308*4882a593Smuzhiyun 	}
309*4882a593Smuzhiyun 
310*4882a593Smuzhiyun 	type = orangefs_inode_type(new_op->
311*4882a593Smuzhiyun 	    downcall.resp.getattr.attributes.objtype);
312*4882a593Smuzhiyun 	switch (type) {
313*4882a593Smuzhiyun 	case S_IFREG:
314*4882a593Smuzhiyun 		inode->i_flags = orangefs_inode_flags(&new_op->
315*4882a593Smuzhiyun 		    downcall.resp.getattr.attributes);
316*4882a593Smuzhiyun 		if (flags) {
317*4882a593Smuzhiyun 			inode_size = (loff_t)new_op->
318*4882a593Smuzhiyun 			    downcall.resp.getattr.attributes.size;
319*4882a593Smuzhiyun 			inode->i_size = inode_size;
320*4882a593Smuzhiyun 			inode->i_blkbits = ffs(new_op->downcall.resp.getattr.
321*4882a593Smuzhiyun 			    attributes.blksize);
322*4882a593Smuzhiyun 			inode->i_bytes = inode_size;
323*4882a593Smuzhiyun 			inode->i_blocks =
324*4882a593Smuzhiyun 			    (inode_size + 512 - inode_size % 512)/512;
325*4882a593Smuzhiyun 		}
326*4882a593Smuzhiyun 		break;
327*4882a593Smuzhiyun 	case S_IFDIR:
328*4882a593Smuzhiyun 		if (flags) {
329*4882a593Smuzhiyun 			inode->i_size = PAGE_SIZE;
330*4882a593Smuzhiyun 			inode_set_bytes(inode, inode->i_size);
331*4882a593Smuzhiyun 		}
332*4882a593Smuzhiyun 		set_nlink(inode, 1);
333*4882a593Smuzhiyun 		break;
334*4882a593Smuzhiyun 	case S_IFLNK:
335*4882a593Smuzhiyun 		if (flags & ORANGEFS_GETATTR_NEW) {
336*4882a593Smuzhiyun 			inode->i_size = (loff_t)strlen(new_op->
337*4882a593Smuzhiyun 			    downcall.resp.getattr.link_target);
338*4882a593Smuzhiyun 			ret = strscpy(orangefs_inode->link_target,
339*4882a593Smuzhiyun 			    new_op->downcall.resp.getattr.link_target,
340*4882a593Smuzhiyun 			    ORANGEFS_NAME_MAX);
341*4882a593Smuzhiyun 			if (ret == -E2BIG) {
342*4882a593Smuzhiyun 				ret = -EIO;
343*4882a593Smuzhiyun 				goto out_unlock;
344*4882a593Smuzhiyun 			}
345*4882a593Smuzhiyun 			inode->i_link = orangefs_inode->link_target;
346*4882a593Smuzhiyun 		}
347*4882a593Smuzhiyun 		break;
348*4882a593Smuzhiyun 	/* i.e. -1 */
349*4882a593Smuzhiyun 	default:
350*4882a593Smuzhiyun 		/* XXX: ESTALE?  This is what is done if it is not new. */
351*4882a593Smuzhiyun 		orangefs_make_bad_inode(inode);
352*4882a593Smuzhiyun 		ret = -ESTALE;
353*4882a593Smuzhiyun 		goto out_unlock;
354*4882a593Smuzhiyun 	}
355*4882a593Smuzhiyun 
356*4882a593Smuzhiyun 	inode->i_uid = make_kuid(&init_user_ns, new_op->
357*4882a593Smuzhiyun 	    downcall.resp.getattr.attributes.owner);
358*4882a593Smuzhiyun 	inode->i_gid = make_kgid(&init_user_ns, new_op->
359*4882a593Smuzhiyun 	    downcall.resp.getattr.attributes.group);
360*4882a593Smuzhiyun 	inode->i_atime.tv_sec = (time64_t)new_op->
361*4882a593Smuzhiyun 	    downcall.resp.getattr.attributes.atime;
362*4882a593Smuzhiyun 	inode->i_mtime.tv_sec = (time64_t)new_op->
363*4882a593Smuzhiyun 	    downcall.resp.getattr.attributes.mtime;
364*4882a593Smuzhiyun 	inode->i_ctime.tv_sec = (time64_t)new_op->
365*4882a593Smuzhiyun 	    downcall.resp.getattr.attributes.ctime;
366*4882a593Smuzhiyun 	inode->i_atime.tv_nsec = 0;
367*4882a593Smuzhiyun 	inode->i_mtime.tv_nsec = 0;
368*4882a593Smuzhiyun 	inode->i_ctime.tv_nsec = 0;
369*4882a593Smuzhiyun 
370*4882a593Smuzhiyun 	/* special case: mark the root inode as sticky */
371*4882a593Smuzhiyun 	inode->i_mode = type | (is_root_handle(inode) ? S_ISVTX : 0) |
372*4882a593Smuzhiyun 	    orangefs_inode_perms(&new_op->downcall.resp.getattr.attributes);
373*4882a593Smuzhiyun 
374*4882a593Smuzhiyun 	orangefs_inode->getattr_time = jiffies +
375*4882a593Smuzhiyun 	    orangefs_getattr_timeout_msecs*HZ/1000;
376*4882a593Smuzhiyun 	ret = 0;
377*4882a593Smuzhiyun out_unlock:
378*4882a593Smuzhiyun 	spin_unlock(&inode->i_lock);
379*4882a593Smuzhiyun out:
380*4882a593Smuzhiyun 	op_release(new_op);
381*4882a593Smuzhiyun 	return ret;
382*4882a593Smuzhiyun }
383*4882a593Smuzhiyun 
orangefs_inode_check_changed(struct inode * inode)384*4882a593Smuzhiyun int orangefs_inode_check_changed(struct inode *inode)
385*4882a593Smuzhiyun {
386*4882a593Smuzhiyun 	struct orangefs_inode_s *orangefs_inode = ORANGEFS_I(inode);
387*4882a593Smuzhiyun 	struct orangefs_kernel_op_s *new_op;
388*4882a593Smuzhiyun 	int ret;
389*4882a593Smuzhiyun 
390*4882a593Smuzhiyun 	gossip_debug(GOSSIP_UTILS_DEBUG, "%s: called on inode %pU\n", __func__,
391*4882a593Smuzhiyun 	    get_khandle_from_ino(inode));
392*4882a593Smuzhiyun 
393*4882a593Smuzhiyun 	new_op = op_alloc(ORANGEFS_VFS_OP_GETATTR);
394*4882a593Smuzhiyun 	if (!new_op)
395*4882a593Smuzhiyun 		return -ENOMEM;
396*4882a593Smuzhiyun 	new_op->upcall.req.getattr.refn = orangefs_inode->refn;
397*4882a593Smuzhiyun 	new_op->upcall.req.getattr.mask = ORANGEFS_ATTR_SYS_TYPE |
398*4882a593Smuzhiyun 	    ORANGEFS_ATTR_SYS_LNK_TARGET;
399*4882a593Smuzhiyun 
400*4882a593Smuzhiyun 	ret = service_operation(new_op, __func__,
401*4882a593Smuzhiyun 	    get_interruptible_flag(inode));
402*4882a593Smuzhiyun 	if (ret != 0)
403*4882a593Smuzhiyun 		goto out;
404*4882a593Smuzhiyun 
405*4882a593Smuzhiyun 	ret = orangefs_inode_is_stale(inode,
406*4882a593Smuzhiyun 	    &new_op->downcall.resp.getattr.attributes,
407*4882a593Smuzhiyun 	    new_op->downcall.resp.getattr.link_target);
408*4882a593Smuzhiyun out:
409*4882a593Smuzhiyun 	op_release(new_op);
410*4882a593Smuzhiyun 	return ret;
411*4882a593Smuzhiyun }
412*4882a593Smuzhiyun 
413*4882a593Smuzhiyun /*
414*4882a593Smuzhiyun  * issues a orangefs setattr request to make sure the new attribute values
415*4882a593Smuzhiyun  * take effect if successful.  returns 0 on success; -errno otherwise
416*4882a593Smuzhiyun  */
orangefs_inode_setattr(struct inode * inode)417*4882a593Smuzhiyun int orangefs_inode_setattr(struct inode *inode)
418*4882a593Smuzhiyun {
419*4882a593Smuzhiyun 	struct orangefs_inode_s *orangefs_inode = ORANGEFS_I(inode);
420*4882a593Smuzhiyun 	struct orangefs_kernel_op_s *new_op;
421*4882a593Smuzhiyun 	int ret;
422*4882a593Smuzhiyun 
423*4882a593Smuzhiyun 	new_op = op_alloc(ORANGEFS_VFS_OP_SETATTR);
424*4882a593Smuzhiyun 	if (!new_op)
425*4882a593Smuzhiyun 		return -ENOMEM;
426*4882a593Smuzhiyun 
427*4882a593Smuzhiyun 	spin_lock(&inode->i_lock);
428*4882a593Smuzhiyun 	new_op->upcall.uid = from_kuid(&init_user_ns, orangefs_inode->attr_uid);
429*4882a593Smuzhiyun 	new_op->upcall.gid = from_kgid(&init_user_ns, orangefs_inode->attr_gid);
430*4882a593Smuzhiyun 	new_op->upcall.req.setattr.refn = orangefs_inode->refn;
431*4882a593Smuzhiyun 	copy_attributes_from_inode(inode,
432*4882a593Smuzhiyun 	    &new_op->upcall.req.setattr.attributes);
433*4882a593Smuzhiyun 	orangefs_inode->attr_valid = 0;
434*4882a593Smuzhiyun 	if (!new_op->upcall.req.setattr.attributes.mask) {
435*4882a593Smuzhiyun 		spin_unlock(&inode->i_lock);
436*4882a593Smuzhiyun 		op_release(new_op);
437*4882a593Smuzhiyun 		return 0;
438*4882a593Smuzhiyun 	}
439*4882a593Smuzhiyun 	spin_unlock(&inode->i_lock);
440*4882a593Smuzhiyun 
441*4882a593Smuzhiyun 	ret = service_operation(new_op, __func__,
442*4882a593Smuzhiyun 	    get_interruptible_flag(inode) | ORANGEFS_OP_WRITEBACK);
443*4882a593Smuzhiyun 	gossip_debug(GOSSIP_UTILS_DEBUG,
444*4882a593Smuzhiyun 	    "orangefs_inode_setattr: returning %d\n", ret);
445*4882a593Smuzhiyun 	if (ret)
446*4882a593Smuzhiyun 		orangefs_make_bad_inode(inode);
447*4882a593Smuzhiyun 
448*4882a593Smuzhiyun 	op_release(new_op);
449*4882a593Smuzhiyun 
450*4882a593Smuzhiyun 	if (ret == 0)
451*4882a593Smuzhiyun 		orangefs_inode->getattr_time = jiffies - 1;
452*4882a593Smuzhiyun 	return ret;
453*4882a593Smuzhiyun }
454*4882a593Smuzhiyun 
455*4882a593Smuzhiyun /*
456*4882a593Smuzhiyun  * The following is a very dirty hack that is now a permanent part of the
457*4882a593Smuzhiyun  * ORANGEFS protocol. See protocol.h for more error definitions.
458*4882a593Smuzhiyun  */
459*4882a593Smuzhiyun 
460*4882a593Smuzhiyun /* The order matches include/orangefs-types.h in the OrangeFS source. */
461*4882a593Smuzhiyun static int PINT_errno_mapping[] = {
462*4882a593Smuzhiyun 	0, EPERM, ENOENT, EINTR, EIO, ENXIO, EBADF, EAGAIN, ENOMEM,
463*4882a593Smuzhiyun 	EFAULT, EBUSY, EEXIST, ENODEV, ENOTDIR, EISDIR, EINVAL, EMFILE,
464*4882a593Smuzhiyun 	EFBIG, ENOSPC, EROFS, EMLINK, EPIPE, EDEADLK, ENAMETOOLONG,
465*4882a593Smuzhiyun 	ENOLCK, ENOSYS, ENOTEMPTY, ELOOP, EWOULDBLOCK, ENOMSG, EUNATCH,
466*4882a593Smuzhiyun 	EBADR, EDEADLOCK, ENODATA, ETIME, ENONET, EREMOTE, ECOMM,
467*4882a593Smuzhiyun 	EPROTO, EBADMSG, EOVERFLOW, ERESTART, EMSGSIZE, EPROTOTYPE,
468*4882a593Smuzhiyun 	ENOPROTOOPT, EPROTONOSUPPORT, EOPNOTSUPP, EADDRINUSE,
469*4882a593Smuzhiyun 	EADDRNOTAVAIL, ENETDOWN, ENETUNREACH, ENETRESET, ENOBUFS,
470*4882a593Smuzhiyun 	ETIMEDOUT, ECONNREFUSED, EHOSTDOWN, EHOSTUNREACH, EALREADY,
471*4882a593Smuzhiyun 	EACCES, ECONNRESET, ERANGE
472*4882a593Smuzhiyun };
473*4882a593Smuzhiyun 
orangefs_normalize_to_errno(__s32 error_code)474*4882a593Smuzhiyun int orangefs_normalize_to_errno(__s32 error_code)
475*4882a593Smuzhiyun {
476*4882a593Smuzhiyun 	__u32 i;
477*4882a593Smuzhiyun 
478*4882a593Smuzhiyun 	/* Success */
479*4882a593Smuzhiyun 	if (error_code == 0) {
480*4882a593Smuzhiyun 		return 0;
481*4882a593Smuzhiyun 	/*
482*4882a593Smuzhiyun 	 * This shouldn't ever happen. If it does it should be fixed on the
483*4882a593Smuzhiyun 	 * server.
484*4882a593Smuzhiyun 	 */
485*4882a593Smuzhiyun 	} else if (error_code > 0) {
486*4882a593Smuzhiyun 		gossip_err("orangefs: error status received.\n");
487*4882a593Smuzhiyun 		gossip_err("orangefs: assuming error code is inverted.\n");
488*4882a593Smuzhiyun 		error_code = -error_code;
489*4882a593Smuzhiyun 	}
490*4882a593Smuzhiyun 
491*4882a593Smuzhiyun 	/*
492*4882a593Smuzhiyun 	 * XXX: This is very bad since error codes from ORANGEFS may not be
493*4882a593Smuzhiyun 	 * suitable for return into userspace.
494*4882a593Smuzhiyun 	 */
495*4882a593Smuzhiyun 
496*4882a593Smuzhiyun 	/*
497*4882a593Smuzhiyun 	 * Convert ORANGEFS error values into errno values suitable for return
498*4882a593Smuzhiyun 	 * from the kernel.
499*4882a593Smuzhiyun 	 */
500*4882a593Smuzhiyun 	if ((-error_code) & ORANGEFS_NON_ERRNO_ERROR_BIT) {
501*4882a593Smuzhiyun 		if (((-error_code) &
502*4882a593Smuzhiyun 		    (ORANGEFS_ERROR_NUMBER_BITS|ORANGEFS_NON_ERRNO_ERROR_BIT|
503*4882a593Smuzhiyun 		    ORANGEFS_ERROR_BIT)) == ORANGEFS_ECANCEL) {
504*4882a593Smuzhiyun 			/*
505*4882a593Smuzhiyun 			 * cancellation error codes generally correspond to
506*4882a593Smuzhiyun 			 * a timeout from the client's perspective
507*4882a593Smuzhiyun 			 */
508*4882a593Smuzhiyun 			error_code = -ETIMEDOUT;
509*4882a593Smuzhiyun 		} else {
510*4882a593Smuzhiyun 			/* assume a default error code */
511*4882a593Smuzhiyun 			gossip_err("%s: bad error code :%d:.\n",
512*4882a593Smuzhiyun 				__func__,
513*4882a593Smuzhiyun 				error_code);
514*4882a593Smuzhiyun 			error_code = -EINVAL;
515*4882a593Smuzhiyun 		}
516*4882a593Smuzhiyun 
517*4882a593Smuzhiyun 	/* Convert ORANGEFS encoded errno values into regular errno values. */
518*4882a593Smuzhiyun 	} else if ((-error_code) & ORANGEFS_ERROR_BIT) {
519*4882a593Smuzhiyun 		i = (-error_code) & ~(ORANGEFS_ERROR_BIT|ORANGEFS_ERROR_CLASS_BITS);
520*4882a593Smuzhiyun 		if (i < ARRAY_SIZE(PINT_errno_mapping))
521*4882a593Smuzhiyun 			error_code = -PINT_errno_mapping[i];
522*4882a593Smuzhiyun 		else
523*4882a593Smuzhiyun 			error_code = -EINVAL;
524*4882a593Smuzhiyun 
525*4882a593Smuzhiyun 	/*
526*4882a593Smuzhiyun 	 * Only ORANGEFS protocol error codes should ever come here. Otherwise
527*4882a593Smuzhiyun 	 * there is a bug somewhere.
528*4882a593Smuzhiyun 	 */
529*4882a593Smuzhiyun 	} else {
530*4882a593Smuzhiyun 		gossip_err("%s: unknown error code.\n", __func__);
531*4882a593Smuzhiyun 		error_code = -EINVAL;
532*4882a593Smuzhiyun 	}
533*4882a593Smuzhiyun 	return error_code;
534*4882a593Smuzhiyun }
535*4882a593Smuzhiyun 
536*4882a593Smuzhiyun #define NUM_MODES 11
ORANGEFS_util_translate_mode(int mode)537*4882a593Smuzhiyun __s32 ORANGEFS_util_translate_mode(int mode)
538*4882a593Smuzhiyun {
539*4882a593Smuzhiyun 	int ret = 0;
540*4882a593Smuzhiyun 	int i = 0;
541*4882a593Smuzhiyun 	static int modes[NUM_MODES] = {
542*4882a593Smuzhiyun 		S_IXOTH, S_IWOTH, S_IROTH,
543*4882a593Smuzhiyun 		S_IXGRP, S_IWGRP, S_IRGRP,
544*4882a593Smuzhiyun 		S_IXUSR, S_IWUSR, S_IRUSR,
545*4882a593Smuzhiyun 		S_ISGID, S_ISUID
546*4882a593Smuzhiyun 	};
547*4882a593Smuzhiyun 	static int orangefs_modes[NUM_MODES] = {
548*4882a593Smuzhiyun 		ORANGEFS_O_EXECUTE, ORANGEFS_O_WRITE, ORANGEFS_O_READ,
549*4882a593Smuzhiyun 		ORANGEFS_G_EXECUTE, ORANGEFS_G_WRITE, ORANGEFS_G_READ,
550*4882a593Smuzhiyun 		ORANGEFS_U_EXECUTE, ORANGEFS_U_WRITE, ORANGEFS_U_READ,
551*4882a593Smuzhiyun 		ORANGEFS_G_SGID, ORANGEFS_U_SUID
552*4882a593Smuzhiyun 	};
553*4882a593Smuzhiyun 
554*4882a593Smuzhiyun 	for (i = 0; i < NUM_MODES; i++)
555*4882a593Smuzhiyun 		if (mode & modes[i])
556*4882a593Smuzhiyun 			ret |= orangefs_modes[i];
557*4882a593Smuzhiyun 
558*4882a593Smuzhiyun 	return ret;
559*4882a593Smuzhiyun }
560*4882a593Smuzhiyun #undef NUM_MODES
561