nfs-ganesha 1.4
|
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 */