Print this page
OS-20 share_nfs(1m) charset handling is unreliable
OS-22 Page fault at nfscmd_dropped_entrysize+0x1e()
OS-23 NFSv2/3/4: READDIR responses are inconsistent when charset conversion fails
OS-24 rfs3_readdir(): Issues related to nfscmd_convdirent()
Reviewed by: Jan Kryl <jan.kryl@nexenta.com>
Reviewed by: Gordon Ross <gordon.ross@nexenta.com>

@@ -25,10 +25,13 @@
 
 /*
  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
+/*
+ * Copyright 2013 Nexenta Systems, Inc.  All rights reserved.
+ */
 
 #include <sys/param.h>
 #include <sys/types.h>
 #include <sys/systm.h>
 #include <sys/cred.h>

@@ -772,15 +775,10 @@
                                 }
                         }
                 }
 
 reencode_attrs:
-                /* encode the BOOLEAN for the existence of the next entry */
-                IXDR_PUT_U_INT32(ptr, true);
-                /* encode the COOKIE for the entry */
-                IXDR_PUT_U_HYPER(ptr, dp->d_off);
-
                 name = nfscmd_convname(ca, cs->exi, dp->d_name,
                     NFSCMD_CONV_OUTBOUND, MAXPATHLEN + 1);
 
                 if (name == NULL) {
                         rddir_next_offset = dp->d_off;

@@ -792,25 +790,15 @@
                 rndup = RNDUP(namelen) / BYTES_PER_XDR_UNIT;
 
                 /* room for LENGTH + string ? */
                 if ((ptr + (1 + rndup)) > ptr_redzone) {
                         no_space = TRUE;
+                        if (name != dp->d_name)
+                                kmem_free(name, MAXPATHLEN + 1);
                         continue;
                 }
 
-                /* encode the LENGTH of the name */
-                IXDR_PUT_U_INT32(ptr, namelen);
-                /* encode the RNDUP FILL first */
-                ptr[rndup - 1] = 0;
-                /* encode the NAME of the entry */
-                bcopy(name, (char *)ptr, namelen);
-                /* now bump the ptr after... */
-                ptr += rndup;
-
-                if (name != dp->d_name)
-                        kmem_free(name, MAXPATHLEN + 1);
-
                 /*
                  * Keep checking on the dircount to see if we have
                  * reached the limit; from the RFC, dircount is to be
                  * the XDR encoded limit of the cookie plus name.
                  * So the count is the name, XDR_UNIT of length for

@@ -819,13 +807,32 @@
                  * client's APIs.
                  */
                 dircount -= DIRENT64_RECLEN(namelen);
                 if (nents != 0 && dircount < 0) {
                         no_space = TRUE;
+                        if (name != dp->d_name)
+                                kmem_free(name, MAXPATHLEN + 1);
                         continue;
                 }
 
+                /* encode the BOOLEAN for the existence of the next entry */
+                IXDR_PUT_U_INT32(ptr, true);
+                /* encode the COOKIE for the entry */
+                IXDR_PUT_U_HYPER(ptr, dp->d_off);
+
+                /* encode the LENGTH of the name */
+                IXDR_PUT_U_INT32(ptr, namelen);
+                /* encode the RNDUP FILL first */
+                ptr[rndup - 1] = 0;
+                /* encode the NAME of the entry */
+                bcopy(name, (char *)ptr, namelen);
+                /* now bump the ptr after... */
+                ptr += rndup;
+
+                if (name != dp->d_name)
+                        kmem_free(name, MAXPATHLEN + 1);
+
                 /*
                  * Attributes requested?
                  * Gather up the attribute info and the previous VOP_LOOKUP()
                  * succeeded; if an error occurs on the VOP_GETATTR() then
                  * return just the error (again if it is requested).