nfs-ganesha 1.4

nfs_Rmdir.c

Go to the documentation of this file.
00001 /*
00002  * vim:expandtab:shiftwidth=8:tabstop=8:
00003  *
00004  * Copyright CEA/DAM/DIF  (2008)
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 
00036 #ifdef HAVE_CONFIG_H
00037 #include "config.h"
00038 #endif
00039 
00040 #ifdef _SOLARIS
00041 #include "solaris_port.h"
00042 #endif
00043 
00044 #include <stdio.h>
00045 #include <string.h>
00046 #include <pthread.h>
00047 #include <fcntl.h>
00048 #include <sys/file.h>           /* for having FNDELAY */
00049 #include "HashData.h"
00050 #include "HashTable.h"
00051 #include "log.h"
00052 #include "ganesha_rpc.h"
00053 #include "nfs23.h"
00054 #include "nfs4.h"
00055 #include "mount.h"
00056 #include "nfs_core.h"
00057 #include "cache_inode.h"
00058 #include "nfs_exports.h"
00059 #include "nfs_creds.h"
00060 #include "nfs_proto_functions.h"
00061 #include "nfs_tools.h"
00062 #include "nfs_proto_tools.h"
00063 
00083 int nfs_Rmdir(nfs_arg_t *parg,
00084               exportlist_t *pexport,
00085               fsal_op_context_t *pcontext,
00086               nfs_worker_data_t *pworker,
00087               struct svc_req *preq,
00088               nfs_res_t *pres)
00089 {
00090   cache_entry_t *parent_pentry = NULL;
00091   cache_entry_t *pentry_child = NULL;
00092   fsal_attrib_list_t pre_parent_attr;
00093   fsal_attrib_list_t parent_attr;
00094   fsal_attrib_list_t *ppre_attr;
00095   fsal_attrib_list_t pentry_child_attr;
00096   cache_inode_file_type_t filetype;
00097   cache_inode_file_type_t childtype;
00098   cache_inode_status_t cache_status;
00099   fsal_name_t name;
00100   char *dir_name = NULL;
00101   int rc = NFS_REQ_OK;
00102 
00103   if(isDebug(COMPONENT_NFSPROTO))
00104     {
00105       char str[LEN_FH_STR];
00106 
00107       switch (preq->rq_vers)
00108         {
00109         case NFS_V2:
00110           dir_name = parg->arg_rmdir2.name;
00111           break;
00112         case NFS_V3:
00113           dir_name = parg->arg_rmdir3.object.name;
00114           break;
00115         }
00116 
00117       nfs_FhandleToStr(preq->rq_vers,
00118                        &(parg->arg_rmdir2.dir),
00119                        &(parg->arg_rmdir3.object.dir),
00120                        NULL,
00121                        str);
00122       LogDebug(COMPONENT_NFSPROTO,
00123                "REQUEST PROCESSING: Calling nfs_Rmdir handle: %s name: %s",
00124                str, dir_name);
00125     }
00126 
00127   if(preq->rq_vers == NFS_V3)
00128     {
00129       /* to avoid setting it on each error case */
00130       pres->res_rmdir3.RMDIR3res_u.resfail.dir_wcc.before.attributes_follow = FALSE;
00131       pres->res_rmdir3.RMDIR3res_u.resfail.dir_wcc.after.attributes_follow = FALSE;
00132       ppre_attr = NULL;
00133     }
00134 
00135   /* Convert file handle into a pentry */
00136   if((parent_pentry = nfs_FhandleToCache(preq->rq_vers,
00137                                          &(parg->arg_rmdir2.dir),
00138                                          &(parg->arg_rmdir3.object.dir),
00139                                          NULL,
00140                                          &(pres->res_stat2),
00141                                          &(pres->res_rmdir3.status),
00142                                          NULL,
00143                                          &pre_parent_attr,
00144                                          pcontext, &rc)) == NULL)
00145     {
00146       /* Stale NFS FH ? */
00147       goto out;
00148     }
00149 
00150   /* get directory attributes before action (for V3 reply) */
00151   ppre_attr = &pre_parent_attr;
00152 
00153   /* Extract the filetype */
00154   filetype = cache_inode_fsal_type_convert(pre_parent_attr.type);
00155 
00156   /*
00157    * Sanity checks: new directory name must be non-null; parent must be
00158    * a directory. 
00159    */
00160   if(filetype != DIRECTORY)
00161     {
00162       switch (preq->rq_vers)
00163         {
00164         case NFS_V2:
00165           pres->res_stat2 = NFSERR_NOTDIR;
00166           break;
00167         case NFS_V3:
00168           pres->res_rmdir3.status = NFS3ERR_NOTDIR;
00169           break;
00170         }
00171 
00172       rc = NFS_REQ_OK;
00173       goto out;
00174     }
00175 
00176   switch (preq->rq_vers)
00177     {
00178     case NFS_V2:
00179       dir_name = parg->arg_rmdir2.name;
00180       break;
00181 
00182     case NFS_V3:
00183       dir_name = parg->arg_rmdir3.object.name;
00184       break;
00185 
00186     }
00187 
00188   //if(dir_name == NULL || strlen(dir_name) == 0)
00189   if(dir_name == NULL || *dir_name == '\0' )
00190     {
00191       cache_status = CACHE_INODE_INVALID_ARGUMENT;      /* for lack of better... */
00192     }
00193   else
00194     {
00195       if((cache_status = cache_inode_error_convert(FSAL_str2name(dir_name,
00196                                                                  FSAL_MAX_NAME_LEN,
00197                                                                  &name))) ==
00198          CACHE_INODE_SUCCESS)
00199         {
00200           /*
00201            * Lookup to the entry to be removed to check if it is a directory
00202            */
00203           if((pentry_child = cache_inode_lookup(parent_pentry,
00204                                                 &name,
00205                                                 &pentry_child_attr,
00206                                                 pcontext,
00207                                                 &cache_status)) != NULL)
00208             {
00209               /* Extract the filetype */
00210               childtype = cache_inode_fsal_type_convert(pentry_child_attr.type);
00211 
00212               /*
00213                * Sanity check: make sure we are about to remove a directory
00214                */
00215               if(childtype != DIRECTORY)
00216                 {
00217                   switch (preq->rq_vers)
00218                     {
00219                     case NFS_V2:
00220                       pres->res_stat2 = NFSERR_NOTDIR;
00221                       break;
00222 
00223                     case NFS_V3:
00224                       pres->res_rmdir3.status = NFS3ERR_NOTDIR;
00225                       break;
00226                     }
00227                   rc = NFS_REQ_OK;
00228                   goto out;
00229                 }
00230 
00231               /*
00232                * Remove the directory.  Use NULL vnode for the directory
00233                * that's being removed because we know the directory's name. 
00234                */
00235 
00236               if(cache_inode_remove(parent_pentry,
00237                                     &name,
00238                                     &parent_attr,
00239                                     pcontext, &cache_status) == CACHE_INODE_SUCCESS)
00240                 {
00241                   switch (preq->rq_vers)
00242                     {
00243                     case NFS_V2:
00244                       pres->res_stat2 = NFS_OK;
00245                       break;
00246 
00247                     case NFS_V3:
00248                       /* Build Weak Cache Coherency data */
00249                       nfs_SetWccData(pexport,
00250                                      ppre_attr,
00251                                      &parent_attr,
00252                                      &(pres->res_rmdir3.RMDIR3res_u.resok.dir_wcc));
00253 
00254                       pres->res_rmdir3.status = NFS3_OK;
00255                       break;
00256                     }
00257                   rc = NFS_REQ_OK;
00258                   goto out;
00259                 }
00260             }
00261         }
00262     }
00263 
00264   /* If we are here, there was an error */
00265   if(nfs_RetryableError(cache_status))
00266     {
00267       rc = NFS_REQ_DROP;
00268       goto out;
00269     }
00270 
00271   nfs_SetFailedStatus(pcontext, pexport,
00272                       preq->rq_vers,
00273                       cache_status,
00274                       &pres->res_stat2,
00275                       &pres->res_rmdir3.status,
00276                       NULL, NULL,
00277                       parent_pentry,
00278                       ppre_attr,
00279                       &(pres->res_rmdir3.RMDIR3res_u.resfail.dir_wcc), NULL, NULL, NULL);
00280 
00281   rc = NFS_REQ_OK;
00282 
00283 out:
00284   /* return references */
00285   if (pentry_child)
00286       cache_inode_put(pentry_child);
00287 
00288   if (parent_pentry)
00289       cache_inode_put(parent_pentry);
00290 
00291   return (rc);
00292 
00293 }                               /* nfs_Rmdir */
00294 
00303 void nfs_Rmdir_Free(nfs_res_t * resp)
00304 {
00305   /* Nothing to do here */
00306   return;
00307 }                               /* nfs_Rmdir_Free */