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,34 ****
--- 25,37 ----
  
  /*
   * 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,786 ****
                                  }
                          }
                  }
  
  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;
--- 775,784 ----
*** 792,816 ****
                  rndup = RNDUP(namelen) / BYTES_PER_XDR_UNIT;
  
                  /* room for LENGTH + string ? */
                  if ((ptr + (1 + rndup)) > ptr_redzone) {
                          no_space = TRUE;
                          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
--- 790,804 ----
                  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;
                  }
  
                  /*
                   * 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,831 ****
--- 807,838 ----
                   * 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).