nfs-ganesha 1.4

nfs4_op_close.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 <pthread.h>
00045 #include "log.h"
00046 #include "nfs4.h"
00047 #include "sal_functions.h"
00048 #include "nfs_proto_tools.h"
00049 #include "nfs_proto_functions.h"
00050 
00065 #define arg_CLOSE4 op->nfs_argop4_u.opclose
00066 #define res_CLOSE4 resp->nfs_resop4_u.opclose
00067 
00068 int nfs4_op_close(struct nfs_argop4 *op, compound_data_t * data, struct nfs_resop4 *resp)
00069 {
00070   char __attribute__ ((__unused__)) funcname[] = "nfs4_op_close";
00071 
00072   int                    rc = 0;
00073   state_t              * pstate_found = NULL;
00074   cache_inode_status_t   cache_status;
00075   state_status_t         state_status;
00076   state_owner_t        * popen_owner;
00077   const char           * tag = "CLOSE";
00078   struct glist_head    * glist, * glistn;
00079 
00080   LogDebug(COMPONENT_STATE,
00081            "Entering NFS v4 CLOSE handler -----------------------------------------------------");
00082 
00083   memset(&res_CLOSE4, 0, sizeof(res_CLOSE4));
00084   resp->resop = NFS4_OP_CLOSE;
00085   res_CLOSE4.status = NFS4_OK;
00086 
00087   /*
00088    * Do basic checks on a filehandle
00089    * Object should be a file
00090    */
00091   res_CLOSE4.status = nfs4_sanity_check_FH(data, REGULAR_FILE);
00092   if(res_CLOSE4.status != NFS4_OK)
00093     return res_CLOSE4.status;
00094 
00095   if(data->current_entry == NULL)
00096     {
00097       res_CLOSE4.status = NFS4ERR_SERVERFAULT;
00098       return res_CLOSE4.status;
00099     }
00100 
00101 
00102   /* Check stateid correctness and get pointer to state */
00103   if((rc = nfs4_Check_Stateid(&arg_CLOSE4.open_stateid,
00104                               data->current_entry,
00105                               &pstate_found,
00106                               data,
00107                               STATEID_SPECIAL_FOR_LOCK,
00108                               tag)) != NFS4_OK)
00109     {
00110       res_CLOSE4.status = rc;
00111       LogDebug(COMPONENT_STATE,
00112                "CLOSE failed nfs4_Check_Stateid");
00113       return res_CLOSE4.status;
00114     }
00115 
00116   popen_owner = pstate_found->state_powner;
00117 
00118   P(popen_owner->so_mutex);
00119 
00120   /* Check seqid */
00121   if(!Check_nfs4_seqid(popen_owner, arg_CLOSE4.seqid, op, data, resp, tag))
00122     {
00123       /* Response is all setup for us and LogDebug told what was wrong */
00124       V(popen_owner->so_mutex);
00125       return res_CLOSE4.status;
00126     }
00127 
00128   V(popen_owner->so_mutex);
00129 
00130   pthread_rwlock_wrlock(&data->current_entry->state_lock);
00131   /* Check is held locks remain */
00132   glist_for_each(glist, &pstate_found->state_data.share.share_lockstates)
00133     {
00134       state_t * plock_state = glist_entry(glist,
00135                                           state_t,
00136                                           state_data.lock.state_sharelist);
00137 
00138       if(!glist_empty(&plock_state->state_data.lock.state_locklist))
00139         {
00140           res_CLOSE4.status = NFS4ERR_LOCKS_HELD;
00141 
00142           pthread_rwlock_unlock(&data->current_entry->state_lock);
00143           LogDebug(COMPONENT_STATE,
00144                    "NFS4 Close with existing locks");
00145 
00146           /* Save the response in the open owner */
00147           Copy_nfs4_state_req(popen_owner, arg_CLOSE4.seqid, op, data, resp, tag);
00148 
00149           return res_CLOSE4.status;
00150         }
00151     }
00152 
00153 
00154   /* Handle stateid/seqid for success */
00155   update_stateid(pstate_found,
00156                  &res_CLOSE4.CLOSE4res_u.open_stateid,
00157                  data,
00158                  tag);
00159 
00160   /* Save the response in the open owner */
00161   Copy_nfs4_state_req(popen_owner, arg_CLOSE4.seqid, op, data, resp, tag);
00162 
00163   /* File is closed, release the corresponding lock states */
00164   glist_for_each_safe(glist, glistn, &pstate_found->state_data.share.share_lockstates)
00165     {
00166       state_t * plock_state = glist_entry(glist,
00167                                           state_t,
00168                                           state_data.lock.state_sharelist);
00169 
00170       if((state_status
00171           = state_del_locked(plock_state,
00172                              data->current_entry)) != STATE_SUCCESS)
00173         {
00174           LogDebug(COMPONENT_STATE,
00175                    "CLOSE failed to release lock stateid error %s",
00176                    state_err_str(state_status));
00177         }
00178     }
00179 
00180   /* File is closed, release the share state */
00181   if(pstate_found->state_type == STATE_TYPE_SHARE)
00182     {
00183       if(state_share_remove(pstate_found->state_pentry,
00184                             data->pcontext,
00185                             popen_owner,
00186                             pstate_found,
00187                             &state_status) != STATE_SUCCESS)
00188         {
00189           LogDebug(COMPONENT_STATE,
00190                    "CLOSE failed to release share state error %s",
00191                    state_err_str(state_status));
00192         }
00193     }
00194 
00195   /* File is closed, release the corresponding state */
00196   if((state_status
00197       = state_del_locked(pstate_found,
00198                          data->current_entry)) != STATE_SUCCESS)
00199     {
00200       LogDebug(COMPONENT_STATE,
00201                "CLOSE failed to release stateid error %s",
00202                state_err_str(state_status));
00203     }
00204 
00205   /* Close the file in FSAL through the cache inode */
00206   if(cache_inode_close(data->current_entry,
00207                        0,
00208                        &cache_status) != CACHE_INODE_SUCCESS)
00209     {
00210       res_CLOSE4.status = nfs4_Errno(cache_status);
00211       pthread_rwlock_unlock(&data->current_entry->state_lock);
00212 
00213       /* Save the response in the open owner */
00214       Copy_nfs4_state_req(popen_owner, arg_CLOSE4.seqid, op, data, resp, tag);
00215 
00216       return res_CLOSE4.status;
00217     }
00218 
00219   pthread_rwlock_unlock(&data->current_entry->state_lock);
00220   res_CLOSE4.status = NFS4_OK;
00221 
00222   if(isFullDebug(COMPONENT_STATE) && isFullDebug(COMPONENT_MEMLEAKS))
00223     {
00224       nfs_State_PrintAll();
00225       nfs4_owner_PrintAll();
00226     }
00227 
00228   return NFS4_OK;
00229 }                               /* nfs4_op_close */
00230 
00241 void nfs4_op_close_Free(CLOSE4res * resp)
00242 {
00243   /* Nothing to be done */
00244   return;
00245 }                               /* nfs4_op_close_Free */
00246 
00247 void nfs4_op_close_CopyRes(CLOSE4res * resp_dst, CLOSE4res * resp_src)
00248 {
00249   /* Nothing to be done */
00250   return;
00251 }