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