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.6
 
   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_MMAP_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(current_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(current_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 size)
 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	new_op = op_alloc(ORANGEFS_VFS_OP_GETATTR);
 265	if (!new_op)
 266		return -ENOMEM;
 267	new_op->upcall.req.getattr.refn = orangefs_inode->refn;
 268	new_op->upcall.req.getattr.mask = size ?
 269	    ORANGEFS_ATTR_SYS_ALL_NOHINT : ORANGEFS_ATTR_SYS_ALL_NOHINT_NOSIZE;
 
 
 
 
 
 
 
 270
 271	ret = service_operation(new_op, __func__,
 272	    get_interruptible_flag(inode));
 273	if (ret != 0)
 274		goto out;
 275
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 276	type = orangefs_inode_type(new_op->
 277	    downcall.resp.getattr.attributes.objtype);
 278	ret = orangefs_inode_is_stale(inode, new,
 279	    &new_op->downcall.resp.getattr.attributes,
 280	    new_op->downcall.resp.getattr.link_target);
 281	if (ret) {
 282		ret = -ESTALE;
 283		goto out;
 284	}
 285
 286	switch (type) {
 287	case S_IFREG:
 288		inode->i_flags = orangefs_inode_flags(&new_op->
 289		    downcall.resp.getattr.attributes);
 290		if (size) {
 291			inode_size = (loff_t)new_op->
 292			    downcall.resp.getattr.attributes.size;
 293			rounded_up_size =
 294			    (inode_size + (4096 - (inode_size % 4096)));
 295			inode->i_size = inode_size;
 296			orangefs_inode->blksize =
 297			    new_op->downcall.resp.getattr.attributes.blksize;
 298			spin_lock(&inode->i_lock);
 299			inode->i_bytes = inode_size;
 300			inode->i_blocks =
 301			    (unsigned long)(rounded_up_size / 512);
 302			spin_unlock(&inode->i_lock);
 303		}
 304		break;
 305	case S_IFDIR:
 306		inode->i_size = PAGE_SIZE;
 307		orangefs_inode->blksize = (1 << inode->i_blkbits);
 308		spin_lock(&inode->i_lock);
 309		inode_set_bytes(inode, inode->i_size);
 310		spin_unlock(&inode->i_lock);
 311		set_nlink(inode, 1);
 312		break;
 313	case S_IFLNK:
 314		if (new) {
 315			inode->i_size = (loff_t)strlen(new_op->
 316			    downcall.resp.getattr.link_target);
 317			orangefs_inode->blksize = (1 << inode->i_blkbits);
 318			ret = strscpy(orangefs_inode->link_target,
 319			    new_op->downcall.resp.getattr.link_target,
 320			    ORANGEFS_NAME_MAX);
 321			if (ret == -E2BIG) {
 322				ret = -EIO;
 323				goto out;
 324			}
 325			inode->i_link = orangefs_inode->link_target;
 326		}
 327		break;
 
 
 
 
 
 
 328	}
 329
 330	inode->i_uid = make_kuid(&init_user_ns, new_op->
 331	    downcall.resp.getattr.attributes.owner);
 332	inode->i_gid = make_kgid(&init_user_ns, new_op->
 333	    downcall.resp.getattr.attributes.group);
 334	inode->i_atime.tv_sec = (time64_t)new_op->
 335	    downcall.resp.getattr.attributes.atime;
 336	inode->i_mtime.tv_sec = (time64_t)new_op->
 337	    downcall.resp.getattr.attributes.mtime;
 338	inode->i_ctime.tv_sec = (time64_t)new_op->
 339	    downcall.resp.getattr.attributes.ctime;
 340	inode->i_atime.tv_nsec = 0;
 341	inode->i_mtime.tv_nsec = 0;
 342	inode->i_ctime.tv_nsec = 0;
 343
 344	/* special case: mark the root inode as sticky */
 345	inode->i_mode = type | (is_root_handle(inode) ? S_ISVTX : 0) |
 346	    orangefs_inode_perms(&new_op->downcall.resp.getattr.attributes);
 347
 
 
 348	ret = 0;
 
 
 349out:
 350	op_release(new_op);
 351	return ret;
 352}
 353
 354int orangefs_inode_check_changed(struct inode *inode)
 355{
 356	struct orangefs_inode_s *orangefs_inode = ORANGEFS_I(inode);
 357	struct orangefs_kernel_op_s *new_op;
 358	int ret;
 359
 360	gossip_debug(GOSSIP_UTILS_DEBUG, "%s: called on inode %pU\n", __func__,
 361	    get_khandle_from_ino(inode));
 362
 363	new_op = op_alloc(ORANGEFS_VFS_OP_GETATTR);
 364	if (!new_op)
 365		return -ENOMEM;
 366	new_op->upcall.req.getattr.refn = orangefs_inode->refn;
 367	new_op->upcall.req.getattr.mask = ORANGEFS_ATTR_SYS_TYPE |
 368	    ORANGEFS_ATTR_SYS_LNK_TARGET;
 369
 370	ret = service_operation(new_op, __func__,
 371	    get_interruptible_flag(inode));
 372	if (ret != 0)
 373		goto out;
 374
 375	ret = orangefs_inode_is_stale(inode, 0,
 376	    &new_op->downcall.resp.getattr.attributes,
 377	    new_op->downcall.resp.getattr.link_target);
 378out:
 379	op_release(new_op);
 380	return ret;
 381}
 382
 383/*
 384 * issues a orangefs setattr request to make sure the new attribute values
 385 * take effect if successful.  returns 0 on success; -errno otherwise
 386 */
 387int orangefs_inode_setattr(struct inode *inode, struct iattr *iattr)
 388{
 389	struct orangefs_inode_s *orangefs_inode = ORANGEFS_I(inode);
 390	struct orangefs_kernel_op_s *new_op;
 391	int ret;
 392
 393	new_op = op_alloc(ORANGEFS_VFS_OP_SETATTR);
 394	if (!new_op)
 395		return -ENOMEM;
 396
 
 
 
 397	new_op->upcall.req.setattr.refn = orangefs_inode->refn;
 398	ret = copy_attributes_from_inode(inode,
 399		       &new_op->upcall.req.setattr.attributes,
 400		       iattr);
 401	if (ret >= 0) {
 402		ret = service_operation(new_op, __func__,
 403				get_interruptible_flag(inode));
 404
 405		gossip_debug(GOSSIP_UTILS_DEBUG,
 406			     "orangefs_inode_setattr: returning %d\n",
 407			     ret);
 408	}
 409
 410	op_release(new_op);
 411
 412	/*
 413	 * successful setattr should clear the atime, mtime and
 414	 * ctime flags.
 415	 */
 416	if (ret == 0) {
 417		ClearAtimeFlag(orangefs_inode);
 418		ClearMtimeFlag(orangefs_inode);
 419		ClearCtimeFlag(orangefs_inode);
 420		ClearModeFlag(orangefs_inode);
 421	}
 422
 423	return ret;
 424}
 425
 426int orangefs_flush_inode(struct inode *inode)
 427{
 428	/*
 429	 * If it is a dirty inode, this function gets called.
 430	 * Gather all the information that needs to be setattr'ed
 431	 * Right now, this will only be used for mode, atime, mtime
 432	 * and/or ctime.
 433	 */
 434	struct iattr wbattr;
 435	int ret;
 436	int mtime_flag;
 437	int ctime_flag;
 438	int atime_flag;
 439	int mode_flag;
 440	struct orangefs_inode_s *orangefs_inode = ORANGEFS_I(inode);
 441
 442	memset(&wbattr, 0, sizeof(wbattr));
 443
 444	/*
 445	 * check inode flags up front, and clear them if they are set.  This
 446	 * will prevent multiple processes from all trying to flush the same
 447	 * inode if they call close() simultaneously
 448	 */
 449	mtime_flag = MtimeFlag(orangefs_inode);
 450	ClearMtimeFlag(orangefs_inode);
 451	ctime_flag = CtimeFlag(orangefs_inode);
 452	ClearCtimeFlag(orangefs_inode);
 453	atime_flag = AtimeFlag(orangefs_inode);
 454	ClearAtimeFlag(orangefs_inode);
 455	mode_flag = ModeFlag(orangefs_inode);
 456	ClearModeFlag(orangefs_inode);
 457
 458	/*  -- Lazy atime,mtime and ctime update --
 459	 * Note: all times are dictated by server in the new scheme
 460	 * and not by the clients
 461	 *
 462	 * Also mode updates are being handled now..
 463	 */
 464
 465	if (mtime_flag)
 466		wbattr.ia_valid |= ATTR_MTIME;
 467	if (ctime_flag)
 468		wbattr.ia_valid |= ATTR_CTIME;
 469	if (atime_flag)
 470		wbattr.ia_valid |= ATTR_ATIME;
 471
 472	if (mode_flag) {
 473		wbattr.ia_mode = inode->i_mode;
 474		wbattr.ia_valid |= ATTR_MODE;
 475	}
 476
 477	gossip_debug(GOSSIP_UTILS_DEBUG,
 478		     "*********** orangefs_flush_inode: %pU "
 479		     "(ia_valid %d)\n",
 480		     get_khandle_from_ino(inode),
 481		     wbattr.ia_valid);
 482	if (wbattr.ia_valid == 0) {
 483		gossip_debug(GOSSIP_UTILS_DEBUG,
 484			     "orangefs_flush_inode skipping setattr()\n");
 485		return 0;
 486	}
 
 487
 
 
 488	gossip_debug(GOSSIP_UTILS_DEBUG,
 489		     "orangefs_flush_inode (%pU) writing mode %o\n",
 490		     get_khandle_from_ino(inode),
 491		     inode->i_mode);
 492
 493	ret = orangefs_inode_setattr(inode, &wbattr);
 494
 495	return ret;
 496}
 497
 498int orangefs_unmount_sb(struct super_block *sb)
 499{
 500	int ret = -EINVAL;
 501	struct orangefs_kernel_op_s *new_op = NULL;
 502
 503	gossip_debug(GOSSIP_UTILS_DEBUG,
 504		     "orangefs_unmount_sb called on sb %p\n",
 505		     sb);
 506
 507	new_op = op_alloc(ORANGEFS_VFS_OP_FS_UMOUNT);
 508	if (!new_op)
 509		return -ENOMEM;
 510	new_op->upcall.req.fs_umount.id = ORANGEFS_SB(sb)->id;
 511	new_op->upcall.req.fs_umount.fs_id = ORANGEFS_SB(sb)->fs_id;
 512	strncpy(new_op->upcall.req.fs_umount.orangefs_config_server,
 513		ORANGEFS_SB(sb)->devname,
 514		ORANGEFS_MAX_SERVER_ADDR_LEN);
 515
 516	gossip_debug(GOSSIP_UTILS_DEBUG,
 517		     "Attempting ORANGEFS Unmount via host %s\n",
 518		     new_op->upcall.req.fs_umount.orangefs_config_server);
 519
 520	ret = service_operation(new_op, "orangefs_fs_umount", 0);
 521
 522	gossip_debug(GOSSIP_UTILS_DEBUG,
 523		     "orangefs_unmount: got return value of %d\n", ret);
 524	if (ret)
 525		sb = ERR_PTR(ret);
 526	else
 527		ORANGEFS_SB(sb)->mount_pending = 1;
 528
 529	op_release(new_op);
 
 
 
 530	return ret;
 531}
 532
 533void orangefs_make_bad_inode(struct inode *inode)
 534{
 535	if (is_root_handle(inode)) {
 536		/*
 537		 * if this occurs, the pvfs2-client-core was killed but we
 538		 * can't afford to lose the inode operations and such
 539		 * associated with the root handle in any case.
 540		 */
 541		gossip_debug(GOSSIP_UTILS_DEBUG,
 542			     "*** NOT making bad root inode %pU\n",
 543			     get_khandle_from_ino(inode));
 544	} else {
 545		gossip_debug(GOSSIP_UTILS_DEBUG,
 546			     "*** making bad inode %pU\n",
 547			     get_khandle_from_ino(inode));
 548		make_bad_inode(inode);
 549	}
 550}
 551
 552/*
 553 * The following is a very dirty hack that is now a permanent part of the
 554 * ORANGEFS protocol. See protocol.h for more error definitions.
 555 */
 556
 557/* The order matches include/orangefs-types.h in the OrangeFS source. */
 558static int PINT_errno_mapping[] = {
 559	0, EPERM, ENOENT, EINTR, EIO, ENXIO, EBADF, EAGAIN, ENOMEM,
 560	EFAULT, EBUSY, EEXIST, ENODEV, ENOTDIR, EISDIR, EINVAL, EMFILE,
 561	EFBIG, ENOSPC, EROFS, EMLINK, EPIPE, EDEADLK, ENAMETOOLONG,
 562	ENOLCK, ENOSYS, ENOTEMPTY, ELOOP, EWOULDBLOCK, ENOMSG, EUNATCH,
 563	EBADR, EDEADLOCK, ENODATA, ETIME, ENONET, EREMOTE, ECOMM,
 564	EPROTO, EBADMSG, EOVERFLOW, ERESTART, EMSGSIZE, EPROTOTYPE,
 565	ENOPROTOOPT, EPROTONOSUPPORT, EOPNOTSUPP, EADDRINUSE,
 566	EADDRNOTAVAIL, ENETDOWN, ENETUNREACH, ENETRESET, ENOBUFS,
 567	ETIMEDOUT, ECONNREFUSED, EHOSTDOWN, EHOSTUNREACH, EALREADY,
 568	EACCES, ECONNRESET, ERANGE
 569};
 570
 571int orangefs_normalize_to_errno(__s32 error_code)
 572{
 573	__u32 i;
 574
 575	/* Success */
 576	if (error_code == 0) {
 577		return 0;
 578	/*
 579	 * This shouldn't ever happen. If it does it should be fixed on the
 580	 * server.
 581	 */
 582	} else if (error_code > 0) {
 583		gossip_err("orangefs: error status receieved.\n");
 584		gossip_err("orangefs: assuming error code is inverted.\n");
 585		error_code = -error_code;
 586	}
 587
 588	/*
 589	 * XXX: This is very bad since error codes from ORANGEFS may not be
 590	 * suitable for return into userspace.
 591	 */
 592
 593	/*
 594	 * Convert ORANGEFS error values into errno values suitable for return
 595	 * from the kernel.
 596	 */
 597	if ((-error_code) & ORANGEFS_NON_ERRNO_ERROR_BIT) {
 598		if (((-error_code) &
 599		    (ORANGEFS_ERROR_NUMBER_BITS|ORANGEFS_NON_ERRNO_ERROR_BIT|
 600		    ORANGEFS_ERROR_BIT)) == ORANGEFS_ECANCEL) {
 601			/*
 602			 * cancellation error codes generally correspond to
 603			 * a timeout from the client's perspective
 604			 */
 605			error_code = -ETIMEDOUT;
 606		} else {
 607			/* assume a default error code */
 608			gossip_err("orangefs: warning: got error code without errno equivalent: %d.\n", error_code);
 
 
 609			error_code = -EINVAL;
 610		}
 611
 612	/* Convert ORANGEFS encoded errno values into regular errno values. */
 613	} else if ((-error_code) & ORANGEFS_ERROR_BIT) {
 614		i = (-error_code) & ~(ORANGEFS_ERROR_BIT|ORANGEFS_ERROR_CLASS_BITS);
 615		if (i < sizeof(PINT_errno_mapping)/sizeof(*PINT_errno_mapping))
 616			error_code = -PINT_errno_mapping[i];
 617		else
 618			error_code = -EINVAL;
 619
 620	/*
 621	 * Only ORANGEFS protocol error codes should ever come here. Otherwise
 622	 * there is a bug somewhere.
 623	 */
 624	} else {
 625		gossip_err("orangefs: orangefs_normalize_to_errno: got error code which is not from ORANGEFS.\n");
 
 626	}
 627	return error_code;
 628}
 629
 630#define NUM_MODES 11
 631__s32 ORANGEFS_util_translate_mode(int mode)
 632{
 633	int ret = 0;
 634	int i = 0;
 635	static int modes[NUM_MODES] = {
 636		S_IXOTH, S_IWOTH, S_IROTH,
 637		S_IXGRP, S_IWGRP, S_IRGRP,
 638		S_IXUSR, S_IWUSR, S_IRUSR,
 639		S_ISGID, S_ISUID
 640	};
 641	static int orangefs_modes[NUM_MODES] = {
 642		ORANGEFS_O_EXECUTE, ORANGEFS_O_WRITE, ORANGEFS_O_READ,
 643		ORANGEFS_G_EXECUTE, ORANGEFS_G_WRITE, ORANGEFS_G_READ,
 644		ORANGEFS_U_EXECUTE, ORANGEFS_U_WRITE, ORANGEFS_U_READ,
 645		ORANGEFS_G_SGID, ORANGEFS_U_SUID
 646	};
 647
 648	for (i = 0; i < NUM_MODES; i++)
 649		if (mode & modes[i])
 650			ret |= orangefs_modes[i];
 651
 652	return ret;
 653}
 654#undef NUM_MODES
 655
 656/*
 657 * After obtaining a string representation of the client's debug
 658 * keywords and their associated masks, this function is called to build an
 659 * array of these values.
 660 */
 661int orangefs_prepare_cdm_array(char *debug_array_string)
 662{
 663	int i;
 664	int rc = -EINVAL;
 665	char *cds_head = NULL;
 666	char *cds_delimiter = NULL;
 667	int keyword_len = 0;
 668
 669	gossip_debug(GOSSIP_UTILS_DEBUG, "%s: start\n", __func__);
 670
 671	/*
 672	 * figure out how many elements the cdm_array needs.
 673	 */
 674	for (i = 0; i < strlen(debug_array_string); i++)
 675		if (debug_array_string[i] == '\n')
 676			cdm_element_count++;
 677
 678	if (!cdm_element_count) {
 679		pr_info("No elements in client debug array string!\n");
 680		goto out;
 681	}
 682
 683	cdm_array =
 684		kzalloc(cdm_element_count * sizeof(struct client_debug_mask),
 685			GFP_KERNEL);
 686	if (!cdm_array) {
 687		pr_info("malloc failed for cdm_array!\n");
 688		rc = -ENOMEM;
 689		goto out;
 690	}
 691
 692	cds_head = debug_array_string;
 693
 694	for (i = 0; i < cdm_element_count; i++) {
 695		cds_delimiter = strchr(cds_head, '\n');
 696		*cds_delimiter = '\0';
 697
 698		keyword_len = strcspn(cds_head, " ");
 699
 700		cdm_array[i].keyword = kzalloc(keyword_len + 1, GFP_KERNEL);
 701		if (!cdm_array[i].keyword) {
 702			rc = -ENOMEM;
 703			goto out;
 704		}
 705
 706		sscanf(cds_head,
 707		       "%s %llx %llx",
 708		       cdm_array[i].keyword,
 709		       (unsigned long long *)&(cdm_array[i].mask1),
 710		       (unsigned long long *)&(cdm_array[i].mask2));
 711
 712		if (!strcmp(cdm_array[i].keyword, ORANGEFS_VERBOSE))
 713			client_verbose_index = i;
 714
 715		if (!strcmp(cdm_array[i].keyword, ORANGEFS_ALL))
 716			client_all_index = i;
 717
 718		cds_head = cds_delimiter + 1;
 719	}
 720
 721	rc = cdm_element_count;
 722
 723	gossip_debug(GOSSIP_UTILS_DEBUG, "%s: rc:%d:\n", __func__, rc);
 724
 725out:
 726
 727	return rc;
 728
 729}
 730
 731/*
 732 * /sys/kernel/debug/orangefs/debug-help can be catted to
 733 * see all the available kernel and client debug keywords.
 734 *
 735 * When the kernel boots, we have no idea what keywords the
 736 * client supports, nor their associated masks.
 737 *
 738 * We pass through this function once at boot and stamp a
 739 * boilerplate "we don't know" message for the client in the
 740 * debug-help file. We pass through here again when the client
 741 * starts and then we can fill out the debug-help file fully.
 742 *
 743 * The client might be restarted any number of times between
 744 * reboots, we only build the debug-help file the first time.
 745 */
 746int orangefs_prepare_debugfs_help_string(int at_boot)
 747{
 748	int rc = -EINVAL;
 749	int i;
 750	int byte_count = 0;
 751	char *client_title = "Client Debug Keywords:\n";
 752	char *kernel_title = "Kernel Debug Keywords:\n";
 753
 754	gossip_debug(GOSSIP_UTILS_DEBUG, "%s: start\n", __func__);
 755
 756	if (at_boot) {
 757		byte_count += strlen(HELP_STRING_UNINITIALIZED);
 758		client_title = HELP_STRING_UNINITIALIZED;
 759	} else {
 760		/*
 761		 * fill the client keyword/mask array and remember
 762		 * how many elements there were.
 763		 */
 764		cdm_element_count =
 765			orangefs_prepare_cdm_array(client_debug_array_string);
 766		if (cdm_element_count <= 0)
 767			goto out;
 768
 769		/* Count the bytes destined for debug_help_string. */
 770		byte_count += strlen(client_title);
 771
 772		for (i = 0; i < cdm_element_count; i++) {
 773			byte_count += strlen(cdm_array[i].keyword + 2);
 774			if (byte_count >= DEBUG_HELP_STRING_SIZE) {
 775				pr_info("%s: overflow 1!\n", __func__);
 776				goto out;
 777			}
 778		}
 779
 780		gossip_debug(GOSSIP_UTILS_DEBUG,
 781			     "%s: cdm_element_count:%d:\n",
 782			     __func__,
 783			     cdm_element_count);
 784	}
 785
 786	byte_count += strlen(kernel_title);
 787	for (i = 0; i < num_kmod_keyword_mask_map; i++) {
 788		byte_count +=
 789			strlen(s_kmod_keyword_mask_map[i].keyword + 2);
 790		if (byte_count >= DEBUG_HELP_STRING_SIZE) {
 791			pr_info("%s: overflow 2!\n", __func__);
 792			goto out;
 793		}
 794	}
 795
 796	/* build debug_help_string. */
 797	debug_help_string = kzalloc(DEBUG_HELP_STRING_SIZE, GFP_KERNEL);
 798	if (!debug_help_string) {
 799		rc = -ENOMEM;
 800		goto out;
 801	}
 802
 803	strcat(debug_help_string, client_title);
 804
 805	if (!at_boot) {
 806		for (i = 0; i < cdm_element_count; i++) {
 807			strcat(debug_help_string, "\t");
 808			strcat(debug_help_string, cdm_array[i].keyword);
 809			strcat(debug_help_string, "\n");
 810		}
 811	}
 812
 813	strcat(debug_help_string, "\n");
 814	strcat(debug_help_string, kernel_title);
 815
 816	for (i = 0; i < num_kmod_keyword_mask_map; i++) {
 817		strcat(debug_help_string, "\t");
 818		strcat(debug_help_string, s_kmod_keyword_mask_map[i].keyword);
 819		strcat(debug_help_string, "\n");
 820	}
 821
 822	rc = 0;
 823
 824out:
 825
 826	return rc;
 827
 828}
 829
 830/*
 831 * kernel = type 0
 832 * client = type 1
 833 */
 834void debug_mask_to_string(void *mask, int type)
 835{
 836	int i;
 837	int len = 0;
 838	char *debug_string;
 839	int element_count = 0;
 840
 841	gossip_debug(GOSSIP_UTILS_DEBUG, "%s: start\n", __func__);
 842
 843	if (type) {
 844		debug_string = client_debug_string;
 845		element_count = cdm_element_count;
 846	} else {
 847		debug_string = kernel_debug_string;
 848		element_count = num_kmod_keyword_mask_map;
 849	}
 850
 851	memset(debug_string, 0, ORANGEFS_MAX_DEBUG_STRING_LEN);
 852
 853	/*
 854	 * Some keywords, like "all" or "verbose", are amalgams of
 855	 * numerous other keywords. Make a special check for those
 856	 * before grinding through the whole mask only to find out
 857	 * later...
 858	 */
 859	if (check_amalgam_keyword(mask, type))
 860		goto out;
 861
 862	/* Build the debug string. */
 863	for (i = 0; i < element_count; i++)
 864		if (type)
 865			do_c_string(mask, i);
 866		else
 867			do_k_string(mask, i);
 868
 869	len = strlen(debug_string);
 870
 871	if ((len) && (type))
 872		client_debug_string[len - 1] = '\0';
 873	else if (len)
 874		kernel_debug_string[len - 1] = '\0';
 875	else if (type)
 876		strcpy(client_debug_string, "none");
 877	else
 878		strcpy(kernel_debug_string, "none");
 879
 880out:
 881gossip_debug(GOSSIP_UTILS_DEBUG, "%s: string:%s:\n", __func__, debug_string);
 882
 883	return;
 884
 885}
 886
 887void do_k_string(void *k_mask, int index)
 888{
 889	__u64 *mask = (__u64 *) k_mask;
 890
 891	if (keyword_is_amalgam((char *) s_kmod_keyword_mask_map[index].keyword))
 892		goto out;
 893
 894	if (*mask & s_kmod_keyword_mask_map[index].mask_val) {
 895		if ((strlen(kernel_debug_string) +
 896		     strlen(s_kmod_keyword_mask_map[index].keyword))
 897			< ORANGEFS_MAX_DEBUG_STRING_LEN - 1) {
 898				strcat(kernel_debug_string,
 899				       s_kmod_keyword_mask_map[index].keyword);
 900				strcat(kernel_debug_string, ",");
 901			} else {
 902				gossip_err("%s: overflow!\n", __func__);
 903				strcpy(kernel_debug_string, ORANGEFS_ALL);
 904				goto out;
 905			}
 906	}
 907
 908out:
 909
 910	return;
 911}
 912
 913void do_c_string(void *c_mask, int index)
 914{
 915	struct client_debug_mask *mask = (struct client_debug_mask *) c_mask;
 916
 917	if (keyword_is_amalgam(cdm_array[index].keyword))
 918		goto out;
 919
 920	if ((mask->mask1 & cdm_array[index].mask1) ||
 921	    (mask->mask2 & cdm_array[index].mask2)) {
 922		if ((strlen(client_debug_string) +
 923		     strlen(cdm_array[index].keyword) + 1)
 924			< ORANGEFS_MAX_DEBUG_STRING_LEN - 2) {
 925				strcat(client_debug_string,
 926				       cdm_array[index].keyword);
 927				strcat(client_debug_string, ",");
 928			} else {
 929				gossip_err("%s: overflow!\n", __func__);
 930				strcpy(client_debug_string, ORANGEFS_ALL);
 931				goto out;
 932			}
 933	}
 934out:
 935	return;
 936}
 937
 938int keyword_is_amalgam(char *keyword)
 939{
 940	int rc = 0;
 941
 942	if ((!strcmp(keyword, ORANGEFS_ALL)) || (!strcmp(keyword, ORANGEFS_VERBOSE)))
 943		rc = 1;
 944
 945	return rc;
 946}
 947
 948/*
 949 * kernel = type 0
 950 * client = type 1
 951 *
 952 * return 1 if we found an amalgam.
 953 */
 954int check_amalgam_keyword(void *mask, int type)
 955{
 956	__u64 *k_mask;
 957	struct client_debug_mask *c_mask;
 958	int k_all_index = num_kmod_keyword_mask_map - 1;
 959	int rc = 0;
 960
 961	if (type) {
 962		c_mask = (struct client_debug_mask *) mask;
 963
 964		if ((c_mask->mask1 == cdm_array[client_all_index].mask1) &&
 965		    (c_mask->mask2 == cdm_array[client_all_index].mask2)) {
 966			strcpy(client_debug_string, ORANGEFS_ALL);
 967			rc = 1;
 968			goto out;
 969		}
 970
 971		if ((c_mask->mask1 == cdm_array[client_verbose_index].mask1) &&
 972		    (c_mask->mask2 == cdm_array[client_verbose_index].mask2)) {
 973			strcpy(client_debug_string, ORANGEFS_VERBOSE);
 974			rc = 1;
 975			goto out;
 976		}
 977
 978	} else {
 979		k_mask = (__u64 *) mask;
 980
 981		if (*k_mask >= s_kmod_keyword_mask_map[k_all_index].mask_val) {
 982			strcpy(kernel_debug_string, ORANGEFS_ALL);
 983			rc = 1;
 984			goto out;
 985		}
 986	}
 987
 988out:
 989
 990	return rc;
 991}
 992
 993/*
 994 * kernel = type 0
 995 * client = type 1
 996 */
 997void debug_string_to_mask(char *debug_string, void *mask, int type)
 998{
 999	char *unchecked_keyword;
1000	int i;
1001	char *strsep_fodder = kstrdup(debug_string, GFP_KERNEL);
1002	char *original_pointer;
1003	int element_count = 0;
1004	struct client_debug_mask *c_mask;
1005	__u64 *k_mask;
1006
1007	gossip_debug(GOSSIP_UTILS_DEBUG, "%s: start\n", __func__);
1008
1009	if (type) {
1010		c_mask = (struct client_debug_mask *)mask;
1011		element_count = cdm_element_count;
1012	} else {
1013		k_mask = (__u64 *)mask;
1014		*k_mask = 0;
1015		element_count = num_kmod_keyword_mask_map;
1016	}
1017
1018	original_pointer = strsep_fodder;
1019	while ((unchecked_keyword = strsep(&strsep_fodder, ",")))
1020		if (strlen(unchecked_keyword)) {
1021			for (i = 0; i < element_count; i++)
1022				if (type)
1023					do_c_mask(i,
1024						  unchecked_keyword,
1025						  &c_mask);
1026				else
1027					do_k_mask(i,
1028						  unchecked_keyword,
1029						  &k_mask);
1030		}
1031
1032	kfree(original_pointer);
1033}
1034
1035void do_c_mask(int i,
1036	       char *unchecked_keyword,
1037	       struct client_debug_mask **sane_mask)
1038{
1039
1040	if (!strcmp(cdm_array[i].keyword, unchecked_keyword)) {
1041		(**sane_mask).mask1 = (**sane_mask).mask1 | cdm_array[i].mask1;
1042		(**sane_mask).mask2 = (**sane_mask).mask2 | cdm_array[i].mask2;
1043	}
1044}
1045
1046void do_k_mask(int i, char *unchecked_keyword, __u64 **sane_mask)
1047{
1048
1049	if (!strcmp(s_kmod_keyword_mask_map[i].keyword, unchecked_keyword))
1050		**sane_mask = (**sane_mask) |
1051				s_kmod_keyword_mask_map[i].mask_val;
1052}