--- a/usr/src/uts/common/fs/nfs/nfs4_srv_readdir.c Mon Oct 27 23:12:59 2008 -0700
+++ b/usr/src/uts/common/fs/nfs/nfs4_srv_readdir.c Tue Oct 28 03:34:04 2008 -0700
@@ -23,8 +23,6 @@
* Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
-
#include <sys/param.h>
#include <sys/types.h>
#include <sys/systm.h>
@@ -49,6 +47,7 @@
#include <nfs/nfs.h>
#include <nfs/export.h>
#include <nfs/nfs4.h>
+#include <nfs/nfs_cmd.h>
/*
@@ -285,31 +284,31 @@
/* Calculate space available */
if (sb.f_bavail != (fsblkcnt64_t)-1) {
psbe->space_avail =
- (fattr4_space_avail) sb.f_frsize *
- (fattr4_space_avail) sb.f_bavail;
+ (fattr4_space_avail) sb.f_frsize *
+ (fattr4_space_avail) sb.f_bavail;
} else {
psbe->space_avail =
- (fattr4_space_avail) sb.f_bavail;
+ (fattr4_space_avail) sb.f_bavail;
}
/* Calculate space free */
if (sb.f_bfree != (fsblkcnt64_t)-1) {
psbe->space_free =
- (fattr4_space_free) sb.f_frsize *
- (fattr4_space_free) sb.f_bfree;
+ (fattr4_space_free) sb.f_frsize *
+ (fattr4_space_free) sb.f_bfree;
} else {
psbe->space_free =
- (fattr4_space_free) sb.f_bfree;
+ (fattr4_space_free) sb.f_bfree;
}
/* Calculate space total */
if (sb.f_blocks != (fsblkcnt64_t)-1) {
psbe->space_total =
- (fattr4_space_total) sb.f_frsize *
- (fattr4_space_total) sb.f_blocks;
+ (fattr4_space_total) sb.f_frsize *
+ (fattr4_space_total) sb.f_blocks;
} else {
psbe->space_total =
- (fattr4_space_total) sb.f_blocks;
+ (fattr4_space_total) sb.f_blocks;
}
/* For use later on attr encode */
@@ -399,6 +398,8 @@
int lu_set, lg_set;
utf8string owner, group;
int owner_error, group_error;
+ struct sockaddr *ca;
+ char *name = NULL;
DTRACE_NFSV4_2(op__readdir__start, struct compound_state *, cs,
READDIR4args *, args);
@@ -458,14 +459,14 @@
/* Is there pseudo-fs work that is needed for this readdir? */
check_visible = PSEUDO(cs->exi) ||
- ! is_exported_sec(cs->nfsflavor, cs->exi) ||
- cs->access & CS_ACCESS_LIMITED;
+ ! is_exported_sec(cs->nfsflavor, cs->exi) ||
+ cs->access & CS_ACCESS_LIMITED;
/* Check the requested attributes and only do the work if needed */
if (ar & (FATTR4_MAXFILESIZE_MASK |
- FATTR4_MAXLINK_MASK |
- FATTR4_MAXNAME_MASK)) {
+ FATTR4_MAXLINK_MASK |
+ FATTR4_MAXNAME_MASK)) {
if (error = rfs4_get_pc_encode(cs->vp, &dpce, ar, cs->cr)) {
*cs->statusp = resp->status = puterrno4(error);
goto out;
@@ -530,7 +531,7 @@
if (mpcount > MAXBSIZE)
args->maxcount = mpcount = MAXBSIZE;
mp = allocb_wait(RNDUP(mpcount), BPRI_MED,
- STR_NOSIG, &alloc_err);
+ STR_NOSIG, &alloc_err);
}
ASSERT(mp != NULL);
@@ -553,10 +554,10 @@
*/
if (args->maxcount < (mpcount - 128))
ptr_redzone =
- (uint32_t *)(((char *)ptr) + RNDUP(args->maxcount));
+ (uint32_t *)(((char *)ptr) + RNDUP(args->maxcount));
else
ptr_redzone =
- (uint32_t *)((((char *)ptr) + RNDUP(mpcount)) - 128);
+ (uint32_t *)((((char *)ptr) + RNDUP(mpcount)) - 128);
/*
* Set the dircount; this will be used as the size for the
@@ -595,6 +596,8 @@
rddir_next_offset = (offset_t)args->cookie;
+ ca = (struct sockaddr *)svc_getrpccaller(req->rq_xprt)->buf;
+
readagain:
no_space = FALSE;
@@ -646,7 +649,7 @@
lastentry_ptr = ptr;
no_space = 0;
for (dp = (struct dirent64 *)rddir_data;
- !no_space && rddir_result_size > 0; dp = nextdp(dp)) {
+ !no_space && rddir_result_size > 0; dp = nextdp(dp)) {
/* reset expseudo */
expseudo = 0;
@@ -681,54 +684,54 @@
* encoded later in the "attributes" section.
*/
ae = ar;
- if (ar != 0) {
- error = nfs4_readdir_getvp(dvp, dp->d_name,
- &vp, &newexi, req, cs,
- expseudo);
- if (error == ENOENT) {
- rddir_next_offset = dp->d_off;
- continue;
- }
+ if (ar == 0)
+ goto reencode_attrs;
- rddirattr_error = error;
+ error = nfs4_readdir_getvp(dvp, dp->d_name,
+ &vp, &newexi, req, cs, expseudo);
+ if (error == ENOENT) {
+ rddir_next_offset = dp->d_off;
+ continue;
+ }
+
+ rddirattr_error = error;
- /*
- * The vp obtained from above may be from a
- * different filesystem mount and the vfs-like
- * attributes should be obtained from that
- * different vfs; only do this if appropriate.
- */
- if (vp &&
- (vfs_different = (dvp->v_vfsp != vp->v_vfsp))) {
- if (ar & (FATTR4_FILES_AVAIL_MASK |
- FATTR4_FILES_FREE_MASK |
- FATTR4_FILES_TOTAL_MASK |
- FATTR4_FILES_AVAIL_MASK |
- FATTR4_FILES_FREE_MASK |
- FATTR4_FILES_TOTAL_MASK)) {
- if (error =
- rfs4_get_sb_encode(dvp->v_vfsp, &sbe)) {
- /* Remove attrs from encode */
- ae &= ~(FATTR4_FILES_AVAIL_MASK |
- FATTR4_FILES_FREE_MASK |
- FATTR4_FILES_TOTAL_MASK |
- FATTR4_FILES_AVAIL_MASK |
- FATTR4_FILES_FREE_MASK |
- FATTR4_FILES_TOTAL_MASK);
- rddirattr_error = error;
- }
+ /*
+ * The vp obtained from above may be from a
+ * different filesystem mount and the vfs-like
+ * attributes should be obtained from that
+ * different vfs; only do this if appropriate.
+ */
+ if (vp &&
+ (vfs_different = (dvp->v_vfsp != vp->v_vfsp))) {
+ if (ar & (FATTR4_FILES_AVAIL_MASK |
+ FATTR4_FILES_FREE_MASK |
+ FATTR4_FILES_TOTAL_MASK |
+ FATTR4_FILES_AVAIL_MASK |
+ FATTR4_FILES_FREE_MASK |
+ FATTR4_FILES_TOTAL_MASK)) {
+ if (error =
+ rfs4_get_sb_encode(dvp->v_vfsp,
+ &sbe)) {
+ /* Remove attrs from encode */
+ ae &= ~(FATTR4_FILES_AVAIL_MASK |
+ FATTR4_FILES_FREE_MASK |
+ FATTR4_FILES_TOTAL_MASK |
+ FATTR4_FILES_AVAIL_MASK |
+ FATTR4_FILES_FREE_MASK |
+ FATTR4_FILES_TOTAL_MASK);
+ rddirattr_error = error;
}
- if (ar & (FATTR4_MAXFILESIZE_MASK |
- FATTR4_MAXLINK_MASK |
- FATTR4_MAXNAME_MASK)) {
- if (error =
- rfs4_get_pc_encode(cs->vp,
- &pce, ar, cs->cr)) {
- ar &= ~(FATTR4_MAXFILESIZE_MASK |
- FATTR4_MAXLINK_MASK |
- FATTR4_MAXNAME_MASK);
- rddirattr_error = error;
- }
+ }
+ if (ar & (FATTR4_MAXFILESIZE_MASK |
+ FATTR4_MAXLINK_MASK |
+ FATTR4_MAXNAME_MASK)) {
+ if (error = rfs4_get_pc_encode(cs->vp,
+ &pce, ar, cs->cr)) {
+ ar &= ~(FATTR4_MAXFILESIZE_MASK |
+ FATTR4_MAXLINK_MASK |
+ FATTR4_MAXNAME_MASK);
+ rddirattr_error = error;
}
}
}
@@ -739,8 +742,15 @@
/* 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;
+ continue;
+ }
/* Calculate the dirent name length */
- namelen = strlen(dp->d_name);
+ namelen = strlen(name);
rndup = RNDUP(namelen) / BYTES_PER_XDR_UNIT;
@@ -755,10 +765,13 @@
/* encode the RNDUP FILL first */
ptr[rndup - 1] = 0;
/* encode the NAME of the entry */
- bcopy(dp->d_name, (char *)ptr, namelen);
+ 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
@@ -788,14 +801,14 @@
if (ae != 0) {
if (!vp) {
ae = ar & (FATTR4_RDATTR_ERROR_MASK |
- FATTR4_MOUNTED_ON_FILEID_MASK);
+ FATTR4_MOUNTED_ON_FILEID_MASK);
} else {
va.va_mask = AT_ALL;
rddirattr_error =
- VOP_GETATTR(vp, &va, 0, cs->cr, NULL);
+ VOP_GETATTR(vp, &va, 0, cs->cr, NULL);
if (rddirattr_error)
ae = ar & (FATTR4_RDATTR_ERROR_MASK |
- FATTR4_MOUNTED_ON_FILEID_MASK);
+ FATTR4_MOUNTED_ON_FILEID_MASK);
}
}
@@ -839,7 +852,7 @@
if (ae & FATTR4_SUPPORTED_ATTRS_MASK) {
IXDR_PUT_INT32(ptr, 2);
IXDR_PUT_HYPER(ptr,
- rfs4_supported_attrs);
+ rfs4_supported_attrs);
}
if (ae & FATTR4_TYPE_MASK) {
uint_t ftype = vt_to_nf4[va.va_type];
@@ -858,7 +871,7 @@
if (ae & FATTR4_CHANGE_MASK) {
u_longlong_t change;
NFS4_SET_FATTR4_CHANGE(change,
- va.va_ctime);
+ va.va_ctime);
IXDR_PUT_HYPER(ptr, change);
}
if (ae & FATTR4_SIZE_MASK) {
@@ -919,8 +932,8 @@
}
if (ae & FATTR4_RDATTR_ERROR_MASK) {
rddirattr_error =
- (rddirattr_error == 0 ?
- 0 : puterrno4(rddirattr_error));
+ (rddirattr_error == 0 ?
+ 0 : puterrno4(rddirattr_error));
IXDR_PUT_U_INT32(ptr, rddirattr_error);
}
@@ -974,8 +987,8 @@
uint_t isit;
pc_val = FALSE;
(void) VOP_PATHCONF(vp,
- _PC_CHOWN_RESTRICTED,
- &pc_val, cs->cr, NULL);
+ _PC_CHOWN_RESTRICTED,
+ &pc_val, cs->cr, NULL);
isit = (pc_val ? TRUE : FALSE);
IXDR_PUT_U_INT32(ptr, isit);
}
@@ -1146,29 +1159,26 @@
*/
if (ae & FATTR4_OWNER_MASK) {
if (!lu_set) {
- owner_error = nfs_idmap_uid_str(va.va_uid,
- &owner, TRUE);
- if (!owner_error) {
- lu_set = TRUE;
- lastuid = va.va_uid;
- }
- } else {
- if (va.va_uid != lastuid) {
+ owner_error = nfs_idmap_uid_str(
+ va.va_uid, &owner, TRUE);
+ if (!owner_error) {
+ lu_set = TRUE;
+ lastuid = va.va_uid;
+ }
+ } else if (va.va_uid != lastuid) {
if (owner.utf8string_len != 0) {
- kmem_free(owner.utf8string_val,
- owner.utf8string_len);
+ kmem_free(owner.utf8string_val,
+ owner.utf8string_len);
owner.utf8string_len = 0;
owner.utf8string_val = NULL;
}
owner_error = nfs_idmap_uid_str(
- va.va_uid,
- &owner, TRUE);
+ va.va_uid, &owner, TRUE);
if (!owner_error) {
lastuid = va.va_uid;
} else {
lu_set = FALSE;
}
- }
}
if (!owner_error) {
if ((ptr +
@@ -1187,14 +1197,14 @@
}
/* encode the LENGTH of owner string */
IXDR_PUT_U_INT32(ptr,
- owner.utf8string_len);
+ owner.utf8string_len);
/* encode the RNDUP FILL first */
rndup = RNDUP(owner.utf8string_len) /
- BYTES_PER_XDR_UNIT;
+ BYTES_PER_XDR_UNIT;
ptr[rndup - 1] = 0;
/* encode the OWNER */
bcopy(owner.utf8string_val, ptr,
- owner.utf8string_len);
+ owner.utf8string_len);
ptr += rndup;
}
}
@@ -1204,29 +1214,28 @@
*/
if (ae & FATTR4_OWNER_GROUP_MASK) {
if (!lg_set) {
- group_error =
+ group_error =
nfs_idmap_gid_str(va.va_gid,
- &group, TRUE);
- if (!group_error) {
- lg_set = TRUE;
- lastgid = va.va_gid;
- }
- } else {
- if (va.va_gid != lastgid) {
+ &group, TRUE);
+ if (!group_error) {
+ lg_set = TRUE;
+ lastgid = va.va_gid;
+ }
+ } else if (va.va_gid != lastgid) {
if (group.utf8string_len != 0) {
- kmem_free(group.utf8string_val,
- group.utf8string_len);
- group.utf8string_len = 0;
- group.utf8string_val = NULL;
+ kmem_free(
+ group.utf8string_val,
+ group.utf8string_len);
+ group.utf8string_len = 0;
+ group.utf8string_val = NULL;
}
group_error =
- nfs_idmap_gid_str(va.va_gid,
- &group, TRUE);
+ nfs_idmap_gid_str(va.va_gid,
+ &group, TRUE);
if (!group_error)
lastgid = va.va_gid;
else
lg_set = FALSE;
- }
}
if (!group_error) {
if ((ptr +
@@ -1245,14 +1254,14 @@
}
/* encode the LENGTH of owner string */
IXDR_PUT_U_INT32(ptr,
- group.utf8string_len);
+ group.utf8string_len);
/* encode the RNDUP FILL first */
rndup = RNDUP(group.utf8string_len) /
- BYTES_PER_XDR_UNIT;
+ BYTES_PER_XDR_UNIT;
ptr[rndup - 1] = 0;
/* encode the OWNER */
bcopy(group.utf8string_val, ptr,
- group.utf8string_len);
+ group.utf8string_len);
ptr += rndup;
}
}
@@ -1286,9 +1295,9 @@
if (ae & FATTR4_RAWDEV_MASK) {
fattr4_rawdev rd;
rd.specdata1 =
- (uint32)getmajor(va.va_rdev);
+ (uint32)getmajor(va.va_rdev);
rd.specdata2 =
- (uint32)getminor(va.va_rdev);
+ (uint32)getminor(va.va_rdev);
IXDR_PUT_U_INT32(ptr, rd.specdata1);
IXDR_PUT_U_INT32(ptr, rd.specdata2);
}
@@ -1342,7 +1351,7 @@
u_longlong_t sec =
(u_longlong_t)va.va_atime.tv_sec;
uint_t nsec =
- (uint_t)va.va_atime.tv_nsec;
+ (uint_t)va.va_atime.tv_nsec;
IXDR_PUT_HYPER(ptr, sec);
IXDR_PUT_INT32(ptr, nsec);
}
@@ -1365,7 +1374,7 @@
u_longlong_t sec =
(u_longlong_t)va.va_ctime.tv_sec;
uint_t nsec =
- (uint_t)va.va_ctime.tv_nsec;
+ (uint_t)va.va_ctime.tv_nsec;
IXDR_PUT_HYPER(ptr, sec);
IXDR_PUT_INT32(ptr, nsec);
}
@@ -1373,7 +1382,7 @@
u_longlong_t sec =
(u_longlong_t)va.va_mtime.tv_sec;
uint_t nsec =
- (uint_t)va.va_mtime.tv_nsec;
+ (uint_t)va.va_mtime.tv_nsec;
IXDR_PUT_HYPER(ptr, sec);
IXDR_PUT_INT32(ptr, nsec);
}
@@ -1406,9 +1415,9 @@
/* "go back" and encode the attributes' length */
attr_length =
- (char *)ptr -
- (char *)attr_offset_ptr -
- BYTES_PER_XDR_UNIT;
+ (char *)ptr -
+ (char *)attr_offset_ptr -
+ BYTES_PER_XDR_UNIT;
IXDR_PUT_U_INT32(attr_offset_ptr, attr_length);
/*