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