Linux kernel mirror (for testing)
git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel
os
linux
1// SPDX-License-Identifier: GPL-2.0-only
2
3#include <linux/module.h>
4#include <linux/nfs_common.h>
5#include <linux/nfs4.h>
6
7/*
8 * We need to translate between nfs status return values and
9 * the local errno values which may not be the same.
10 */
11static const struct {
12 int stat;
13 int errno;
14} nfs_errtbl[] = {
15 { NFS_OK, 0 },
16 { NFSERR_PERM, -EPERM },
17 { NFSERR_NOENT, -ENOENT },
18 { NFSERR_IO, -EIO },
19 { NFSERR_NXIO, -ENXIO },
20 { NFSERR_ACCES, -EACCES },
21 { NFSERR_EXIST, -EEXIST },
22 { NFSERR_XDEV, -EXDEV },
23 { NFSERR_NODEV, -ENODEV },
24 { NFSERR_NOTDIR, -ENOTDIR },
25 { NFSERR_ISDIR, -EISDIR },
26 { NFSERR_INVAL, -EINVAL },
27 { NFSERR_FBIG, -EFBIG },
28 { NFSERR_NOSPC, -ENOSPC },
29 { NFSERR_ROFS, -EROFS },
30 { NFSERR_MLINK, -EMLINK },
31 { NFSERR_NAMETOOLONG, -ENAMETOOLONG },
32 { NFSERR_NOTEMPTY, -ENOTEMPTY },
33 { NFSERR_DQUOT, -EDQUOT },
34 { NFSERR_STALE, -ESTALE },
35 { NFSERR_REMOTE, -EREMOTE },
36#ifdef EWFLUSH
37 { NFSERR_WFLUSH, -EWFLUSH },
38#endif
39 { NFSERR_BADHANDLE, -EBADHANDLE },
40 { NFSERR_NOT_SYNC, -ENOTSYNC },
41 { NFSERR_BAD_COOKIE, -EBADCOOKIE },
42 { NFSERR_NOTSUPP, -ENOTSUPP },
43 { NFSERR_TOOSMALL, -ETOOSMALL },
44 { NFSERR_SERVERFAULT, -EREMOTEIO },
45 { NFSERR_BADTYPE, -EBADTYPE },
46 { NFSERR_JUKEBOX, -EJUKEBOX },
47};
48
49/**
50 * nfs_stat_to_errno - convert an NFS status code to a local errno
51 * @status: NFS status code to convert
52 *
53 * Returns a local errno value, or -EIO if the NFS status code is
54 * not recognized. This function is used jointly by NFSv2 and NFSv3.
55 */
56int nfs_stat_to_errno(enum nfs_stat status)
57{
58 int i;
59
60 for (i = 0; i < ARRAY_SIZE(nfs_errtbl); i++) {
61 if (nfs_errtbl[i].stat == (int)status)
62 return nfs_errtbl[i].errno;
63 }
64 return -EIO;
65}
66EXPORT_SYMBOL_GPL(nfs_stat_to_errno);
67
68/*
69 * We need to translate between nfs v4 status return values and
70 * the local errno values which may not be the same.
71 *
72 * nfs4_errtbl_common[] is used before more specialized mappings
73 * available in nfs4_errtbl[] or nfs4_errtbl_localio[].
74 */
75static const struct {
76 int stat;
77 int errno;
78} nfs4_errtbl_common[] = {
79 { NFS4_OK, 0 },
80 { NFS4ERR_PERM, -EPERM },
81 { NFS4ERR_NOENT, -ENOENT },
82 { NFS4ERR_IO, -EIO },
83 { NFS4ERR_NXIO, -ENXIO },
84 { NFS4ERR_ACCESS, -EACCES },
85 { NFS4ERR_EXIST, -EEXIST },
86 { NFS4ERR_XDEV, -EXDEV },
87 { NFS4ERR_NOTDIR, -ENOTDIR },
88 { NFS4ERR_ISDIR, -EISDIR },
89 { NFS4ERR_INVAL, -EINVAL },
90 { NFS4ERR_FBIG, -EFBIG },
91 { NFS4ERR_NOSPC, -ENOSPC },
92 { NFS4ERR_ROFS, -EROFS },
93 { NFS4ERR_MLINK, -EMLINK },
94 { NFS4ERR_NAMETOOLONG, -ENAMETOOLONG },
95 { NFS4ERR_NOTEMPTY, -ENOTEMPTY },
96 { NFS4ERR_DQUOT, -EDQUOT },
97 { NFS4ERR_STALE, -ESTALE },
98 { NFS4ERR_BADHANDLE, -EBADHANDLE },
99 { NFS4ERR_BAD_COOKIE, -EBADCOOKIE },
100 { NFS4ERR_NOTSUPP, -ENOTSUPP },
101 { NFS4ERR_TOOSMALL, -ETOOSMALL },
102 { NFS4ERR_BADTYPE, -EBADTYPE },
103 { NFS4ERR_SYMLINK, -ELOOP },
104 { NFS4ERR_DEADLOCK, -EDEADLK },
105};
106
107static const struct {
108 int stat;
109 int errno;
110} nfs4_errtbl[] = {
111 { NFS4ERR_SERVERFAULT, -EREMOTEIO },
112 { NFS4ERR_LOCKED, -EAGAIN },
113 { NFS4ERR_OP_ILLEGAL, -EOPNOTSUPP },
114 { NFS4ERR_NOXATTR, -ENODATA },
115 { NFS4ERR_XATTR2BIG, -E2BIG },
116};
117
118/*
119 * Convert an NFS error code to a local one.
120 * This one is used by NFSv4.
121 */
122int nfs4_stat_to_errno(int stat)
123{
124 int i;
125
126 /* First check nfs4_errtbl_common */
127 for (i = 0; i < ARRAY_SIZE(nfs4_errtbl_common); i++) {
128 if (nfs4_errtbl_common[i].stat == stat)
129 return nfs4_errtbl_common[i].errno;
130 }
131 /* Then check nfs4_errtbl */
132 for (i = 0; i < ARRAY_SIZE(nfs4_errtbl); i++) {
133 if (nfs4_errtbl[i].stat == stat)
134 return nfs4_errtbl[i].errno;
135 }
136 if (stat <= 10000 || stat > 10100) {
137 /* The server is looney tunes. */
138 return -EREMOTEIO;
139 }
140 /* If we cannot translate the error, the recovery routines should
141 * handle it.
142 * Note: remaining NFSv4 error codes have values > 10000, so should
143 * not conflict with native Linux error codes.
144 */
145 return -stat;
146}
147EXPORT_SYMBOL_GPL(nfs4_stat_to_errno);
148
149/*
150 * This table is useful for conversion from local errno to NFS error.
151 * It provides more logically correct mappings for use with LOCALIO
152 * (which is focused on converting from errno to NFS status).
153 */
154static const struct {
155 int stat;
156 int errno;
157} nfs4_errtbl_localio[] = {
158 /* Map errors differently than nfs4_errtbl */
159 { NFS4ERR_IO, -EREMOTEIO },
160 { NFS4ERR_DELAY, -EAGAIN },
161 { NFS4ERR_FBIG, -E2BIG },
162 /* Map errors not handled by nfs4_errtbl */
163 { NFS4ERR_STALE, -EBADF },
164 { NFS4ERR_STALE, -EOPENSTALE },
165 { NFS4ERR_DELAY, -ETIMEDOUT },
166 { NFS4ERR_DELAY, -ERESTARTSYS },
167 { NFS4ERR_DELAY, -ENOMEM },
168 { NFS4ERR_IO, -ETXTBSY },
169 { NFS4ERR_IO, -EBUSY },
170 { NFS4ERR_SERVERFAULT, -ESERVERFAULT },
171 { NFS4ERR_SERVERFAULT, -ENFILE },
172 { NFS4ERR_IO, -EUCLEAN },
173 { NFS4ERR_PERM, -ENOKEY },
174};
175
176/*
177 * Convert an errno to an NFS error code for LOCALIO.
178 */
179__u32 nfs_localio_errno_to_nfs4_stat(int errno)
180{
181 int i;
182
183 /* First check nfs4_errtbl_common */
184 for (i = 0; i < ARRAY_SIZE(nfs4_errtbl_common); i++) {
185 if (nfs4_errtbl_common[i].errno == errno)
186 return nfs4_errtbl_common[i].stat;
187 }
188 /* Then check nfs4_errtbl_localio */
189 for (i = 0; i < ARRAY_SIZE(nfs4_errtbl_localio); i++) {
190 if (nfs4_errtbl_localio[i].errno == errno)
191 return nfs4_errtbl_localio[i].stat;
192 }
193 /* If we cannot translate the error, the recovery routines should
194 * handle it.
195 * Note: remaining NFSv4 error codes have values > 10000, so should
196 * not conflict with native Linux error codes.
197 */
198 return NFS4ERR_SERVERFAULT;
199}
200EXPORT_SYMBOL_GPL(nfs_localio_errno_to_nfs4_stat);