LCOV - code coverage report
Current view: top level - fs/nfs - nfs2xdr.c (source / functions) Hit Total Coverage
Test: combined.info Lines: 0 266 0.0 %
Date: 2022-04-01 13:59:58 Functions: 0 32 0.0 %
Branches: 0 84 0.0 %

           Branch data     Line data    Source code
       1                 :            : // SPDX-License-Identifier: GPL-2.0
       2                 :            : /*
       3                 :            :  * linux/fs/nfs/nfs2xdr.c
       4                 :            :  *
       5                 :            :  * XDR functions to encode/decode NFS RPC arguments and results.
       6                 :            :  *
       7                 :            :  * Copyright (C) 1992, 1993, 1994  Rick Sladkey
       8                 :            :  * Copyright (C) 1996 Olaf Kirch
       9                 :            :  * 04 Aug 1998  Ion Badulescu <ionut@cs.columbia.edu>
      10                 :            :  *              FIFO's need special handling in NFSv2
      11                 :            :  */
      12                 :            : 
      13                 :            : #include <linux/param.h>
      14                 :            : #include <linux/time.h>
      15                 :            : #include <linux/mm.h>
      16                 :            : #include <linux/errno.h>
      17                 :            : #include <linux/string.h>
      18                 :            : #include <linux/in.h>
      19                 :            : #include <linux/pagemap.h>
      20                 :            : #include <linux/proc_fs.h>
      21                 :            : #include <linux/sunrpc/clnt.h>
      22                 :            : #include <linux/nfs.h>
      23                 :            : #include <linux/nfs2.h>
      24                 :            : #include <linux/nfs_fs.h>
      25                 :            : #include "nfstrace.h"
      26                 :            : #include "internal.h"
      27                 :            : 
      28                 :            : #define NFSDBG_FACILITY         NFSDBG_XDR
      29                 :            : 
      30                 :            : /* Mapping from NFS error code to "errno" error code. */
      31                 :            : #define errno_NFSERR_IO         EIO
      32                 :            : 
      33                 :            : /*
      34                 :            :  * Declare the space requirements for NFS arguments and replies as
      35                 :            :  * number of 32bit-words
      36                 :            :  */
      37                 :            : #define NFS_fhandle_sz          (8)
      38                 :            : #define NFS_sattr_sz            (8)
      39                 :            : #define NFS_filename_sz         (1+(NFS2_MAXNAMLEN>>2))
      40                 :            : #define NFS_path_sz             (1+(NFS2_MAXPATHLEN>>2))
      41                 :            : #define NFS_fattr_sz            (17)
      42                 :            : #define NFS_info_sz             (5)
      43                 :            : #define NFS_entry_sz            (NFS_filename_sz+3)
      44                 :            : 
      45                 :            : #define NFS_diropargs_sz        (NFS_fhandle_sz+NFS_filename_sz)
      46                 :            : #define NFS_removeargs_sz       (NFS_fhandle_sz+NFS_filename_sz)
      47                 :            : #define NFS_sattrargs_sz        (NFS_fhandle_sz+NFS_sattr_sz)
      48                 :            : #define NFS_readlinkargs_sz     (NFS_fhandle_sz)
      49                 :            : #define NFS_readargs_sz         (NFS_fhandle_sz+3)
      50                 :            : #define NFS_writeargs_sz        (NFS_fhandle_sz+4)
      51                 :            : #define NFS_createargs_sz       (NFS_diropargs_sz+NFS_sattr_sz)
      52                 :            : #define NFS_renameargs_sz       (NFS_diropargs_sz+NFS_diropargs_sz)
      53                 :            : #define NFS_linkargs_sz         (NFS_fhandle_sz+NFS_diropargs_sz)
      54                 :            : #define NFS_symlinkargs_sz      (NFS_diropargs_sz+1+NFS_sattr_sz)
      55                 :            : #define NFS_readdirargs_sz      (NFS_fhandle_sz+2)
      56                 :            : 
      57                 :            : #define NFS_attrstat_sz         (1+NFS_fattr_sz)
      58                 :            : #define NFS_diropres_sz         (1+NFS_fhandle_sz+NFS_fattr_sz)
      59                 :            : #define NFS_readlinkres_sz      (2+1)
      60                 :            : #define NFS_readres_sz          (1+NFS_fattr_sz+1+1)
      61                 :            : #define NFS_writeres_sz         (NFS_attrstat_sz)
      62                 :            : #define NFS_stat_sz             (1)
      63                 :            : #define NFS_readdirres_sz       (1+1)
      64                 :            : #define NFS_statfsres_sz        (1+NFS_info_sz)
      65                 :            : 
      66                 :            : static int nfs_stat_to_errno(enum nfs_stat);
      67                 :            : 
      68                 :            : /*
      69                 :            :  * Encode/decode NFSv2 basic data types
      70                 :            :  *
      71                 :            :  * Basic NFSv2 data types are defined in section 2.3 of RFC 1094:
      72                 :            :  * "NFS: Network File System Protocol Specification".
      73                 :            :  *
      74                 :            :  * Not all basic data types have their own encoding and decoding
      75                 :            :  * functions.  For run-time efficiency, some data types are encoded
      76                 :            :  * or decoded inline.
      77                 :            :  */
      78                 :            : 
      79                 :            : static struct user_namespace *rpc_userns(const struct rpc_clnt *clnt)
      80                 :            : {
      81                 :            :         if (clnt && clnt->cl_cred)
      82                 :            :                 return clnt->cl_cred->user_ns;
      83                 :            :         return &init_user_ns;
      84                 :            : }
      85                 :            : 
      86                 :          0 : static struct user_namespace *rpc_rqst_userns(const struct rpc_rqst *rqstp)
      87                 :            : {
      88                 :          0 :         if (rqstp->rq_task)
      89                 :            :                 return rpc_userns(rqstp->rq_task->tk_client);
      90                 :            :         return &init_user_ns;
      91                 :            : }
      92                 :            : 
      93                 :            : /*
      94                 :            :  *      typedef opaque  nfsdata<>;
      95                 :            :  */
      96                 :            : static int decode_nfsdata(struct xdr_stream *xdr, struct nfs_pgio_res *result)
      97                 :            : {
      98                 :            :         u32 recvd, count;
      99                 :            :         __be32 *p;
     100                 :            : 
     101                 :            :         p = xdr_inline_decode(xdr, 4);
     102                 :            :         if (unlikely(!p))
     103                 :            :                 return -EIO;
     104                 :            :         count = be32_to_cpup(p);
     105                 :            :         recvd = xdr_read_pages(xdr, count);
     106                 :            :         if (unlikely(count > recvd))
     107                 :            :                 goto out_cheating;
     108                 :            : out:
     109                 :            :         result->eof = 0;     /* NFSv2 does not pass EOF flag on the wire. */
     110                 :            :         result->count = count;
     111                 :            :         return count;
     112                 :            : out_cheating:
     113                 :            :         dprintk("NFS: server cheating in read result: "
     114                 :            :                 "count %u > recvd %u\n", count, recvd);
     115                 :            :         count = recvd;
     116                 :            :         goto out;
     117                 :            : }
     118                 :            : 
     119                 :            : /*
     120                 :            :  *      enum stat {
     121                 :            :  *              NFS_OK = 0,
     122                 :            :  *              NFSERR_PERM = 1,
     123                 :            :  *              NFSERR_NOENT = 2,
     124                 :            :  *              NFSERR_IO = 5,
     125                 :            :  *              NFSERR_NXIO = 6,
     126                 :            :  *              NFSERR_ACCES = 13,
     127                 :            :  *              NFSERR_EXIST = 17,
     128                 :            :  *              NFSERR_NODEV = 19,
     129                 :            :  *              NFSERR_NOTDIR = 20,
     130                 :            :  *              NFSERR_ISDIR = 21,
     131                 :            :  *              NFSERR_FBIG = 27,
     132                 :            :  *              NFSERR_NOSPC = 28,
     133                 :            :  *              NFSERR_ROFS = 30,
     134                 :            :  *              NFSERR_NAMETOOLONG = 63,
     135                 :            :  *              NFSERR_NOTEMPTY = 66,
     136                 :            :  *              NFSERR_DQUOT = 69,
     137                 :            :  *              NFSERR_STALE = 70,
     138                 :            :  *              NFSERR_WFLUSH = 99
     139                 :            :  *      };
     140                 :            :  */
     141                 :          0 : static int decode_stat(struct xdr_stream *xdr, enum nfs_stat *status)
     142                 :            : {
     143                 :          0 :         __be32 *p;
     144                 :            : 
     145                 :          0 :         p = xdr_inline_decode(xdr, 4);
     146         [ #  # ]:          0 :         if (unlikely(!p))
     147                 :            :                 return -EIO;
     148         [ #  # ]:          0 :         if (unlikely(*p != cpu_to_be32(NFS_OK)))
     149                 :          0 :                 goto out_status;
     150                 :          0 :         *status = 0;
     151                 :          0 :         return 0;
     152                 :            : out_status:
     153                 :          0 :         *status = be32_to_cpup(p);
     154                 :          0 :         trace_nfs_xdr_status(xdr, (int)*status);
     155                 :          0 :         return 0;
     156                 :            : }
     157                 :            : 
     158                 :            : /*
     159                 :            :  * 2.3.2.  ftype
     160                 :            :  *
     161                 :            :  *      enum ftype {
     162                 :            :  *              NFNON = 0,
     163                 :            :  *              NFREG = 1,
     164                 :            :  *              NFDIR = 2,
     165                 :            :  *              NFBLK = 3,
     166                 :            :  *              NFCHR = 4,
     167                 :            :  *              NFLNK = 5
     168                 :            :  *      };
     169                 :            :  *
     170                 :            :  */
     171                 :            : static __be32 *xdr_decode_ftype(__be32 *p, u32 *type)
     172                 :            : {
     173                 :            :         *type = be32_to_cpup(p++);
     174                 :            :         if (unlikely(*type > NF2FIFO))
     175                 :            :                 *type = NFBAD;
     176                 :            :         return p;
     177                 :            : }
     178                 :            : 
     179                 :            : /*
     180                 :            :  * 2.3.3.  fhandle
     181                 :            :  *
     182                 :            :  *      typedef opaque fhandle[FHSIZE];
     183                 :            :  */
     184                 :          0 : static void encode_fhandle(struct xdr_stream *xdr, const struct nfs_fh *fh)
     185                 :            : {
     186                 :          0 :         __be32 *p;
     187                 :            : 
     188                 :          0 :         p = xdr_reserve_space(xdr, NFS2_FHSIZE);
     189                 :          0 :         memcpy(p, fh->data, NFS2_FHSIZE);
     190                 :          0 : }
     191                 :            : 
     192                 :          0 : static int decode_fhandle(struct xdr_stream *xdr, struct nfs_fh *fh)
     193                 :            : {
     194                 :          0 :         __be32 *p;
     195                 :            : 
     196                 :          0 :         p = xdr_inline_decode(xdr, NFS2_FHSIZE);
     197         [ #  # ]:          0 :         if (unlikely(!p))
     198                 :            :                 return -EIO;
     199                 :          0 :         fh->size = NFS2_FHSIZE;
     200                 :          0 :         memcpy(fh->data, p, NFS2_FHSIZE);
     201                 :          0 :         return 0;
     202                 :            : }
     203                 :            : 
     204                 :            : /*
     205                 :            :  * 2.3.4.  timeval
     206                 :            :  *
     207                 :            :  *      struct timeval {
     208                 :            :  *              unsigned int seconds;
     209                 :            :  *              unsigned int useconds;
     210                 :            :  *      };
     211                 :            :  */
     212                 :            : static __be32 *xdr_encode_time(__be32 *p, const struct timespec64 *timep)
     213                 :            : {
     214                 :            :         *p++ = cpu_to_be32((u32)timep->tv_sec);
     215                 :            :         if (timep->tv_nsec != 0)
     216                 :            :                 *p++ = cpu_to_be32(timep->tv_nsec / NSEC_PER_USEC);
     217                 :            :         else
     218                 :            :                 *p++ = cpu_to_be32(0);
     219                 :            :         return p;
     220                 :            : }
     221                 :            : 
     222                 :            : /*
     223                 :            :  * Passing the invalid value useconds=1000000 is a Sun convention for
     224                 :            :  * "set to current server time".  It's needed to make permissions checks
     225                 :            :  * for the "touch" program across v2 mounts to Solaris and Irix servers
     226                 :            :  * work correctly.  See description of sattr in section 6.1 of "NFS
     227                 :            :  * Illustrated" by Brent Callaghan, Addison-Wesley, ISBN 0-201-32750-5.
     228                 :            :  */
     229                 :            : static __be32 *xdr_encode_current_server_time(__be32 *p,
     230                 :            :                                               const struct timespec64 *timep)
     231                 :            : {
     232                 :            :         *p++ = cpu_to_be32(timep->tv_sec);
     233                 :            :         *p++ = cpu_to_be32(1000000);
     234                 :            :         return p;
     235                 :            : }
     236                 :            : 
     237                 :            : static __be32 *xdr_decode_time(__be32 *p, struct timespec64 *timep)
     238                 :            : {
     239                 :            :         timep->tv_sec = be32_to_cpup(p++);
     240                 :            :         timep->tv_nsec = be32_to_cpup(p++) * NSEC_PER_USEC;
     241                 :            :         return p;
     242                 :            : }
     243                 :            : 
     244                 :            : /*
     245                 :            :  * 2.3.5.  fattr
     246                 :            :  *
     247                 :            :  *      struct fattr {
     248                 :            :  *              ftype           type;
     249                 :            :  *              unsigned int    mode;
     250                 :            :  *              unsigned int    nlink;
     251                 :            :  *              unsigned int    uid;
     252                 :            :  *              unsigned int    gid;
     253                 :            :  *              unsigned int    size;
     254                 :            :  *              unsigned int    blocksize;
     255                 :            :  *              unsigned int    rdev;
     256                 :            :  *              unsigned int    blocks;
     257                 :            :  *              unsigned int    fsid;
     258                 :            :  *              unsigned int    fileid;
     259                 :            :  *              timeval         atime;
     260                 :            :  *              timeval         mtime;
     261                 :            :  *              timeval         ctime;
     262                 :            :  *      };
     263                 :            :  *
     264                 :            :  */
     265                 :            : static int decode_fattr(struct xdr_stream *xdr, struct nfs_fattr *fattr,
     266                 :            :                 struct user_namespace *userns)
     267                 :            : {
     268                 :            :         u32 rdev, type;
     269                 :            :         __be32 *p;
     270                 :            : 
     271                 :            :         p = xdr_inline_decode(xdr, NFS_fattr_sz << 2);
     272                 :            :         if (unlikely(!p))
     273                 :            :                 return -EIO;
     274                 :            : 
     275                 :            :         fattr->valid |= NFS_ATTR_FATTR_V2;
     276                 :            : 
     277                 :            :         p = xdr_decode_ftype(p, &type);
     278                 :            : 
     279                 :            :         fattr->mode = be32_to_cpup(p++);
     280                 :            :         fattr->nlink = be32_to_cpup(p++);
     281                 :            :         fattr->uid = make_kuid(userns, be32_to_cpup(p++));
     282                 :            :         if (!uid_valid(fattr->uid))
     283                 :            :                 goto out_uid;
     284                 :            :         fattr->gid = make_kgid(userns, be32_to_cpup(p++));
     285                 :            :         if (!gid_valid(fattr->gid))
     286                 :            :                 goto out_gid;
     287                 :            :                 
     288                 :            :         fattr->size = be32_to_cpup(p++);
     289                 :            :         fattr->du.nfs2.blocksize = be32_to_cpup(p++);
     290                 :            : 
     291                 :            :         rdev = be32_to_cpup(p++);
     292                 :            :         fattr->rdev = new_decode_dev(rdev);
     293                 :            :         if (type == (u32)NFCHR && rdev == (u32)NFS2_FIFO_DEV) {
     294                 :            :                 fattr->mode = (fattr->mode & ~S_IFMT) | S_IFIFO;
     295                 :            :                 fattr->rdev = 0;
     296                 :            :         }
     297                 :            : 
     298                 :            :         fattr->du.nfs2.blocks = be32_to_cpup(p++);
     299                 :            :         fattr->fsid.major = be32_to_cpup(p++);
     300                 :            :         fattr->fsid.minor = 0;
     301                 :            :         fattr->fileid = be32_to_cpup(p++);
     302                 :            : 
     303                 :            :         p = xdr_decode_time(p, &fattr->atime);
     304                 :            :         p = xdr_decode_time(p, &fattr->mtime);
     305                 :            :         xdr_decode_time(p, &fattr->ctime);
     306                 :            :         fattr->change_attr = nfs_timespec_to_change_attr(&fattr->ctime);
     307                 :            : 
     308                 :            :         return 0;
     309                 :            : out_uid:
     310                 :            :         dprintk("NFS: returned invalid uid\n");
     311                 :            :         return -EINVAL;
     312                 :            : out_gid:
     313                 :            :         dprintk("NFS: returned invalid gid\n");
     314                 :            :         return -EINVAL;
     315                 :            : }
     316                 :            : 
     317                 :            : /*
     318                 :            :  * 2.3.6.  sattr
     319                 :            :  *
     320                 :            :  *      struct sattr {
     321                 :            :  *              unsigned int    mode;
     322                 :            :  *              unsigned int    uid;
     323                 :            :  *              unsigned int    gid;
     324                 :            :  *              unsigned int    size;
     325                 :            :  *              timeval         atime;
     326                 :            :  *              timeval         mtime;
     327                 :            :  *      };
     328                 :            :  */
     329                 :            : 
     330                 :            : #define NFS2_SATTR_NOT_SET      (0xffffffff)
     331                 :            : 
     332                 :            : static __be32 *xdr_time_not_set(__be32 *p)
     333                 :            : {
     334                 :            :         *p++ = cpu_to_be32(NFS2_SATTR_NOT_SET);
     335                 :            :         *p++ = cpu_to_be32(NFS2_SATTR_NOT_SET);
     336                 :            :         return p;
     337                 :            : }
     338                 :            : 
     339                 :            : static void encode_sattr(struct xdr_stream *xdr, const struct iattr *attr,
     340                 :            :                 struct user_namespace *userns)
     341                 :            : {
     342                 :            :         __be32 *p;
     343                 :            : 
     344                 :            :         p = xdr_reserve_space(xdr, NFS_sattr_sz << 2);
     345                 :            : 
     346                 :            :         if (attr->ia_valid & ATTR_MODE)
     347                 :            :                 *p++ = cpu_to_be32(attr->ia_mode);
     348                 :            :         else
     349                 :            :                 *p++ = cpu_to_be32(NFS2_SATTR_NOT_SET);
     350                 :            :         if (attr->ia_valid & ATTR_UID)
     351                 :            :                 *p++ = cpu_to_be32(from_kuid_munged(userns, attr->ia_uid));
     352                 :            :         else
     353                 :            :                 *p++ = cpu_to_be32(NFS2_SATTR_NOT_SET);
     354                 :            :         if (attr->ia_valid & ATTR_GID)
     355                 :            :                 *p++ = cpu_to_be32(from_kgid_munged(userns, attr->ia_gid));
     356                 :            :         else
     357                 :            :                 *p++ = cpu_to_be32(NFS2_SATTR_NOT_SET);
     358                 :            :         if (attr->ia_valid & ATTR_SIZE)
     359                 :            :                 *p++ = cpu_to_be32((u32)attr->ia_size);
     360                 :            :         else
     361                 :            :                 *p++ = cpu_to_be32(NFS2_SATTR_NOT_SET);
     362                 :            : 
     363                 :            :         if (attr->ia_valid & ATTR_ATIME_SET)
     364                 :            :                 p = xdr_encode_time(p, &attr->ia_atime);
     365                 :            :         else if (attr->ia_valid & ATTR_ATIME)
     366                 :            :                 p = xdr_encode_current_server_time(p, &attr->ia_atime);
     367                 :            :         else
     368                 :            :                 p = xdr_time_not_set(p);
     369                 :            :         if (attr->ia_valid & ATTR_MTIME_SET)
     370                 :            :                 xdr_encode_time(p, &attr->ia_mtime);
     371                 :            :         else if (attr->ia_valid & ATTR_MTIME)
     372                 :            :                 xdr_encode_current_server_time(p, &attr->ia_mtime);
     373                 :            :         else
     374                 :            :                 xdr_time_not_set(p);
     375                 :            : }
     376                 :            : 
     377                 :            : /*
     378                 :            :  * 2.3.7.  filename
     379                 :            :  *
     380                 :            :  *      typedef string filename<MAXNAMLEN>;
     381                 :            :  */
     382                 :          0 : static void encode_filename(struct xdr_stream *xdr,
     383                 :            :                             const char *name, u32 length)
     384                 :            : {
     385                 :          0 :         __be32 *p;
     386                 :            : 
     387         [ #  # ]:          0 :         WARN_ON_ONCE(length > NFS2_MAXNAMLEN);
     388                 :          0 :         p = xdr_reserve_space(xdr, 4 + length);
     389                 :          0 :         xdr_encode_opaque(p, name, length);
     390                 :          0 : }
     391                 :            : 
     392                 :          0 : static int decode_filename_inline(struct xdr_stream *xdr,
     393                 :            :                                   const char **name, u32 *length)
     394                 :            : {
     395                 :          0 :         __be32 *p;
     396                 :          0 :         u32 count;
     397                 :            : 
     398                 :          0 :         p = xdr_inline_decode(xdr, 4);
     399         [ #  # ]:          0 :         if (unlikely(!p))
     400                 :            :                 return -EIO;
     401         [ #  # ]:          0 :         count = be32_to_cpup(p);
     402         [ #  # ]:          0 :         if (count > NFS3_MAXNAMLEN)
     403                 :          0 :                 goto out_nametoolong;
     404                 :          0 :         p = xdr_inline_decode(xdr, count);
     405         [ #  # ]:          0 :         if (unlikely(!p))
     406                 :            :                 return -EIO;
     407                 :          0 :         *name = (const char *)p;
     408                 :          0 :         *length = count;
     409                 :          0 :         return 0;
     410                 :            : out_nametoolong:
     411                 :          0 :         dprintk("NFS: returned filename too long: %u\n", count);
     412                 :          0 :         return -ENAMETOOLONG;
     413                 :            : }
     414                 :            : 
     415                 :            : /*
     416                 :            :  * 2.3.8.  path
     417                 :            :  *
     418                 :            :  *      typedef string path<MAXPATHLEN>;
     419                 :            :  */
     420                 :          0 : static void encode_path(struct xdr_stream *xdr, struct page **pages, u32 length)
     421                 :            : {
     422                 :          0 :         __be32 *p;
     423                 :            : 
     424                 :          0 :         p = xdr_reserve_space(xdr, 4);
     425                 :          0 :         *p = cpu_to_be32(length);
     426                 :          0 :         xdr_write_pages(xdr, pages, 0, length);
     427                 :          0 : }
     428                 :            : 
     429                 :          0 : static int decode_path(struct xdr_stream *xdr)
     430                 :            : {
     431                 :          0 :         u32 length, recvd;
     432                 :          0 :         __be32 *p;
     433                 :            : 
     434                 :          0 :         p = xdr_inline_decode(xdr, 4);
     435         [ #  # ]:          0 :         if (unlikely(!p))
     436                 :            :                 return -EIO;
     437         [ #  # ]:          0 :         length = be32_to_cpup(p);
     438   [ #  #  #  # ]:          0 :         if (unlikely(length >= xdr->buf->page_len || length > NFS_MAXPATHLEN))
     439                 :          0 :                 goto out_size;
     440                 :          0 :         recvd = xdr_read_pages(xdr, length);
     441         [ #  # ]:          0 :         if (unlikely(length > recvd))
     442                 :          0 :                 goto out_cheating;
     443                 :          0 :         xdr_terminate_string(xdr->buf, length);
     444                 :          0 :         return 0;
     445                 :            : out_size:
     446                 :          0 :         dprintk("NFS: returned pathname too long: %u\n", length);
     447                 :          0 :         return -ENAMETOOLONG;
     448                 :            : out_cheating:
     449                 :          0 :         dprintk("NFS: server cheating in pathname result: "
     450                 :            :                 "length %u > received %u\n", length, recvd);
     451                 :          0 :         return -EIO;
     452                 :            : }
     453                 :            : 
     454                 :            : /*
     455                 :            :  * 2.3.9.  attrstat
     456                 :            :  *
     457                 :            :  *      union attrstat switch (stat status) {
     458                 :            :  *      case NFS_OK:
     459                 :            :  *              fattr attributes;
     460                 :            :  *      default:
     461                 :            :  *              void;
     462                 :            :  *      };
     463                 :            :  */
     464                 :            : static int decode_attrstat(struct xdr_stream *xdr, struct nfs_fattr *result,
     465                 :            :                            __u32 *op_status,
     466                 :            :                            struct user_namespace *userns)
     467                 :            : {
     468                 :            :         enum nfs_stat status;
     469                 :            :         int error;
     470                 :            : 
     471                 :            :         error = decode_stat(xdr, &status);
     472                 :            :         if (unlikely(error))
     473                 :            :                 goto out;
     474                 :            :         if (op_status)
     475                 :            :                 *op_status = status;
     476                 :            :         if (status != NFS_OK)
     477                 :            :                 goto out_default;
     478                 :            :         error = decode_fattr(xdr, result, userns);
     479                 :            : out:
     480                 :            :         return error;
     481                 :            : out_default:
     482                 :            :         return nfs_stat_to_errno(status);
     483                 :            : }
     484                 :            : 
     485                 :            : /*
     486                 :            :  * 2.3.10.  diropargs
     487                 :            :  *
     488                 :            :  *      struct diropargs {
     489                 :            :  *              fhandle  dir;
     490                 :            :  *              filename name;
     491                 :            :  *      };
     492                 :            :  */
     493                 :          0 : static void encode_diropargs(struct xdr_stream *xdr, const struct nfs_fh *fh,
     494                 :            :                              const char *name, u32 length)
     495                 :            : {
     496                 :          0 :         encode_fhandle(xdr, fh);
     497                 :          0 :         encode_filename(xdr, name, length);
     498                 :            : }
     499                 :            : 
     500                 :            : /*
     501                 :            :  * 2.3.11.  diropres
     502                 :            :  *
     503                 :            :  *      union diropres switch (stat status) {
     504                 :            :  *      case NFS_OK:
     505                 :            :  *              struct {
     506                 :            :  *                      fhandle file;
     507                 :            :  *                      fattr   attributes;
     508                 :            :  *              } diropok;
     509                 :            :  *      default:
     510                 :            :  *              void;
     511                 :            :  *      };
     512                 :            :  */
     513                 :            : static int decode_diropok(struct xdr_stream *xdr, struct nfs_diropok *result,
     514                 :            :                 struct user_namespace *userns)
     515                 :            : {
     516                 :            :         int error;
     517                 :            : 
     518                 :            :         error = decode_fhandle(xdr, result->fh);
     519                 :            :         if (unlikely(error))
     520                 :            :                 goto out;
     521                 :            :         error = decode_fattr(xdr, result->fattr, userns);
     522                 :            : out:
     523                 :            :         return error;
     524                 :            : }
     525                 :            : 
     526                 :            : static int decode_diropres(struct xdr_stream *xdr, struct nfs_diropok *result,
     527                 :            :                 struct user_namespace *userns)
     528                 :            : {
     529                 :            :         enum nfs_stat status;
     530                 :            :         int error;
     531                 :            : 
     532                 :            :         error = decode_stat(xdr, &status);
     533                 :            :         if (unlikely(error))
     534                 :            :                 goto out;
     535                 :            :         if (status != NFS_OK)
     536                 :            :                 goto out_default;
     537                 :            :         error = decode_diropok(xdr, result, userns);
     538                 :            : out:
     539                 :            :         return error;
     540                 :            : out_default:
     541                 :            :         return nfs_stat_to_errno(status);
     542                 :            : }
     543                 :            : 
     544                 :            : 
     545                 :            : /*
     546                 :            :  * NFSv2 XDR encode functions
     547                 :            :  *
     548                 :            :  * NFSv2 argument types are defined in section 2.2 of RFC 1094:
     549                 :            :  * "NFS: Network File System Protocol Specification".
     550                 :            :  */
     551                 :            : 
     552                 :          0 : static void nfs2_xdr_enc_fhandle(struct rpc_rqst *req,
     553                 :            :                                  struct xdr_stream *xdr,
     554                 :            :                                  const void *data)
     555                 :            : {
     556                 :          0 :         const struct nfs_fh *fh = data;
     557                 :            : 
     558                 :          0 :         encode_fhandle(xdr, fh);
     559                 :          0 : }
     560                 :            : 
     561                 :            : /*
     562                 :            :  * 2.2.3.  sattrargs
     563                 :            :  *
     564                 :            :  *      struct sattrargs {
     565                 :            :  *              fhandle file;
     566                 :            :  *              sattr attributes;
     567                 :            :  *      };
     568                 :            :  */
     569                 :          0 : static void nfs2_xdr_enc_sattrargs(struct rpc_rqst *req,
     570                 :            :                                    struct xdr_stream *xdr,
     571                 :            :                                    const void *data)
     572                 :            : {
     573                 :          0 :         const struct nfs_sattrargs *args = data;
     574                 :            : 
     575                 :          0 :         encode_fhandle(xdr, args->fh);
     576                 :          0 :         encode_sattr(xdr, args->sattr, rpc_rqst_userns(req));
     577                 :          0 : }
     578                 :            : 
     579                 :          0 : static void nfs2_xdr_enc_diropargs(struct rpc_rqst *req,
     580                 :            :                                    struct xdr_stream *xdr,
     581                 :            :                                    const void *data)
     582                 :            : {
     583                 :          0 :         const struct nfs_diropargs *args = data;
     584                 :            : 
     585                 :          0 :         encode_diropargs(xdr, args->fh, args->name, args->len);
     586                 :          0 : }
     587                 :            : 
     588                 :          0 : static void nfs2_xdr_enc_readlinkargs(struct rpc_rqst *req,
     589                 :            :                                       struct xdr_stream *xdr,
     590                 :            :                                       const void *data)
     591                 :            : {
     592                 :          0 :         const struct nfs_readlinkargs *args = data;
     593                 :            : 
     594                 :          0 :         encode_fhandle(xdr, args->fh);
     595                 :          0 :         rpc_prepare_reply_pages(req, args->pages, args->pgbase,
     596                 :            :                                 args->pglen, NFS_readlinkres_sz);
     597                 :          0 : }
     598                 :            : 
     599                 :            : /*
     600                 :            :  * 2.2.7.  readargs
     601                 :            :  *
     602                 :            :  *      struct readargs {
     603                 :            :  *              fhandle file;
     604                 :            :  *              unsigned offset;
     605                 :            :  *              unsigned count;
     606                 :            :  *              unsigned totalcount;
     607                 :            :  *      };
     608                 :            :  */
     609                 :          0 : static void encode_readargs(struct xdr_stream *xdr,
     610                 :            :                             const struct nfs_pgio_args *args)
     611                 :            : {
     612                 :          0 :         u32 offset = args->offset;
     613                 :          0 :         u32 count = args->count;
     614                 :          0 :         __be32 *p;
     615                 :            : 
     616                 :          0 :         encode_fhandle(xdr, args->fh);
     617                 :            : 
     618                 :          0 :         p = xdr_reserve_space(xdr, 4 + 4 + 4);
     619                 :          0 :         *p++ = cpu_to_be32(offset);
     620                 :          0 :         *p++ = cpu_to_be32(count);
     621                 :          0 :         *p = cpu_to_be32(count);
     622                 :          0 : }
     623                 :            : 
     624                 :          0 : static void nfs2_xdr_enc_readargs(struct rpc_rqst *req,
     625                 :            :                                   struct xdr_stream *xdr,
     626                 :            :                                   const void *data)
     627                 :            : {
     628                 :          0 :         const struct nfs_pgio_args *args = data;
     629                 :            : 
     630                 :          0 :         encode_readargs(xdr, args);
     631                 :          0 :         rpc_prepare_reply_pages(req, args->pages, args->pgbase,
     632                 :            :                                 args->count, NFS_readres_sz);
     633                 :          0 :         req->rq_rcv_buf.flags |= XDRBUF_READ;
     634                 :          0 : }
     635                 :            : 
     636                 :            : /*
     637                 :            :  * 2.2.9.  writeargs
     638                 :            :  *
     639                 :            :  *      struct writeargs {
     640                 :            :  *              fhandle file;
     641                 :            :  *              unsigned beginoffset;
     642                 :            :  *              unsigned offset;
     643                 :            :  *              unsigned totalcount;
     644                 :            :  *              nfsdata data;
     645                 :            :  *      };
     646                 :            :  */
     647                 :          0 : static void encode_writeargs(struct xdr_stream *xdr,
     648                 :            :                              const struct nfs_pgio_args *args)
     649                 :            : {
     650                 :          0 :         u32 offset = args->offset;
     651                 :          0 :         u32 count = args->count;
     652                 :          0 :         __be32 *p;
     653                 :            : 
     654                 :          0 :         encode_fhandle(xdr, args->fh);
     655                 :            : 
     656                 :          0 :         p = xdr_reserve_space(xdr, 4 + 4 + 4 + 4);
     657                 :          0 :         *p++ = cpu_to_be32(offset);
     658                 :          0 :         *p++ = cpu_to_be32(offset);
     659                 :          0 :         *p++ = cpu_to_be32(count);
     660                 :            : 
     661                 :            :         /* nfsdata */
     662                 :          0 :         *p = cpu_to_be32(count);
     663                 :          0 :         xdr_write_pages(xdr, args->pages, args->pgbase, count);
     664                 :          0 : }
     665                 :            : 
     666                 :          0 : static void nfs2_xdr_enc_writeargs(struct rpc_rqst *req,
     667                 :            :                                    struct xdr_stream *xdr,
     668                 :            :                                    const void *data)
     669                 :            : {
     670                 :          0 :         const struct nfs_pgio_args *args = data;
     671                 :            : 
     672                 :          0 :         encode_writeargs(xdr, args);
     673                 :          0 :         xdr->buf->flags |= XDRBUF_WRITE;
     674                 :          0 : }
     675                 :            : 
     676                 :            : /*
     677                 :            :  * 2.2.10.  createargs
     678                 :            :  *
     679                 :            :  *      struct createargs {
     680                 :            :  *              diropargs where;
     681                 :            :  *              sattr attributes;
     682                 :            :  *      };
     683                 :            :  */
     684                 :          0 : static void nfs2_xdr_enc_createargs(struct rpc_rqst *req,
     685                 :            :                                     struct xdr_stream *xdr,
     686                 :            :                                     const void *data)
     687                 :            : {
     688                 :          0 :         const struct nfs_createargs *args = data;
     689                 :            : 
     690                 :          0 :         encode_diropargs(xdr, args->fh, args->name, args->len);
     691                 :          0 :         encode_sattr(xdr, args->sattr, rpc_rqst_userns(req));
     692                 :          0 : }
     693                 :            : 
     694                 :          0 : static void nfs2_xdr_enc_removeargs(struct rpc_rqst *req,
     695                 :            :                                     struct xdr_stream *xdr,
     696                 :            :                                     const void *data)
     697                 :            : {
     698                 :          0 :         const struct nfs_removeargs *args = data;
     699                 :            : 
     700                 :          0 :         encode_diropargs(xdr, args->fh, args->name.name, args->name.len);
     701                 :          0 : }
     702                 :            : 
     703                 :            : /*
     704                 :            :  * 2.2.12.  renameargs
     705                 :            :  *
     706                 :            :  *      struct renameargs {
     707                 :            :  *              diropargs from;
     708                 :            :  *              diropargs to;
     709                 :            :  *      };
     710                 :            :  */
     711                 :          0 : static void nfs2_xdr_enc_renameargs(struct rpc_rqst *req,
     712                 :            :                                     struct xdr_stream *xdr,
     713                 :            :                                     const void *data)
     714                 :            : {
     715                 :          0 :         const struct nfs_renameargs *args = data;
     716                 :          0 :         const struct qstr *old = args->old_name;
     717                 :          0 :         const struct qstr *new = args->new_name;
     718                 :            : 
     719                 :          0 :         encode_diropargs(xdr, args->old_dir, old->name, old->len);
     720                 :          0 :         encode_diropargs(xdr, args->new_dir, new->name, new->len);
     721                 :          0 : }
     722                 :            : 
     723                 :            : /*
     724                 :            :  * 2.2.13.  linkargs
     725                 :            :  *
     726                 :            :  *      struct linkargs {
     727                 :            :  *              fhandle from;
     728                 :            :  *              diropargs to;
     729                 :            :  *      };
     730                 :            :  */
     731                 :          0 : static void nfs2_xdr_enc_linkargs(struct rpc_rqst *req,
     732                 :            :                                   struct xdr_stream *xdr,
     733                 :            :                                   const void *data)
     734                 :            : {
     735                 :          0 :         const struct nfs_linkargs *args = data;
     736                 :            : 
     737                 :          0 :         encode_fhandle(xdr, args->fromfh);
     738                 :          0 :         encode_diropargs(xdr, args->tofh, args->toname, args->tolen);
     739                 :          0 : }
     740                 :            : 
     741                 :            : /*
     742                 :            :  * 2.2.14.  symlinkargs
     743                 :            :  *
     744                 :            :  *      struct symlinkargs {
     745                 :            :  *              diropargs from;
     746                 :            :  *              path to;
     747                 :            :  *              sattr attributes;
     748                 :            :  *      };
     749                 :            :  */
     750                 :          0 : static void nfs2_xdr_enc_symlinkargs(struct rpc_rqst *req,
     751                 :            :                                      struct xdr_stream *xdr,
     752                 :            :                                      const void *data)
     753                 :            : {
     754                 :          0 :         const struct nfs_symlinkargs *args = data;
     755                 :            : 
     756                 :          0 :         encode_diropargs(xdr, args->fromfh, args->fromname, args->fromlen);
     757                 :          0 :         encode_path(xdr, args->pages, args->pathlen);
     758                 :          0 :         encode_sattr(xdr, args->sattr, rpc_rqst_userns(req));
     759                 :          0 : }
     760                 :            : 
     761                 :            : /*
     762                 :            :  * 2.2.17.  readdirargs
     763                 :            :  *
     764                 :            :  *      struct readdirargs {
     765                 :            :  *              fhandle dir;
     766                 :            :  *              nfscookie cookie;
     767                 :            :  *              unsigned count;
     768                 :            :  *      };
     769                 :            :  */
     770                 :          0 : static void encode_readdirargs(struct xdr_stream *xdr,
     771                 :            :                                const struct nfs_readdirargs *args)
     772                 :            : {
     773                 :          0 :         __be32 *p;
     774                 :            : 
     775                 :          0 :         encode_fhandle(xdr, args->fh);
     776                 :            : 
     777                 :          0 :         p = xdr_reserve_space(xdr, 4 + 4);
     778                 :          0 :         *p++ = cpu_to_be32(args->cookie);
     779                 :          0 :         *p = cpu_to_be32(args->count);
     780                 :          0 : }
     781                 :            : 
     782                 :          0 : static void nfs2_xdr_enc_readdirargs(struct rpc_rqst *req,
     783                 :            :                                      struct xdr_stream *xdr,
     784                 :            :                                      const void *data)
     785                 :            : {
     786                 :          0 :         const struct nfs_readdirargs *args = data;
     787                 :            : 
     788                 :          0 :         encode_readdirargs(xdr, args);
     789                 :          0 :         rpc_prepare_reply_pages(req, args->pages, 0,
     790                 :            :                                 args->count, NFS_readdirres_sz);
     791                 :          0 : }
     792                 :            : 
     793                 :            : /*
     794                 :            :  * NFSv2 XDR decode functions
     795                 :            :  *
     796                 :            :  * NFSv2 result types are defined in section 2.2 of RFC 1094:
     797                 :            :  * "NFS: Network File System Protocol Specification".
     798                 :            :  */
     799                 :            : 
     800                 :          0 : static int nfs2_xdr_dec_stat(struct rpc_rqst *req, struct xdr_stream *xdr,
     801                 :            :                              void *__unused)
     802                 :            : {
     803                 :          0 :         enum nfs_stat status;
     804                 :          0 :         int error;
     805                 :            : 
     806                 :          0 :         error = decode_stat(xdr, &status);
     807         [ #  # ]:          0 :         if (unlikely(error))
     808                 :          0 :                 goto out;
     809         [ #  # ]:          0 :         if (status != NFS_OK)
     810                 :          0 :                 goto out_default;
     811                 :          0 : out:
     812                 :            :         return error;
     813                 :            : out_default:
     814                 :          0 :         return nfs_stat_to_errno(status);
     815                 :            : }
     816                 :            : 
     817                 :          0 : static int nfs2_xdr_dec_attrstat(struct rpc_rqst *req, struct xdr_stream *xdr,
     818                 :            :                                  void *result)
     819                 :            : {
     820                 :          0 :         return decode_attrstat(xdr, result, NULL, rpc_rqst_userns(req));
     821                 :            : }
     822                 :            : 
     823                 :          0 : static int nfs2_xdr_dec_diropres(struct rpc_rqst *req, struct xdr_stream *xdr,
     824                 :            :                                  void *result)
     825                 :            : {
     826                 :          0 :         return decode_diropres(xdr, result, rpc_rqst_userns(req));
     827                 :            : }
     828                 :            : 
     829                 :            : /*
     830                 :            :  * 2.2.6.  readlinkres
     831                 :            :  *
     832                 :            :  *      union readlinkres switch (stat status) {
     833                 :            :  *      case NFS_OK:
     834                 :            :  *              path data;
     835                 :            :  *      default:
     836                 :            :  *              void;
     837                 :            :  *      };
     838                 :            :  */
     839                 :          0 : static int nfs2_xdr_dec_readlinkres(struct rpc_rqst *req,
     840                 :            :                                     struct xdr_stream *xdr, void *__unused)
     841                 :            : {
     842                 :          0 :         enum nfs_stat status;
     843                 :          0 :         int error;
     844                 :            : 
     845                 :          0 :         error = decode_stat(xdr, &status);
     846         [ #  # ]:          0 :         if (unlikely(error))
     847                 :          0 :                 goto out;
     848         [ #  # ]:          0 :         if (status != NFS_OK)
     849                 :          0 :                 goto out_default;
     850                 :          0 :         error = decode_path(xdr);
     851                 :            : out:
     852                 :            :         return error;
     853                 :            : out_default:
     854                 :          0 :         return nfs_stat_to_errno(status);
     855                 :            : }
     856                 :            : 
     857                 :            : /*
     858                 :            :  * 2.2.7.  readres
     859                 :            :  *
     860                 :            :  *      union readres switch (stat status) {
     861                 :            :  *      case NFS_OK:
     862                 :            :  *              fattr attributes;
     863                 :            :  *              nfsdata data;
     864                 :            :  *      default:
     865                 :            :  *              void;
     866                 :            :  *      };
     867                 :            :  */
     868                 :          0 : static int nfs2_xdr_dec_readres(struct rpc_rqst *req, struct xdr_stream *xdr,
     869                 :            :                                 void *data)
     870                 :            : {
     871                 :          0 :         struct nfs_pgio_res *result = data;
     872                 :          0 :         enum nfs_stat status;
     873                 :          0 :         int error;
     874                 :            : 
     875                 :          0 :         error = decode_stat(xdr, &status);
     876         [ #  # ]:          0 :         if (unlikely(error))
     877                 :          0 :                 goto out;
     878                 :          0 :         result->op_status = status;
     879         [ #  # ]:          0 :         if (status != NFS_OK)
     880                 :          0 :                 goto out_default;
     881                 :          0 :         error = decode_fattr(xdr, result->fattr, rpc_rqst_userns(req));
     882         [ #  # ]:          0 :         if (unlikely(error))
     883                 :          0 :                 goto out;
     884                 :          0 :         error = decode_nfsdata(xdr, result);
     885                 :            : out:
     886                 :            :         return error;
     887                 :            : out_default:
     888                 :          0 :         return nfs_stat_to_errno(status);
     889                 :            : }
     890                 :            : 
     891                 :          0 : static int nfs2_xdr_dec_writeres(struct rpc_rqst *req, struct xdr_stream *xdr,
     892                 :            :                                  void *data)
     893                 :            : {
     894                 :          0 :         struct nfs_pgio_res *result = data;
     895                 :            : 
     896                 :            :         /* All NFSv2 writes are "file sync" writes */
     897                 :          0 :         result->verf->committed = NFS_FILE_SYNC;
     898                 :          0 :         return decode_attrstat(xdr, result->fattr, &result->op_status,
     899                 :            :                         rpc_rqst_userns(req));
     900                 :            : }
     901                 :            : 
     902                 :            : /**
     903                 :            :  * nfs2_decode_dirent - Decode a single NFSv2 directory entry stored in
     904                 :            :  *                      the local page cache.
     905                 :            :  * @xdr: XDR stream where entry resides
     906                 :            :  * @entry: buffer to fill in with entry data
     907                 :            :  * @plus: boolean indicating whether this should be a readdirplus entry
     908                 :            :  *
     909                 :            :  * Returns zero if successful, otherwise a negative errno value is
     910                 :            :  * returned.
     911                 :            :  *
     912                 :            :  * This function is not invoked during READDIR reply decoding, but
     913                 :            :  * rather whenever an application invokes the getdents(2) system call
     914                 :            :  * on a directory already in our cache.
     915                 :            :  *
     916                 :            :  * 2.2.17.  entry
     917                 :            :  *
     918                 :            :  *      struct entry {
     919                 :            :  *              unsigned        fileid;
     920                 :            :  *              filename        name;
     921                 :            :  *              nfscookie       cookie;
     922                 :            :  *              entry           *nextentry;
     923                 :            :  *      };
     924                 :            :  */
     925                 :          0 : int nfs2_decode_dirent(struct xdr_stream *xdr, struct nfs_entry *entry,
     926                 :            :                        bool plus)
     927                 :            : {
     928                 :          0 :         __be32 *p;
     929                 :          0 :         int error;
     930                 :            : 
     931                 :          0 :         p = xdr_inline_decode(xdr, 4);
     932         [ #  # ]:          0 :         if (unlikely(!p))
     933                 :            :                 return -EAGAIN;
     934         [ #  # ]:          0 :         if (*p++ == xdr_zero) {
     935                 :          0 :                 p = xdr_inline_decode(xdr, 4);
     936         [ #  # ]:          0 :                 if (unlikely(!p))
     937                 :            :                         return -EAGAIN;
     938         [ #  # ]:          0 :                 if (*p++ == xdr_zero)
     939                 :            :                         return -EAGAIN;
     940                 :          0 :                 entry->eof = 1;
     941                 :          0 :                 return -EBADCOOKIE;
     942                 :            :         }
     943                 :            : 
     944                 :          0 :         p = xdr_inline_decode(xdr, 4);
     945         [ #  # ]:          0 :         if (unlikely(!p))
     946                 :            :                 return -EAGAIN;
     947                 :          0 :         entry->ino = be32_to_cpup(p);
     948                 :            : 
     949                 :          0 :         error = decode_filename_inline(xdr, &entry->name, &entry->len);
     950         [ #  # ]:          0 :         if (unlikely(error))
     951                 :            :                 return error;
     952                 :            : 
     953                 :            :         /*
     954                 :            :          * The type (size and byte order) of nfscookie isn't defined in
     955                 :            :          * RFC 1094.  This implementation assumes that it's an XDR uint32.
     956                 :            :          */
     957                 :          0 :         entry->prev_cookie = entry->cookie;
     958                 :          0 :         p = xdr_inline_decode(xdr, 4);
     959         [ #  # ]:          0 :         if (unlikely(!p))
     960                 :            :                 return -EAGAIN;
     961                 :          0 :         entry->cookie = be32_to_cpup(p);
     962                 :            : 
     963                 :          0 :         entry->d_type = DT_UNKNOWN;
     964                 :            : 
     965                 :          0 :         return 0;
     966                 :            : }
     967                 :            : 
     968                 :            : /*
     969                 :            :  * 2.2.17.  readdirres
     970                 :            :  *
     971                 :            :  *      union readdirres switch (stat status) {
     972                 :            :  *      case NFS_OK:
     973                 :            :  *              struct {
     974                 :            :  *                      entry *entries;
     975                 :            :  *                      bool eof;
     976                 :            :  *              } readdirok;
     977                 :            :  *      default:
     978                 :            :  *              void;
     979                 :            :  *      };
     980                 :            :  *
     981                 :            :  * Read the directory contents into the page cache, but don't
     982                 :            :  * touch them.  The actual decoding is done by nfs2_decode_dirent()
     983                 :            :  * during subsequent nfs_readdir() calls.
     984                 :            :  */
     985                 :          0 : static int decode_readdirok(struct xdr_stream *xdr)
     986                 :            : {
     987                 :          0 :         return xdr_read_pages(xdr, xdr->buf->page_len);
     988                 :            : }
     989                 :            : 
     990                 :          0 : static int nfs2_xdr_dec_readdirres(struct rpc_rqst *req,
     991                 :            :                                    struct xdr_stream *xdr, void *__unused)
     992                 :            : {
     993                 :          0 :         enum nfs_stat status;
     994                 :          0 :         int error;
     995                 :            : 
     996                 :          0 :         error = decode_stat(xdr, &status);
     997         [ #  # ]:          0 :         if (unlikely(error))
     998                 :          0 :                 goto out;
     999         [ #  # ]:          0 :         if (status != NFS_OK)
    1000                 :          0 :                 goto out_default;
    1001                 :          0 :         error = decode_readdirok(xdr);
    1002                 :            : out:
    1003                 :            :         return error;
    1004                 :            : out_default:
    1005                 :          0 :         return nfs_stat_to_errno(status);
    1006                 :            : }
    1007                 :            : 
    1008                 :            : /*
    1009                 :            :  * 2.2.18.  statfsres
    1010                 :            :  *
    1011                 :            :  *      union statfsres (stat status) {
    1012                 :            :  *      case NFS_OK:
    1013                 :            :  *              struct {
    1014                 :            :  *                      unsigned tsize;
    1015                 :            :  *                      unsigned bsize;
    1016                 :            :  *                      unsigned blocks;
    1017                 :            :  *                      unsigned bfree;
    1018                 :            :  *                      unsigned bavail;
    1019                 :            :  *              } info;
    1020                 :            :  *      default:
    1021                 :            :  *              void;
    1022                 :            :  *      };
    1023                 :            :  */
    1024                 :          0 : static int decode_info(struct xdr_stream *xdr, struct nfs2_fsstat *result)
    1025                 :            : {
    1026                 :          0 :         __be32 *p;
    1027                 :            : 
    1028                 :          0 :         p = xdr_inline_decode(xdr, NFS_info_sz << 2);
    1029         [ #  # ]:          0 :         if (unlikely(!p))
    1030                 :            :                 return -EIO;
    1031                 :          0 :         result->tsize  = be32_to_cpup(p++);
    1032                 :          0 :         result->bsize  = be32_to_cpup(p++);
    1033                 :          0 :         result->blocks = be32_to_cpup(p++);
    1034                 :          0 :         result->bfree  = be32_to_cpup(p++);
    1035                 :          0 :         result->bavail = be32_to_cpup(p);
    1036                 :          0 :         return 0;
    1037                 :            : }
    1038                 :            : 
    1039                 :          0 : static int nfs2_xdr_dec_statfsres(struct rpc_rqst *req, struct xdr_stream *xdr,
    1040                 :            :                                   void *result)
    1041                 :            : {
    1042                 :          0 :         enum nfs_stat status;
    1043                 :          0 :         int error;
    1044                 :            : 
    1045                 :          0 :         error = decode_stat(xdr, &status);
    1046         [ #  # ]:          0 :         if (unlikely(error))
    1047                 :          0 :                 goto out;
    1048         [ #  # ]:          0 :         if (status != NFS_OK)
    1049                 :          0 :                 goto out_default;
    1050                 :          0 :         error = decode_info(xdr, result);
    1051                 :            : out:
    1052                 :            :         return error;
    1053                 :            : out_default:
    1054                 :          0 :         return nfs_stat_to_errno(status);
    1055                 :            : }
    1056                 :            : 
    1057                 :            : 
    1058                 :            : /*
    1059                 :            :  * We need to translate between nfs status return values and
    1060                 :            :  * the local errno values which may not be the same.
    1061                 :            :  */
    1062                 :            : static const struct {
    1063                 :            :         int stat;
    1064                 :            :         int errno;
    1065                 :            : } nfs_errtbl[] = {
    1066                 :            :         { NFS_OK,               0               },
    1067                 :            :         { NFSERR_PERM,          -EPERM          },
    1068                 :            :         { NFSERR_NOENT,         -ENOENT         },
    1069                 :            :         { NFSERR_IO,            -errno_NFSERR_IO},
    1070                 :            :         { NFSERR_NXIO,          -ENXIO          },
    1071                 :            : /*      { NFSERR_EAGAIN,        -EAGAIN         }, */
    1072                 :            :         { NFSERR_ACCES,         -EACCES         },
    1073                 :            :         { NFSERR_EXIST,         -EEXIST         },
    1074                 :            :         { NFSERR_XDEV,          -EXDEV          },
    1075                 :            :         { NFSERR_NODEV,         -ENODEV         },
    1076                 :            :         { NFSERR_NOTDIR,        -ENOTDIR        },
    1077                 :            :         { NFSERR_ISDIR,         -EISDIR         },
    1078                 :            :         { NFSERR_INVAL,         -EINVAL         },
    1079                 :            :         { NFSERR_FBIG,          -EFBIG          },
    1080                 :            :         { NFSERR_NOSPC,         -ENOSPC         },
    1081                 :            :         { NFSERR_ROFS,          -EROFS          },
    1082                 :            :         { NFSERR_MLINK,         -EMLINK         },
    1083                 :            :         { NFSERR_NAMETOOLONG,   -ENAMETOOLONG   },
    1084                 :            :         { NFSERR_NOTEMPTY,      -ENOTEMPTY      },
    1085                 :            :         { NFSERR_DQUOT,         -EDQUOT         },
    1086                 :            :         { NFSERR_STALE,         -ESTALE         },
    1087                 :            :         { NFSERR_REMOTE,        -EREMOTE        },
    1088                 :            : #ifdef EWFLUSH
    1089                 :            :         { NFSERR_WFLUSH,        -EWFLUSH        },
    1090                 :            : #endif
    1091                 :            :         { NFSERR_BADHANDLE,     -EBADHANDLE     },
    1092                 :            :         { NFSERR_NOT_SYNC,      -ENOTSYNC       },
    1093                 :            :         { NFSERR_BAD_COOKIE,    -EBADCOOKIE     },
    1094                 :            :         { NFSERR_NOTSUPP,       -ENOTSUPP       },
    1095                 :            :         { NFSERR_TOOSMALL,      -ETOOSMALL      },
    1096                 :            :         { NFSERR_SERVERFAULT,   -EREMOTEIO      },
    1097                 :            :         { NFSERR_BADTYPE,       -EBADTYPE       },
    1098                 :            :         { NFSERR_JUKEBOX,       -EJUKEBOX       },
    1099                 :            :         { -1,                   -EIO            }
    1100                 :            : };
    1101                 :            : 
    1102                 :            : /**
    1103                 :            :  * nfs_stat_to_errno - convert an NFS status code to a local errno
    1104                 :            :  * @status: NFS status code to convert
    1105                 :            :  *
    1106                 :            :  * Returns a local errno value, or -EIO if the NFS status code is
    1107                 :            :  * not recognized.  This function is used jointly by NFSv2 and NFSv3.
    1108                 :            :  */
    1109                 :          0 : static int nfs_stat_to_errno(enum nfs_stat status)
    1110                 :            : {
    1111                 :          0 :         int i;
    1112                 :            : 
    1113   [ #  #  #  #  :          0 :         for (i = 0; nfs_errtbl[i].stat != -1; i++) {
          #  #  #  #  #  
                      # ]
    1114   [ #  #  #  #  :          0 :                 if (nfs_errtbl[i].stat == (int)status)
          #  #  #  #  #  
                      # ]
    1115                 :          0 :                         return nfs_errtbl[i].errno;
    1116                 :            :         }
    1117                 :          0 :         dprintk("NFS: Unrecognized nfs status value: %u\n", status);
    1118                 :          0 :         return nfs_errtbl[i].errno;
    1119                 :            : }
    1120                 :            : 
    1121                 :            : #define PROC(proc, argtype, restype, timer)                             \
    1122                 :            : [NFSPROC_##proc] = {                                                    \
    1123                 :            :         .p_proc     =  NFSPROC_##proc,                                  \
    1124                 :            :         .p_encode   =  nfs2_xdr_enc_##argtype,                          \
    1125                 :            :         .p_decode   =  nfs2_xdr_dec_##restype,                          \
    1126                 :            :         .p_arglen   =  NFS_##argtype##_sz,                              \
    1127                 :            :         .p_replen   =  NFS_##restype##_sz,                              \
    1128                 :            :         .p_timer    =  timer,                                           \
    1129                 :            :         .p_statidx  =  NFSPROC_##proc,                                  \
    1130                 :            :         .p_name     =  #proc,                                           \
    1131                 :            :         }
    1132                 :            : const struct rpc_procinfo nfs_procedures[] = {
    1133                 :            :         PROC(GETATTR,   fhandle,        attrstat,       1),
    1134                 :            :         PROC(SETATTR,   sattrargs,      attrstat,       0),
    1135                 :            :         PROC(LOOKUP,    diropargs,      diropres,       2),
    1136                 :            :         PROC(READLINK,  readlinkargs,   readlinkres,    3),
    1137                 :            :         PROC(READ,      readargs,       readres,        3),
    1138                 :            :         PROC(WRITE,     writeargs,      writeres,       4),
    1139                 :            :         PROC(CREATE,    createargs,     diropres,       0),
    1140                 :            :         PROC(REMOVE,    removeargs,     stat,           0),
    1141                 :            :         PROC(RENAME,    renameargs,     stat,           0),
    1142                 :            :         PROC(LINK,      linkargs,       stat,           0),
    1143                 :            :         PROC(SYMLINK,   symlinkargs,    stat,           0),
    1144                 :            :         PROC(MKDIR,     createargs,     diropres,       0),
    1145                 :            :         PROC(RMDIR,     diropargs,      stat,           0),
    1146                 :            :         PROC(READDIR,   readdirargs,    readdirres,     3),
    1147                 :            :         PROC(STATFS,    fhandle,        statfsres,      0),
    1148                 :            : };
    1149                 :            : 
    1150                 :            : static unsigned int nfs_version2_counts[ARRAY_SIZE(nfs_procedures)];
    1151                 :            : const struct rpc_version nfs_version2 = {
    1152                 :            :         .number                 = 2,
    1153                 :            :         .nrprocs                = ARRAY_SIZE(nfs_procedures),
    1154                 :            :         .procs                  = nfs_procedures,
    1155                 :            :         .counts                 = nfs_version2_counts,
    1156                 :            : };

Generated by: LCOV version 1.14