nfs-ganesha 1.4

nfs41_op_lockt.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 
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 "HashData.h"
00049 #include "HashTable.h"
00050 #include "log.h"
00051 #include "ganesha_rpc.h"
00052 #include "nfs4.h"
00053 #include "nfs_core.h"
00054 #include "sal_functions.h"
00055 #include "nfs_proto_functions.h"
00056 #include "nfs_proto_tools.h"
00057 
00075 #define arg_LOCKT4 op->nfs_argop4_u.oplockt
00076 #define res_LOCKT4 resp->nfs_resop4_u.oplockt
00077 
00078 int nfs41_op_lockt(struct nfs_argop4 *op, compound_data_t * data, struct nfs_resop4 *resp)
00079 {
00080   state_status_t            state_status;
00081   state_nfs4_owner_name_t   owner_name;
00082   state_owner_t           * plock_owner;
00083   state_owner_t           * conflict_owner = NULL;
00084   fsal_lock_param_t         lock_desc, conflict_desc;
00085 
00086   LogDebug(COMPONENT_NFS_V4_LOCK,
00087            "Entering NFS v4.1 LOCKT handler -----------------------------------------------------");
00088 
00089   /* Initialize to sane default */
00090   resp->resop = NFS4_OP_LOCKT;
00091   res_LOCKT4.status = NFS4_OK;
00092 
00093   /*
00094    * Do basic checks on a filehandle
00095    * LOCKT is done only on a file
00096    */
00097   res_LOCKT4.status = nfs4_sanity_check_FH(data, REGULAR_FILE);
00098   if(res_LOCKT4.status != NFS4_OK)
00099     return res_LOCKT4.status;
00100 
00101   /* Lock length should not be 0 */
00102   if(arg_LOCKT4.length == 0LL)
00103     {
00104       res_LOCKT4.status = NFS4ERR_INVAL;
00105       return res_LOCKT4.status;
00106     }
00107 
00108   if (nfs_in_grace())
00109     {
00110       res_LOCKT4.status = NFS4ERR_GRACE;
00111       return res_LOCKT4.status;
00112     }
00113 
00114   /* Convert lock parameters to internal types */
00115   switch(arg_LOCKT4.locktype)
00116     {
00117       case READ_LT:
00118       case READW_LT:
00119         lock_desc.lock_type = FSAL_LOCK_R;
00120         break;
00121 
00122       case WRITE_LT:
00123       case WRITEW_LT:
00124         lock_desc.lock_type = FSAL_LOCK_W;
00125         break;
00126     }
00127 
00128   lock_desc.lock_start = arg_LOCKT4.offset;
00129 
00130   if(arg_LOCKT4.length != STATE_LOCK_OFFSET_EOF)
00131     lock_desc.lock_length = arg_LOCKT4.length;
00132   else
00133     lock_desc.lock_length = 0;
00134 
00135   /* Check for range overflow.
00136    * Comparing beyond 2^64 is not possible int 64 bits precision,
00137    * but off+len > 2^64-1 is equivalent to len > 2^64-1 - off
00138    */
00139   if(lock_desc.lock_length > (STATE_LOCK_OFFSET_EOF - lock_desc.lock_start))
00140     {
00141       res_LOCKT4.status = NFS4ERR_INVAL;
00142       return res_LOCKT4.status;
00143     }
00144 
00145   /* Is this lock_owner known ? */
00146   convert_nfs4_lock_owner(&arg_LOCKT4.owner, &owner_name,
00147                           data->psession->clientid);
00148 
00149   if(!nfs4_owner_Get_Pointer(&owner_name, &plock_owner))
00150     {
00151       /* This lock owner is not known yet, allocated and set up a new one */
00152       plock_owner = create_nfs4_owner(&owner_name,
00153                                       data->psession->pclientid_record,
00154                                       STATE_LOCK_OWNER_NFSV4,
00155                                       NULL,
00156                                       0);
00157 
00158       if(plock_owner == NULL)
00159         {
00160           LogFullDebug(COMPONENT_NFS_V4_LOCK,
00161                        "LOCKT unable to create lock owner");
00162           res_LOCKT4.status = NFS4ERR_SERVERFAULT;
00163           return res_LOCKT4.status;
00164         }
00165     }
00166   else if(isFullDebug(COMPONENT_NFS_V4_LOCK))
00167     {
00168       char str[HASHTABLE_DISPLAY_STRLEN];
00169 
00170       DisplayOwner(plock_owner, str);
00171       
00172       LogFullDebug(COMPONENT_NFS_V4_LOCK,
00173                    "LOCKT A previously known owner is used %s",
00174                    str);
00175     }
00176 
00177   LogLock(COMPONENT_NFS_V4_LOCK, NIV_FULL_DEBUG,
00178           "LOCKT",
00179           data->current_entry,
00180           data->pcontext,
00181           plock_owner,
00182           &lock_desc);
00183 
00184   /* Now we have a lock owner and a stateid.
00185    * Go ahead and test the lock in SAL (and FSAL).
00186    */
00187   if(state_test(data->current_entry,
00188                 data->pcontext,
00189                 data->pexport,
00190                 plock_owner,
00191                 &lock_desc,
00192                 &conflict_owner,
00193                 &conflict_desc,
00194                 &state_status) == STATE_LOCK_CONFLICT)
00195     {
00196       /* A  conflicting lock from a different lock_owner, returns NFS4ERR_DENIED */
00197       Process_nfs4_conflict(&res_LOCKT4.LOCKT4res_u.denied,
00198                             conflict_owner,
00199                             &conflict_desc);
00200     }
00201 
00202   /* Release NFS4 Open Owner reference */
00203   dec_state_owner_ref(plock_owner);
00204 
00205   /* Return result */
00206   res_LOCKT4.status = nfs4_Errno_state(state_status);
00207   return res_LOCKT4.status;
00208 
00209 }                               /* nfs41_op_lockt */
00210 
00221 void nfs41_op_lockt_Free(LOCKT4res * resp)
00222 {
00223   if(resp->status == NFS4ERR_DENIED)
00224     Release_nfs4_denied(&resp->LOCKT4res_u.denied);
00225 }                               /* nfs41_op_lockt_Free */