Linux Audio

Check our new training course

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