Author: mav
Date: Thu Jul  4 15:21:27 2013
New Revision: 252701
URL: http://svnweb.freebsd.org/changeset/base/252701

Log:
  MFC  r240780, r252468:
  Make nfs_readdir() more careful about using response data, cached in global
  buffer. For now it fixes bug when following `ls` command will return data
  from previous one aborted by pager. Also it should allow to read several
  directories same time, for example, for recursive tracerse.

Modified:
  stable/9/lib/libstand/nfs.c
Directory Properties:
  stable/9/lib/libstand/   (props changed)

Modified: stable/9/lib/libstand/nfs.c
==============================================================================
--- stable/9/lib/libstand/nfs.c Thu Jul  4 15:19:45 2013        (r252700)
+++ stable/9/lib/libstand/nfs.c Thu Jul  4 15:21:27 2013        (r252701)
@@ -181,6 +181,7 @@ struct nfs_iodesc {
        uint32_t fhsize;
        u_char fh[NFS_V3MAXFHSIZE];
        struct nfsv3_fattrs fa; /* all in network order */
+       uint64_t cookie;
 };
 #endif /* OLD_NFSV2 */
 
@@ -755,6 +756,7 @@ nfs_readdir(struct open_file *f, struct 
        struct nfs_readdir_data *rd;
        struct nfs_readdir_off  *roff = NULL;
        static char *buf;
+       static struct nfs_iodesc *pfp = NULL;
        static n_long cookie = 0;
        size_t cc;
        n_long eof;
@@ -768,13 +770,14 @@ nfs_readdir(struct open_file *f, struct 
                u_char d[NFS_READDIRSIZE];
        } rdata;
 
-       if (cookie == 0) {
+       if (fp != pfp || fp->off != cookie) {
+               pfp = NULL;
        refill:
                args = &sdata.d;
                bzero(args, sizeof(*args));
 
                bcopy(fp->fh, args->fh, NFS_FHSIZE);
-               args->cookie = htonl(cookie);
+               args->cookie = htonl(fp->off);
                args->count  = htonl(NFS_READDIRSIZE);
 
                cc = rpc_call(fp->iodesc, NFS_PROG, NFS_VER2, NFSPROC_READDIR,
@@ -784,6 +787,8 @@ nfs_readdir(struct open_file *f, struct 
                roff = (struct nfs_readdir_off *)buf;
                if (ntohl(roff->cookie) != 0)
                        return EIO;
+               pfp = fp;
+               cookie = fp->off;
        }
        roff = (struct nfs_readdir_off *)buf;
 
@@ -804,7 +809,7 @@ nfs_readdir(struct open_file *f, struct 
 
        buf += (sizeof(struct nfs_readdir_data) + roundup(htonl(rd->len),4));
        roff = (struct nfs_readdir_off *)buf;
-       cookie = ntohl(roff->cookie);
+       fp->off = cookie = ntohl(roff->cookie);
        return 0;
 }
 #else  /* !OLD_NFSV2 */
@@ -1260,6 +1265,7 @@ out:
 #endif
        if (!error) {
                currfd->off = 0;
+               currfd->cookie = 0;
                f->f_fsdata = (void *)currfd;
                return (0);
        }
@@ -1398,11 +1404,9 @@ nfs_readdir(struct open_file *f, struct 
        struct nfsv3_readdir_repl *repl;
        struct nfsv3_readdir_entry *rent;
        static char *buf;
-       static uint32_t cookie0 = 0;
-       static uint32_t cookie1 = 0;
+       static struct nfs_iodesc *pfp = NULL;
+       static uint64_t cookie = 0;
        size_t cc;
-       static uint32_t cookieverf0 = 0;
-       static uint32_t cookieverf1 = 0;
        int pos;
 
        struct args {
@@ -1418,7 +1422,8 @@ nfs_readdir(struct open_file *f, struct 
                u_char d[NFS_READDIRSIZE];
        } rdata;
 
-       if (cookie0 == 0 && cookie1 == 0) {
+       if (fp != pfp || fp->off != cookie) {
+               pfp = NULL;
        refill:
                args = &sdata.d;
                bzero(args, sizeof(*args));
@@ -1426,10 +1431,10 @@ nfs_readdir(struct open_file *f, struct 
                args->fhsize = htonl(fp->fhsize);
                bcopy(fp->fh, args->fhpluscookie, fp->fhsize);
                pos = roundup(fp->fhsize, sizeof(uint32_t)) / sizeof(uint32_t);
-               args->fhpluscookie[pos++] = cookie0;
-               args->fhpluscookie[pos++] = cookie1;
-               args->fhpluscookie[pos++] = cookieverf0;
-               args->fhpluscookie[pos++] = cookieverf1;
+               args->fhpluscookie[pos++] = htonl(fp->off >> 32);
+               args->fhpluscookie[pos++] = htonl(fp->off);
+               args->fhpluscookie[pos++] = htonl(fp->cookie >> 32);
+               args->fhpluscookie[pos++] = htonl(fp->cookie);
                args->fhpluscookie[pos] = htonl(NFS_READDIRSIZE);
 
                cc = rpc_call(fp->iodesc, NFS_PROG, NFS_VER3, NFSPROCV3_READDIR,
@@ -1440,8 +1445,10 @@ nfs_readdir(struct open_file *f, struct 
                repl = (struct nfsv3_readdir_repl *)buf;
                if (repl->errno != 0)
                        return (ntohl(repl->errno));
-               cookieverf0 = repl->cookiev0;
-               cookieverf1 = repl->cookiev1;
+               pfp = fp;
+               cookie = fp->off;
+               fp->cookie = ((uint64_t)ntohl(repl->cookiev0) << 32) |
+                   ntohl(repl->cookiev1);
                buf += sizeof (struct nfsv3_readdir_repl);
        }
        rent = (struct nfsv3_readdir_entry *)buf;
@@ -1449,10 +1456,7 @@ nfs_readdir(struct open_file *f, struct 
        if (rent->follows == 0) {
                /* fid0 is actually eof */
                if (rent->fid0 != 0) {
-                       cookie0 = 0;
-                       cookie1 = 0;
-                       cookieverf0 = 0;
-                       cookieverf1 = 0;
+                       cookie = 0;
                        return (ENOENT);
                }
                goto refill;
@@ -1463,8 +1467,9 @@ nfs_readdir(struct open_file *f, struct 
        d->d_name[d->d_namlen] = '\0';
 
        pos = roundup(d->d_namlen, sizeof(uint32_t)) / sizeof(uint32_t);
-       cookie0 = rent->nameplus[pos++];
-       cookie1 = rent->nameplus[pos++];
+       fp->off = cookie = ((uint64_t)ntohl(rent->nameplus[pos]) << 32) |
+           ntohl(rent->nameplus[pos + 1]);
+       pos += 2;
        buf = (u_char *)&rent->nameplus[pos];
        return (0);
 }
_______________________________________________
[email protected] mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-stable-9
To unsubscribe, send any mail to "[email protected]"

Reply via email to