nfs-ganesha 1.4

9p_walk.c

Go to the documentation of this file.
00001 /*
00002  * vim:expandtab:shiftwidth=8:tabstop=8:
00003  *
00004  * Copyright CEA/DAM/DIF  (2011)
00005  * contributeur : Philippe DENIEL   philippe.deniel@cea.fr
00006  *                Thomas LEIBOVICI  thomas.leibovici@cea.fr
00007  *
00008  *
00009  * This program is free software; you can redistribute it and/or
00010  * modify it under the terms of the GNU Lesser General Public
00011  * License as published by the Free Software Foundation; either
00012  * version 3 of the License, or (at your option) any later version.
00013  *
00014  * This program is distributed in the hope that it will be useful,
00015  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00016  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00017  * Lesser General Public License for more details.
00018  *
00019  * You should have received a copy of the GNU Lesser General Public
00020  * License along with this library; if not, write to the Free Software
00021  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
00022  *
00023  * ---------------------------------------
00024  */
00025 
00035 #ifdef HAVE_CONFIG_H
00036 #include "config.h"
00037 #endif
00038 
00039 #ifdef _SOLARIS
00040 #include "solaris_port.h"
00041 #endif
00042 
00043 #include <stdio.h>
00044 #include <string.h>
00045 #include <pthread.h>
00046 #include <sys/stat.h>
00047 #include "nfs_core.h"
00048 #include "log.h"
00049 #include "cache_inode.h"
00050 #include "fsal.h"
00051 #include "9p.h"
00052 
00053 
00054 int _9p_walk( _9p_request_data_t * preq9p, 
00055                   void  * pworker_data,
00056                   u32 * plenout, 
00057                   char * preply)
00058 {
00059   char * cursor = preq9p->_9pmsg + _9P_HDR_SIZE + _9P_TYPE_SIZE ;
00060 
00061   u16 * msgtag = NULL ;
00062   u32 * fid    = NULL ;
00063   u32 * newfid = NULL ;
00064   u16 * nwname = NULL ;
00065   u16 * wnames_len[_9P_MAXWELEM] ;
00066   char * wnames_str[_9P_MAXWELEM] ;
00067 
00068   u16 * nwqid ;
00069 
00070   unsigned int i = 0 ;
00071 
00072   fsal_name_t name ; 
00073   fsal_attrib_list_t fsalattr ;
00074   cache_inode_status_t cache_status ;
00075   cache_entry_t * pentry = NULL ;
00076 
00077   _9p_fid_t * pfid = NULL ;
00078   _9p_fid_t * pnewfid = NULL ;
00079 
00080   if ( !preq9p || !pworker_data || !plenout || !preply )
00081    return -1 ;
00082 
00083   /* Get data */
00084   _9p_getptr( cursor, msgtag, u16 ) ; 
00085   _9p_getptr( cursor, fid,    u32 ) ; 
00086   _9p_getptr( cursor, newfid, u32 ) ; 
00087   _9p_getptr( cursor, nwname, u16 ) ; 
00088 
00089   LogDebug( COMPONENT_9P, "TWALK: tag=%u fid=%u newfid=%u nwname=%u",
00090             (u32)*msgtag, *fid, *newfid, *nwname ) ;
00091 
00092   for( i = 0 ; i < *nwname ; i++ )
00093    {
00094      _9p_getstr( cursor, wnames_len[i], wnames_str[i] ) ;
00095       LogDebug( COMPONENT_9P, "TWALK (component): tag=%u fid=%u newfid=%u nwnames=%.*s",
00096                 (u32)*msgtag, *fid, *newfid, *(wnames_len[i]), wnames_str[i] ) ;
00097    }
00098 
00099   if( *fid >= _9P_FID_PER_CONN )
00100    return _9p_rerror( preq9p, msgtag, ERANGE, plenout, preply ) ;
00101 
00102   if( *newfid >= _9P_FID_PER_CONN )
00103    return _9p_rerror( preq9p, msgtag, ERANGE, plenout, preply ) ;
00104 
00105   pfid = &preq9p->pconn->fids[*fid] ;
00106   pnewfid = &preq9p->pconn->fids[*newfid] ;
00107 
00108   /* Is this a lookup or a fid cloning operation ? */
00109   if( *nwname == 0 )
00110    {
00111       /* Cloning operation */
00112       memcpy( (char *)pnewfid, (char *)pfid, sizeof( _9p_fid_t ) ) ;
00113   
00114       /* Set the new fid id */
00115       pnewfid->fid = *newfid ;
00116    }
00117   else 
00118    {
00119       pnewfid->fid = *newfid ;
00120       pnewfid->fsal_op_context = pfid->fsal_op_context ;
00121       pnewfid->pexport = pfid->pexport ;
00122 
00123       /* the walk is in fact a lookup */
00124       pentry = pfid->pentry ;
00125       for( i = 0 ; i <  *nwname ; i ++ )
00126         {
00127            snprintf( name.name, FSAL_MAX_NAME_LEN, "%.*s", *(wnames_len[i]), wnames_str[i] ) ;
00128            name.len =  *(wnames_len[i]) + 1 ;
00129 
00130            LogDebug( COMPONENT_9P, "TWALK (lookup): tag=%u fid=%u newfid=%u (component %u/%u :%s)",
00131             (u32)*msgtag, *fid, *newfid, i+1, *nwname, name.name ) ;
00132 
00133            /* refcount +1 */
00134            if( ( pnewfid->pentry = cache_inode_lookup( pentry,
00135                                                        &name,
00136                                                        &fsalattr,
00137                                                        &pfid->fsal_op_context,
00138                                                        &cache_status ) ) == NULL )
00139               return _9p_rerror( preq9p, msgtag, _9p_tools_errno( cache_status ), plenout, preply ) ;
00140 
00141            pentry =  pnewfid->pentry ;
00142         }
00143 
00144      /* Build the qid */
00145      pnewfid->qid.version = 0 ; /* No cache, we want the client to stay synchronous with the server */
00146      pnewfid->qid.path = (u64)pnewfid->pentry->attributes.fileid ;
00147 
00148      pnewfid->specdata.xattr.xattr_id = 0 ;
00149      pnewfid->specdata.xattr.xattr_content = NULL ;
00150 
00151      switch( pfid->pentry->type )
00152       {
00153         case REGULAR_FILE:
00154         case CHARACTER_FILE:
00155         case BLOCK_FILE:
00156         case SOCKET_FILE:
00157         case FIFO_FILE:
00158           pnewfid->qid.type = _9P_QTFILE ;
00159           break ;
00160 
00161         case SYMBOLIC_LINK:
00162           pnewfid->qid.type = _9P_QTSYMLINK ;
00163           break ;
00164 
00165         case DIRECTORY:
00166         case FS_JUNCTION:
00167           pnewfid->qid.type = _9P_QTDIR ;
00168           break ;
00169 
00170         case UNASSIGNED:
00171         case RECYCLED:
00172         default:
00173           LogMajor( COMPONENT_9P, "implementation error, you should not see this message !!!!!!" ) ;
00174           return _9p_rerror( preq9p, msgtag, EINVAL, plenout, preply ) ;
00175           break ;
00176       }
00177 
00178    }
00179 
00180   /* As much qid as requested fid */
00181   nwqid = nwname ;
00182 
00183    /* Build the reply */
00184   _9p_setinitptr( cursor, preply, _9P_RWALK ) ;
00185   _9p_setptr( cursor, msgtag, u16 ) ;
00186 
00187   
00188   _9p_setptr( cursor, nwqid, u16 ) ;
00189   for( i = 0 ; i < *nwqid ; i++ )
00190     { 
00191       _9p_setqid( cursor, pnewfid->qid ) ;
00192     }
00193 
00194   _9p_setendptr( cursor, preply ) ;
00195   _9p_checkbound( cursor, preply, plenout ) ;
00196 
00197   LogDebug( COMPONENT_9P, "RWALK: tag=%u fid=%u newfid=%u nwqid=%u fileid=%llu pentry=%p",
00198             (u32)*msgtag, *fid, *newfid, *nwqid,  (unsigned long long)pnewfid->qid.path, pnewfid->pentry ) ;
00199 
00200   return 1 ;
00201 }
00202