nfs4_srv_readdir.c revision 7c478bd95313f5f23a4c958a745db2134aa03244
1N/A * The contents of this file are subject to the terms of the 1N/A * Common Development and Distribution License, Version 1.0 only 1N/A * (the "License"). You may not use this file except in compliance 1N/A * See the License for the specific language governing permissions 1N/A * and limitations under the License. 1N/A * When distributing Covered Code, include this CDDL HEADER in each 1N/A * If applicable, add the following below this CDDL HEADER, with the 1N/A * fields enclosed by brackets "[]" replaced with your own identifying 1N/A * information: Portions Copyright [yyyy] [name of copyright owner] 1N/A * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 1N/A * Use is subject to license terms. 1N/A#
pragma ident "%Z%%M% %I% %E% SMI" 1N/A * RFS4_MINLEN_ENTRY4: XDR-encoded size of smallest possible dirent. 1N/A * This is used to return NFS4ERR_TOOSMALL when clients specify 1N/A * maxcount that isn't large enough to hold the smallest possible 1N/A * XDR encoded dirent. 1N/A * sizeof cookie (8 bytes) + 1N/A * sizeof name_len (4 bytes) + 1N/A * sizeof smallest (padded) name (4 bytes) + 1N/A * sizeof bitmap4_len (12 bytes) + NOTE: we always encode len=2 bm4 1N/A * sizeof attrlist4_len (4 bytes) + 1N/A * sizeof next boolean (4 bytes) 1N/A * RFS4_MINLEN_RDDIR4: XDR-encoded size of READDIR op reply containing 1N/A * the smallest possible entry4 (assumes no attrs requested). 1N/A * sizeof nfsstat4 (4 bytes) + 1N/A * sizeof verifier4 (8 bytes) + 1N/A * sizeof entsecond_to_ry4list bool (4 bytes) + 1N/A * sizeof entry4 (36 bytes) + 1N/A * sizeof eof bool (4 bytes) 1N/A * RFS4_MINLEN_RDDIR_BUF: minimum length of buffer server will provide to 1N/A * VOP_READDIR. Its value is the size of the maximum possible dirent 1N/A * for solaris. The DIRENT64_RECLEN macro returns the size of dirent 1N/A * required for a given name length. MAXNAMELEN is the maximum 1N/A * filename length allowed in Solaris. The first two DIRENT64_RECLEN() 1N/A * macros are to allow for . and .. entries -- just a minor tweak to try 1N/A * and guarantee that buffer we give to VOP_READDIR will be large enough 1N/A * to hold ., .., and the largest possible solaris dirent64. 1N/A 0,
NF4REG,
NF4DIR,
NF4BLK,
NF4CHR,
NF4LNK,
NF4FIFO, 0, 0,
NF4SOCK, 0
1N/A /* Is this object mounted upon? */ 1N/A * Nothing more to do if object is not a mount point or 1N/A * a possible LOFS shadow of an LOFS mount (which won't 1N/A * have v_vfsmountedhere set) 1N/A * Something is mounted here. Traverse and manage the * If VOP_FID not supported by underlying fs (mntfs, procfs, * etc.), then return attrs for stub instead of VROOT object. * If it fails for any other reason, then return the error. /* go back to vnode that is "under" mount */ /* Save the exi and present the new one to checkauth4() */ /* Get the right cred like lookup does */ /* Reset what call_checkauth4() may have set */ /* This is the set of pathconf data for vfs */ /* Maximum Name Length */ /* This is the set of statvfs data that is ready for encoding */ /* Grab the per filesystem info */ /* Calculate space available */ /* Calculate space free */ /* Calculate space total */ /* For use later on attr encode */ * Macros to handle if we have don't have enough space for the requested * attributes and this is the first entry and the * requested attributes are more than the minimal useful * set, reset the attributes to the minimal set and * retry the encoding. If the client has asked for both * mounted_on_fileid and fileid, prefer mounted_on_fileid. * If readdir only needs to return FILEID, we can take it from the * dirent struct and save doing the lookup. /* Maximum read and write size */ * If there is an unshared filesystem mounted on this vnode, * do not allow readdir in this directory. * If write-only attrs are requested, then fail the readdir op /* Is there pseudo-fs work that is needed for this readdir? */ /* Check the requested attributes and only do the work if needed */ /* If there is statvfs data requested, pick it up once */ * Max transfer size of the server is the absolute limite. * If the client has decided to max out with something really * tiny, then return toosmall. Otherwise, move forward and * see if a single entry can be encoded. * How large should the mblk be for outgoing encoding. * mp will contain the data to be sent out in the readdir reply. * It will be freed after the reply has been sent. * Let's roundup the data to a BYTES_PER_XDR_UNIX multiple, * so that the call to xdrmblk_putmblk() never fails. * The allocation of the client's requested size has * failed. It may be that the size is too large for * current system utilization; step down to a "common" * size and wait for the allocation to occur. * The "redzone" at the end of the encoding buffer is used * to deal with xdr encoding length. Instead of checking * each encoding of an attribute value before it is done, * make the assumption that it will fit into the buffer and * The largest block of attributes that are encoded without * checking the redzone is 18 * BYTES_PER_XDR_UNIT (72 bytes) * "round" to 128 as the redzone size. * Set the dircount; this will be used as the size for the * readdir of the underlying filesystem. First make sure * that it is large enough to do a reasonable readdir (client * may have short changed us - it is an advisory number); * then make sure that it isn't too large. * After all of that, if maxcount is "small" then just use * that for the dircount number. /* number of entries fully encoded in outgoing buffer */ /* The allocation failed; downsize and wait for it this time */ /* Move on to reading the directory contents */ /* Reading at the end of the directory */ /* encode the BOOLEAN marking no further entries */ /* encode the BOOLEAN signifying end of directory */ /* skip "." and ".." entries */ * Only if the client requested attributes... * If the VOP_LOOKUP fails ENOENT, then skip this entry * for the readdir response. If there was another error, * then set the rddirattr_error and the error will be * encoded later in the "attributes" section. * 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. /* Remove attrs from encode */ /* encode the BOOLEAN for the existence of the next entry */ /* encode the COOKIE for the entry */ /* Calculate the dirent name length */ /* room for LENGTH + string ? */ /* encode the LENGTH of the name */ /* encode the RNDUP FILL first */ /* encode the NAME of the entry */ /* now bump the ptr after... */ * 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 * that name and 2 * XDR_UNIT bytes of cookie; * However, use the regular DIRENT64 to match most * 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). * Note that the previous VOP_LOOKUP() could have failed * itself which leaves this code without anything for * Also note that the readdir_attr_error is left in the * encoding mask if requested and so is the mounted_on_fileid. /* START OF ATTRIBUTE ENCODING */ /* encode the LENGTH of the BITMAP4 array */ /* encode the default LENGTH of the attributes for entry */ /* Check if any of the first 32 attributes are being encoded */ if (
ae &
0xffffffff00000000) {
* Redzone check is done at the end of this section. * This particular section will encode a maximum of * 18 * BYTES_PER_XDR_UNIT of data /* Check the redzone boundary */ * Redzone check is done at the end of this section. * This particular section will encode a maximum of * 4 * BYTES_PER_XDR_UNIT of data. * NOTE: that if ACLs are supported that the * redzone calculations will need to change. /* Check the redzone boundary */ * Redzone check is done before the filehandle /* encode the RNDUP FILL first */ /* Check the redzone boundary */ * Redzone check is done at the end of this section. * This particular section will encode a maximum of * 15 * BYTES_PER_XDR_UNIT of data. /* Check the redzone boundary */ if (
ae &
0x00000000ffffffff) {
* Redzone check is done at the end of this section. * This particular section will encode a maximum of * 3 * BYTES_PER_XDR_UNIT of data. /* Check the redzone boundary */ * Redzone check is done before the encoding of the * owner string since the length is indeterminate. /* encode the LENGTH of owner string */ /* encode the RNDUP FILL first */ * Redzone check is done before the encoding of the * group string since the length is indeterminate. /* encode the LENGTH of owner string */ /* encode the RNDUP FILL first */ * Redzone check is done at the end of this section. * This particular section will encode a maximum of * 10 * BYTES_PER_XDR_UNIT of data. /* Check the redzone boundary */ * Redzone check is done at the end of this section. * This particular section will encode a maximum of * 14 * BYTES_PER_XDR_UNIT of data. /* Check the redzone boundary */ /* Reset to directory's vfs info when encoding complete */ /* "go back" and encode the attributes' length */ * If there was trouble obtaining a mapping for either * the owner or group attributes, then remove them from * bitmap4 for this entry and reset the bitmap value /* END OF ATTRIBUTE ENCODING */ * Check for the case that another VOP_READDIR() has to be done. * - no space encoding error * - no entry successfully encoded * - still more directory to read * If no_space is set then we terminated prematurely, * rewind to the last entry and this can never be EOF. eof =
FALSE;
/* ended encoded prematurely */ * If we have entries, always return them, otherwise only error * if we ran out of space. /* encode the BOOLEAN marking no further entries */ /* encode the BOOLEAN signifying end of directory */