nfs-ganesha 1.4

state_misc.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  * \File    state_misc.c
00026  * \author  $Author: deniel $
00027  * \date    $Date: 2006/01/05 15:14:51 $
00028  * \version $Revision: 1.63 $
00029  * \brief   Some routines for management of the state abstraction layer, shared by other calls.
00030  *
00031  * state_misc.c : Some routines for management of the state abstraction layer, shared by other calls.
00032  *
00033  *
00034  */
00035 #ifdef HAVE_CONFIG_H
00036 #include "config.h"
00037 #endif
00038 
00039 #ifdef _SOLARIS
00040 #include "solaris_port.h"
00041 #endif                          /* _SOLARIS */
00042 
00043 #include <unistd.h>
00044 #include <sys/types.h>
00045 #include <sys/param.h>
00046 #include <time.h>
00047 #include <pthread.h>
00048 #include <string.h>
00049 #include <ctype.h>
00050 #include <assert.h>
00051 
00052 #include "log.h"
00053 #include "HashData.h"
00054 #include "HashTable.h"
00055 #include "fsal.h"
00056 #include "sal_functions.h"
00057 #include "cache_inode_lru.h"
00058 
00059 pool_t *state_owner_pool; /*< Pool for NFSv4 files's open owner */
00060 pool_t *state_nfs4_owner_name_pool; /*< Pool for NFSv4 files's open_owner */
00061 pool_t *state_v4_pool; /*< Pool for NFSv4 files's states */
00062 
00063 const char *state_err_str(state_status_t err)
00064 {
00065   switch(err)
00066     {
00067       case STATE_SUCCESS:               return "STATE_SUCCESS";
00068       case STATE_MALLOC_ERROR:          return "STATE_MALLOC_ERROR";
00069       case STATE_POOL_MUTEX_INIT_ERROR: return "STATE_POOL_MUTEX_INIT_ERROR";
00070       case STATE_GET_NEW_LRU_ENTRY:     return "STATE_GET_NEW_LRU_ENTRY";
00071       case STATE_UNAPPROPRIATED_KEY:    return "STATE_UNAPPROPRIATED_KEY";
00072       case STATE_INIT_ENTRY_FAILED:     return "STATE_INIT_ENTRY_FAILED";
00073       case STATE_FSAL_ERROR:            return "STATE_FSAL_ERROR";
00074       case STATE_LRU_ERROR:             return "STATE_LRU_ERROR";
00075       case STATE_HASH_SET_ERROR:        return "STATE_HASH_SET_ERROR";
00076       case STATE_NOT_A_DIRECTORY:       return "STATE_NOT_A_DIRECTORY";
00077       case STATE_INCONSISTENT_ENTRY:    return "STATE_INCONSISTENT_ENTRY";
00078       case STATE_BAD_TYPE:              return "STATE_BAD_TYPE";
00079       case STATE_ENTRY_EXISTS:          return "STATE_ENTRY_EXISTS";
00080       case STATE_DIR_NOT_EMPTY:         return "STATE_DIR_NOT_EMPTY";
00081       case STATE_NOT_FOUND:             return "STATE_NOT_FOUND";
00082       case STATE_INVALID_ARGUMENT:      return "STATE_INVALID_ARGUMENT";
00083       case STATE_INSERT_ERROR:          return "STATE_INSERT_ERROR";
00084       case STATE_HASH_TABLE_ERROR:      return "STATE_HASH_TABLE_ERROR";
00085       case STATE_FSAL_EACCESS:          return "STATE_FSAL_EACCESS";
00086       case STATE_IS_A_DIRECTORY:        return "STATE_IS_A_DIRECTORY";
00087       case STATE_FSAL_EPERM:            return "STATE_FSAL_EPERM";
00088       case STATE_NO_SPACE_LEFT:         return "STATE_NO_SPACE_LEFT";
00089       case STATE_CACHE_CONTENT_ERROR:   return "STATE_CACHE_CONTENT_ERROR";
00090       case STATE_CACHE_CONTENT_EXISTS:  return "STATE_CACHE_CONTENT_EXISTS";
00091       case STATE_CACHE_CONTENT_EMPTY:   return "STATE_CACHE_CONTENT_EMPTY";
00092       case STATE_READ_ONLY_FS:          return "STATE_READ_ONLY_FS";
00093       case STATE_IO_ERROR:              return "STATE_IO_ERROR";
00094       case STATE_FSAL_ESTALE:           return "STATE_FSAL_ESTALE";
00095       case STATE_FSAL_ERR_SEC:          return "STATE_FSAL_ERR_SEC";
00096       case STATE_STATE_CONFLICT:        return "STATE_STATE_CONFLICT";
00097       case STATE_QUOTA_EXCEEDED:        return "STATE_QUOTA_EXCEEDED";
00098       case STATE_DEAD_ENTRY:            return "STATE_DEAD_ENTRY";
00099       case STATE_ASYNC_POST_ERROR:      return "STATE_ASYNC_POST_ERROR";
00100       case STATE_NOT_SUPPORTED:         return "STATE_NOT_SUPPORTED";
00101       case STATE_STATE_ERROR:           return "STATE_STATE_ERROR";
00102       case STATE_FSAL_DELAY:            return "STATE_FSAL_DELAY";
00103       case STATE_NAME_TOO_LONG:         return "STATE_NAME_TOO_LONG";
00104       case STATE_LOCK_CONFLICT:         return "STATE_LOCK_CONFLICT";
00105       case STATE_LOCK_BLOCKED:          return "STATE_LOCK_BLOCKED";
00106       case STATE_LOCK_DEADLOCK:         return "STATE_LOCK_DEADLOCK";
00107       case STATE_BAD_COOKIE:            return "STATE_BAD_COOKIE";
00108       case STATE_FILE_BIG:              return "STATE_FILE_BIG";
00109       case STATE_GRACE_PERIOD:          return "STATE_GRACE_PERIOD";
00110       case STATE_CACHE_INODE_ERR:       return "STATE_CACHE_INODE_ERR";
00111       case STATE_SIGNAL_ERROR:          return "STATE_SIGNAL_ERROR";
00112       case STATE_KILLED:                return "STATE_KILLED";
00113       case STATE_FILE_OPEN:             return "STATE_FILE_OPEN";
00114     }
00115   return "unknown";
00116 }
00117 
00118 state_status_t cache_inode_status_to_state_status(cache_inode_status_t status)
00119 {
00120   switch(status)
00121     {
00122       case CACHE_INODE_SUCCESS:               return STATE_SUCCESS;
00123       case CACHE_INODE_MALLOC_ERROR:          return STATE_MALLOC_ERROR;
00124       case CACHE_INODE_POOL_MUTEX_INIT_ERROR: return STATE_POOL_MUTEX_INIT_ERROR;
00125       case CACHE_INODE_GET_NEW_LRU_ENTRY:     return STATE_GET_NEW_LRU_ENTRY;
00126       case CACHE_INODE_UNAPPROPRIATED_KEY:    return STATE_UNAPPROPRIATED_KEY;
00127       case CACHE_INODE_INIT_ENTRY_FAILED:     return STATE_INIT_ENTRY_FAILED;
00128       case CACHE_INODE_FSAL_ERROR:            return STATE_FSAL_ERROR;
00129       case CACHE_INODE_LRU_ERROR:             return STATE_LRU_ERROR;
00130       case CACHE_INODE_HASH_SET_ERROR:        return STATE_HASH_SET_ERROR;
00131       case CACHE_INODE_NOT_A_DIRECTORY:       return STATE_NOT_A_DIRECTORY;
00132       case CACHE_INODE_INCONSISTENT_ENTRY:    return STATE_INCONSISTENT_ENTRY;
00133       case CACHE_INODE_BAD_TYPE:              return STATE_BAD_TYPE;
00134       case CACHE_INODE_ENTRY_EXISTS:          return STATE_ENTRY_EXISTS;
00135       case CACHE_INODE_DIR_NOT_EMPTY:         return STATE_DIR_NOT_EMPTY;
00136       case CACHE_INODE_NOT_FOUND:             return STATE_NOT_FOUND;
00137       case CACHE_INODE_INVALID_ARGUMENT:      return STATE_INVALID_ARGUMENT;
00138       case CACHE_INODE_INSERT_ERROR:          return STATE_INSERT_ERROR;
00139       case CACHE_INODE_HASH_TABLE_ERROR:      return STATE_HASH_TABLE_ERROR;
00140       case CACHE_INODE_FSAL_EACCESS:          return STATE_FSAL_EACCESS;
00141       case CACHE_INODE_IS_A_DIRECTORY:        return STATE_IS_A_DIRECTORY;
00142       case CACHE_INODE_FSAL_EPERM:            return STATE_FSAL_EPERM;
00143       case CACHE_INODE_NO_SPACE_LEFT:         return STATE_NO_SPACE_LEFT;
00144       case CACHE_INODE_CACHE_CONTENT_ERROR:   return STATE_CACHE_CONTENT_ERROR;
00145       case CACHE_INODE_CACHE_CONTENT_EXISTS:  return STATE_CACHE_CONTENT_EXISTS;
00146       case CACHE_INODE_CACHE_CONTENT_EMPTY:   return STATE_CACHE_CONTENT_EMPTY;
00147       case CACHE_INODE_READ_ONLY_FS:          return STATE_READ_ONLY_FS;
00148       case CACHE_INODE_IO_ERROR:              return STATE_IO_ERROR;
00149       case CACHE_INODE_FSAL_ESTALE:           return STATE_FSAL_ESTALE;
00150       case CACHE_INODE_FSAL_ERR_SEC:          return STATE_FSAL_ERR_SEC;
00151       case CACHE_INODE_STATE_CONFLICT:        return STATE_STATE_CONFLICT;
00152       case CACHE_INODE_QUOTA_EXCEEDED:        return STATE_QUOTA_EXCEEDED;
00153       case CACHE_INODE_DEAD_ENTRY:            return STATE_DEAD_ENTRY;
00154       case CACHE_INODE_ASYNC_POST_ERROR:      return STATE_ASYNC_POST_ERROR;
00155       case CACHE_INODE_NOT_SUPPORTED:         return STATE_NOT_SUPPORTED;
00156       case CACHE_INODE_STATE_ERROR:           return STATE_STATE_ERROR;
00157       case CACHE_INODE_DELAY:                 return STATE_FSAL_DELAY;
00158       case CACHE_INODE_NAME_TOO_LONG:         return STATE_NAME_TOO_LONG;
00159       case CACHE_INODE_BAD_COOKIE:            return STATE_BAD_COOKIE;
00160       case CACHE_INODE_FILE_BIG:              return STATE_FILE_BIG;
00161       case CACHE_INODE_KILLED:                return STATE_KILLED;
00162       case CACHE_INODE_FILE_OPEN:             return STATE_FILE_OPEN;
00163     }
00164   return STATE_CACHE_INODE_ERR;
00165 }
00166 
00178 state_status_t state_error_convert(fsal_status_t fsal_status)
00179 {
00180   switch (fsal_status.major)
00181     {
00182     case ERR_FSAL_NO_ERROR:
00183       return STATE_SUCCESS;
00184 
00185     case ERR_FSAL_NOENT:
00186       return STATE_NOT_FOUND;
00187 
00188     case ERR_FSAL_DELAY:
00189     case ERR_FSAL_ACCESS:
00190       /* EDELAY and EACCESS are documented by fcntl as
00191        * indicating lock conflict
00192        */
00193       return STATE_LOCK_CONFLICT;
00194 
00195     case ERR_FSAL_PERM:
00196       return STATE_FSAL_EPERM;
00197 
00198     case ERR_FSAL_NOSPC:
00199       return STATE_NO_SPACE_LEFT;
00200 
00201     case ERR_FSAL_ROFS:
00202       return STATE_READ_ONLY_FS;
00203 
00204     case ERR_FSAL_IO:
00205     case ERR_FSAL_NXIO:
00206       return STATE_IO_ERROR;
00207 
00208     case ERR_FSAL_STALE:
00209     case ERR_FSAL_BADHANDLE:
00210     case ERR_FSAL_FHEXPIRED:
00211       return STATE_FSAL_ESTALE;
00212 
00213     case ERR_FSAL_INVAL:
00214     case ERR_FSAL_OVERFLOW:
00215       return STATE_INVALID_ARGUMENT;
00216 
00217     case ERR_FSAL_SEC:
00218       return STATE_FSAL_ERR_SEC;
00219 
00220     case ERR_FSAL_NOTSUPP:
00221     case ERR_FSAL_ATTRNOTSUPP:
00222       return STATE_NOT_SUPPORTED;
00223 
00224     case ERR_FSAL_NOMEM:
00225       return STATE_MALLOC_ERROR;
00226 
00227     case ERR_FSAL_DEADLOCK:
00228       return STATE_LOCK_DEADLOCK;
00229 
00230     case ERR_FSAL_BADCOOKIE:
00231       return STATE_BAD_COOKIE;
00232 
00233     case ERR_FSAL_NOT_OPENED:
00234       LogDebug(COMPONENT_STATE,
00235                "Conversion of ERR_FSAL_NOT_OPENED to STATE_FSAL_ERROR");
00236       return STATE_FSAL_ERROR;
00237 
00238     case ERR_FSAL_SYMLINK:
00239     case ERR_FSAL_ISDIR:
00240     case ERR_FSAL_BADTYPE:
00241       return STATE_BAD_TYPE;
00242 
00243     case ERR_FSAL_FBIG:
00244       return STATE_FILE_BIG;
00245 
00246     case ERR_FSAL_FILE_OPEN:
00247       return STATE_FILE_OPEN;
00248 
00249     case ERR_FSAL_BLOCKED:
00250       return STATE_LOCK_BLOCKED;
00251 
00252     case ERR_FSAL_DQUOT:
00253     case ERR_FSAL_NAMETOOLONG:
00254     case ERR_FSAL_EXIST:
00255     case ERR_FSAL_NOTEMPTY:
00256     case ERR_FSAL_NOTDIR:
00257     case ERR_FSAL_INTERRUPT:
00258     case ERR_FSAL_FAULT:
00259     case ERR_FSAL_NOT_INIT:
00260     case ERR_FSAL_ALREADY_INIT:
00261     case ERR_FSAL_BAD_INIT:
00262     case ERR_FSAL_NO_QUOTA:
00263     case ERR_FSAL_XDEV:
00264     case ERR_FSAL_MLINK:
00265     case ERR_FSAL_TOOSMALL:
00266     case ERR_FSAL_TIMEOUT:
00267     case ERR_FSAL_SERVERFAULT:
00268       /* These errors should be handled inside state (or should never be seen by state) */
00269       LogDebug(COMPONENT_STATE,
00270                "Conversion of FSAL error %d,%d to STATE_FSAL_ERROR",
00271                fsal_status.major, fsal_status.minor);
00272       return STATE_FSAL_ERROR;
00273     }
00274 
00275   /* We should never reach this line, this may produce a warning with certain compiler */
00276   LogCrit(COMPONENT_STATE,
00277           "Default conversion to STATE_FSAL_ERROR for error %d, line %u should never be reached",
00278            fsal_status.major, __LINE__);
00279   return STATE_FSAL_ERROR;
00280 }                               /* state_error_convert */
00281 
00282 /* Error conversion routines */
00292 nfsstat4 nfs4_Errno_state(state_status_t error)
00293 {
00294   nfsstat4 nfserror= NFS4ERR_INVAL;
00295 
00296   switch (error)
00297     {
00298     case STATE_SUCCESS:
00299       nfserror = NFS4_OK;
00300       break;
00301 
00302     case STATE_MALLOC_ERROR:
00303       nfserror = NFS4ERR_RESOURCE;
00304       break;
00305 
00306     case STATE_POOL_MUTEX_INIT_ERROR:
00307     case STATE_GET_NEW_LRU_ENTRY:
00308     case STATE_INIT_ENTRY_FAILED:
00309     case STATE_CACHE_CONTENT_EXISTS:
00310     case STATE_CACHE_CONTENT_EMPTY:
00311       nfserror = NFS4ERR_SERVERFAULT;
00312       break;
00313 
00314     case STATE_UNAPPROPRIATED_KEY:
00315       nfserror = NFS4ERR_BADHANDLE;
00316       break;
00317 
00318     case STATE_BAD_TYPE:
00319       nfserror = NFS4ERR_INVAL;
00320       break;
00321 
00322     case STATE_NOT_A_DIRECTORY:
00323       nfserror = NFS4ERR_NOTDIR;
00324       break;
00325 
00326     case STATE_ENTRY_EXISTS:
00327       nfserror = NFS4ERR_EXIST;
00328       break;
00329 
00330     case STATE_DIR_NOT_EMPTY:
00331       nfserror = NFS4ERR_NOTEMPTY;
00332       break;
00333 
00334     case STATE_NOT_FOUND:
00335       nfserror = NFS4ERR_NOENT;
00336       break;
00337 
00338     case STATE_FSAL_ERROR:
00339     case STATE_INSERT_ERROR:
00340     case STATE_LRU_ERROR:
00341     case STATE_HASH_SET_ERROR:
00342       nfserror = NFS4ERR_IO;
00343       break;
00344 
00345     case STATE_FSAL_EACCESS:
00346       nfserror = NFS4ERR_ACCESS;
00347       break;
00348 
00349     case STATE_FSAL_EPERM:
00350     case STATE_FSAL_ERR_SEC:
00351       nfserror = NFS4ERR_PERM;
00352       break;
00353 
00354     case STATE_NO_SPACE_LEFT:
00355       nfserror = NFS4ERR_NOSPC;
00356       break;
00357 
00358     case STATE_IS_A_DIRECTORY:
00359       nfserror = NFS4ERR_ISDIR;
00360       break;
00361 
00362     case STATE_READ_ONLY_FS:
00363       nfserror = NFS4ERR_ROFS;
00364       break;
00365 
00366     case STATE_IO_ERROR:
00367       nfserror = NFS4ERR_IO;
00368       break;
00369 
00370     case STATE_FILE_OPEN:
00371       nfserror = NFS4ERR_FILE_OPEN;
00372       break;
00373 
00374      case STATE_NAME_TOO_LONG:
00375       nfserror = NFS4ERR_NAMETOOLONG;
00376       break;
00377 
00378     case STATE_KILLED:
00379     case STATE_DEAD_ENTRY:
00380     case STATE_FSAL_ESTALE:
00381       nfserror = NFS4ERR_STALE;
00382       break;
00383 
00384     case STATE_STATE_CONFLICT:
00385       nfserror = NFS4ERR_SHARE_DENIED;
00386       break;
00387 
00388     case STATE_QUOTA_EXCEEDED:
00389       nfserror = NFS4ERR_DQUOT;
00390       break;
00391 
00392     case STATE_NOT_SUPPORTED:
00393       nfserror = NFS4ERR_NOTSUPP;
00394       break;
00395 
00396     case STATE_FSAL_DELAY:
00397       nfserror = NFS4ERR_DELAY;
00398       break;
00399 
00400     case STATE_FILE_BIG:
00401       nfserror = NFS4ERR_FBIG;
00402       break;
00403 
00404     case STATE_LOCK_DEADLOCK:
00405       nfserror = NFS4ERR_DEADLOCK;
00406       break;
00407 
00408     case STATE_LOCK_BLOCKED:
00409     case STATE_LOCK_CONFLICT:
00410       nfserror = NFS4ERR_DENIED;
00411       break;
00412 
00413     case STATE_STATE_ERROR:
00414       nfserror = NFS4ERR_BAD_STATEID;
00415       break;
00416 
00417     case STATE_BAD_COOKIE:
00418       nfserror = NFS4ERR_BAD_COOKIE;
00419       break;
00420 
00421     case STATE_GRACE_PERIOD:
00422       nfserror = NFS4ERR_GRACE;
00423       break;
00424 
00425     case STATE_INVALID_ARGUMENT:
00426     case STATE_CACHE_INODE_ERR:
00427     case STATE_INCONSISTENT_ENTRY:
00428     case STATE_HASH_TABLE_ERROR:
00429     case STATE_CACHE_CONTENT_ERROR:
00430     case STATE_ASYNC_POST_ERROR:
00431     case STATE_SIGNAL_ERROR:
00432       /* Should not occur */
00433       nfserror = NFS4ERR_INVAL;
00434       break;
00435     }
00436 
00437   return nfserror;
00438 }                               /* nfs4_Errno_state */
00439 
00449 nfsstat3 nfs3_Errno_state(state_status_t error)
00450 {
00451   nfsstat3 nfserror= NFS3ERR_INVAL;
00452 
00453   switch (error)
00454     {
00455     case STATE_SUCCESS:
00456       nfserror = NFS3_OK;
00457       break;
00458 
00459     case STATE_MALLOC_ERROR:
00460     case STATE_POOL_MUTEX_INIT_ERROR:
00461     case STATE_GET_NEW_LRU_ENTRY:
00462     case STATE_UNAPPROPRIATED_KEY:
00463     case STATE_INIT_ENTRY_FAILED:
00464     case STATE_CACHE_CONTENT_EXISTS:
00465     case STATE_CACHE_CONTENT_EMPTY:
00466     case STATE_INSERT_ERROR:
00467     case STATE_LRU_ERROR:
00468     case STATE_HASH_SET_ERROR:
00469     case STATE_FILE_OPEN:
00470       LogCrit(COMPONENT_NFSPROTO,
00471               "Error %u converted to NFS3ERR_IO but was set non-retryable",
00472               error);
00473       nfserror = NFS3ERR_IO;
00474       break;
00475 
00476     case STATE_INVALID_ARGUMENT:
00477       nfserror = NFS3ERR_INVAL;
00478       break;
00479 
00480     case STATE_FSAL_ERROR:
00481     case STATE_CACHE_CONTENT_ERROR:
00483       LogCrit(COMPONENT_NFSPROTO,
00484               "Error STATE_FSAL_ERROR converted to NFS3ERR_IO but was set non-retryable");
00485       nfserror = NFS3ERR_IO;
00486       break;
00487 
00488     case STATE_NOT_A_DIRECTORY:
00489       nfserror = NFS3ERR_NOTDIR;
00490       break;
00491 
00492     case STATE_ENTRY_EXISTS:
00493       nfserror = NFS3ERR_EXIST;
00494       break;
00495 
00496     case STATE_DIR_NOT_EMPTY:
00497       nfserror = NFS3ERR_NOTEMPTY;
00498       break;
00499 
00500     case STATE_NOT_FOUND:
00501       nfserror = NFS3ERR_NOENT;
00502       break;
00503 
00504     case STATE_FSAL_EACCESS:
00505       nfserror = NFS3ERR_ACCES;
00506       break;
00507 
00508     case STATE_FSAL_EPERM:
00509     case STATE_FSAL_ERR_SEC:
00510       nfserror = NFS3ERR_PERM;
00511       break;
00512 
00513     case STATE_NO_SPACE_LEFT:
00514       nfserror = NFS3ERR_NOSPC;
00515       break;
00516 
00517     case STATE_IS_A_DIRECTORY:
00518       nfserror = NFS3ERR_ISDIR;
00519       break;
00520 
00521     case STATE_READ_ONLY_FS:
00522       nfserror = NFS3ERR_ROFS;
00523       break;
00524 
00525     case STATE_KILLED:
00526     case STATE_DEAD_ENTRY:
00527     case STATE_FSAL_ESTALE:
00528       nfserror = NFS3ERR_STALE;
00529       break;
00530 
00531     case STATE_QUOTA_EXCEEDED:
00532       nfserror = NFS3ERR_DQUOT;
00533       break;
00534 
00535     case STATE_BAD_TYPE:
00536       nfserror = NFS3ERR_BADTYPE;
00537       break;
00538 
00539     case STATE_NOT_SUPPORTED:
00540       nfserror = NFS3ERR_NOTSUPP;
00541       break;
00542 
00543     case STATE_FSAL_DELAY:
00544       nfserror = NFS3ERR_JUKEBOX;
00545       break;
00546 
00547     case STATE_IO_ERROR:
00548         LogCrit(COMPONENT_NFSPROTO,
00549                 "Error STATE_IO_ERROR converted to NFS3ERR_IO but was set non-retryable");
00550       nfserror = NFS3ERR_IO;
00551       break;
00552 
00553     case STATE_NAME_TOO_LONG:
00554       nfserror = NFS3ERR_NAMETOOLONG;
00555       break;
00556 
00557     case STATE_FILE_BIG:
00558       nfserror = NFS3ERR_FBIG;
00559       break;
00560 
00561     case STATE_BAD_COOKIE:
00562       nfserror = NFS3ERR_BAD_COOKIE;
00563       break;
00564 
00565     case STATE_CACHE_INODE_ERR:
00566     case STATE_INCONSISTENT_ENTRY:
00567     case STATE_HASH_TABLE_ERROR:
00568     case STATE_STATE_CONFLICT:
00569     case STATE_ASYNC_POST_ERROR:
00570     case STATE_STATE_ERROR:
00571     case STATE_LOCK_CONFLICT:
00572     case STATE_LOCK_BLOCKED:
00573     case STATE_LOCK_DEADLOCK:
00574     case STATE_GRACE_PERIOD:
00575     case STATE_SIGNAL_ERROR:
00576         /* Should not occur */
00577         LogDebug(COMPONENT_NFSPROTO,
00578                  "Unexpected status for conversion = %s",
00579                  state_err_str(error));
00580       nfserror = NFS3ERR_INVAL;
00581       break;
00582     }
00583 
00584   return nfserror;
00585 }                               /* nfs3_Errno_state */
00586 
00596 nfsstat2 nfs2_Errno_state(state_status_t error)
00597 {
00598   nfsstat2 nfserror= NFSERR_IO;
00599 
00600   switch (error)
00601     {
00602     case STATE_SUCCESS:
00603       nfserror = NFS_OK;
00604       break;
00605 
00606     case STATE_MALLOC_ERROR:
00607     case STATE_POOL_MUTEX_INIT_ERROR:
00608     case STATE_GET_NEW_LRU_ENTRY:
00609     case STATE_UNAPPROPRIATED_KEY:
00610     case STATE_INIT_ENTRY_FAILED:
00611     case STATE_BAD_TYPE:
00612     case STATE_CACHE_CONTENT_EXISTS:
00613     case STATE_CACHE_CONTENT_EMPTY:
00614     case STATE_INSERT_ERROR:
00615     case STATE_LRU_ERROR:
00616     case STATE_HASH_SET_ERROR:
00617     case STATE_INVALID_ARGUMENT:
00618       LogCrit(COMPONENT_NFSPROTO,
00619               "Error %u converted to NFSERR_IO but was set non-retryable",
00620               error);
00621       nfserror = NFSERR_IO;
00622       break;
00623 
00624     case STATE_NOT_A_DIRECTORY:
00625       nfserror = NFSERR_NOTDIR;
00626       break;
00627 
00628     case STATE_ENTRY_EXISTS:
00629       nfserror = NFSERR_EXIST;
00630       break;
00631 
00632     case STATE_FSAL_ERROR:
00633     case STATE_CACHE_CONTENT_ERROR:
00634       LogCrit(COMPONENT_NFSPROTO,
00635               "Error STATE_FSAL_ERROR converted to NFSERR_IO but was set non-retryable");
00636       nfserror = NFSERR_IO;
00637       break;
00638 
00639     case STATE_DIR_NOT_EMPTY:
00640       nfserror = NFSERR_NOTEMPTY;
00641       break;
00642 
00643     case STATE_NOT_FOUND:
00644       nfserror = NFSERR_NOENT;
00645       break;
00646 
00647     case STATE_FSAL_EACCESS:
00648       nfserror = NFSERR_ACCES;
00649       break;
00650 
00651     case STATE_NO_SPACE_LEFT:
00652       nfserror = NFSERR_NOSPC;
00653       break;
00654 
00655     case STATE_FSAL_EPERM:
00656     case STATE_FSAL_ERR_SEC:
00657       nfserror = NFSERR_PERM;
00658       break;
00659 
00660     case STATE_IS_A_DIRECTORY:
00661       nfserror = NFSERR_ISDIR;
00662       break;
00663 
00664     case STATE_READ_ONLY_FS:
00665       nfserror = NFSERR_ROFS;
00666       break;
00667 
00668     case STATE_KILLED:
00669     case STATE_DEAD_ENTRY:
00670     case STATE_FSAL_ESTALE:
00671       nfserror = NFSERR_STALE;
00672       break;
00673 
00674     case STATE_QUOTA_EXCEEDED:
00675       nfserror = NFSERR_DQUOT;
00676       break;
00677 
00678     case STATE_IO_ERROR:
00679       LogCrit(COMPONENT_NFSPROTO,
00680               "Error STATE_IO_ERROR converted to NFSERR_IO but was set non-retryable");
00681       nfserror = NFSERR_IO;
00682       break;
00683 
00684     case STATE_NAME_TOO_LONG:
00685       nfserror = NFSERR_NAMETOOLONG;
00686       break;
00687 
00688     case STATE_CACHE_INODE_ERR:
00689     case STATE_INCONSISTENT_ENTRY:
00690     case STATE_HASH_TABLE_ERROR:
00691     case STATE_STATE_CONFLICT:
00692     case STATE_ASYNC_POST_ERROR:
00693     case STATE_STATE_ERROR:
00694     case STATE_LOCK_CONFLICT:
00695     case STATE_LOCK_BLOCKED:
00696     case STATE_LOCK_DEADLOCK:
00697     case STATE_NOT_SUPPORTED:
00698     case STATE_FSAL_DELAY:
00699     case STATE_BAD_COOKIE:
00700     case STATE_FILE_BIG:
00701     case STATE_GRACE_PERIOD:
00702     case STATE_SIGNAL_ERROR:
00703     case STATE_FILE_OPEN:
00704         /* Should not occur */
00705         LogDebug(COMPONENT_NFSPROTO,
00706                  "Unexpected conversion for status = %s",
00707                  state_err_str(error));
00708       nfserror = NFSERR_IO;
00709       break;
00710     }
00711 
00712   return nfserror;
00713 }                               /* nfs2_Errno_state */
00714 
00715 const char * invalid_state_owner_type = "INVALID STATE OWNER TYPE";
00716 
00717 const char * state_owner_type_to_str(state_owner_type_t type)
00718 {
00719   switch(type)
00720     {
00721       case STATE_LOCK_OWNER_UNKNOWN:     return "STATE_LOCK_OWNER_UNKNOWN";
00722 #ifdef _USE_NLM
00723       case STATE_LOCK_OWNER_NLM:         return "STATE_LOCK_OWNER_NLM";
00724 #endif
00725 #ifdef _USE_9P
00726       case STATE_LOCK_OWNER_9P:          return "STALE_LOCK_OWNER_9P";
00727 #endif
00728       case STATE_OPEN_OWNER_NFSV4:       return "STATE_OPEN_OWNER_NFSV4";
00729       case STATE_LOCK_OWNER_NFSV4:       return "STATE_LOCK_OWNER_NFSV4";
00730       case STATE_CLIENTID_OWNER_NFSV4:   return "STATE_CLIENTID_OWNER_NFSV4";
00731     }
00732   return invalid_state_owner_type;
00733 }
00734 
00735 int different_owners(state_owner_t *powner1, state_owner_t *powner2)
00736 {
00737   if(powner1 == NULL || powner2 == NULL)
00738     return 1;
00739 
00740   /* Shortcut in case we actually are pointing to the same owner structure */
00741   if(powner1 == powner2)
00742     return 0;
00743 
00744   if(powner1->so_type != powner2->so_type)
00745     return 1;
00746 
00747   switch(powner1->so_type)
00748     {
00749 #ifdef _USE_NLM
00750       case STATE_LOCK_OWNER_NLM:
00751         if(powner2->so_type != STATE_LOCK_OWNER_NLM)
00752            return 1;
00753         return compare_nlm_owner(powner1, powner2);
00754 #endif
00755 #ifdef _USE_9P
00756       case STATE_LOCK_OWNER_9P:
00757         if(powner2->so_type != STATE_LOCK_OWNER_9P)
00758            return 1;
00759         return compare_9p_owner(powner1, powner2);
00760 #endif
00761       case STATE_OPEN_OWNER_NFSV4:
00762       case STATE_LOCK_OWNER_NFSV4:
00763       case STATE_CLIENTID_OWNER_NFSV4:
00764         if(powner1->so_type != powner2->so_type)
00765           return 1;
00766         return compare_nfs4_owner(powner1, powner2);
00767 
00768       case STATE_LOCK_OWNER_UNKNOWN:
00769         break;
00770     }
00771 
00772   return 1;
00773 }
00774 
00775 int DisplayOwner(state_owner_t *powner, char *buf)
00776 {
00777   if(powner != NULL)
00778     switch(powner->so_type)
00779       {
00780 #ifdef _USE_NLM
00781         case STATE_LOCK_OWNER_NLM:
00782           return display_nlm_owner(powner, buf);
00783 #endif
00784 #ifdef _USE_9P
00785         case STATE_LOCK_OWNER_9P:
00786           return display_9p_owner(powner, buf);
00787 #endif
00788 
00789         case STATE_OPEN_OWNER_NFSV4:
00790         case STATE_LOCK_OWNER_NFSV4:
00791         case STATE_CLIENTID_OWNER_NFSV4:
00792           return display_nfs4_owner(powner, buf);
00793 
00794         case STATE_LOCK_OWNER_UNKNOWN:
00795           return sprintf(buf,
00796                          "%s powner=%p: refcount=%d",
00797                          state_owner_type_to_str(powner->so_type), powner, powner->so_refcount);
00798     }
00799 
00800   return sprintf(buf, "%s", invalid_state_owner_type);
00801 }
00802 
00803 int Hash_dec_state_owner_ref(hash_buffer_t *buffval)
00804 {
00805   int rc;
00806   state_owner_t *powner = (state_owner_t *)(buffval->pdata);
00807 
00808   P(powner->so_mutex);
00809 
00810   powner->so_refcount--;
00811 
00812   if(isFullDebug(COMPONENT_STATE))
00813     {
00814       char str[HASHTABLE_DISPLAY_STRLEN];
00815 
00816       DisplayOwner(powner, str);
00817       LogFullDebug(COMPONENT_STATE,
00818                    "Decrement refcount for {%s}",
00819                    str);
00820     }
00821 
00822   rc = powner->so_refcount;
00823 
00824   V(powner->so_mutex);
00825 
00826   return rc;
00827 }
00828 
00829 void Hash_inc_state_owner_ref(hash_buffer_t *buffval)
00830 {
00831   state_owner_t *powner = (state_owner_t *)(buffval->pdata);
00832 
00833   P(powner->so_mutex);
00834   powner->so_refcount++;
00835 
00836   if(isFullDebug(COMPONENT_STATE))
00837     {
00838       char str[HASHTABLE_DISPLAY_STRLEN];
00839 
00840       DisplayOwner(powner, str);
00841       LogFullDebug(COMPONENT_STATE,
00842                    "Increment refcount for {%s}",
00843                    str);
00844     }
00845 
00846   V(powner->so_mutex);
00847 }
00848 
00849 void inc_state_owner_ref_locked(state_owner_t *powner)
00850 {
00851   powner->so_refcount++;
00852 
00853   if(isFullDebug(COMPONENT_STATE))
00854     {
00855       char str[HASHTABLE_DISPLAY_STRLEN];
00856 
00857       DisplayOwner(powner, str);
00858       LogFullDebug(COMPONENT_STATE,
00859                    "Increment refcount for {%s}",
00860                    str);
00861     }
00862 
00863   V(powner->so_mutex);
00864 }
00865 
00866 void inc_state_owner_ref(state_owner_t *powner)
00867 {
00868   P(powner->so_mutex);
00869 
00870   inc_state_owner_ref_locked(powner);
00871 }
00872 
00873 void dec_state_owner_ref_locked(state_owner_t        * powner)
00874 {
00875   bool_t remove = FALSE;
00876   char   str[HASHTABLE_DISPLAY_STRLEN];
00877 
00878   if(isDebug(COMPONENT_STATE))
00879     DisplayOwner(powner, str);
00880 
00881   if(powner->so_refcount > 1)
00882     {
00883       powner->so_refcount--;
00884 
00885       LogFullDebug(COMPONENT_STATE,
00886                    "Decrement refcount for {%s}",
00887                    str);
00888     }
00889   else
00890     {
00891       LogFullDebug(COMPONENT_STATE,
00892                    "Refcount for {%s} is 1",
00893                    str);
00894       remove = TRUE;
00895     }
00896 
00897   V(powner->so_mutex);
00898 
00899   if(remove)
00900     {
00901       switch(powner->so_type)
00902         {
00903 #ifdef _USE_NLM
00904           case STATE_LOCK_OWNER_NLM:
00905             remove_nlm_owner(powner, str);
00906             break;
00907 #endif
00908 #ifdef _USE_9P
00909           case STATE_LOCK_OWNER_9P:
00910             remove_9p_owner( powner, str);
00911 #endif
00912           case STATE_OPEN_OWNER_NFSV4:
00913           case STATE_LOCK_OWNER_NFSV4:
00914           case STATE_CLIENTID_OWNER_NFSV4:
00915             remove_nfs4_owner(powner, str);
00916             break;
00917 
00918           case STATE_LOCK_OWNER_UNKNOWN:
00919             LogDebug(COMPONENT_STATE,
00920                      "Unexpected removal of powner=%p: %s",
00921                      powner, str);
00922             break;
00923         }
00924     }
00925 }
00926 
00927 void dec_state_owner_ref(state_owner_t        * powner)
00928 {
00929   P(powner->so_mutex);
00930 
00931   dec_state_owner_ref_locked(powner);
00932 }
00933 
00934 void state_wipe_file(cache_entry_t        * pentry)
00935 {
00936   bool_t had_lock = FALSE;
00937 
00938   /*
00939    * currently, only REGULAR files can have state; byte range locks and
00940    * stateid (for v4).  In the future, 4.1, directories could have
00941    * delegations, which is state.  At that point, we may need to modify
00942    * this routine to clear state on directories.
00943    */
00944   if (pentry->type != REGULAR_FILE)
00945     return;
00946 
00947   /* The state lock may have been acquired by the caller. */
00948   if (pthread_rwlock_trywrlock(&pentry->state_lock))
00949     {
00950       /* This thread already has some kind of lock, but we don't know
00951          if it's a write lock. */
00952       had_lock = TRUE;
00953       pthread_rwlock_unlock(&pentry->state_lock);
00954     }
00955   pthread_rwlock_wrlock(&pentry->state_lock);
00956   state_lock_wipe(pentry);
00957   state_nfs4_state_wipe(pentry);
00958   if (!had_lock)
00959     {
00960       pthread_rwlock_unlock(&pentry->state_lock);
00961     }
00962 }
00963 
00964 int DisplayOpaqueValue(char * value, int len, char * str)
00965 {
00966   unsigned int   i = 0;
00967   char         * strtmp = str;
00968 
00969   if(value == NULL || len == 0)
00970     return sprintf(str, "(NULL)");
00971 
00972   strtmp += sprintf(strtmp, "(%d:", len);
00973 
00974   assert(len > 0);
00975 
00976   if(len < 0 || len > 1024)
00977     len = 1024;
00978 
00979   for(i = 0; i < len; i++)
00980     if(!isprint(value[i]))
00981       break;
00982 
00983   if(i == len)
00984     {
00985       memcpy(strtmp, value, len);
00986       strtmp += len;
00987       *strtmp = '\0';
00988     }
00989   else
00990     {
00991       strtmp += sprintf(strtmp, "0x");
00992       for(i = 0; i < len; i++)
00993         strtmp += sprintf(strtmp, "%02x", (unsigned char)value[i]);
00994     }
00995 
00996   strtmp += sprintf(strtmp, ")");
00997 
00998   return strtmp - str;
00999 }