Merge tag 'idmapped-mounts-v5.12' of git://git.kernel.org/pub/scm/linux/kernel/git...
[platform/kernel/linux-rpi.git] / fs / nfsd / nfsproc.c
index 0ea0554..a8d5449 100644 (file)
@@ -149,14 +149,15 @@ out:
 static __be32
 nfsd_proc_readlink(struct svc_rqst *rqstp)
 {
-       struct nfsd_readlinkargs *argp = rqstp->rq_argp;
+       struct nfsd_fhandle *argp = rqstp->rq_argp;
        struct nfsd_readlinkres *resp = rqstp->rq_resp;
+       char *buffer = page_address(*(rqstp->rq_next_page++));
 
        dprintk("nfsd: READLINK %s\n", SVCFH_fmt(&argp->fh));
 
        /* Read the symlink. */
        resp->len = NFS_MAXPATHLEN;
-       resp->status = nfsd_readlink(rqstp, &argp->fh, argp->buffer, &resp->len);
+       resp->status = nfsd_readlink(rqstp, &argp->fh, buffer, &resp->len);
 
        fh_put(&argp->fh);
        return rpc_success;
@@ -171,32 +172,36 @@ nfsd_proc_read(struct svc_rqst *rqstp)
 {
        struct nfsd_readargs *argp = rqstp->rq_argp;
        struct nfsd_readres *resp = rqstp->rq_resp;
+       unsigned int len;
        u32 eof;
+       int v;
 
        dprintk("nfsd: READ    %s %d bytes at %d\n",
                SVCFH_fmt(&argp->fh),
                argp->count, argp->offset);
 
+       argp->count = min_t(u32, argp->count, NFSSVC_MAXBLKSIZE_V2);
+
+       v = 0;
+       len = argp->count;
+       while (len > 0) {
+               struct page *page = *(rqstp->rq_next_page++);
+
+               rqstp->rq_vec[v].iov_base = page_address(page);
+               rqstp->rq_vec[v].iov_len = min_t(unsigned int, len, PAGE_SIZE);
+               len -= rqstp->rq_vec[v].iov_len;
+               v++;
+       }
+
        /* Obtain buffer pointer for payload. 19 is 1 word for
         * status, 17 words for fattr, and 1 word for the byte count.
         */
-
-       if (NFSSVC_MAXBLKSIZE_V2 < argp->count) {
-               char buf[RPC_MAX_ADDRBUFLEN];
-               printk(KERN_NOTICE
-                       "oversized read request from %s (%d bytes)\n",
-                               svc_print_addr(rqstp, buf, sizeof(buf)),
-                               argp->count);
-               argp->count = NFSSVC_MAXBLKSIZE_V2;
-       }
        svc_reserve_auth(rqstp, (19<<2) + argp->count + 4);
 
        resp->count = argp->count;
-       resp->status = nfsd_read(rqstp, fh_copy(&resp->fh, &argp->fh),
-                                argp->offset,
-                                rqstp->rq_vec, argp->vlen,
-                                &resp->count,
-                                &eof);
+       fh_copy(&resp->fh, &argp->fh);
+       resp->status = nfsd_read(rqstp, &resp->fh, argp->offset,
+                                rqstp->rq_vec, v, &resp->count, &eof);
        if (resp->status == nfs_ok)
                resp->status = fh_getattr(&resp->fh, &resp->stat);
        else if (resp->status == nfserr_jukebox)
@@ -548,6 +553,20 @@ nfsd_proc_rmdir(struct svc_rqst *rqstp)
        return rpc_success;
 }
 
+static void nfsd_init_dirlist_pages(struct svc_rqst *rqstp,
+                                   struct nfsd_readdirres *resp,
+                                   int count)
+{
+       count = min_t(u32, count, PAGE_SIZE);
+
+       /* Convert byte count to number of words (i.e. >> 2),
+        * and reserve room for the NULL ptr & eof flag (-2 words) */
+       resp->buflen = (count >> 2) - 2;
+
+       resp->buffer = page_address(*rqstp->rq_next_page);
+       rqstp->rq_next_page++;
+}
+
 /*
  * Read a portion of a directory.
  */
@@ -556,31 +575,24 @@ nfsd_proc_readdir(struct svc_rqst *rqstp)
 {
        struct nfsd_readdirargs *argp = rqstp->rq_argp;
        struct nfsd_readdirres *resp = rqstp->rq_resp;
-       int             count;
        loff_t          offset;
+       __be32          *buffer;
 
        dprintk("nfsd: READDIR  %s %d bytes at %d\n",
                SVCFH_fmt(&argp->fh),           
                argp->count, argp->cookie);
 
-       /* Shrink to the client read size */
-       count = (argp->count >> 2) - 2;
-
-       /* Make sure we've room for the NULL ptr & eof flag */
-       count -= 2;
-       if (count < 0)
-               count = 0;
+       nfsd_init_dirlist_pages(rqstp, resp, argp->count);
+       buffer = resp->buffer;
 
-       resp->buffer = argp->buffer;
        resp->offset = NULL;
-       resp->buflen = count;
        resp->common.err = nfs_ok;
        /* Read directory and encode entries on the fly */
        offset = argp->cookie;
        resp->status = nfsd_readdir(rqstp, &argp->fh, &offset,
                                    &resp->common, nfssvc_encode_entry);
 
-       resp->count = resp->buffer - argp->buffer;
+       resp->count = resp->buffer - buffer;
        if (resp->offset)
                *resp->offset = htonl(offset);
 
@@ -623,16 +635,18 @@ static const struct svc_procedure nfsd_procedures2[18] = {
                .pc_ressize = sizeof(struct nfsd_voidres),
                .pc_cachetype = RC_NOCACHE,
                .pc_xdrressize = 0,
+               .pc_name = "NULL",
        },
        [NFSPROC_GETATTR] = {
                .pc_func = nfsd_proc_getattr,
-               .pc_decode = nfssvc_decode_fhandle,
+               .pc_decode = nfssvc_decode_fhandleargs,
                .pc_encode = nfssvc_encode_attrstat,
                .pc_release = nfssvc_release_attrstat,
                .pc_argsize = sizeof(struct nfsd_fhandle),
                .pc_ressize = sizeof(struct nfsd_attrstat),
                .pc_cachetype = RC_NOCACHE,
                .pc_xdrressize = ST+AT,
+               .pc_name = "GETATTR",
        },
        [NFSPROC_SETATTR] = {
                .pc_func = nfsd_proc_setattr,
@@ -643,6 +657,7 @@ static const struct svc_procedure nfsd_procedures2[18] = {
                .pc_ressize = sizeof(struct nfsd_attrstat),
                .pc_cachetype = RC_REPLBUFF,
                .pc_xdrressize = ST+AT,
+               .pc_name = "SETATTR",
        },
        [NFSPROC_ROOT] = {
                .pc_func = nfsd_proc_root,
@@ -652,6 +667,7 @@ static const struct svc_procedure nfsd_procedures2[18] = {
                .pc_ressize = sizeof(struct nfsd_voidres),
                .pc_cachetype = RC_NOCACHE,
                .pc_xdrressize = 0,
+               .pc_name = "ROOT",
        },
        [NFSPROC_LOOKUP] = {
                .pc_func = nfsd_proc_lookup,
@@ -662,15 +678,17 @@ static const struct svc_procedure nfsd_procedures2[18] = {
                .pc_ressize = sizeof(struct nfsd_diropres),
                .pc_cachetype = RC_NOCACHE,
                .pc_xdrressize = ST+FH+AT,
+               .pc_name = "LOOKUP",
        },
        [NFSPROC_READLINK] = {
                .pc_func = nfsd_proc_readlink,
-               .pc_decode = nfssvc_decode_readlinkargs,
+               .pc_decode = nfssvc_decode_fhandleargs,
                .pc_encode = nfssvc_encode_readlinkres,
-               .pc_argsize = sizeof(struct nfsd_readlinkargs),
+               .pc_argsize = sizeof(struct nfsd_fhandle),
                .pc_ressize = sizeof(struct nfsd_readlinkres),
                .pc_cachetype = RC_NOCACHE,
                .pc_xdrressize = ST+1+NFS_MAXPATHLEN/4,
+               .pc_name = "READLINK",
        },
        [NFSPROC_READ] = {
                .pc_func = nfsd_proc_read,
@@ -681,6 +699,7 @@ static const struct svc_procedure nfsd_procedures2[18] = {
                .pc_ressize = sizeof(struct nfsd_readres),
                .pc_cachetype = RC_NOCACHE,
                .pc_xdrressize = ST+AT+1+NFSSVC_MAXBLKSIZE_V2/4,
+               .pc_name = "READ",
        },
        [NFSPROC_WRITECACHE] = {
                .pc_func = nfsd_proc_writecache,
@@ -690,6 +709,7 @@ static const struct svc_procedure nfsd_procedures2[18] = {
                .pc_ressize = sizeof(struct nfsd_voidres),
                .pc_cachetype = RC_NOCACHE,
                .pc_xdrressize = 0,
+               .pc_name = "WRITECACHE",
        },
        [NFSPROC_WRITE] = {
                .pc_func = nfsd_proc_write,
@@ -700,6 +720,7 @@ static const struct svc_procedure nfsd_procedures2[18] = {
                .pc_ressize = sizeof(struct nfsd_attrstat),
                .pc_cachetype = RC_REPLBUFF,
                .pc_xdrressize = ST+AT,
+               .pc_name = "WRITE",
        },
        [NFSPROC_CREATE] = {
                .pc_func = nfsd_proc_create,
@@ -710,6 +731,7 @@ static const struct svc_procedure nfsd_procedures2[18] = {
                .pc_ressize = sizeof(struct nfsd_diropres),
                .pc_cachetype = RC_REPLBUFF,
                .pc_xdrressize = ST+FH+AT,
+               .pc_name = "CREATE",
        },
        [NFSPROC_REMOVE] = {
                .pc_func = nfsd_proc_remove,
@@ -719,6 +741,7 @@ static const struct svc_procedure nfsd_procedures2[18] = {
                .pc_ressize = sizeof(struct nfsd_stat),
                .pc_cachetype = RC_REPLSTAT,
                .pc_xdrressize = ST,
+               .pc_name = "REMOVE",
        },
        [NFSPROC_RENAME] = {
                .pc_func = nfsd_proc_rename,
@@ -728,6 +751,7 @@ static const struct svc_procedure nfsd_procedures2[18] = {
                .pc_ressize = sizeof(struct nfsd_stat),
                .pc_cachetype = RC_REPLSTAT,
                .pc_xdrressize = ST,
+               .pc_name = "RENAME",
        },
        [NFSPROC_LINK] = {
                .pc_func = nfsd_proc_link,
@@ -737,6 +761,7 @@ static const struct svc_procedure nfsd_procedures2[18] = {
                .pc_ressize = sizeof(struct nfsd_stat),
                .pc_cachetype = RC_REPLSTAT,
                .pc_xdrressize = ST,
+               .pc_name = "LINK",
        },
        [NFSPROC_SYMLINK] = {
                .pc_func = nfsd_proc_symlink,
@@ -746,6 +771,7 @@ static const struct svc_procedure nfsd_procedures2[18] = {
                .pc_ressize = sizeof(struct nfsd_stat),
                .pc_cachetype = RC_REPLSTAT,
                .pc_xdrressize = ST,
+               .pc_name = "SYMLINK",
        },
        [NFSPROC_MKDIR] = {
                .pc_func = nfsd_proc_mkdir,
@@ -756,6 +782,7 @@ static const struct svc_procedure nfsd_procedures2[18] = {
                .pc_ressize = sizeof(struct nfsd_diropres),
                .pc_cachetype = RC_REPLBUFF,
                .pc_xdrressize = ST+FH+AT,
+               .pc_name = "MKDIR",
        },
        [NFSPROC_RMDIR] = {
                .pc_func = nfsd_proc_rmdir,
@@ -765,6 +792,7 @@ static const struct svc_procedure nfsd_procedures2[18] = {
                .pc_ressize = sizeof(struct nfsd_stat),
                .pc_cachetype = RC_REPLSTAT,
                .pc_xdrressize = ST,
+               .pc_name = "RMDIR",
        },
        [NFSPROC_READDIR] = {
                .pc_func = nfsd_proc_readdir,
@@ -773,15 +801,17 @@ static const struct svc_procedure nfsd_procedures2[18] = {
                .pc_argsize = sizeof(struct nfsd_readdirargs),
                .pc_ressize = sizeof(struct nfsd_readdirres),
                .pc_cachetype = RC_NOCACHE,
+               .pc_name = "READDIR",
        },
        [NFSPROC_STATFS] = {
                .pc_func = nfsd_proc_statfs,
-               .pc_decode = nfssvc_decode_fhandle,
+               .pc_decode = nfssvc_decode_fhandleargs,
                .pc_encode = nfssvc_encode_statfsres,
                .pc_argsize = sizeof(struct nfsd_fhandle),
                .pc_ressize = sizeof(struct nfsd_statfsres),
                .pc_cachetype = RC_NOCACHE,
                .pc_xdrressize = ST+5,
+               .pc_name = "STATFS",
        },
 };