diff options
-rw-r--r-- | fs/orangefs/protocol.h | 286 | ||||
-rw-r--r-- | fs/orangefs/pvfs2-utils.c | 58 |
2 files changed, 80 insertions, 264 deletions
diff --git a/fs/orangefs/protocol.h b/fs/orangefs/protocol.h index cdbde64..b374c4b 100644 --- a/fs/orangefs/protocol.h +++ b/fs/orangefs/protocol.h @@ -100,262 +100,40 @@ typedef __s32 PVFS_error; typedef __s64 PVFS_offset; #define PVFS2_SUPER_MAGIC 0x20030528 -#define PVFS_ERROR_BIT (1 << 30) -#define PVFS_NON_ERRNO_ERROR_BIT (1 << 29) -#define IS_PVFS_ERROR(__error) ((__error)&(PVFS_ERROR_BIT)) -#define IS_PVFS_NON_ERRNO_ERROR(__error) \ -(((__error)&(PVFS_NON_ERRNO_ERROR_BIT)) && IS_PVFS_ERROR(__error)) -#define PVFS_ERROR_TO_ERRNO(__error) PVFS_get_errno_mapping(__error) - -/* 7 bits are used for the errno mapped error codes */ -#define PVFS_ERROR_CODE(__error) \ -((__error) & (__s32)(0x7f|PVFS_ERROR_BIT)) -#define PVFS_ERROR_CLASS(__error) \ -((__error) & ~((__s32)(0x7f|PVFS_ERROR_BIT|PVFS_NON_ERRNO_ERROR_BIT))) -#define PVFS_NON_ERRNO_ERROR_CODE(__error) \ -((__error) & (__s32)(127|PVFS_ERROR_BIT|PVFS_NON_ERRNO_ERROR_BIT)) - -/* PVFS2 error codes, compliments of asm/errno.h */ -#define PVFS_EPERM E(1) /* Operation not permitted */ -#define PVFS_ENOENT E(2) /* No such file or directory */ -#define PVFS_EINTR E(3) /* Interrupted system call */ -#define PVFS_EIO E(4) /* I/O error */ -#define PVFS_ENXIO E(5) /* No such device or address */ -#define PVFS_EBADF E(6) /* Bad file number */ -#define PVFS_EAGAIN E(7) /* Try again */ -#define PVFS_ENOMEM E(8) /* Out of memory */ -#define PVFS_EFAULT E(9) /* Bad address */ -#define PVFS_EBUSY E(10) /* Device or resource busy */ -#define PVFS_EEXIST E(11) /* File exists */ -#define PVFS_ENODEV E(12) /* No such device */ -#define PVFS_ENOTDIR E(13) /* Not a directory */ -#define PVFS_EISDIR E(14) /* Is a directory */ -#define PVFS_EINVAL E(15) /* Invalid argument */ -#define PVFS_EMFILE E(16) /* Too many open files */ -#define PVFS_EFBIG E(17) /* File too large */ -#define PVFS_ENOSPC E(18) /* No space left on device */ -#define PVFS_EROFS E(19) /* Read-only file system */ -#define PVFS_EMLINK E(20) /* Too many links */ -#define PVFS_EPIPE E(21) /* Broken pipe */ -#define PVFS_EDEADLK E(22) /* Resource deadlock would occur */ -#define PVFS_ENAMETOOLONG E(23) /* File name too long */ -#define PVFS_ENOLCK E(24) /* No record locks available */ -#define PVFS_ENOSYS E(25) /* Function not implemented */ -#define PVFS_ENOTEMPTY E(26) /* Directory not empty */ - /* -#define PVFS_ELOOP E(27) * Too many symbolic links encountered - */ -#define PVFS_EWOULDBLOCK E(28) /* Operation would block */ -#define PVFS_ENOMSG E(29) /* No message of desired type */ -#define PVFS_EUNATCH E(30) /* Protocol driver not attached */ -#define PVFS_EBADR E(31) /* Invalid request descriptor */ -#define PVFS_EDEADLOCK E(32) -#define PVFS_ENODATA E(33) /* No data available */ -#define PVFS_ETIME E(34) /* Timer expired */ -#define PVFS_ENONET E(35) /* Machine is not on the network */ -#define PVFS_EREMOTE E(36) /* Object is remote */ -#define PVFS_ECOMM E(37) /* Communication error on send */ -#define PVFS_EPROTO E(38) /* Protocol error */ -#define PVFS_EBADMSG E(39) /* Not a data message */ - /* -#define PVFS_EOVERFLOW E(40) * Value too large for defined data - * type - */ - /* -#define PVFS_ERESTART E(41) * Interrupted system call should be - * restarted - */ -#define PVFS_EMSGSIZE E(42) /* Message too long */ -#define PVFS_EPROTOTYPE E(43) /* Protocol wrong type for socket */ -#define PVFS_ENOPROTOOPT E(44) /* Protocol not available */ -#define PVFS_EPROTONOSUPPORT E(45) /* Protocol not supported */ - /* -#define PVFS_EOPNOTSUPP E(46) * Operation not supported on transport - * endpoint - */ -#define PVFS_EADDRINUSE E(47) /* Address already in use */ -#define PVFS_EADDRNOTAVAIL E(48) /* Cannot assign requested address */ -#define PVFS_ENETDOWN E(49) /* Network is down */ -#define PVFS_ENETUNREACH E(50) /* Network is unreachable */ - /* -#define PVFS_ENETRESET E(51) * Network dropped connection because - * of reset - */ -#define PVFS_ENOBUFS E(52) /* No buffer space available */ -#define PVFS_ETIMEDOUT E(53) /* Connection timed out */ -#define PVFS_ECONNREFUSED E(54) /* Connection refused */ -#define PVFS_EHOSTDOWN E(55) /* Host is down */ -#define PVFS_EHOSTUNREACH E(56) /* No route to host */ -#define PVFS_EALREADY E(57) /* Operation already in progress */ -#define PVFS_EACCES E(58) /* Access not allowed */ -#define PVFS_ECONNRESET E(59) /* Connection reset by peer */ -#define PVFS_ERANGE E(60) /* Math out of range or buf too small */ - -/***************** non-errno/pvfs2 specific error codes *****************/ -#define PVFS_ECANCEL (1|(PVFS_NON_ERRNO_ERROR_BIT|PVFS_ERROR_BIT)) -#define PVFS_EDEVINIT (2|(PVFS_NON_ERRNO_ERROR_BIT|PVFS_ERROR_BIT)) -#define PVFS_EDETAIL (3|(PVFS_NON_ERRNO_ERROR_BIT|PVFS_ERROR_BIT)) -#define PVFS_EHOSTNTFD (4|(PVFS_NON_ERRNO_ERROR_BIT|PVFS_ERROR_BIT)) -#define PVFS_EADDRNTFD (5|(PVFS_NON_ERRNO_ERROR_BIT|PVFS_ERROR_BIT)) -#define PVFS_ENORECVR (6|(PVFS_NON_ERRNO_ERROR_BIT|PVFS_ERROR_BIT)) -#define PVFS_ETRYAGAIN (7|(PVFS_NON_ERRNO_ERROR_BIT|PVFS_ERROR_BIT)) -#define PVFS_ENOTPVFS (8|(PVFS_NON_ERRNO_ERROR_BIT|PVFS_ERROR_BIT)) -#define PVFS_ESECURITY (9|(PVFS_NON_ERRNO_ERROR_BIT|PVFS_ERROR_BIT)) -/* - * NOTE: PLEASE DO NOT ARBITRARILY ADD NEW ERRNO ERROR CODES! - * - * IF YOU CHOOSE TO ADD A NEW ERROR CODE (DESPITE OUR PLEA), YOU ALSO - * NEED TO INCREMENT PVFS_ERRNO MAX (BELOW) AND ADD A MAPPING TO A - * UNIX ERRNO VALUE IN THE MACROS BELOW (USED IN - * src/common/misc/errno-mapping.c and the kernel module) - */ -#define PVFS_ERRNO_MAX 61 - -#define PVFS_ERROR_BMI (1 << 7) /* BMI-specific error */ -#define PVFS_ERROR_TROVE (2 << 7) /* Trove-specific error */ -#define PVFS_ERROR_FLOW (3 << 7) -#define PVFS_ERROR_SM (4 << 7) /* state machine specific error */ -#define PVFS_ERROR_SCHED (5 << 7) -#define PVFS_ERROR_CLIENT (6 << 7) -#define PVFS_ERROR_DEV (7 << 7) /* device file interaction */ - -#define PVFS_ERROR_CLASS_BITS \ - (PVFS_ERROR_BMI | \ - PVFS_ERROR_TROVE | \ - PVFS_ERROR_FLOW | \ - PVFS_ERROR_SM | \ - PVFS_ERROR_SCHED | \ - PVFS_ERROR_CLIENT | \ - PVFS_ERROR_DEV) - -#define DECLARE_ERRNO_MAPPING() \ -__s32 PINT_errno_mapping[PVFS_ERRNO_MAX + 1] = { \ - 0, /* leave this one empty */ \ - EPERM, /* 1 */ \ - ENOENT, \ - EINTR, \ - EIO, \ - ENXIO, \ - EBADF, \ - EAGAIN, \ - ENOMEM, \ - EFAULT, \ - EBUSY, /* 10 */ \ - EEXIST, \ - ENODEV, \ - ENOTDIR, \ - EISDIR, \ - EINVAL, \ - EMFILE, \ - EFBIG, \ - ENOSPC, \ - EROFS, \ - EMLINK, /* 20 */ \ - EPIPE, \ - EDEADLK, \ - ENAMETOOLONG, \ - ENOLCK, \ - ENOSYS, \ - ENOTEMPTY, \ - ELOOP, \ - EWOULDBLOCK, \ - ENOMSG, \ - EUNATCH, /* 30 */ \ - EBADR, \ - EDEADLOCK, \ - ENODATA, \ - ETIME, \ - ENONET, \ - EREMOTE, \ - ECOMM, \ - EPROTO, \ - EBADMSG, \ - EOVERFLOW, /* 40 */ \ - ERESTART, \ - EMSGSIZE, \ - EPROTOTYPE, \ - ENOPROTOOPT, \ - EPROTONOSUPPORT, \ - EOPNOTSUPP, \ - EADDRINUSE, \ - EADDRNOTAVAIL, \ - ENETDOWN, \ - ENETUNREACH, /* 50 */ \ - ENETRESET, \ - ENOBUFS, \ - ETIMEDOUT, \ - ECONNREFUSED, \ - EHOSTDOWN, \ - EHOSTUNREACH, \ - EALREADY, \ - EACCES, \ - ECONNRESET, /* 59 */ \ - ERANGE, \ - 0 /* PVFS_ERRNO_MAX */ \ -}; \ -const char *PINT_non_errno_strerror_mapping[] = { \ - "Success", /* 0 */ \ - "Operation cancelled (possibly due to timeout)", \ - "Device initialization failed", \ - "Detailed per-server errors are available", \ - "Unknown host", \ - "No address associated with name", \ - "Unknown server error", \ - "Host name lookup failure", \ - "Path contains non-PVFS elements", \ - "Security error", \ -}; \ -__s32 PINT_non_errno_mapping[] = { \ - 0, /* leave this one empty */ \ - PVFS_ECANCEL, /* 1 */ \ - PVFS_EDEVINIT, /* 2 */ \ - PVFS_EDETAIL, /* 3 */ \ - PVFS_EHOSTNTFD, /* 4 */ \ - PVFS_EADDRNTFD, /* 5 */ \ - PVFS_ENORECVR, /* 6 */ \ - PVFS_ETRYAGAIN, /* 7 */ \ - PVFS_ENOTPVFS, /* 8 */ \ - PVFS_ESECURITY, /* 9 */ \ -} +/* PVFS2 error codes are a signed 32-bit integer. Error codes are negative, but + * the sign is stripped before decoding. */ -/* - * NOTE: PVFS_get_errno_mapping will convert a PVFS_ERROR_CODE to an - * errno value. If the error code is a pvfs2 specific error code - * (i.e. a PVFS_NON_ERRNO_ERROR_CODE), PVFS_get_errno_mapping will - * return an index into the PINT_non_errno_strerror_mapping array which - * can be used for getting the pvfs2 specific strerror message given - * the error code. if the value is not a recognized error code, the - * passed in value will be returned unchanged. - */ -#define DECLARE_ERRNO_MAPPING_AND_FN() \ -extern __s32 PINT_errno_mapping[]; \ -extern __s32 PINT_non_errno_mapping[]; \ -extern const char *PINT_non_errno_strerror_mapping[]; \ -static __s32 PVFS_get_errno_mapping(__s32 error) \ -{ \ - __s32 ret = error, mask = 0; \ - __s32 positive = ((error > -1) ? 1 : 0); \ - if (IS_PVFS_NON_ERRNO_ERROR((positive ? error : -error))) { \ - mask = (PVFS_NON_ERRNO_ERROR_BIT | \ - PVFS_ERROR_BIT | \ - PVFS_ERROR_CLASS_BITS); \ - ret = PVFS_NON_ERRNO_ERROR_CODE(((positive ? \ - error : \ - abs(error))) & \ - ~mask); \ - } \ - else if (IS_PVFS_ERROR((positive ? error : -error))) { \ - mask = (PVFS_ERROR_BIT | \ - PVFS_ERROR_CLASS_BITS); \ - ret = PINT_errno_mapping[PVFS_ERROR_CODE(((positive ? \ - error : \ - abs(error))) & \ - ~mask)]; \ - } \ - return ret; \ -} \ -DECLARE_ERRNO_MAPPING() +/* Bit 31 is not used since it is the sign. */ + +/* Bit 30 specifies that this is a PVFS2 error. A PVFS2 error is either an + * encoded errno value or a PVFS2 protocol error. */ +#define PVFS_ERROR_BIT (1 << 30) + +/* Bit 29 specifies that this is a PVFS2 protocol error and not an encoded + * errno value. */ +#define PVFS_NON_ERRNO_ERROR_BIT (1 << 29) + +/* Bits 9, 8, and 7 specify the error class, which encodes the section of + * server code the error originated in for logging purposes. It is not used + * in the kernel except to be masked out. */ +#define PVFS_ERROR_CLASS_BITS 0x380 + +/* Bits 6 - 0 are reserved for the actual error code. */ +#define PVFS_ERROR_NUMBER_BITS 0x7f + +/* Encoded errno values are decoded by PINT_errno_mapping in pvfs2-utils.c. */ + +/* Our own PVFS2 protocol error codes. */ +#define PVFS_ECANCEL (1|PVFS_NON_ERRNO_ERROR_BIT|PVFS_ERROR_BIT) +#define PVFS_EDEVINIT (2|PVFS_NON_ERRNO_ERROR_BIT|PVFS_ERROR_BIT) +#define PVFS_EDETAIL (3|PVFS_NON_ERRNO_ERROR_BIT|PVFS_ERROR_BIT) +#define PVFS_EHOSTNTFD (4|PVFS_NON_ERRNO_ERROR_BIT|PVFS_ERROR_BIT) +#define PVFS_EADDRNTFD (5|PVFS_NON_ERRNO_ERROR_BIT|PVFS_ERROR_BIT) +#define PVFS_ENORECVR (6|PVFS_NON_ERRNO_ERROR_BIT|PVFS_ERROR_BIT) +#define PVFS_ETRYAGAIN (7|PVFS_NON_ERRNO_ERROR_BIT|PVFS_ERROR_BIT) +#define PVFS_ENOTPVFS (8|PVFS_NON_ERRNO_ERROR_BIT|PVFS_ERROR_BIT) +#define PVFS_ESECURITY (9|PVFS_NON_ERRNO_ERROR_BIT|PVFS_ERROR_BIT) /* permission bits */ #define PVFS_O_EXECUTE (1 << 0) diff --git a/fs/orangefs/pvfs2-utils.c b/fs/orangefs/pvfs2-utils.c index 834e066..086ebbb 100644 --- a/fs/orangefs/pvfs2-utils.c +++ b/fs/orangefs/pvfs2-utils.c @@ -662,20 +662,45 @@ __u64 pvfs2_convert_time_field(void *time_ptr) return pvfs2_time; } -/* macro defined in include/pvfs2-types.h */ -DECLARE_ERRNO_MAPPING_AND_FN(); +/* The following is a very dirty hack that is now a permanent part of the + * PVFS2 protocol. See protocol.h for more error definitions. */ + +/* The order matches include/pvfs2-types.h in the OrangeFS source. */ +static int PINT_errno_mapping[] = { + 0, EPERM, ENOENT, EINTR, EIO, ENXIO, EBADF, EAGAIN, ENOMEM, + EFAULT, EBUSY, EEXIST, ENODEV, ENOTDIR, EISDIR, EINVAL, EMFILE, + EFBIG, ENOSPC, EROFS, EMLINK, EPIPE, EDEADLK, ENAMETOOLONG, + ENOLCK, ENOSYS, ENOTEMPTY, ELOOP, EWOULDBLOCK, ENOMSG, EUNATCH, + EBADR, EDEADLOCK, ENODATA, ETIME, ENONET, EREMOTE, ECOMM, + EPROTO, EBADMSG, EOVERFLOW, ERESTART, EMSGSIZE, EPROTOTYPE, + ENOPROTOOPT, EPROTONOSUPPORT, EOPNOTSUPP, EADDRINUSE, + EADDRNOTAVAIL, ENETDOWN, ENETUNREACH, ENETRESET, ENOBUFS, + ETIMEDOUT, ECONNREFUSED, EHOSTDOWN, EHOSTUNREACH, EALREADY, + EACCES, ECONNRESET, ERANGE +}; int pvfs2_normalize_to_errno(__s32 error_code) { - if (error_code > 0) { + /* Success */ + if (error_code == 0) { + return 0; + /* This shouldn't ever happen. If it does it should be fixed on the + * server. */ + } else if (error_code > 0) { gossip_err("pvfs2: error status receieved.\n"); gossip_err("pvfs2: assuming error code is inverted.\n"); error_code = -error_code; } - /* convert any error codes that are in pvfs2 format */ - if (IS_PVFS_NON_ERRNO_ERROR(-error_code)) { - if (PVFS_NON_ERRNO_ERROR_CODE(-error_code) == PVFS_ECANCEL) { + /* XXX: This is very bad since error codes from PVFS2 may not be + * suitable for return into userspace. */ + + /* Convert PVFS2 error values into errno values suitable for return + * from the kernel. */ + if ((-error_code) & PVFS_NON_ERRNO_ERROR_BIT) { + if (((-error_code) & + (PVFS_ERROR_NUMBER_BITS|PVFS_NON_ERRNO_ERROR_BIT| + PVFS_ERROR_BIT)) == PVFS_ECANCEL) { /* * cancellation error codes generally correspond to * a timeout from the client's perspective @@ -683,12 +708,25 @@ int pvfs2_normalize_to_errno(__s32 error_code) error_code = -ETIMEDOUT; } else { /* assume a default error code */ - gossip_err("pvfs2: warning: got error code without errno equivalent: %d.\n", - error_code); + gossip_err("pvfs2: warning: got error code without " + "errno equivalent: %d.\n", error_code); error_code = -EINVAL; } - } else if (IS_PVFS_ERROR(-error_code)) { - error_code = -PVFS_ERROR_TO_ERRNO(-error_code); + + /* Convert PVFS2 encoded errno values into regular errno values. */ + } else if ((-error_code) & PVFS_ERROR_BIT) { + __u32 i; + i = (-error_code) & ~(PVFS_ERROR_BIT|PVFS_ERROR_CLASS_BITS); + if (i < sizeof PINT_errno_mapping/sizeof *PINT_errno_mapping) + error_code = -PINT_errno_mapping[i]; + else + error_code = -EINVAL; + + /* Only PVFS2 protocol error codes should ever come here. Otherwise + * there is a bug somewhere. */ + } else { + gossip_err("pvfs2: pvfs2_normalize_to_errno: got error code" + "which is not from PVFS2.\n"); } return error_code; } |