Skip to content
Snippets Groups Projects
nfs4xdr.c 118 KiB
Newer Older
  • Learn to ignore specific revisions
  • Benny Halevy's avatar
    Benny Halevy committed
    nfs4_xdr_dec_setacl(struct rpc_rqst *rqstp, __be32 *p,
    		    struct nfs_setaclres *res)
    
    {
    	struct xdr_stream xdr;
    	struct compound_hdr hdr;
    	int status;
    
    	xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
    	status = decode_compound_hdr(&xdr, &hdr);
    	if (status)
    		goto out;
    	status = decode_putfh(&xdr);
    	if (status)
    		goto out;
    
    	status = decode_setattr(&xdr);
    
    Linus Torvalds's avatar
    Linus Torvalds committed
    
    
    /*
     * Decode GETACL response
     */
    static int
    
    Benny Halevy's avatar
    Benny Halevy committed
    nfs4_xdr_dec_getacl(struct rpc_rqst *rqstp, __be32 *p,
    		    struct nfs_getaclres *res)
    
    {
    	struct xdr_stream xdr;
    	struct compound_hdr hdr;
    	int status;
    
    	xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
    	status = decode_compound_hdr(&xdr, &hdr);
    	if (status)
    		goto out;
    	status = decode_putfh(&xdr);
    	if (status)
    		goto out;
    
    Benny Halevy's avatar
    Benny Halevy committed
    	status = decode_getacl(&xdr, rqstp, &res->acl_len);
    
    Linus Torvalds's avatar
    Linus Torvalds committed
    /*
     * Decode CLOSE response
     */
    
    Al Viro's avatar
    Al Viro committed
    static int nfs4_xdr_dec_close(struct rpc_rqst *rqstp, __be32 *p, struct nfs_closeres *res)
    
    Linus Torvalds's avatar
    Linus Torvalds committed
    {
    
    Andy Adamson's avatar
    Andy Adamson committed
    	struct xdr_stream xdr;
    	struct compound_hdr hdr;
    	int status;
    
    	xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
    	status = decode_compound_hdr(&xdr, &hdr);
    	if (status)
    		goto out;
    	status = decode_putfh(&xdr);
    	if (status)
    		goto out;
    	status = decode_close(&xdr, res);
    
    	if (status != 0)
    		goto out;
    	/*
    	 * Note: Server may do delete on close for this file
    	 * 	in which case the getattr call will fail with
    	 * 	an ESTALE error. Shouldn't be a problem,
    	 * 	though, since fattr->valid will remain unset.
    	 */
    	decode_getfattr(&xdr, res->fattr, res->server);
    
    Linus Torvalds's avatar
    Linus Torvalds committed
    out:
    
    Andy Adamson's avatar
    Andy Adamson committed
    	return status;
    
    Linus Torvalds's avatar
    Linus Torvalds committed
    }
    
    /*
     * Decode OPEN response
     */
    
    Al Viro's avatar
    Al Viro committed
    static int nfs4_xdr_dec_open(struct rpc_rqst *rqstp, __be32 *p, struct nfs_openres *res)
    
    Linus Torvalds's avatar
    Linus Torvalds committed
    {
    
    Andy Adamson's avatar
    Andy Adamson committed
    	struct xdr_stream xdr;
    	struct compound_hdr hdr;
    	int status;
    
    	xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
    	status = decode_compound_hdr(&xdr, &hdr);
    	if (status)
    		goto out;
    	status = decode_putfh(&xdr);
    	if (status)
    		goto out;
    	status = decode_savefh(&xdr);
    	if (status)
    		goto out;
    	status = decode_open(&xdr, res);
    
    	if (decode_getfh(&xdr, &res->fh) != 0)
    
    Linus Torvalds's avatar
    Linus Torvalds committed
    		goto out;
    
    	if (decode_getfattr(&xdr, res->f_attr, res->server) != 0)
    		goto out;
    
    	if (decode_restorefh(&xdr) != 0)
    
    		goto out;
    	decode_getfattr(&xdr, res->dir_attr, res->server);
    
    Linus Torvalds's avatar
    Linus Torvalds committed
    out:
    
    Andy Adamson's avatar
    Andy Adamson committed
    	return status;
    
    Linus Torvalds's avatar
    Linus Torvalds committed
    }
    
    /*
     * Decode OPEN_CONFIRM response
     */
    
    Al Viro's avatar
    Al Viro committed
    static int nfs4_xdr_dec_open_confirm(struct rpc_rqst *rqstp, __be32 *p, struct nfs_open_confirmres *res)
    
    Linus Torvalds's avatar
    Linus Torvalds committed
    {
    
    Andy Adamson's avatar
    Andy Adamson committed
    	struct xdr_stream xdr;
    	struct compound_hdr hdr;
    	int status;
    
    	xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
    	status = decode_compound_hdr(&xdr, &hdr);
    	if (status)
    		goto out;
    	status = decode_putfh(&xdr);
    	if (status)
    		goto out;
    	status = decode_open_confirm(&xdr, res);
    
    Linus Torvalds's avatar
    Linus Torvalds committed
    out:
    
    Andy Adamson's avatar
    Andy Adamson committed
    	return status;
    
    Linus Torvalds's avatar
    Linus Torvalds committed
    }
    
    /*
     * Decode OPEN response
     */
    
    Al Viro's avatar
    Al Viro committed
    static int nfs4_xdr_dec_open_noattr(struct rpc_rqst *rqstp, __be32 *p, struct nfs_openres *res)
    
    Linus Torvalds's avatar
    Linus Torvalds committed
    {
    
    Andy Adamson's avatar
    Andy Adamson committed
    	struct xdr_stream xdr;
    	struct compound_hdr hdr;
    	int status;
    
    	xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
    	status = decode_compound_hdr(&xdr, &hdr);
    	if (status)
    		goto out;
    	status = decode_putfh(&xdr);
    	if (status)
    		goto out;
    	status = decode_open(&xdr, res);
    	if (status)
    		goto out;
    
    	decode_getfattr(&xdr, res->f_attr, res->server);
    
    Linus Torvalds's avatar
    Linus Torvalds committed
    out:
    
    Andy Adamson's avatar
    Andy Adamson committed
    	return status;
    
    Linus Torvalds's avatar
    Linus Torvalds committed
    }
    
    /*
     * Decode SETATTR response
     */
    
    Al Viro's avatar
    Al Viro committed
    static int nfs4_xdr_dec_setattr(struct rpc_rqst *rqstp, __be32 *p, struct nfs_setattrres *res)
    
    Linus Torvalds's avatar
    Linus Torvalds committed
    {
    
    Andy Adamson's avatar
    Andy Adamson committed
    	struct xdr_stream xdr;
    	struct compound_hdr hdr;
    	int status;
    
    	xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
    	status = decode_compound_hdr(&xdr, &hdr);
    	if (status)
    		goto out;
    	status = decode_putfh(&xdr);
    	if (status)
    		goto out;
    
    	status = decode_setattr(&xdr);
    
    Andy Adamson's avatar
    Andy Adamson committed
    	if (status)
    		goto out;
    
    	decode_getfattr(&xdr, res->fattr, res->server);
    
    Linus Torvalds's avatar
    Linus Torvalds committed
    out:
    
    Andy Adamson's avatar
    Andy Adamson committed
    	return status;
    
    Linus Torvalds's avatar
    Linus Torvalds committed
    }
    
    /*
     * Decode LOCK response
     */
    
    Al Viro's avatar
    Al Viro committed
    static int nfs4_xdr_dec_lock(struct rpc_rqst *rqstp, __be32 *p, struct nfs_lock_res *res)
    
    Linus Torvalds's avatar
    Linus Torvalds committed
    {
    	struct xdr_stream xdr;
    	struct compound_hdr hdr;
    	int status;
    
    	xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
    	status = decode_compound_hdr(&xdr, &hdr);
    	if (status)
    		goto out;
    	status = decode_putfh(&xdr);
    	if (status)
    		goto out;
    	status = decode_lock(&xdr, res);
    out:
    	return status;
    }
    
    /*
     * Decode LOCKT response
     */
    
    Al Viro's avatar
    Al Viro committed
    static int nfs4_xdr_dec_lockt(struct rpc_rqst *rqstp, __be32 *p, struct nfs_lockt_res *res)
    
    Linus Torvalds's avatar
    Linus Torvalds committed
    {
    	struct xdr_stream xdr;
    	struct compound_hdr hdr;
    	int status;
    
    	xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
    	status = decode_compound_hdr(&xdr, &hdr);
    	if (status)
    		goto out;
    	status = decode_putfh(&xdr);
    	if (status)
    		goto out;
    	status = decode_lockt(&xdr, res);
    out:
    	return status;
    }
    
    /*
     * Decode LOCKU response
     */
    
    Al Viro's avatar
    Al Viro committed
    static int nfs4_xdr_dec_locku(struct rpc_rqst *rqstp, __be32 *p, struct nfs_locku_res *res)
    
    Linus Torvalds's avatar
    Linus Torvalds committed
    {
    	struct xdr_stream xdr;
    	struct compound_hdr hdr;
    	int status;
    
    	xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
    	status = decode_compound_hdr(&xdr, &hdr);
    	if (status)
    		goto out;
    	status = decode_putfh(&xdr);
    	if (status)
    		goto out;
    	status = decode_locku(&xdr, res);
    out:
    	return status;
    }
    
    /*
     * Decode READLINK response
     */
    
    static int nfs4_xdr_dec_readlink(struct rpc_rqst *rqstp, __be32 *p,
    				 struct nfs4_readlink_res *res)
    
    Linus Torvalds's avatar
    Linus Torvalds committed
    {
    	struct xdr_stream xdr;
    	struct compound_hdr hdr;
    	int status;
    
    	xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
    	status = decode_compound_hdr(&xdr, &hdr);
    	if (status)
    		goto out;
    	status = decode_putfh(&xdr);
    	if (status)
    		goto out;
    	status = decode_readlink(&xdr, rqstp);
    out:
    	return status;
    }
    
    /*
     * Decode READDIR response
     */
    
    Al Viro's avatar
    Al Viro committed
    static int nfs4_xdr_dec_readdir(struct rpc_rqst *rqstp, __be32 *p, struct nfs4_readdir_res *res)
    
    Linus Torvalds's avatar
    Linus Torvalds committed
    {
    	struct xdr_stream xdr;
    	struct compound_hdr hdr;
    	int status;
    
    	xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
    	status = decode_compound_hdr(&xdr, &hdr);
    	if (status)
    		goto out;
    	status = decode_putfh(&xdr);
    	if (status)
    		goto out;
    	status = decode_readdir(&xdr, rqstp, res);
    out:
    	return status;
    }
    
    /*
     * Decode Read response
     */
    
    Al Viro's avatar
    Al Viro committed
    static int nfs4_xdr_dec_read(struct rpc_rqst *rqstp, __be32 *p, struct nfs_readres *res)
    
    Linus Torvalds's avatar
    Linus Torvalds committed
    {
    	struct xdr_stream xdr;
    	struct compound_hdr hdr;
    	int status;
    
    	xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
    	status = decode_compound_hdr(&xdr, &hdr);
    	if (status)
    		goto out;
    	status = decode_putfh(&xdr);
    	if (status)
    		goto out;
    	status = decode_read(&xdr, rqstp, res);
    	if (!status)
    		status = res->count;
    out:
    	return status;
    }
    
    /*
     * Decode WRITE response
     */
    
    Al Viro's avatar
    Al Viro committed
    static int nfs4_xdr_dec_write(struct rpc_rqst *rqstp, __be32 *p, struct nfs_writeres *res)
    
    Linus Torvalds's avatar
    Linus Torvalds committed
    {
    	struct xdr_stream xdr;
    	struct compound_hdr hdr;
    	int status;
    
    	xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
    	status = decode_compound_hdr(&xdr, &hdr);
    	if (status)
    		goto out;
    	status = decode_putfh(&xdr);
    	if (status)
    		goto out;
    	status = decode_write(&xdr, res);
    
    	if (status)
    		goto out;
    	decode_getfattr(&xdr, res->fattr, res->server);
    
    Linus Torvalds's avatar
    Linus Torvalds committed
    	if (!status)
    		status = res->count;
    out:
    	return status;
    }
    
    /*
     * Decode COMMIT response
     */
    
    Al Viro's avatar
    Al Viro committed
    static int nfs4_xdr_dec_commit(struct rpc_rqst *rqstp, __be32 *p, struct nfs_writeres *res)
    
    Linus Torvalds's avatar
    Linus Torvalds committed
    {
    	struct xdr_stream xdr;
    	struct compound_hdr hdr;
    	int status;
    
    	xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
    	status = decode_compound_hdr(&xdr, &hdr);
    	if (status)
    		goto out;
    	status = decode_putfh(&xdr);
    	if (status)
    		goto out;
    	status = decode_commit(&xdr, res);
    
    	if (status)
    		goto out;
    	decode_getfattr(&xdr, res->fattr, res->server);
    
    Linus Torvalds's avatar
    Linus Torvalds committed
    out:
    	return status;
    }
    
    /*
     * FSINFO request
     */
    
    Benny Halevy's avatar
    Benny Halevy committed
    static int nfs4_xdr_dec_fsinfo(struct rpc_rqst *req, __be32 *p,
    			       struct nfs4_fsinfo_res *res)
    
    Linus Torvalds's avatar
    Linus Torvalds committed
    {
    	struct xdr_stream xdr;
    	struct compound_hdr hdr;
    	int status;
    
    	xdr_init_decode(&xdr, &req->rq_rcv_buf, p);
    	status = decode_compound_hdr(&xdr, &hdr);
    	if (!status)
    		status = decode_putfh(&xdr);
    	if (!status)
    
    Benny Halevy's avatar
    Benny Halevy committed
    		status = decode_fsinfo(&xdr, res->fsinfo);
    
    Linus Torvalds's avatar
    Linus Torvalds committed
    	return status;
    }
    
    /*
     * PATHCONF request
     */
    
    static int nfs4_xdr_dec_pathconf(struct rpc_rqst *req, __be32 *p,
    				 struct nfs4_pathconf_res *res)
    
    Linus Torvalds's avatar
    Linus Torvalds committed
    {
    	struct xdr_stream xdr;
    	struct compound_hdr hdr;
    	int status;
    
    	xdr_init_decode(&xdr, &req->rq_rcv_buf, p);
    	status = decode_compound_hdr(&xdr, &hdr);
    	if (!status)
    		status = decode_putfh(&xdr);
    	if (!status)
    
    		status = decode_pathconf(&xdr, res->pathconf);
    
    Linus Torvalds's avatar
    Linus Torvalds committed
    	return status;
    }
    
    /*
     * STATFS request
     */
    
    Benny Halevy's avatar
    Benny Halevy committed
    static int nfs4_xdr_dec_statfs(struct rpc_rqst *req, __be32 *p,
    			       struct nfs4_statfs_res *res)
    
    Linus Torvalds's avatar
    Linus Torvalds committed
    {
    	struct xdr_stream xdr;
    	struct compound_hdr hdr;
    	int status;
    
    	xdr_init_decode(&xdr, &req->rq_rcv_buf, p);
    	status = decode_compound_hdr(&xdr, &hdr);
    	if (!status)
    		status = decode_putfh(&xdr);
    	if (!status)
    
    Benny Halevy's avatar
    Benny Halevy committed
    		status = decode_statfs(&xdr, res->fsstat);
    
    Linus Torvalds's avatar
    Linus Torvalds committed
    	return status;
    }
    
    /*
     * GETATTR_BITMAP request
     */
    
    Al Viro's avatar
    Al Viro committed
    static int nfs4_xdr_dec_server_caps(struct rpc_rqst *req, __be32 *p, struct nfs4_server_caps_res *res)
    
    Linus Torvalds's avatar
    Linus Torvalds committed
    {
    	struct xdr_stream xdr;
    	struct compound_hdr hdr;
    	int status;
    
    	xdr_init_decode(&xdr, &req->rq_rcv_buf, p);
    	if ((status = decode_compound_hdr(&xdr, &hdr)) != 0)
    		goto out;
    	if ((status = decode_putfh(&xdr)) != 0)
    		goto out;
    	status = decode_server_caps(&xdr, res);
    out:
    	return status;
    }
    
    /*
     * Decode RENEW response
     */
    
    Al Viro's avatar
    Al Viro committed
    static int nfs4_xdr_dec_renew(struct rpc_rqst *rqstp, __be32 *p, void *dummy)
    
    Linus Torvalds's avatar
    Linus Torvalds committed
    {
    	struct xdr_stream xdr;
    	struct compound_hdr hdr;
    	int status;
    
    	xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
    	status = decode_compound_hdr(&xdr, &hdr);
    	if (!status)
    		status = decode_renew(&xdr);
    	return status;
    }
    
    /*
     * a SETCLIENTID request
     */
    
    Al Viro's avatar
    Al Viro committed
    static int nfs4_xdr_dec_setclientid(struct rpc_rqst *req, __be32 *p,
    
    		struct nfs_client *clp)
    
    Linus Torvalds's avatar
    Linus Torvalds committed
    {
    	struct xdr_stream xdr;
    	struct compound_hdr hdr;
    	int status;
    
    	xdr_init_decode(&xdr, &req->rq_rcv_buf, p);
    	status = decode_compound_hdr(&xdr, &hdr);
    	if (!status)
    		status = decode_setclientid(&xdr, clp);
    	return status;
    }
    
    /*
     * a SETCLIENTID_CONFIRM request
     */
    
    Al Viro's avatar
    Al Viro committed
    static int nfs4_xdr_dec_setclientid_confirm(struct rpc_rqst *req, __be32 *p, struct nfs_fsinfo *fsinfo)
    
    Linus Torvalds's avatar
    Linus Torvalds committed
    {
    	struct xdr_stream xdr;
    	struct compound_hdr hdr;
    	int status;
    
    	xdr_init_decode(&xdr, &req->rq_rcv_buf, p);
    	status = decode_compound_hdr(&xdr, &hdr);
    	if (!status)
    		status = decode_setclientid_confirm(&xdr);
    	if (!status)
    		status = decode_putrootfh(&xdr);
    	if (!status)
    		status = decode_fsinfo(&xdr, fsinfo);
    	return status;
    }
    
    /*
     * DELEGRETURN request
     */
    
    Al Viro's avatar
    Al Viro committed
    static int nfs4_xdr_dec_delegreturn(struct rpc_rqst *rqstp, __be32 *p, struct nfs4_delegreturnres *res)
    
    Linus Torvalds's avatar
    Linus Torvalds committed
    {
    	struct xdr_stream xdr;
    	struct compound_hdr hdr;
    	int status;
    
    	xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
    	status = decode_compound_hdr(&xdr, &hdr);
    
    	if (status != 0)
    		goto out;
    	status = decode_putfh(&xdr);
    	if (status != 0)
    		goto out;
    	status = decode_delegreturn(&xdr);
    	decode_getfattr(&xdr, res->fattr, res->server);
    out:
    
    Linus Torvalds's avatar
    Linus Torvalds committed
    	return status;
    }
    
    
    static int nfs4_xdr_dec_fs_locations(struct rpc_rqst *req, __be32 *p,
    				     struct nfs4_fs_locations_res *res)
    
    {
    	struct xdr_stream xdr;
    	struct compound_hdr hdr;
    	int status;
    
    	xdr_init_decode(&xdr, &req->rq_rcv_buf, p);
    	status = decode_compound_hdr(&xdr, &hdr);
    	if (status != 0)
    		goto out;
    	if ((status = decode_putfh(&xdr)) != 0)
    		goto out;
    	if ((status = decode_lookup(&xdr)) != 0)
    		goto out;
    	xdr_enter_page(&xdr, PAGE_SIZE);
    
    	status = decode_getfattr(&xdr, &res->fs_locations->fattr,
    				 res->fs_locations->server);
    
    __be32 *nfs4_decode_dirent(__be32 *p, struct nfs_entry *entry, int plus)
    
    Linus Torvalds's avatar
    Linus Torvalds committed
    {
    	uint32_t bitmap[2] = {0};
    	uint32_t len;
    
    	if (!*p++) {
    		if (!*p)
    			return ERR_PTR(-EAGAIN);
    		entry->eof = 1;
    		return ERR_PTR(-EBADCOOKIE);
    	}
    
    	entry->prev_cookie = entry->cookie;
    	p = xdr_decode_hyper(p, &entry->cookie);
    	entry->len = ntohl(*p++);
    	entry->name = (const char *) p;
    	p += XDR_QUADLEN(entry->len);
    
    	/*
    	 * In case the server doesn't return an inode number,
    	 * we fake one here.  (We don't use inode number 0,
    	 * since glibc seems to choke on it...)
    	 */
    	entry->ino = 1;
    
    	len = ntohl(*p++);		/* bitmap length */
    	if (len-- > 0) {
    		bitmap[0] = ntohl(*p++);
    		if (len-- > 0) {
    			bitmap[1] = ntohl(*p++);
    			p += len;
    		}
    	}
    	len = XDR_QUADLEN(ntohl(*p++));	/* attribute buffer length */
    	if (len > 0) {
    
    		if (bitmap[0] & FATTR4_WORD0_RDATTR_ERROR) {
    			bitmap[0] &= ~FATTR4_WORD0_RDATTR_ERROR;
    			/* Ignore the return value of rdattr_error for now */
    			p++;
    			len--;
    		}
    
    Linus Torvalds's avatar
    Linus Torvalds committed
    		if (bitmap[0] == 0 && bitmap[1] == FATTR4_WORD1_MOUNTED_ON_FILEID)
    			xdr_decode_hyper(p, &entry->ino);
    		else if (bitmap[0] == FATTR4_WORD0_FILEID)
    			xdr_decode_hyper(p, &entry->ino);
    		p += len;
    	}
    
    	entry->eof = !p[0] && p[1];
    	return p;
    }
    
    /*
     * We need to translate between nfs status return values and
     * the local errno values which may not be the same.
     */
    static struct {
    	int stat;
    	int errno;
    } nfs_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_BADOWNER,	-EINVAL		},
    	{ NFS4ERR_BADNAME,	-EINVAL		},
    	{ NFS4ERR_BAD_COOKIE,	-EBADCOOKIE	},
    	{ NFS4ERR_NOTSUPP,	-ENOTSUPP	},
    	{ NFS4ERR_TOOSMALL,	-ETOOSMALL	},
    	{ NFS4ERR_SERVERFAULT,	-ESERVERFAULT	},
    	{ NFS4ERR_BADTYPE,	-EBADTYPE	},
    	{ NFS4ERR_LOCKED,	-EAGAIN		},
    	{ NFS4ERR_RESOURCE,	-EREMOTEIO	},
    	{ NFS4ERR_SYMLINK,	-ELOOP		},
    	{ NFS4ERR_OP_ILLEGAL,	-EOPNOTSUPP	},
    	{ NFS4ERR_DEADLOCK,	-EDEADLK	},
    	{ NFS4ERR_WRONGSEC,	-EPERM		}, /* FIXME: this needs
    
    Linus Torvalds's avatar
    Linus Torvalds committed
    						    * to be handled by a
    						    * middle-layer.
    						    */
    
    Linus Torvalds's avatar
    Linus Torvalds committed
    };
    
    /*
     * Convert an NFS error code to a local one.
     * This one is used jointly by NFSv2 and NFSv3.
     */
    static int
    
    nfs4_stat_to_errno(int stat)
    
    Linus Torvalds's avatar
    Linus Torvalds committed
    {
    	int i;
    	for (i = 0; nfs_errtbl[i].stat != -1; i++) {
    		if (nfs_errtbl[i].stat == stat)
    			return nfs_errtbl[i].errno;
    	}
    	if (stat <= 10000 || stat > 10100) {
    		/* The server is looney tunes. */
    
    Linus Torvalds's avatar
    Linus Torvalds committed
    	}
    	/* 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.
    	 */
    
    Linus Torvalds's avatar
    Linus Torvalds committed
    }
    
    #define PROC(proc, argtype, restype)				\
    [NFSPROC4_CLNT_##proc] = {					\
    	.p_proc   = NFSPROC4_COMPOUND,				\
    	.p_encode = (kxdrproc_t) nfs4_xdr_##argtype,		\
    	.p_decode = (kxdrproc_t) nfs4_xdr_##restype,		\
    
    	.p_arglen = NFS4_##argtype##_sz,			\
    	.p_replen = NFS4_##restype##_sz,			\
    
    	.p_statidx = NFSPROC4_CLNT_##proc,			\
    	.p_name   = #proc,					\
    
    Linus Torvalds's avatar
    Linus Torvalds committed
    
    struct rpc_procinfo	nfs4_procedures[] = {
      PROC(READ,		enc_read,	dec_read),
      PROC(WRITE,		enc_write,	dec_write),
      PROC(COMMIT,		enc_commit,	dec_commit),
      PROC(OPEN,		enc_open,	dec_open),
      PROC(OPEN_CONFIRM,	enc_open_confirm,	dec_open_confirm),
      PROC(OPEN_NOATTR,	enc_open_noattr,	dec_open_noattr),
      PROC(OPEN_DOWNGRADE,	enc_open_downgrade,	dec_open_downgrade),
      PROC(CLOSE,		enc_close,	dec_close),
      PROC(SETATTR,		enc_setattr,	dec_setattr),
      PROC(FSINFO,		enc_fsinfo,	dec_fsinfo),
      PROC(RENEW,		enc_renew,	dec_renew),
      PROC(SETCLIENTID,	enc_setclientid,	dec_setclientid),
      PROC(SETCLIENTID_CONFIRM,	enc_setclientid_confirm,	dec_setclientid_confirm),
      PROC(LOCK,            enc_lock,       dec_lock),
      PROC(LOCKT,           enc_lockt,      dec_lockt),
      PROC(LOCKU,           enc_locku,      dec_locku),
      PROC(ACCESS,		enc_access,	dec_access),
      PROC(GETATTR,		enc_getattr,	dec_getattr),
      PROC(LOOKUP,		enc_lookup,	dec_lookup),
      PROC(LOOKUP_ROOT,	enc_lookup_root,	dec_lookup_root),
      PROC(REMOVE,		enc_remove,	dec_remove),
      PROC(RENAME,		enc_rename,	dec_rename),
      PROC(LINK,		enc_link,	dec_link),
      PROC(SYMLINK,		enc_symlink,	dec_symlink),
      PROC(CREATE,		enc_create,	dec_create),
      PROC(PATHCONF,	enc_pathconf,	dec_pathconf),
      PROC(STATFS,		enc_statfs,	dec_statfs),
      PROC(READLINK,	enc_readlink,	dec_readlink),
      PROC(READDIR,		enc_readdir,	dec_readdir),
      PROC(SERVER_CAPS,	enc_server_caps, dec_server_caps),
      PROC(DELEGRETURN,	enc_delegreturn, dec_delegreturn),
    
      PROC(GETACL,		enc_getacl,	dec_getacl),
    
      PROC(SETACL,		enc_setacl,	dec_setacl),
    
      PROC(FS_LOCATIONS,	enc_fs_locations, dec_fs_locations),
    
    Linus Torvalds's avatar
    Linus Torvalds committed
    };
    
    struct rpc_version		nfs_version4 = {
    	.number			= 4,
    
    	.nrprocs		= ARRAY_SIZE(nfs4_procedures),
    
    Linus Torvalds's avatar
    Linus Torvalds committed
    	.procs			= nfs4_procedures
    };
    
    /*
     * Local variables:
     *  c-basic-offset: 8
     * End:
     */