nfs-ganesha 1.4

nfs4_owner.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 License
00011  * as published by the Free Software Foundation; either version 3 of
00012  * the License, or (at your option) any later version.
00013  *
00014  * This program is distributed in the hope that it will be useful, but
00015  * 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
00022  * 02110-1301 USA
00023  */
00024 
00029 #ifdef HAVE_CONFIG_H
00030 #include "config.h"
00031 #endif
00032 
00033 #ifdef _SOLARIS
00034 #include "solaris_port.h"
00035 #endif
00036 
00037 #include <pthread.h>
00038 #include <ctype.h>
00039 #include "log.h"
00040 #include "HashData.h"
00041 #include "HashTable.h"
00042 #include "nfs4.h"
00043 #include "sal_functions.h"
00044 #include "nfs_proto_functions.h"
00045 #include "nfs_core.h"
00046 
00047 size_t strnlen(const char *s, size_t maxlen);
00048 
00049 hash_table_t *ht_nfs4_owner;
00050 
00051 uint32_t nfs4_owner_counter = 0;
00052 pthread_mutex_t nfs4_owner_counter_lock = PTHREAD_MUTEX_INITIALIZER;
00053 
00054 int display_nfs4_owner_key(hash_buffer_t * pbuff, char *str)
00055 {
00056   char                    * type;
00057   char                    * strtmp = str;
00058   state_nfs4_owner_name_t * pname = (state_nfs4_owner_name_t *) pbuff->pdata;
00059 
00060   if(pname->son_islock)
00061     type = "lock";
00062   else
00063     type = "open";
00064 
00065   strtmp += sprintf(strtmp, "clientid=%"PRIx64" %s owner=",
00066                     pname->son_clientid,
00067                     type);
00068 
00069   strtmp += DisplayOpaqueValue(pname->son_owner_val,
00070                                pname->son_owner_len,
00071                                strtmp);
00072 
00073   return strtmp - str;
00074 }
00075 
00076 int display_nfs4_owner(state_owner_t *powner, char *str)
00077 {
00078   char         * strtmp = str;
00079 
00080   strtmp += sprintf(strtmp, "%s %p:",
00081                     state_owner_type_to_str(powner->so_type),
00082                     powner);
00083 
00084   strtmp += sprintf(strtmp, " clientid={%"PRIx64"} owner=",
00085                     powner->so_owner.so_nfs4_owner.so_clientid);
00086 
00087   strtmp += DisplayOpaqueValue(powner->so_owner_val,
00088                                powner->so_owner_len,
00089                                strtmp);
00090 
00091   strtmp += sprintf(strtmp, " confirmed=%u counter=%u seqid=%u refcount=%d",
00092                     powner->so_owner.so_nfs4_owner.so_confirmed,
00093                     powner->so_owner.so_nfs4_owner.so_counter,
00094                     powner->so_owner.so_nfs4_owner.so_seqid,
00095                     powner->so_refcount);
00096 
00097   if(powner->so_owner.so_nfs4_owner.so_related_owner != NULL)
00098     {
00099       strtmp += sprintf(strtmp, " related_owner={");
00100       strtmp += display_nfs4_owner(powner->so_owner.so_nfs4_owner.so_related_owner, strtmp);
00101       strtmp += sprintf(strtmp, "}");
00102     }
00103 
00104   return strtmp - str;
00105 }
00106 
00107 int display_nfs4_owner_val(hash_buffer_t * pbuff, char *str)
00108 {
00109   return display_nfs4_owner((state_owner_t *) (pbuff->pdata), str);
00110 }
00111 
00112 int compare_nfs4_owner(state_owner_t * powner1,
00113                        state_owner_t * powner2)
00114 {
00115   if(isFullDebug(COMPONENT_STATE) && isDebug(COMPONENT_HASHTABLE))
00116     {
00117       char str1[HASHTABLE_DISPLAY_STRLEN];
00118       char str2[HASHTABLE_DISPLAY_STRLEN];
00119 
00120       display_nfs4_owner(powner1, str1);
00121       display_nfs4_owner(powner2, str2);
00122       LogFullDebug(COMPONENT_STATE,
00123                    "{%s} vs {%s}", str1, str2);
00124     }
00125 
00126   if(powner1 == NULL || powner2 == NULL)
00127     return 1;
00128 
00129   if(powner1 == powner2)
00130     return 0;
00131 
00132   if(powner1->so_type == STATE_LOCK_OWNER_NFSV4 &&
00133      powner2->so_type == STATE_OPEN_OWNER_NFSV4)
00134     return compare_nfs4_owner(powner1->so_owner.so_nfs4_owner.so_related_owner,
00135                               powner2);
00136 
00137   if(powner2->so_type == STATE_LOCK_OWNER_NFSV4 &&
00138      powner1->so_type == STATE_OPEN_OWNER_NFSV4)
00139     return compare_nfs4_owner(powner2->so_owner.so_nfs4_owner.so_related_owner,
00140                               powner1);
00141 
00142   if(powner1->so_type != powner2->so_type)
00143     return 1;
00144 
00145   if(powner1->so_owner.so_nfs4_owner.so_clientid !=
00146      powner2->so_owner.so_nfs4_owner.so_clientid)
00147     return 1;
00148 
00149   if(powner1->so_owner_len !=
00150      powner2->so_owner_len)
00151     return 1;
00152 
00153   return memcmp(powner1->so_owner_val,
00154                 powner2->so_owner_val,
00155                 powner1->so_owner_len);
00156 }
00157 
00158 int compare_nfs4_owner_key(hash_buffer_t * buff1, hash_buffer_t * buff2)
00159 {
00160   if(isFullDebug(COMPONENT_STATE) && isDebug(COMPONENT_HASHTABLE))
00161     {
00162       char str1[HASHTABLE_DISPLAY_STRLEN];
00163       char str2[HASHTABLE_DISPLAY_STRLEN];
00164 
00165       display_nfs4_owner_key(buff1, str1);
00166       display_nfs4_owner_key(buff2, str2);
00167       if(isDebug(COMPONENT_HASHTABLE))
00168         LogFullDebug(COMPONENT_STATE,
00169                      "{%s} vs {%s}", str1, str2);
00170     }
00171 
00172   state_nfs4_owner_name_t *pname1 = (state_nfs4_owner_name_t *) buff1->pdata;
00173   state_nfs4_owner_name_t *pname2 = (state_nfs4_owner_name_t *) buff2->pdata;
00174 
00175   if(pname1 == NULL || pname2 == NULL)
00176     return 1;
00177 
00178   if(pname1->son_islock != pname2->son_islock)
00179     return 1;
00180 
00181   if(pname1->son_clientid != pname2->son_clientid)
00182     return 1;
00183 
00184   if(pname1->son_owner_len != pname2->son_owner_len)
00185     return 1;
00186 
00187   return memcmp(pname1->son_owner_val, pname2->son_owner_val, pname1->son_owner_len);
00188 }                               /* compare_nfs4_owner */
00189 
00190 uint32_t nfs4_owner_value_hash_func(hash_parameter_t * p_hparam,
00191                                     hash_buffer_t * buffclef)
00192 {
00193   unsigned int sum = 0;
00194   unsigned int i = 0;
00195   unsigned char c = 0;
00196   unsigned long res = 0;
00197 
00198   state_nfs4_owner_name_t *pname = (state_nfs4_owner_name_t *) buffclef->pdata;
00199 
00200   /* Compute the sum of all the characters */
00201   for(i = 0; i < pname->son_owner_len; i++)
00202     {
00203       c = ((char *)pname->son_owner_val)[i];
00204       sum += c;
00205     }
00206 
00207   res = (unsigned long)(pname->son_clientid) + (unsigned long)sum + pname->son_owner_len + pname->son_islock;
00208 
00209   if(isDebug(COMPONENT_HASHTABLE))
00210     LogFullDebug(COMPONENT_STATE,
00211                  "value = %lu", res % p_hparam->index_size);
00212 
00213   return (unsigned long)(res % p_hparam->index_size);
00214 
00215 }                               /* nfs4_owner_value_hash_func */
00216 
00217 uint64_t nfs4_owner_rbt_hash_func(hash_parameter_t * p_hparam,
00218                                   hash_buffer_t * buffclef)
00219 {
00220   state_nfs4_owner_name_t *pname = (state_nfs4_owner_name_t *) buffclef->pdata;
00221 
00222   unsigned int sum = 0;
00223   unsigned int i = 0;
00224   unsigned char c = 0;
00225   unsigned long res = 0;
00226 
00227   /* Compute the sum of all the characters */
00228   for(i = 0; i < pname->son_owner_len; i++)
00229     {
00230       c = ((char *)pname->son_owner_val)[i];
00231       sum += c;
00232     }
00233 
00234   res = (unsigned long)(pname->son_clientid) + (unsigned long)sum + pname->son_owner_len + pname->son_islock;
00235 
00236   if(isDebug(COMPONENT_HASHTABLE))
00237     LogFullDebug(COMPONENT_STATE, "rbt = %lu", res);
00238 
00239   return res;
00240 }                               /* state_id_rbt_hash_func */
00241 
00242 void remove_nfs4_owner(state_owner_t        * powner,
00243                        const char           * str)
00244 {
00245   hash_buffer_t           buffkey, old_key, old_value;
00246   state_nfs4_owner_name_t oname;
00247   int                     rc;
00248 
00249   memset(&oname, 0, sizeof(oname));
00250 
00251   oname.son_clientid  = powner->so_owner.so_nfs4_owner.so_clientid;
00252   oname.son_owner_len = powner->so_owner_len;
00253   oname.son_islock    = powner->so_type == STATE_LOCK_OWNER_NFSV4;
00254   memcpy(oname.son_owner_val, powner->so_owner_val, powner->so_owner_len);
00255 
00256   buffkey.pdata = (caddr_t) &oname;
00257   buffkey.len   = sizeof(*powner);
00258 
00259   rc = HashTable_DelRef(ht_nfs4_owner,
00260                         &buffkey,
00261                         &old_key,
00262                         &old_value,
00263                         Hash_dec_state_owner_ref);
00264 
00265   switch(rc)
00266     {
00267       case HASHTABLE_SUCCESS:
00268         if(powner->so_type == STATE_LOCK_OWNER_NFSV4 &&
00269            powner->so_owner.so_nfs4_owner.so_related_owner != NULL)
00270           dec_state_owner_ref(powner->so_owner.so_nfs4_owner.so_related_owner);
00271 
00272         /* Release the owner_name (key) and owner (data) back to appropriate pools */
00273         LogFullDebug(COMPONENT_STATE, "Free %s", str);
00274 
00275         nfs4_Compound_FreeOne(&powner->so_owner.so_nfs4_owner.so_resp);
00276 
00277         P(powner->so_owner.so_nfs4_owner.so_pclientid->cid_mutex);
00278 
00279         glist_del(&powner->so_owner.so_nfs4_owner.so_perclient);
00280 
00281         V(powner->so_owner.so_nfs4_owner.so_pclientid->cid_mutex);
00282 
00283         dec_client_id_ref(powner->so_owner.so_nfs4_owner.so_pclientid);
00284 
00285         pool_free(state_owner_pool, old_value.pdata);
00286         pool_free(state_nfs4_owner_name_pool, old_key.pdata);
00287         break;
00288 
00289       case HASHTABLE_NOT_DELETED:
00290         /* ref count didn't end up at 0, don't free. */
00291         LogDebug(COMPONENT_STATE,
00292                  "HashTable_DelRef didn't reduce refcount to 0 for %s",
00293                   str);
00294         break;
00295 
00296       default:
00297         /* some problem occurred */
00298         LogDebug(COMPONENT_STATE,
00299                  "HashTable_DelRef failed (%s) for %s",
00300                   hash_table_err_to_str(rc), str);
00301         break;
00302     }
00303 }
00304 
00316 int Init_nfs4_owner(nfs4_owner_parameter_t param)
00317 {
00318 
00319   if((ht_nfs4_owner = HashTable_Init(&param.hash_param)) == NULL)
00320     {
00321       LogCrit(COMPONENT_STATE,
00322               "Cannot init NFS Open Owner cache");
00323       return -1;
00324     }
00325 
00326   return 0;
00327 }                               /* nfs4_Init_nfs4_owner */
00328 
00338 int nfs4_owner_Set(state_nfs4_owner_name_t * pname,
00339                    state_owner_t           * powner)
00340 {
00341   hash_buffer_t buffkey;
00342   hash_buffer_t buffval;
00343   int rc;
00344 
00345   buffkey.pdata = (caddr_t) pname;
00346   buffkey.len = sizeof(state_nfs4_owner_name_t);
00347 
00348   if(isFullDebug(COMPONENT_STATE) && isDebug(COMPONENT_HASHTABLE))
00349     {
00350       char str[HASHTABLE_DISPLAY_STRLEN];
00351 
00352       display_nfs4_owner_key(&buffkey, str);
00353       LogFullDebug(COMPONENT_STATE,
00354                    "KEY {%s}", str);
00355     }
00356 
00357   buffval.pdata = (caddr_t) powner;
00358   buffval.len = sizeof(state_owner_t);
00359 
00360   P(nfs4_owner_counter_lock);
00361   nfs4_owner_counter += 1;
00362   powner->so_owner.so_nfs4_owner.so_counter = nfs4_owner_counter;
00363   V(nfs4_owner_counter_lock);
00364 
00365   rc = HashTable_Test_And_Set
00366      (ht_nfs4_owner, &buffkey, &buffval,
00367       HASHTABLE_SET_HOW_SET_NO_OVERWRITE);
00368   if(rc != HASHTABLE_SUCCESS)
00369     {
00370       LogDebug(COMPONENT_STATE,
00371                "Failed to insert nfs4 owner into hash table rc = %d", rc);
00372       return 0;
00373     }
00374 
00375   return 1;
00376 }                               /* nfs4_owner_Set */
00377 
00390 int nfs4_owner_Get_Pointer(state_nfs4_owner_name_t  * pname,
00391                            state_owner_t           ** powner)
00392 {
00393   hash_buffer_t buffkey;
00394   hash_buffer_t buffval;
00395 
00396   buffkey.pdata = (caddr_t) pname;
00397   buffkey.len = sizeof(state_nfs4_owner_name_t);
00398 
00399   if(isFullDebug(COMPONENT_STATE) && isDebug(COMPONENT_HASHTABLE))
00400     {
00401       char str[HASHTABLE_DISPLAY_STRLEN];
00402 
00403       display_nfs4_owner_key(&buffkey, str);
00404       LogFullDebug(COMPONENT_STATE,
00405                    "KEY {%s}", str);
00406     }
00407 
00408   if(HashTable_GetRef(ht_nfs4_owner,
00409                       &buffkey,
00410                       &buffval,
00411                       Hash_inc_state_owner_ref) != HASHTABLE_SUCCESS)
00412     {
00413       *powner = NULL;
00414       LogFullDebug(COMPONENT_STATE,
00415                    "NOTFOUND");
00416       return 0;
00417     }
00418 
00419   *powner = (state_owner_t *) buffval.pdata;
00420 
00421   LogFullDebug(COMPONENT_STATE,
00422                "FOUND");
00423 
00424   return 1;
00425 }                               /* nfs4_owner_Get_Pointer */
00426 
00436 void nfs4_owner_PrintAll(void)
00437 {
00438   HashTable_Log(COMPONENT_STATE, ht_nfs4_owner);
00439 }                               /* nfs4_owner_PrintAll */
00440 
00441 void convert_nfs4_open_owner(open_owner4             * pnfsowner,
00442                              state_nfs4_owner_name_t * pname_owner,
00443                              clientid4                 clientid)
00444 {
00445   memset(pname_owner, 0, sizeof(*pname_owner));
00446 
00447   if (clientid)
00448     {
00449       pname_owner->son_clientid = clientid;
00450     }
00451   else
00452     {
00453       pname_owner->son_clientid  = pnfsowner->clientid;
00454     }
00455   pname_owner->son_owner_len = pnfsowner->owner.owner_len;
00456   pname_owner->son_islock    = FALSE;
00457   memcpy(pname_owner->son_owner_val,
00458          pnfsowner->owner.owner_val,
00459          pnfsowner->owner.owner_len);
00460 }                               /* convert_nfs4_open_owner */
00461 
00462 void convert_nfs4_lock_owner(lock_owner4             * pnfsowner,
00463                              state_nfs4_owner_name_t * pname_owner,
00464                              clientid4                 clientid)
00465 {
00466   memset(pname_owner, 0, sizeof(*pname_owner));
00467 
00468   if (clientid)
00469     {
00470       pname_owner->son_clientid = clientid;
00471     }
00472   else
00473     {
00474       pname_owner->son_clientid  = pnfsowner->clientid;
00475     }
00476   pname_owner->son_owner_len = pnfsowner->owner.owner_len;
00477   pname_owner->son_islock    = TRUE;
00478   memcpy(pname_owner->son_owner_val,
00479          pnfsowner->owner.owner_val,
00480          pnfsowner->owner.owner_len);
00481 }                               /* convert_nfs4_lock_owner */
00482 
00483 state_owner_t *create_nfs4_owner(state_nfs4_owner_name_t * pname,
00484                                  nfs_client_id_t         * pclientid,
00485                                  state_owner_type_t        type,
00486                                  state_owner_t           * related_owner,
00487                                  unsigned int              init_seqid)
00488 {
00489   state_owner_t           * powner;
00490   state_nfs4_owner_name_t * powner_name;
00491 
00492   /* This lock owner is not known yet, allocated and set up a new one */
00493   powner = pool_alloc(state_owner_pool, NULL);
00494 
00495   if(powner == NULL)
00496     return NULL;
00497 
00498   powner_name = pool_alloc(state_nfs4_owner_name_pool, NULL);
00499 
00500   if(powner_name == NULL)
00501     {
00502       pool_free(state_owner_pool, powner);
00503       return NULL;
00504     }
00505 
00506   *powner_name = *pname;
00507 
00508   /* set up the content of the open_owner */
00509   memset(powner, 0, sizeof(*powner));
00510   powner->so_type                                 = type;
00511   powner->so_owner.so_nfs4_owner.so_seqid         = init_seqid;
00512   powner->so_owner.so_nfs4_owner.so_related_owner = related_owner;
00513   powner->so_owner.so_nfs4_owner.so_clientid      = pname->son_clientid;
00514   powner->so_owner.so_nfs4_owner.so_pclientid     = pclientid;
00515   powner->so_owner_len                            = pname->son_owner_len;
00516   powner->so_owner.so_nfs4_owner.so_resp.resop    = NFS4_OP_ILLEGAL;
00517   powner->so_owner.so_nfs4_owner.so_args.argop    = NFS4_OP_ILLEGAL;
00518   powner->so_refcount                             = 1;
00519 #if 0
00520   /* WAITING FOR COMMUNITY FIX */
00521   /* setting lock owner confirmed */
00522   if ( type == STATE_LOCK_OWNER_NFSV4)
00523     powner->so_owner.so_nfs4_owner.so_confirmed   = 1;
00524 #endif
00525   init_glist(&powner->so_lock_list);
00526   init_glist(&powner->so_owner.so_nfs4_owner.so_state_list);
00527 
00528   memcpy(powner->so_owner_val,
00529          pname->son_owner_val,
00530          pname->son_owner_len);
00531 
00532   powner->so_owner_val[powner->so_owner_len] = '\0';
00533 
00534   if(pthread_mutex_init(&powner->so_mutex, NULL) == -1)
00535     {
00536       pool_free(state_owner_pool, powner);
00537       pool_free(state_nfs4_owner_name_pool, powner_name);
00538       return NULL;
00539     }
00540 
00541   if(!nfs4_owner_Set(powner_name, powner))
00542     {
00543       pool_free(state_owner_pool, powner);
00544       pool_free(state_nfs4_owner_name_pool, powner_name);
00545       return NULL;
00546     }
00547 
00548   if(isFullDebug(COMPONENT_STATE))
00549     {
00550       char str[HASHTABLE_DISPLAY_STRLEN];
00551 
00552       DisplayOwner(powner, str);
00553       LogFullDebug(COMPONENT_STATE,
00554                    "New Owner %s", str);
00555     }
00556 
00557   /* Increment refcount on related owner */
00558   if(related_owner != NULL)
00559     inc_state_owner_ref(related_owner);
00560 
00561   P(pclientid->cid_mutex);
00562 
00563   if (type == STATE_OPEN_OWNER_NFSV4)
00564     {
00565       /* If open owner, add to clientid lock owner list */
00566       powner->so_refcount++;
00567       glist_add_tail(&pclientid->cid_openowners, &powner->so_owner.so_nfs4_owner.so_perclient);
00568     }
00569   else if(type == STATE_LOCK_OWNER_NFSV4)
00570     {
00571       /* If lock owner, add to clientid open owner list */
00572       powner->so_refcount++;
00573       glist_add_tail(&pclientid->cid_lockowners, &powner->so_owner.so_nfs4_owner.so_perclient);
00574     }
00575 
00576   /* Increment reference count for clientid record */
00577   inc_client_id_ref(pclientid);
00578 
00579   V(pclientid->cid_mutex);
00580 
00581   return powner;
00582 }
00583 
00584 void Process_nfs4_conflict(LOCK4denied          * denied,    /* NFS v4 LOck4denied structure to fill in */
00585                            state_owner_t        * holder,    /* owner that holds conflicting lock */
00586                            fsal_lock_param_t    * conflict)  /* description of conflicting lock */
00587 {
00588   /* A  conflicting lock from a different lock_owner, returns NFS4ERR_DENIED */
00589   denied->offset = conflict->lock_start;
00590   denied->length = conflict->lock_length;
00591 
00592   if(conflict->lock_type == FSAL_LOCK_R)
00593     denied->locktype = READ_LT;
00594   else
00595     denied->locktype = WRITE_LT;
00596 
00597   if(holder != NULL && holder->so_owner_len != 0)
00598     denied->owner.owner.owner_val = gsh_malloc(holder->so_owner_len);
00599   else
00600     denied->owner.owner.owner_val = NULL;
00601 
00602   LogFullDebug(COMPONENT_STATE,
00603                "denied->owner.owner.owner_val = %p",
00604                denied->owner.owner.owner_val);
00605 
00606   if(denied->owner.owner.owner_val != NULL)
00607     {
00608       denied->owner.owner.owner_len = holder->so_owner_len;
00609 
00610       memcpy(denied->owner.owner.owner_val,
00611              holder->so_owner_val,
00612              holder->so_owner_len);
00613     }
00614   else
00615     {
00616       denied->owner.owner.owner_len = unknown_owner.so_owner_len;
00617       denied->owner.owner.owner_val = unknown_owner.so_owner_val;
00618     }
00619 
00620   if(holder != NULL && holder->so_type == STATE_LOCK_OWNER_NFSV4)
00621     denied->owner.clientid = holder->so_owner.so_nfs4_owner.so_clientid;
00622   else
00623     denied->owner.clientid = 0;
00624 
00625   /* Release any lock owner reference passed back from SAL */
00626   if(holder != NULL)
00627     dec_state_owner_ref(holder);
00628 }
00629 
00630 void Release_nfs4_denied(LOCK4denied * denied)
00631 {
00632   if(denied->owner.owner.owner_val != unknown_owner.so_owner_val &&
00633      denied->owner.owner.owner_val != NULL)
00634     gsh_free(denied->owner.owner.owner_val);
00635 }
00636 
00637 void Copy_nfs4_denied(LOCK4denied * denied_dst, LOCK4denied * denied_src)
00638 {
00639   memcpy(denied_dst, denied_src, sizeof(*denied_dst));
00640 
00641   if(denied_src->owner.owner.owner_val != unknown_owner.so_owner_val &&
00642      denied_src->owner.owner.owner_val != NULL)
00643     {
00644       denied_dst->owner.owner.owner_val
00645         = gsh_malloc(denied_src->owner.owner.owner_len);
00646       LogFullDebug(COMPONENT_STATE,
00647                    "denied_dst->owner.owner.owner_val = %p",
00648                    denied_dst->owner.owner.owner_val);
00649     }
00650 
00651   if(denied_dst->owner.owner.owner_val == NULL)
00652     {
00653       denied_dst->owner.owner.owner_len = unknown_owner.so_owner_len;
00654       denied_dst->owner.owner.owner_val = unknown_owner.so_owner_val;
00655     }
00656 }
00657 
00658 void Copy_nfs4_state_req(state_owner_t   * powner,
00659                          seqid4            seqid,
00660                          nfs_argop4      * args,
00661                          compound_data_t * data,
00662                          nfs_resop4      * resp,
00663                          const char      * tag)
00664 {
00665   /* Simplify use of this function when we may not be keeping any data for the
00666    * state owner
00667    */
00668   if(powner == NULL)
00669     return;
00670 
00671   LogFullDebug(COMPONENT_STATE,
00672                "%s: saving response %p so_seqid %u new seqid %u",
00673                tag, powner, powner->so_owner.so_nfs4_owner.so_seqid, seqid);
00674 
00675   /* Free previous response */
00676   nfs4_Compound_FreeOne(&powner->so_owner.so_nfs4_owner.so_resp);
00677 
00678   /* Copy new response */
00679   nfs4_Compound_CopyResOne(&powner->so_owner.so_nfs4_owner.so_resp, resp);
00680 
00681   /* Deep copy OPEN args? */
00682   if(powner->so_owner.so_nfs4_owner.so_args.argop == NFS4_OP_OPEN)
00683     {
00684     }
00685 
00686   /* Copy bnew args */
00687   memcpy(&powner->so_owner.so_nfs4_owner.so_args,
00688          args,
00689          sizeof(powner->so_owner.so_nfs4_owner.so_args));
00690 
00691   /* Copy new file */
00692   powner->so_owner.so_nfs4_owner.so_last_pentry = data->current_entry;
00693 
00694   /* Deep copy OPEN args? */
00695   if(args->argop == NFS4_OP_OPEN)
00696     {
00697     }
00698 
00699   /* Store new seqid */
00700   powner->so_owner.so_nfs4_owner.so_seqid = seqid;
00701 }
00702 
00714 bool_t Check_nfs4_seqid(state_owner_t   * powner,
00715                         seqid4            seqid,
00716                         nfs_argop4      * args,
00717                         compound_data_t * data,
00718                         nfs_resop4      * resp,
00719                         const char      * tag)
00720 {
00721   seqid4 next;
00722 
00723   /* Check if any owner to verify seqid against */
00724   if(powner == NULL)
00725     {
00726       LogFullDebug(COMPONENT_STATE,
00727                "%s: Unknown owner doesn't have saved seqid, req seqid %u",
00728                tag, seqid);
00729       return TRUE;
00730     }
00731 
00732   /* If this is a new state owner, client may start with any seqid */
00733   if(powner->so_owner.so_nfs4_owner.so_last_pentry == NULL)
00734     {
00735       LogFullDebug(COMPONENT_STATE,
00736                "%s: New owner %p doesn't have saved seqid, req seqid %u",
00737                tag, powner, seqid);
00738       return TRUE;
00739     }
00740 
00741   /* Check for valid next seqid */
00742   next = powner->so_owner.so_nfs4_owner.so_seqid + 1;
00743 
00744   LogFullDebug(COMPONENT_STATE,
00745                "%s: Check powner %p so_seqid %u next %u req seqid %u",
00746                tag, powner, powner->so_owner.so_nfs4_owner.so_seqid, next, seqid);
00747 
00748   if(seqid == next)
00749     return TRUE;
00750 
00751   /* All NFS4 responses have the status in the same place, so use any to set NFS4ERR_BAD_SEQID */
00752   resp->nfs_resop4_u.oplock.status = NFS4ERR_BAD_SEQID;
00753 
00754   /* Now check for valid replay */
00755   if(powner->so_owner.so_nfs4_owner.so_seqid != seqid)
00756     {
00757       LogDebug(COMPONENT_STATE,
00758                "%s: Invalid seqid %u in request (not replay), expected seqid %u, returning NFS4ERR_BAD_SEQID",
00759                tag, seqid, powner->so_owner.so_nfs4_owner.so_seqid);
00760       return FALSE;
00761     }
00762 
00763   if(args->argop != powner->so_owner.so_nfs4_owner.so_args.argop)
00764     {
00765       LogDebug(COMPONENT_STATE,
00766                "%s: Invalid seqid in request %u (not replay - not same op), returning NFS4ERR_BAD_SEQID",
00767                tag, seqid);
00768       return FALSE;
00769     }
00770 
00771   if(powner->so_owner.so_nfs4_owner.so_last_pentry != data->current_entry)
00772     {
00773       LogDebug(COMPONENT_STATE,
00774                "%s: Invalid seqid in request %u (not replay - wrong file), returning NFS4ERR_BAD_SEQID",
00775                tag, seqid);
00776       return FALSE;
00777     }
00778 
00779   // TODO FSF: add more checks here...
00780 
00781   LogDebug(COMPONENT_STATE,
00782            "%s: Copying saved response for seqid %u",
00783            tag, seqid);
00784 
00785   /* Copy the saved response and tell caller to use it */
00786   nfs4_Compound_CopyResOne(resp, &powner->so_owner.so_nfs4_owner.so_resp);
00787 
00788   return FALSE;
00789 }
00790 
00792 state_status_t get_clientid_owner(clientid4 clientid,
00793                                   state_owner_t **clientid_owner)
00794 {
00795   /* Pointer to client record, retrieved by ID and in which the
00796      client state owner is stored */
00797   nfs_client_id_t *pclientid = NULL;
00798   /* Return code for error checking */
00799   int rc = 0;
00800 
00801   if ((rc = nfs_client_id_get_confirmed(clientid, &pclientid))
00802       != CLIENT_ID_SUCCESS)
00803     {
00804       return STATE_NOT_FOUND;
00805     }
00806   else
00807     {
00808       *clientid_owner = &pclientid->cid_owner;
00809       dec_client_id_ref(pclientid);
00810       return STATE_SUCCESS;
00811     }
00812 }