| // SPDX-License-Identifier: GPL-2.0-only |
| |
| #include <linux/module.h> |
| #include <linux/nfs_common.h> |
| #include <linux/nfs4.h> |
| |
| /* |
| * We need to translate between nfs status return values and |
| * the local errno values which may not be the same. |
| */ |
| static const struct { |
| int stat; |
| int errno; |
| } nfs_errtbl[] = { |
| { NFS_OK, 0 }, |
| { NFSERR_PERM, -EPERM }, |
| { NFSERR_NOENT, -ENOENT }, |
| { NFSERR_IO, -errno_NFSERR_IO}, |
| { NFSERR_NXIO, -ENXIO }, |
| /* { NFSERR_EAGAIN, -EAGAIN }, */ |
| { NFSERR_ACCES, -EACCES }, |
| { NFSERR_EXIST, -EEXIST }, |
| { NFSERR_XDEV, -EXDEV }, |
| { NFSERR_NODEV, -ENODEV }, |
| { NFSERR_NOTDIR, -ENOTDIR }, |
| { NFSERR_ISDIR, -EISDIR }, |
| { NFSERR_INVAL, -EINVAL }, |
| { NFSERR_FBIG, -EFBIG }, |
| { NFSERR_NOSPC, -ENOSPC }, |
| { NFSERR_ROFS, -EROFS }, |
| { NFSERR_MLINK, -EMLINK }, |
| { NFSERR_NAMETOOLONG, -ENAMETOOLONG }, |
| { NFSERR_NOTEMPTY, -ENOTEMPTY }, |
| { NFSERR_DQUOT, -EDQUOT }, |
| { NFSERR_STALE, -ESTALE }, |
| { NFSERR_REMOTE, -EREMOTE }, |
| #ifdef EWFLUSH |
| { NFSERR_WFLUSH, -EWFLUSH }, |
| #endif |
| { NFSERR_BADHANDLE, -EBADHANDLE }, |
| { NFSERR_NOT_SYNC, -ENOTSYNC }, |
| { NFSERR_BAD_COOKIE, -EBADCOOKIE }, |
| { NFSERR_NOTSUPP, -ENOTSUPP }, |
| { NFSERR_TOOSMALL, -ETOOSMALL }, |
| { NFSERR_SERVERFAULT, -EREMOTEIO }, |
| { NFSERR_BADTYPE, -EBADTYPE }, |
| { NFSERR_JUKEBOX, -EJUKEBOX }, |
| { -1, -EIO } |
| }; |
| |
| /** |
| * nfs_stat_to_errno - convert an NFS status code to a local errno |
| * @status: NFS status code to convert |
| * |
| * Returns a local errno value, or -EIO if the NFS status code is |
| * not recognized. This function is used jointly by NFSv2 and NFSv3. |
| */ |
| int nfs_stat_to_errno(enum nfs_stat status) |
| { |
| int i; |
| |
| for (i = 0; nfs_errtbl[i].stat != -1; i++) { |
| if (nfs_errtbl[i].stat == (int)status) |
| return nfs_errtbl[i].errno; |
| } |
| return nfs_errtbl[i].errno; |
| } |
| EXPORT_SYMBOL_GPL(nfs_stat_to_errno); |
| |
| /* |
| * We need to translate between nfs v4 status return values and |
| * the local errno values which may not be the same. |
| */ |
| static const struct { |
| int stat; |
| int errno; |
| } nfs4_errtbl[] = { |
| { NFS4_OK, 0 }, |
| { NFS4ERR_PERM, -EPERM }, |
| { NFS4ERR_NOENT, -ENOENT }, |
| { NFS4ERR_IO, -errno_NFSERR_IO}, |
| { NFS4ERR_NXIO, -ENXIO }, |
| { NFS4ERR_ACCESS, -EACCES }, |
| { NFS4ERR_EXIST, -EEXIST }, |
| { NFS4ERR_XDEV, -EXDEV }, |
| { NFS4ERR_NOTDIR, -ENOTDIR }, |
| { NFS4ERR_ISDIR, -EISDIR }, |
| { NFS4ERR_INVAL, -EINVAL }, |
| { NFS4ERR_FBIG, -EFBIG }, |
| { NFS4ERR_NOSPC, -ENOSPC }, |
| { NFS4ERR_ROFS, -EROFS }, |
| { NFS4ERR_MLINK, -EMLINK }, |
| { NFS4ERR_NAMETOOLONG, -ENAMETOOLONG }, |
| { NFS4ERR_NOTEMPTY, -ENOTEMPTY }, |
| { NFS4ERR_DQUOT, -EDQUOT }, |
| { NFS4ERR_STALE, -ESTALE }, |
| { NFS4ERR_BADHANDLE, -EBADHANDLE }, |
| { NFS4ERR_BAD_COOKIE, -EBADCOOKIE }, |
| { NFS4ERR_NOTSUPP, -ENOTSUPP }, |
| { NFS4ERR_TOOSMALL, -ETOOSMALL }, |
| { NFS4ERR_SERVERFAULT, -EREMOTEIO }, |
| { NFS4ERR_BADTYPE, -EBADTYPE }, |
| { NFS4ERR_LOCKED, -EAGAIN }, |
| { NFS4ERR_SYMLINK, -ELOOP }, |
| { NFS4ERR_OP_ILLEGAL, -EOPNOTSUPP }, |
| { NFS4ERR_DEADLOCK, -EDEADLK }, |
| { NFS4ERR_NOXATTR, -ENODATA }, |
| { NFS4ERR_XATTR2BIG, -E2BIG }, |
| { -1, -EIO } |
| }; |
| |
| /* |
| * Convert an NFS error code to a local one. |
| * This one is used by NFSv4. |
| */ |
| int nfs4_stat_to_errno(int stat) |
| { |
| int i; |
| for (i = 0; nfs4_errtbl[i].stat != -1; i++) { |
| if (nfs4_errtbl[i].stat == stat) |
| return nfs4_errtbl[i].errno; |
| } |
| if (stat <= 10000 || stat > 10100) { |
| /* The server is looney tunes. */ |
| return -EREMOTEIO; |
| } |
| /* If we cannot translate the error, the recovery routines should |
| * handle it. |
| * Note: remaining NFSv4 error codes have values > 10000, so should |
| * not conflict with native Linux error codes. |
| */ |
| return -stat; |
| } |
| EXPORT_SYMBOL_GPL(nfs4_stat_to_errno); |