xref: /openbmc/linux/net/9p/error.c (revision 03ab8e6297acd1bc0eedaa050e2a1635c576fd11)
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