11f327613SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
2bd238fb4SLatchesar Ionkov /*
3bd238fb4SLatchesar Ionkov * Error string handling
4bd238fb4SLatchesar Ionkov *
5bd238fb4SLatchesar Ionkov * Plan 9 uses error strings, Unix uses error numbers. These functions
6bd238fb4SLatchesar Ionkov * try to help manage that and provide for dynamically adding error
7bd238fb4SLatchesar Ionkov * mappings.
8bd238fb4SLatchesar Ionkov *
9bd238fb4SLatchesar Ionkov * Copyright (C) 2004 by Eric Van Hensbergen <ericvh@gmail.com>
10bd238fb4SLatchesar Ionkov * Copyright (C) 2002 by Ron Minnich <rminnich@lanl.gov>
11bd238fb4SLatchesar Ionkov */
12bd238fb4SLatchesar Ionkov
135d385153SJoe Perches #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
145d385153SJoe Perches
15bd238fb4SLatchesar Ionkov #include <linux/module.h>
16bd238fb4SLatchesar Ionkov #include <linux/list.h>
17bd238fb4SLatchesar Ionkov #include <linux/jhash.h>
18bd238fb4SLatchesar Ionkov #include <linux/errno.h>
19bd238fb4SLatchesar Ionkov #include <net/9p/9p.h>
20bd238fb4SLatchesar Ionkov
21ee443996SEric Van Hensbergen /**
22ee443996SEric Van Hensbergen * struct errormap - map string errors from Plan 9 to Linux numeric ids
23ee443996SEric Van Hensbergen * @name: string sent over 9P
24ee443996SEric Van Hensbergen * @val: numeric id most closely representing @name
25ee443996SEric Van Hensbergen * @namelen: length of string
26ee443996SEric Van Hensbergen * @list: hash-table list for string lookup
27ee443996SEric Van Hensbergen */
28bd238fb4SLatchesar Ionkov struct errormap {
29bd238fb4SLatchesar Ionkov char *name;
30bd238fb4SLatchesar Ionkov int val;
31bd238fb4SLatchesar Ionkov
32bd238fb4SLatchesar Ionkov int namelen;
33bd238fb4SLatchesar Ionkov struct hlist_node list;
34bd238fb4SLatchesar Ionkov };
35bd238fb4SLatchesar Ionkov
36bd238fb4SLatchesar Ionkov #define ERRHASHSZ 32
37bd238fb4SLatchesar Ionkov static struct hlist_head hash_errmap[ERRHASHSZ];
38bd238fb4SLatchesar Ionkov
39bd238fb4SLatchesar Ionkov /* FixMe - reduce to a reasonable size */
40bd238fb4SLatchesar Ionkov static struct errormap errmap[] = {
41bd238fb4SLatchesar Ionkov {"Operation not permitted", EPERM},
42bd238fb4SLatchesar Ionkov {"wstat prohibited", EPERM},
43bd238fb4SLatchesar Ionkov {"No such file or directory", ENOENT},
44bd238fb4SLatchesar Ionkov {"directory entry not found", ENOENT},
45bd238fb4SLatchesar Ionkov {"file not found", ENOENT},
46bd238fb4SLatchesar Ionkov {"Interrupted system call", EINTR},
47bd238fb4SLatchesar Ionkov {"Input/output error", EIO},
48bd238fb4SLatchesar Ionkov {"No such device or address", ENXIO},
49bd238fb4SLatchesar Ionkov {"Argument list too long", E2BIG},
50bd238fb4SLatchesar Ionkov {"Bad file descriptor", EBADF},
51bd238fb4SLatchesar Ionkov {"Resource temporarily unavailable", EAGAIN},
52bd238fb4SLatchesar Ionkov {"Cannot allocate memory", ENOMEM},
53bd238fb4SLatchesar Ionkov {"Permission denied", EACCES},
54bd238fb4SLatchesar Ionkov {"Bad address", EFAULT},
55bd238fb4SLatchesar Ionkov {"Block device required", ENOTBLK},
56bd238fb4SLatchesar Ionkov {"Device or resource busy", EBUSY},
57bd238fb4SLatchesar Ionkov {"File exists", EEXIST},
58bd238fb4SLatchesar Ionkov {"Invalid cross-device link", EXDEV},
59bd238fb4SLatchesar Ionkov {"No such device", ENODEV},
60bd238fb4SLatchesar Ionkov {"Not a directory", ENOTDIR},
61bd238fb4SLatchesar Ionkov {"Is a directory", EISDIR},
62bd238fb4SLatchesar Ionkov {"Invalid argument", EINVAL},
63bd238fb4SLatchesar Ionkov {"Too many open files in system", ENFILE},
64bd238fb4SLatchesar Ionkov {"Too many open files", EMFILE},
65bd238fb4SLatchesar Ionkov {"Text file busy", ETXTBSY},
66bd238fb4SLatchesar Ionkov {"File too large", EFBIG},
67bd238fb4SLatchesar Ionkov {"No space left on device", ENOSPC},
68bd238fb4SLatchesar Ionkov {"Illegal seek", ESPIPE},
69bd238fb4SLatchesar Ionkov {"Read-only file system", EROFS},
70bd238fb4SLatchesar Ionkov {"Too many links", EMLINK},
71bd238fb4SLatchesar Ionkov {"Broken pipe", EPIPE},
72bd238fb4SLatchesar Ionkov {"Numerical argument out of domain", EDOM},
73bd238fb4SLatchesar Ionkov {"Numerical result out of range", ERANGE},
74bd238fb4SLatchesar Ionkov {"Resource deadlock avoided", EDEADLK},
75bd238fb4SLatchesar Ionkov {"File name too long", ENAMETOOLONG},
76bd238fb4SLatchesar Ionkov {"No locks available", ENOLCK},
77bd238fb4SLatchesar Ionkov {"Function not implemented", ENOSYS},
78bd238fb4SLatchesar Ionkov {"Directory not empty", ENOTEMPTY},
79bd238fb4SLatchesar Ionkov {"Too many levels of symbolic links", ELOOP},
80bd238fb4SLatchesar Ionkov {"No message of desired type", ENOMSG},
81bd238fb4SLatchesar Ionkov {"Identifier removed", EIDRM},
82bd238fb4SLatchesar Ionkov {"No data available", ENODATA},
83bd238fb4SLatchesar Ionkov {"Machine is not on the network", ENONET},
84bd238fb4SLatchesar Ionkov {"Package not installed", ENOPKG},
85bd238fb4SLatchesar Ionkov {"Object is remote", EREMOTE},
86bd238fb4SLatchesar Ionkov {"Link has been severed", ENOLINK},
87bd238fb4SLatchesar Ionkov {"Communication error on send", ECOMM},
88bd238fb4SLatchesar Ionkov {"Protocol error", EPROTO},
89bd238fb4SLatchesar Ionkov {"Bad message", EBADMSG},
90bd238fb4SLatchesar Ionkov {"File descriptor in bad state", EBADFD},
91bd238fb4SLatchesar Ionkov {"Streams pipe error", ESTRPIPE},
92bd238fb4SLatchesar Ionkov {"Too many users", EUSERS},
93bd238fb4SLatchesar Ionkov {"Socket operation on non-socket", ENOTSOCK},
94bd238fb4SLatchesar Ionkov {"Message too long", EMSGSIZE},
95bd238fb4SLatchesar Ionkov {"Protocol not available", ENOPROTOOPT},
96bd238fb4SLatchesar Ionkov {"Protocol not supported", EPROTONOSUPPORT},
97bd238fb4SLatchesar Ionkov {"Socket type not supported", ESOCKTNOSUPPORT},
98bd238fb4SLatchesar Ionkov {"Operation not supported", EOPNOTSUPP},
99bd238fb4SLatchesar Ionkov {"Protocol family not supported", EPFNOSUPPORT},
100bd238fb4SLatchesar Ionkov {"Network is down", ENETDOWN},
101bd238fb4SLatchesar Ionkov {"Network is unreachable", ENETUNREACH},
102bd238fb4SLatchesar Ionkov {"Network dropped connection on reset", ENETRESET},
103bd238fb4SLatchesar Ionkov {"Software caused connection abort", ECONNABORTED},
104bd238fb4SLatchesar Ionkov {"Connection reset by peer", ECONNRESET},
105bd238fb4SLatchesar Ionkov {"No buffer space available", ENOBUFS},
106bd238fb4SLatchesar Ionkov {"Transport endpoint is already connected", EISCONN},
107bd238fb4SLatchesar Ionkov {"Transport endpoint is not connected", ENOTCONN},
108bd238fb4SLatchesar Ionkov {"Cannot send after transport endpoint shutdown", ESHUTDOWN},
109bd238fb4SLatchesar Ionkov {"Connection timed out", ETIMEDOUT},
110bd238fb4SLatchesar Ionkov {"Connection refused", ECONNREFUSED},
111bd238fb4SLatchesar Ionkov {"Host is down", EHOSTDOWN},
112bd238fb4SLatchesar Ionkov {"No route to host", EHOSTUNREACH},
113bd238fb4SLatchesar Ionkov {"Operation already in progress", EALREADY},
114bd238fb4SLatchesar Ionkov {"Operation now in progress", EINPROGRESS},
115bd238fb4SLatchesar Ionkov {"Is a named type file", EISNAM},
116bd238fb4SLatchesar Ionkov {"Remote I/O error", EREMOTEIO},
117bd238fb4SLatchesar Ionkov {"Disk quota exceeded", EDQUOT},
118bd238fb4SLatchesar Ionkov /* errors from fossil, vacfs, and u9fs */
119bd238fb4SLatchesar Ionkov {"fid unknown or out of range", EBADF},
120bd238fb4SLatchesar Ionkov {"permission denied", EACCES},
121bd238fb4SLatchesar Ionkov {"file does not exist", ENOENT},
122bd238fb4SLatchesar Ionkov {"authentication failed", ECONNREFUSED},
123bd238fb4SLatchesar Ionkov {"bad offset in directory read", ESPIPE},
124bd238fb4SLatchesar Ionkov {"bad use of fid", EBADF},
125bd238fb4SLatchesar Ionkov {"wstat can't convert between files and directories", EPERM},
126bd238fb4SLatchesar Ionkov {"directory is not empty", ENOTEMPTY},
127bd238fb4SLatchesar Ionkov {"file exists", EEXIST},
128bd238fb4SLatchesar Ionkov {"file already exists", EEXIST},
129bd238fb4SLatchesar Ionkov {"file or directory already exists", EEXIST},
130bd238fb4SLatchesar Ionkov {"fid already in use", EBADF},
131bd238fb4SLatchesar Ionkov {"file in use", ETXTBSY},
132bd238fb4SLatchesar Ionkov {"i/o error", EIO},
133bd238fb4SLatchesar Ionkov {"file already open for I/O", ETXTBSY},
134bd238fb4SLatchesar Ionkov {"illegal mode", EINVAL},
135bd238fb4SLatchesar Ionkov {"illegal name", ENAMETOOLONG},
136bd238fb4SLatchesar Ionkov {"not a directory", ENOTDIR},
137bd238fb4SLatchesar Ionkov {"not a member of proposed group", EPERM},
138bd238fb4SLatchesar Ionkov {"not owner", EACCES},
139bd238fb4SLatchesar Ionkov {"only owner can change group in wstat", EACCES},
140bd238fb4SLatchesar Ionkov {"read only file system", EROFS},
141bd238fb4SLatchesar Ionkov {"no access to special file", EPERM},
142bd238fb4SLatchesar Ionkov {"i/o count too large", EIO},
143bd238fb4SLatchesar Ionkov {"unknown group", EINVAL},
144bd238fb4SLatchesar Ionkov {"unknown user", EINVAL},
145bd238fb4SLatchesar Ionkov {"bogus wstat buffer", EPROTO},
146bd238fb4SLatchesar Ionkov {"exclusive use file already open", EAGAIN},
147bd238fb4SLatchesar Ionkov {"corrupted directory entry", EIO},
148bd238fb4SLatchesar Ionkov {"corrupted file entry", EIO},
149bd238fb4SLatchesar Ionkov {"corrupted block label", EIO},
150bd238fb4SLatchesar Ionkov {"corrupted meta data", EIO},
151bd238fb4SLatchesar Ionkov {"illegal offset", EINVAL},
152bd238fb4SLatchesar Ionkov {"illegal path element", ENOENT},
153bd238fb4SLatchesar Ionkov {"root of file system is corrupted", EIO},
154bd238fb4SLatchesar Ionkov {"corrupted super block", EIO},
155bd238fb4SLatchesar Ionkov {"protocol botch", EPROTO},
156bd238fb4SLatchesar Ionkov {"file system is full", ENOSPC},
157bd238fb4SLatchesar Ionkov {"file is in use", EAGAIN},
158bd238fb4SLatchesar Ionkov {"directory entry is not allocated", ENOENT},
159bd238fb4SLatchesar Ionkov {"file is read only", EROFS},
160bd238fb4SLatchesar Ionkov {"file has been removed", EIDRM},
161bd238fb4SLatchesar Ionkov {"only support truncation to zero length", EPERM},
162bd238fb4SLatchesar Ionkov {"cannot remove root", EPERM},
163bd238fb4SLatchesar Ionkov {"file too big", EFBIG},
164bd238fb4SLatchesar Ionkov {"venti i/o error", EIO},
165bd238fb4SLatchesar Ionkov /* these are not errors */
166bd238fb4SLatchesar Ionkov {"u9fs rhostsauth: no authentication required", 0},
167bd238fb4SLatchesar Ionkov {"u9fs authnone: no authentication required", 0},
168bd238fb4SLatchesar Ionkov {NULL, -1}
169bd238fb4SLatchesar Ionkov };
170bd238fb4SLatchesar Ionkov
171bd238fb4SLatchesar Ionkov /**
172ee443996SEric Van Hensbergen * p9_error_init - preload mappings into hash list
173bd238fb4SLatchesar Ionkov *
174bd238fb4SLatchesar Ionkov */
175bd238fb4SLatchesar Ionkov
p9_error_init(void)176bd238fb4SLatchesar Ionkov int p9_error_init(void)
177bd238fb4SLatchesar Ionkov {
178bd238fb4SLatchesar Ionkov struct errormap *c;
179bd238fb4SLatchesar Ionkov int bucket;
180bd238fb4SLatchesar Ionkov
181bd238fb4SLatchesar Ionkov /* initialize hash table */
182bd238fb4SLatchesar Ionkov for (bucket = 0; bucket < ERRHASHSZ; bucket++)
183bd238fb4SLatchesar Ionkov INIT_HLIST_HEAD(&hash_errmap[bucket]);
184bd238fb4SLatchesar Ionkov
185bd238fb4SLatchesar Ionkov /* load initial error map into hash table */
186*6e195b0fSDominique Martinet for (c = errmap; c->name; c++) {
187bd238fb4SLatchesar Ionkov c->namelen = strlen(c->name);
188bd238fb4SLatchesar Ionkov bucket = jhash(c->name, c->namelen, 0) % ERRHASHSZ;
189bd238fb4SLatchesar Ionkov INIT_HLIST_NODE(&c->list);
190bd238fb4SLatchesar Ionkov hlist_add_head(&c->list, &hash_errmap[bucket]);
191bd238fb4SLatchesar Ionkov }
192bd238fb4SLatchesar Ionkov
193bd238fb4SLatchesar Ionkov return 1;
194bd238fb4SLatchesar Ionkov }
195bd238fb4SLatchesar Ionkov EXPORT_SYMBOL(p9_error_init);
196bd238fb4SLatchesar Ionkov
197bd238fb4SLatchesar Ionkov /**
1988bf94a92SXiongfeng Wang * p9_errstr2errno - convert error string to error number
199bd238fb4SLatchesar Ionkov * @errstr: error string
200ee443996SEric Van Hensbergen * @len: length of error string
201bd238fb4SLatchesar Ionkov *
202bd238fb4SLatchesar Ionkov */
203bd238fb4SLatchesar Ionkov
p9_errstr2errno(char * errstr,int len)204bd238fb4SLatchesar Ionkov int p9_errstr2errno(char *errstr, int len)
205bd238fb4SLatchesar Ionkov {
206bd238fb4SLatchesar Ionkov int errno;
207bd238fb4SLatchesar Ionkov struct errormap *c;
208bd238fb4SLatchesar Ionkov int bucket;
209bd238fb4SLatchesar Ionkov
210bd238fb4SLatchesar Ionkov errno = 0;
211bd238fb4SLatchesar Ionkov c = NULL;
212bd238fb4SLatchesar Ionkov bucket = jhash(errstr, len, 0) % ERRHASHSZ;
213b67bfe0dSSasha Levin hlist_for_each_entry(c, &hash_errmap[bucket], list) {
214bd238fb4SLatchesar Ionkov if (c->namelen == len && !memcmp(c->name, errstr, len)) {
215bd238fb4SLatchesar Ionkov errno = c->val;
216bd238fb4SLatchesar Ionkov break;
217bd238fb4SLatchesar Ionkov }
218bd238fb4SLatchesar Ionkov }
219bd238fb4SLatchesar Ionkov
220bd238fb4SLatchesar Ionkov if (errno == 0) {
221bd238fb4SLatchesar Ionkov /* TODO: if error isn't found, add it dynamically */
222bd238fb4SLatchesar Ionkov errstr[len] = 0;
2235d385153SJoe Perches pr_err("%s: server reported unknown error %s\n",
224332c421eSEric Van Hensbergen __func__, errstr);
2250aad37efSAbhishek Kulkarni errno = ESERVERFAULT;
226bd238fb4SLatchesar Ionkov }
227bd238fb4SLatchesar Ionkov
228bd238fb4SLatchesar Ionkov return -errno;
229bd238fb4SLatchesar Ionkov }
230bd238fb4SLatchesar Ionkov EXPORT_SYMBOL(p9_errstr2errno);
231