| // SPDX-License-Identifier: GPL-2.0-or-later |
| /* miscellaneous bits |
| * |
| * Copyright (C) 2002, 2007 Red Hat, Inc. All Rights Reserved. |
| * Written by David Howells (dhowells@redhat.com) |
| */ |
| |
| #include <linux/kernel.h> |
| #include <linux/module.h> |
| #include <linux/errno.h> |
| #include "internal.h" |
| #include "afs_fs.h" |
| #include "protocol_uae.h" |
| |
| /* |
| * convert an AFS abort code to a Linux error number |
| */ |
| int afs_abort_to_error(u32 abort_code) |
| { |
| switch (abort_code) { |
| /* Low errno codes inserted into abort namespace */ |
| case 13: return -EACCES; |
| case 27: return -EFBIG; |
| case 30: return -EROFS; |
| |
| /* VICE "special error" codes; 101 - 111 */ |
| case VSALVAGE: return -EIO; |
| case VNOVNODE: return -ENOENT; |
| case VNOVOL: return -ENOMEDIUM; |
| case VVOLEXISTS: return -EEXIST; |
| case VNOSERVICE: return -EIO; |
| case VOFFLINE: return -ENOENT; |
| case VONLINE: return -EEXIST; |
| case VDISKFULL: return -ENOSPC; |
| case VOVERQUOTA: return -EDQUOT; |
| case VBUSY: return -EBUSY; |
| case VMOVED: return -ENXIO; |
| |
| /* Volume Location server errors */ |
| case AFSVL_IDEXIST: return -EEXIST; |
| case AFSVL_IO: return -EREMOTEIO; |
| case AFSVL_NAMEEXIST: return -EEXIST; |
| case AFSVL_CREATEFAIL: return -EREMOTEIO; |
| case AFSVL_NOENT: return -ENOMEDIUM; |
| case AFSVL_EMPTY: return -ENOMEDIUM; |
| case AFSVL_ENTDELETED: return -ENOMEDIUM; |
| case AFSVL_BADNAME: return -EINVAL; |
| case AFSVL_BADINDEX: return -EINVAL; |
| case AFSVL_BADVOLTYPE: return -EINVAL; |
| case AFSVL_BADSERVER: return -EINVAL; |
| case AFSVL_BADPARTITION: return -EINVAL; |
| case AFSVL_REPSFULL: return -EFBIG; |
| case AFSVL_NOREPSERVER: return -ENOENT; |
| case AFSVL_DUPREPSERVER: return -EEXIST; |
| case AFSVL_RWNOTFOUND: return -ENOENT; |
| case AFSVL_BADREFCOUNT: return -EINVAL; |
| case AFSVL_SIZEEXCEEDED: return -EINVAL; |
| case AFSVL_BADENTRY: return -EINVAL; |
| case AFSVL_BADVOLIDBUMP: return -EINVAL; |
| case AFSVL_IDALREADYHASHED: return -EINVAL; |
| case AFSVL_ENTRYLOCKED: return -EBUSY; |
| case AFSVL_BADVOLOPER: return -EBADRQC; |
| case AFSVL_BADRELLOCKTYPE: return -EINVAL; |
| case AFSVL_RERELEASE: return -EREMOTEIO; |
| case AFSVL_BADSERVERFLAG: return -EINVAL; |
| case AFSVL_PERM: return -EACCES; |
| case AFSVL_NOMEM: return -EREMOTEIO; |
| |
| /* Unified AFS error table */ |
| case UAEPERM: return -EPERM; |
| case UAENOENT: return -ENOENT; |
| case UAEACCES: return -EACCES; |
| case UAEBUSY: return -EBUSY; |
| case UAEEXIST: return -EEXIST; |
| case UAENOTDIR: return -ENOTDIR; |
| case UAEISDIR: return -EISDIR; |
| case UAEFBIG: return -EFBIG; |
| case UAENOSPC: return -ENOSPC; |
| case UAEROFS: return -EROFS; |
| case UAEMLINK: return -EMLINK; |
| case UAEDEADLK: return -EDEADLK; |
| case UAENAMETOOLONG: return -ENAMETOOLONG; |
| case UAENOLCK: return -ENOLCK; |
| case UAENOTEMPTY: return -ENOTEMPTY; |
| case UAELOOP: return -ELOOP; |
| case UAEOVERFLOW: return -EOVERFLOW; |
| case UAENOMEDIUM: return -ENOMEDIUM; |
| case UAEDQUOT: return -EDQUOT; |
| |
| /* RXKAD abort codes; from include/rxrpc/packet.h. ET "RXK" == 0x1260B00 */ |
| case RXKADINCONSISTENCY: return -EPROTO; |
| case RXKADPACKETSHORT: return -EPROTO; |
| case RXKADLEVELFAIL: return -EKEYREJECTED; |
| case RXKADTICKETLEN: return -EKEYREJECTED; |
| case RXKADOUTOFSEQUENCE: return -EPROTO; |
| case RXKADNOAUTH: return -EKEYREJECTED; |
| case RXKADBADKEY: return -EKEYREJECTED; |
| case RXKADBADTICKET: return -EKEYREJECTED; |
| case RXKADUNKNOWNKEY: return -EKEYREJECTED; |
| case RXKADEXPIRED: return -EKEYEXPIRED; |
| case RXKADSEALEDINCON: return -EKEYREJECTED; |
| case RXKADDATALEN: return -EKEYREJECTED; |
| case RXKADILLEGALLEVEL: return -EKEYREJECTED; |
| |
| case RXGEN_OPCODE: return -ENOTSUPP; |
| |
| default: return -EREMOTEIO; |
| } |
| } |
| |
| /* |
| * Select the error to report from a set of errors. |
| */ |
| void afs_prioritise_error(struct afs_error *e, int error, u32 abort_code) |
| { |
| switch (error) { |
| case 0: |
| return; |
| default: |
| if (e->error == -ETIMEDOUT || |
| e->error == -ETIME) |
| return; |
| fallthrough; |
| case -ETIMEDOUT: |
| case -ETIME: |
| if (e->error == -ENOMEM || |
| e->error == -ENONET) |
| return; |
| fallthrough; |
| case -ENOMEM: |
| case -ENONET: |
| if (e->error == -ERFKILL) |
| return; |
| fallthrough; |
| case -ERFKILL: |
| if (e->error == -EADDRNOTAVAIL) |
| return; |
| fallthrough; |
| case -EADDRNOTAVAIL: |
| if (e->error == -ENETUNREACH) |
| return; |
| fallthrough; |
| case -ENETUNREACH: |
| if (e->error == -EHOSTUNREACH) |
| return; |
| fallthrough; |
| case -EHOSTUNREACH: |
| if (e->error == -EHOSTDOWN) |
| return; |
| fallthrough; |
| case -EHOSTDOWN: |
| if (e->error == -ECONNREFUSED) |
| return; |
| fallthrough; |
| case -ECONNREFUSED: |
| if (e->error == -ECONNRESET) |
| return; |
| fallthrough; |
| case -ECONNRESET: /* Responded, but call expired. */ |
| if (e->responded) |
| return; |
| e->error = error; |
| return; |
| |
| case -ECONNABORTED: |
| error = afs_abort_to_error(abort_code); |
| fallthrough; |
| case -ENETRESET: /* Responded, but we seem to have changed address */ |
| e->responded = true; |
| e->error = error; |
| return; |
| } |
| } |