nfs-ganesha 1.4

cache_inode.h

Go to the documentation of this file.
00001 /*
00002  *
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  * ---------------------------------------
00025  */
00026 
00036 #ifndef _CACHE_INODE_H
00037 #define _CACHE_INODE_H
00038 
00039 #include <unistd.h>
00040 #include <sys/types.h>
00041 #include <sys/param.h>
00042 #include <time.h>
00043 #include <pthread.h>
00044 
00045 
00046 #include "abstract_mem.h"
00047 #include "HashData.h"
00048 #include "HashTable.h"
00049 #include "avltree.h"
00050 #include "generic_weakref.h"
00051 #include "fsal.h"
00052 #include "log.h"
00053 #include "config_parsing.h"
00054 #include "nfs23.h"
00055 #include "nfs4.h"
00056 #ifdef _USE_NLM
00057 #include "nlm4.h"
00058 #endif
00059 #include "nlm_list.h"
00060 #ifdef _USE_NFS4_ACL
00061 #include "nfs4_acls.h"
00062 #endif /* _USE_NFS4_ACL */
00063 
00064 extern hash_table_t *fh_to_cache_entry_ht; /*< Global hash table for
00065                                                servicing lookups by
00066                                                fsal_handle_t. */
00067 
00068 /* Forward references */
00069 typedef struct cache_entry_t        cache_entry_t;
00070 
00071 static const size_t FILEHANDLE_MAX_LEN_V2 = 32; /*< Maximum size of NFSv2 handle */
00072 static const size_t FILEHANDLE_MAX_LEN_V3 = 64; /*< Maximum size of NFSv3 handle */
00073 static const size_t FILEHANDLE_MAX_LEN_V4 = 128; /*< Maximum size of NFSv4 handle */
00074 
00075 static const size_t CACHE_INODE_UNSTABLE_BUFFERSIZE =
00076   100*1024*1024; /*< Size for Ganesha unstable write buffers*/
00077 
00083 typedef enum cache_inode_expire_type__
00084 {
00085   CACHE_INODE_EXPIRE = 0, /*< Data expire when they have been refreshed
00086                               less recently than grace period
00087                               for their type allows. */
00088   CACHE_INODE_EXPIRE_NEVER = 1, /*< Data never expire based on time. */
00089   CACHE_INODE_EXPIRE_IMMEDIATE = 2 /*< Data are always treated as
00090                                        expired. */
00091 } cache_inode_expire_type_t;
00092 
00097 typedef enum cache_inode_stability__ {
00098   CACHE_INODE_UNSAFE_WRITE_TO_FS_BUFFER = 0,
00099   CACHE_INODE_SAFE_WRITE_TO_FS = 1,
00100   CACHE_INODE_UNSAFE_WRITE_TO_GANESHA_BUFFER = 2
00101 } cache_inode_stability_t;
00102 
00103 
00108 typedef struct cache_inode_lru__
00109 {
00110   struct glist_head q; /*< Link in the physical deque impelmenting a
00111                            portion of the logical LRU. */
00112   pthread_mutex_t mtx; /*< Mutex protecting this entry with regard to
00113                            LRU operations. */
00114   int64_t refcount; /*< Reference count.  This is signed to make
00115                         mistakes easy to see. */
00116   uint32_t pin_refcnt; /*< Unpin it only if this goes down to zero */
00117   uint32_t flags; /*< Flags for details of this entry's status, such
00118                       as whether it is pinned and whetehr it's in L1
00119                       or L2. */
00120   uint32_t lane; /*< The lane in which an entry currently resides, so
00121                      we can lock the deque and decrement the correct
00122                      counter when moving or deleting the entry. */
00123 } cache_inode_lru_t;
00124 
00129 typedef struct cache_inode_parameter__
00130 {
00131   hash_parameter_t hparam; /*< Parameter used for hashtable initialization */
00132 #ifdef _USE_NLM
00133   hash_parameter_t cookie_param; /*< Parameters used for lock cookie hash table
00134                                      initialization */
00135 #endif
00136   fsal_attrib_mask_t attrmask; /*< FSAL attributes to be used in FSAL */
00137   cache_inode_expire_type_t expire_type_attr; /*< Cache inode expiration type
00138                                                   for attributes */
00139   cache_inode_expire_type_t expire_type_link; /*< Cache inode expiration type
00140                                                   for symbolic links */
00141   cache_inode_expire_type_t expire_type_dirent; /*< Cache inode expiration type
00142                                                     for directory entries */
00143   time_t grace_period_attr; /*< Cached attributes grace period */
00144   time_t grace_period_link; /*< Cached link grace period */
00145   time_t grace_period_dirent; /*< Cached dirent grace period */
00146   bool_t getattr_dir_invalidation; /*< Use getattr as for directory
00147                                        invalidation */
00148   bool_t use_test_access; /*< Is FSAL_test_access to be used? */
00149   bool_t use_fsal_hash; /*< Do we rely on FSAL to hash handle or not? */
00150 } cache_inode_parameter_t;
00151 
00152 extern cache_inode_parameter_t cache_inode_params;
00157 typedef struct cache_inode_opened_file__
00158 {
00159   fsal_file_t fd; /*< FSAL specific object representing a given file
00160                       open. */
00161   fsal_openflags_t openflags; /*< Flags showing whether the file is
00162                                   open for reading, writing, or both. */
00163 } cache_inode_opened_file_t;
00164 
00168 typedef enum cache_inode_file_type__
00169 {
00170   UNASSIGNED = 1, /*< No filetype at all. */
00171   REGULAR_FILE = 2, /*< Regular file (can be opened, read, written) */
00172   CHARACTER_FILE = 3, /*< Character special device file */
00173   BLOCK_FILE = 4, /*< Block special device file */
00174   SYMBOLIC_LINK = 5, /*< Symbolic link */
00175   SOCKET_FILE = 6, /*< Unix domain socket. */
00176   FIFO_FILE = 7, /*< FIFO or 'named pipe' */
00177   DIRECTORY = 8, /*< A directory */
00178   FS_JUNCTION = 9, /*< A directory-like node leading from one
00179                        filesystem to another */
00180   RECYCLED = 10 /*< This entry has been recycled */
00181 } cache_inode_file_type_t;
00182 
00188 typedef enum io_direction__
00189 {
00190   CACHE_INODE_READ = 1, /*< Reading */
00191   CACHE_INODE_WRITE = 2 /*< Writing */
00192 } cache_inode_io_direction_t;
00193 
00199 typedef enum cache_inode_dirent_op__
00200 {
00201   CACHE_INODE_DIRENT_OP_LOOKUP = 1, /*< Look up a name */
00202   CACHE_INODE_DIRENT_OP_REMOVE = 2, /*< Remove a name */
00203   CACHE_INODE_DIRENT_OP_RENAME = 3 /*< Rename node */
00204 } cache_inode_dirent_op_t;
00205 
00206 typedef enum cache_inode_avl_which__
00207 { CACHE_INODE_AVL_NAMES = 1,
00208   CACHE_INODE_AVL_COOKIES = 2,
00209   CACHE_INODE_AVL_BOTH = 3
00210 } cache_inode_avl_which_t;
00211 
00212 /* Flags set on cache_entry_t::flags*/
00213 
00214 static const uint32_t CACHE_INODE_TRUST_ATTRS
00215   = 0x00000001; /*< Trust stored attributes */
00216 static const uint32_t CACHE_INODE_TRUST_CONTENT
00217   = 0x00000002; /*< Trust inode content (for the moment, directory and
00218                     symlink) */
00219 static const uint32_t CACHE_INODE_DIR_POPULATED
00220   = 0x00000004; /*< The directory has been populated (negative lookups
00221                   are meaningful) */
00222 
00227 struct cache_inode_symlink__
00228 {
00229   fsal_path_t content; /*< Content of the link */
00230 };
00231 
00237 typedef struct cache_inode_unstable_data__
00238 {
00239   caddr_t buffer; /*< Pointer in memory */
00240   uint64_t offset; /*< Offset (relative to the start of the file) */
00241   uint32_t length; /*< Length */
00242 } cache_inode_unstable_data_t;
00243 
00248 /* The ref counted share reservation state.
00249  *
00250  * Each field represents the count of instances of that flag being present
00251  * in a v3 or v4 share reservation.
00252  *
00253  * There is a separate count of v4 deny write flags so that they can be
00254  * enforced against v3 writes (v3 deny writes can not be enforced against
00255  * v3 writes because there is no connection between the share reservation
00256  * and the write operation). v3 reads will always be allowed.
00257  */
00258 typedef struct cache_inode_share__
00259 {
00260   unsigned int share_access_read;
00261   unsigned int share_access_write;
00262   unsigned int share_deny_read;
00263   unsigned int share_deny_write;
00264   unsigned int share_deny_write_v4; 
00265 } cache_inode_share_t;
00266 
00274 #define DIR_ENTRY_FLAG_NONE     0x0000
00275 #define DIR_ENTRY_FLAG_DELETED  0x0001
00276 
00277 typedef struct cache_inode_dir_entry__
00278 {
00279   struct avltree_node node_hk; /*< AVL node in tree */
00280   struct {
00281     uint64_t k; /*< Integer cookie */
00282     uint32_t p; /*< Number of probes, an efficiency metric */
00283   } hk;
00284   gweakref_t entry; /*< Weak reference pointing to the cache entry */
00285   fsal_name_t name; /*< The filename */
00286   uint64_t fsal_cookie; /*< The cookie returned by the FSAL. */
00287   uint32_t flags; /*< Flags */
00288 } cache_inode_dir_entry_t;
00289 
00336 struct cache_entry_t
00337 {
00338   fsal_handle_t handle; /*< The FSAL Handle */
00339   struct fsal_handle_desc fh_desc; /*< Points to handle.  Adds size,
00340                                        len for hash table etc. */
00341   gweakref_t weakref; /*< A weakref for this entry (pointer and generation
00342                           number.)  The generation number is the only
00343                           interesting part, but this way the weakref
00344                           can be easily stashed somewhere. */
00345   cache_inode_file_type_t type; /*< The type of the entry */
00346   uint32_t flags; /*< Flags for this entry */
00347   time_t change_time; /*< The time of the last operation ganesha knows
00348                           about.  We can ue this for change_info4, but
00349                           atomic MUST BE SET TO FALSE.  Don't use it
00350                           for anything else (servicing getattr,
00351                           etc.) */
00352   time_t attr_time; /*< Time at which we last refreshed attributes. */
00353   cache_inode_lru_t lru; /*< New style LRU link */
00354   pthread_rwlock_t attr_lock; /*< Reader-writer lock for attributes */
00355   fsal_attrib_list_t attributes; /*< The FSAL Attributes */
00356   pthread_rwlock_t state_lock; /*< This is separated out from the
00357                                    content lock, since there are
00358                                    state oerations that don't affect
00359                                    anything guarded by content (for
00360                                    example, a layout return or
00361                                    request has no effect on a cached
00362                                    file handle) and the content lock
00363                                    may be released and reacquired
00364                                    several times in an operation that
00365                                    should not see changes i state. */
00366   struct glist_head state_list; /*< Pointers for state list */
00367   pthread_rwlock_t content_lock; /*< Lock on type-specific cached
00368                                      content.  See locking discipline
00369                                      for details. */
00370   union cache_inode_fsobj__
00371   {
00372     struct cache_inode_file__
00373     {
00374       cache_inode_opened_file_t open_fd;/*< Cached fsal_file_t for
00375                                             optimized access */
00376       struct glist_head lock_list; /*< Pointers for lock list */
00377 #ifdef _USE_NLM
00378       struct glist_head nlm_share_list; 
00379 #endif
00380       cache_inode_unstable_data_t
00381         unstable_data; /*< Unstable data, for use with WRITE/COMMIT */
00382       cache_inode_share_t share_state; /*< Share reservation state for
00383                                            this file. */
00384     } file; /*< REGULAR_FILE data */
00385 
00386     struct cache_inode_symlink__ *symlink; /*< SYMLINK data */
00387 
00388     struct cache_inode_dir__
00389     {
00390       bool_t root; /*< Marks this as the root directory of an export */
00391       uint32_t nbactive; /*< Number of known active children */
00392       char *referral; /*< NULL is not a referral.  If not, this a
00393                           'referral string' */
00394       gweakref_t parent; /*< The parent of this directory
00395                              ('..') */
00396       struct {
00397           struct avltree t;                     
00398           struct avltree c;                     
00399           uint32_t collisions;                  
00400       } avl;
00401     } dir; /*< DIRECTORY data */
00402   } object; /*< Filetype specific data, discriminated by the type
00403                 field.  Note that data for special files is in
00404                 attributes.rawdev */
00405 };
00406 
00407 typedef struct cache_inode_file__ cache_inode_file_t;
00408 typedef struct cache_inode_symlink__ cache_inode_symlink_t;
00409 typedef union cache_inode_fsobj__ cache_inode_fsobj_t;
00410 
00415 typedef struct cache_inode_fsal_data__
00416 {
00417   struct fsal_handle_desc fh_desc;              
00418 } cache_inode_fsal_data_t;
00419 
00424 extern pool_t *cache_inode_entry_pool; /*< Cache entries pool */
00425 extern pool_t *cache_inode_symlink_pool; /*< Pool for SYMLINK data */
00426 extern pool_t *cache_inode_dir_entry_pool; /*< Cached dir entry pool */
00427 
00432 typedef struct cache_inode_gc_policy__
00433 {
00434   uint32_t entries_hwmark; /*< High water mark for cache entries */
00435   uint32_t entries_lwmark; /*< Low water mark for cache_entries */
00436   uint32_t lru_run_interval;  /*< Interval in seconds between runs of
00437                                   the LRU cleaner thread */
00438   bool_t use_fd_cache; /*< Do we cache fd or not? */
00439   uint32_t fd_limit_percent; /*< The percentage of the system-imposed
00440                                  maximum of file descriptors at which
00441                                  Ganesha will deny requests. */
00442   uint32_t fd_hwmark_percent; /*< The percentage of the system-imposed
00443                                   maximum of file descriptors above
00444                                   which Ganesha will make greater
00445                                   efforts at reaping. */
00446   uint32_t fd_lwmark_percent; /*< The percentage of the system-imposed
00447                                   maximum of file descriptors below
00448                                   which Ganesha will not reap file
00449                                   descriptonot reap file
00450                                   descriptorsrs. */
00451   uint32_t reaper_work; /*< Roughly, the amount of work to do on each
00452                             pass through the thread under normal
00453                             conditions.  (Ideally, a multipel of the
00454                             number of lanes.) */
00455   uint32_t biggest_window; /*< The largest window (as a percentage of
00456                                the system-imposed limit on FDs) of
00457                                work that we will do in extremis. */
00458   uint32_t required_progress; /*< Percentage of progress toward the
00459                                   high water mark required in in a
00460                                   pass through the thread when in
00461                                   extremis. */
00462   uint32_t futility_count; /*< Number of failures to approach the high
00463                                watermark before we disable caching,
00464                                when in extremis. */
00465 } cache_inode_gc_policy_t;
00466 
00467 extern cache_inode_gc_policy_t cache_inode_gc_policy;
00468 
00473 typedef union cache_inode_create_arg__
00474 {
00475   fsal_path_t link_content; /*< Content of a symbolic link */
00476   fsal_dev_t  dev_spec; /*< Major/minor numbers for a device file */
00477   bool_t newly_created_dir; /*< True if this directory has just been
00478                                 created, rather than pre-existing and
00479                                 loaded into the cache. */
00480 } cache_inode_create_arg_t;
00481 
00482 /*
00483  * Flags
00484  */
00485 static const uint32_t CACHE_INODE_FLAG_NONE = 0x00; /*< The null flag */
00486 static const uint32_t CACHE_INODE_FLAG_CREATE = 0x01; /*< Indicate that this
00487                                                    inode newly
00488                                                    created, rather
00489                                                    than just being
00490                                                    loaded into the
00491                                                    cache */
00492 static const uint32_t CACHE_INODE_FLAG_LOCK = 0x02; /*< Instruct the called
00493                                                  function to take a
00494                                                  lock on the entry */
00495 static const uint32_t CACHE_INODE_FLAG_ATTR_HOLD = 0x04; /*< For a function
00496                                                       called with the
00497                                                       attribute lock
00498                                                       held, do not
00499                                                       release the
00500                                                       attribute lock
00501                                                       before
00502                                                       returning */
00503 static const uint32_t CACHE_INODE_FLAG_CONTENT_HOLD = 0x08; /*< For a
00504                                                          function
00505                                                          called with
00506                                                          the content
00507                                                          lock held, do
00508                                                          not release
00509                                                          the content
00510                                                          lock before
00511                                                          returning */
00512 static const uint32_t CACHE_INODE_FLAG_ATTR_HAVE = 0x10; /*< For a function,
00513                                                       indicates that
00514                                                       the attribute
00515                                                       lock is held */
00516 static const uint32_t CACHE_INODE_FLAG_CONTENT_HAVE = 0x20; /*< For a
00517                                                          function,
00518                                                          indicates
00519                                                          that the
00520                                                          content lock
00521                                                          is held */
00522 static const uint32_t CACHE_INODE_FLAG_REALLYCLOSE = 0x80; /*< Close a file
00523                                                         even with
00524                                                         caching
00525                                                         enabled */
00526 /*
00527  * Flags to cache_inode_invalidate
00528  */
00529 static const uint32_t CACHE_INODE_INVALIDATE_CLEARBITS = 0x01;
00530 static const uint32_t CACHE_INODE_INVALIDATE_CLOSE = 0x02;
00531 
00532 /*
00533  * Prototypes for the functions
00534  */
00535 
00536 /*
00537  * Possible errors
00538  */
00539 typedef enum cache_inode_status_t
00540 {
00541   CACHE_INODE_SUCCESS               = 0,
00542   CACHE_INODE_MALLOC_ERROR          = 1,
00543   CACHE_INODE_POOL_MUTEX_INIT_ERROR = 2,
00544   CACHE_INODE_GET_NEW_LRU_ENTRY     = 3,
00545   CACHE_INODE_UNAPPROPRIATED_KEY    = 4,
00546   CACHE_INODE_INIT_ENTRY_FAILED     = 5,
00547   CACHE_INODE_FSAL_ERROR            = 6,
00548   CACHE_INODE_LRU_ERROR             = 7,
00549   CACHE_INODE_HASH_SET_ERROR        = 8,
00550   CACHE_INODE_NOT_A_DIRECTORY       = 9,
00551   CACHE_INODE_INCONSISTENT_ENTRY    = 10,
00552   CACHE_INODE_BAD_TYPE              = 11,
00553   CACHE_INODE_ENTRY_EXISTS          = 12,
00554   CACHE_INODE_DIR_NOT_EMPTY         = 13,
00555   CACHE_INODE_NOT_FOUND             = 14,
00556   CACHE_INODE_INVALID_ARGUMENT      = 15,
00557   CACHE_INODE_INSERT_ERROR          = 16,
00558   CACHE_INODE_HASH_TABLE_ERROR      = 17,
00559   CACHE_INODE_FSAL_EACCESS          = 18,
00560   CACHE_INODE_IS_A_DIRECTORY        = 19,
00561   CACHE_INODE_FSAL_EPERM            = 20,
00562   CACHE_INODE_NO_SPACE_LEFT         = 21,
00563   CACHE_INODE_CACHE_CONTENT_ERROR   = 22,
00564   CACHE_INODE_CACHE_CONTENT_EXISTS  = 23,
00565   CACHE_INODE_CACHE_CONTENT_EMPTY   = 24,
00566   CACHE_INODE_READ_ONLY_FS          = 25,
00567   CACHE_INODE_IO_ERROR              = 26,
00568   CACHE_INODE_FSAL_ESTALE           = 27,
00569   CACHE_INODE_FSAL_ERR_SEC          = 28,
00570   CACHE_INODE_STATE_CONFLICT        = 29,
00571   CACHE_INODE_QUOTA_EXCEEDED        = 30,
00572   CACHE_INODE_DEAD_ENTRY            = 31,
00573   CACHE_INODE_ASYNC_POST_ERROR      = 32,
00574   CACHE_INODE_NOT_SUPPORTED         = 33,
00575   CACHE_INODE_STATE_ERROR           = 34,
00576   CACHE_INODE_DELAY                 = 35,
00577   CACHE_INODE_NAME_TOO_LONG         = 36,
00578   CACHE_INODE_BAD_COOKIE            = 40,
00579   CACHE_INODE_FILE_BIG              = 41,
00580   CACHE_INODE_KILLED                = 42,
00581   CACHE_INODE_FILE_OPEN             = 43,
00582 } cache_inode_status_t;
00583 
00596 typedef bool_t(*cache_inode_readdir_cb_t)(
00597      void *opaque,
00598      char *name,
00599      fsal_handle_t *handle,
00600      fsal_attrib_list_t *attrs,
00601      uint64_t cookie);
00602 
00603 const char *cache_inode_err_str(cache_inode_status_t err);
00604 
00605 void cache_inode_clean_entry(cache_entry_t *entry);
00606 int cache_inode_compare_key_fsal(hash_buffer_t *buff1, hash_buffer_t *buff2);
00607 void cache_inode_release_symlink(cache_entry_t *entry);
00608 
00609 hash_table_t *cache_inode_init(cache_inode_parameter_t param,
00610                                cache_inode_status_t * status);
00611 
00612 cache_entry_t *cache_inode_get(cache_inode_fsal_data_t *fsdata,
00613                                fsal_attrib_list_t *attr,
00614                                fsal_op_context_t *context,
00615                                cache_entry_t *associated,
00616                                cache_inode_status_t *status);
00617 void cache_inode_put(cache_entry_t *entry);
00618 
00619 cache_inode_status_t cache_inode_access_sw(cache_entry_t *entry,
00620                                            fsal_accessflags_t access_type,
00621                                            fsal_op_context_t *context,
00622                                            cache_inode_status_t *status,
00623                                            bool_t use_mutex);
00624 cache_inode_status_t cache_inode_access_no_mutex(
00625     cache_entry_t *entry,
00626     fsal_accessflags_t access_type,
00627     fsal_op_context_t *context,
00628     cache_inode_status_t *status);
00629 cache_inode_status_t cache_inode_access(cache_entry_t *entry,
00630                                         fsal_accessflags_t access_type,
00631                                         fsal_op_context_t *context,
00632                                         cache_inode_status_t *status);
00633 
00634 fsal_file_t *cache_inode_fd(cache_entry_t *entry);
00635 
00636 bool_t is_open_for_read(cache_entry_t *entry);
00637 bool_t is_open_for_write(cache_entry_t *entry);
00638 
00639 cache_inode_status_t cache_inode_open(cache_entry_t *entry,
00640                                       fsal_openflags_t openflags,
00641                                       fsal_op_context_t *context,
00642                                       uint32_t flags,
00643                                       cache_inode_status_t *status);
00644 cache_inode_status_t cache_inode_close(cache_entry_t *entry,
00645                                        uint32_t flags,
00646                                        cache_inode_status_t *status);
00647 
00648 cache_entry_t *cache_inode_create(cache_entry_t *entry_parent,
00649                                   fsal_name_t *name,
00650                                   cache_inode_file_type_t type,
00651                                   fsal_accessmode_t mode,
00652                                   cache_inode_create_arg_t *create_arg,
00653                                   fsal_attrib_list_t *attr,
00654                                   fsal_op_context_t *context,
00655                                   cache_inode_status_t *status);
00656 
00657 cache_inode_status_t cache_inode_getattr(cache_entry_t *entry,
00658                                          fsal_attrib_list_t *attr,
00659                                          fsal_op_context_t *context,
00660                                          cache_inode_status_t *status);
00661 
00662 cache_entry_t *cache_inode_lookup_impl(cache_entry_t *entry_parent,
00663                                        fsal_name_t *name,
00664                                        fsal_op_context_t *context,
00665                                        cache_inode_status_t *status);
00666 cache_entry_t *cache_inode_lookup(cache_entry_t *entry_parent,
00667                                   fsal_name_t *name,
00668                                   fsal_attrib_list_t *attr,
00669                                   fsal_op_context_t *context,
00670                                   cache_inode_status_t *status);
00671 
00672 cache_entry_t *cache_inode_lookupp_impl(cache_entry_t *entry,
00673                                         fsal_op_context_t *context,
00674                                         cache_inode_status_t *status);
00675 cache_entry_t *cache_inode_lookupp(cache_entry_t *entry,
00676                                    fsal_op_context_t *context,
00677                                    cache_inode_status_t *status);
00678 
00679 
00680 cache_inode_status_t cache_inode_readlink(cache_entry_t *entry,
00681                                           fsal_path_t *link_content,
00682                                           fsal_op_context_t *context,
00683                                           cache_inode_status_t *status);
00684 
00685 cache_inode_status_t cache_inode_link(cache_entry_t *entry_src,
00686                                       cache_entry_t *entry_dir_dest,
00687                                       fsal_name_t *link_name,
00688                                       fsal_attrib_list_t *attr,
00689                                       fsal_op_context_t *context,
00690                                       cache_inode_status_t *status);
00691 
00692 cache_inode_status_t cache_inode_remove(cache_entry_t *entry,
00693                                         fsal_name_t *node_name,
00694                                         fsal_attrib_list_t *attr,
00695                                         fsal_op_context_t *context,
00696                                         cache_inode_status_t *status);
00697 cache_inode_status_t cache_inode_remove_impl(cache_entry_t *entry,
00698                                              fsal_name_t *name,
00699                                              fsal_op_context_t *context,
00700                                              cache_inode_status_t *status,
00701                                              uint32_t flags);
00702 
00703 cache_inode_status_t cache_inode_clean_internal(
00704      cache_entry_t *to_remove_entry);
00705 
00706 cache_inode_status_t cache_inode_operate_cached_dirent(
00707      cache_entry_t *entry_parent,
00708      fsal_name_t *name,
00709      fsal_name_t *newname,
00710      cache_inode_dirent_op_t dirent_op);
00711 
00712 cache_inode_status_t cache_inode_remove_cached_dirent(
00713      cache_entry_t *entry_parent,
00714      fsal_name_t *name,
00715      cache_inode_status_t *status);
00716 
00717 cache_inode_status_t cache_inode_rename_cached_dirent(
00718      cache_entry_t *entry_parent,
00719      fsal_name_t *oldname,
00720      fsal_name_t *newname,
00721      cache_inode_status_t *status);
00722 
00723 cache_inode_status_t cache_inode_rename(cache_entry_t *entry,
00724                                         fsal_name_t *oldname,
00725                                         cache_entry_t *entry_dirdest,
00726                                         fsal_name_t *newname,
00727                                         fsal_attrib_list_t *attr_src,
00728                                         fsal_attrib_list_t *attr_dst,
00729                                         fsal_op_context_t *context,
00730                                         cache_inode_status_t *status);
00731 
00732 cache_inode_status_t cache_inode_setattr(cache_entry_t *entry,
00733                                          fsal_attrib_list_t *attr,
00734                                          fsal_op_context_t *context,
00735                                          cache_inode_status_t *status);
00736 
00737 cache_inode_status_t
00738 cache_inode_truncate_impl(cache_entry_t *entry,
00739                           fsal_size_t length,
00740                           fsal_attrib_list_t *attr,
00741                           fsal_op_context_t *context,
00742                           cache_inode_status_t *status);
00743 cache_inode_status_t cache_inode_truncate(
00744      cache_entry_t *entry,
00745      fsal_size_t length,
00746      fsal_attrib_list_t *attr,
00747      fsal_op_context_t *context,
00748      cache_inode_status_t *status);
00749 
00750 cache_inode_status_t cache_inode_error_convert(fsal_status_t fsal_status);
00751 
00752 cache_entry_t *cache_inode_new_entry(cache_inode_fsal_data_t *fsdata,
00753                                      fsal_attrib_list_t *attr,
00754                                      cache_inode_file_type_t type,
00755                                      cache_inode_create_arg_t *create_arg,
00756                                      cache_inode_status_t *status);
00757 
00758 cache_inode_status_t cache_inode_add_data_cache(cache_entry_t *entry,
00759                                                 fsal_op_context_t *context,
00760                                                 cache_inode_status_t *status);
00761 cache_inode_status_t cache_inode_release_data_cache(
00762      cache_entry_t *entry,
00763      fsal_op_context_t *context,
00764      cache_inode_status_t *status);
00765 
00766 cache_inode_status_t cache_inode_rdwr(cache_entry_t *entry,
00767                                       cache_inode_io_direction_t io_direction,
00768                                       uint64_t offset,
00769                                       size_t io_size,
00770                                       size_t *bytes_moved,
00771                                       void *buffer,
00772                                       bool_t *eof,
00773                                       fsal_op_context_t *context,
00774                                       cache_inode_stability_t stable,
00775                                       cache_inode_status_t *status);
00776 
00777 static inline cache_inode_status_t
00778 cache_inode_read(cache_entry_t *entry,
00779                  uint64_t offset,
00780                  size_t io_size,
00781                  size_t *bytes_moved,
00782                  void *buffer,
00783                  bool_t *eof,
00784                  fsal_op_context_t *context,
00785                  cache_inode_stability_t stable,
00786                  cache_inode_status_t *status)
00787 {
00788   return cache_inode_rdwr(entry, CACHE_INODE_READ, offset, io_size,
00789                           bytes_moved, buffer, eof, context,
00790                           stable, status);
00791 }
00792 
00793 static inline cache_inode_status_t
00794 cache_inode_write(cache_entry_t *entry,
00795                   uint64_t offset,
00796                   size_t io_size,
00797                   size_t *bytes_moved,
00798                   void *buffer,
00799                   bool_t *eof,
00800                   fsal_op_context_t *context,
00801                   cache_inode_stability_t stable,
00802                   cache_inode_status_t *status)
00803 {
00804   return cache_inode_rdwr(entry, CACHE_INODE_WRITE, offset, io_size,
00805                           bytes_moved, buffer, eof, context,
00806                           stable, status);
00807 }
00808 
00809 cache_inode_status_t cache_inode_commit(cache_entry_t *entry,
00810                                         uint64_t offset,
00811                                         size_t count,
00812                                         cache_inode_stability_t stability,
00813                                         fsal_op_context_t *context,
00814                                         cache_inode_status_t *status);
00815 
00816 cache_inode_status_t cache_inode_readdir_populate(
00817      cache_entry_t *directory,
00818      fsal_op_context_t *context,
00819      cache_inode_status_t *status);
00820 cache_inode_status_t cache_inode_readdir(cache_entry_t *directory,
00821                                          uint64_t cookie,
00822                                          unsigned int *nbfound,
00823                                          bool_t *eod_met,
00824                                          fsal_op_context_t *context,
00825                                          cache_inode_readdir_cb_t cb,
00826                                          void *cb_opaque,
00827                                          cache_inode_status_t *status);
00828 
00829 cache_inode_status_t cache_inode_add_cached_dirent(
00830      cache_entry_t *parent,
00831      fsal_name_t *name,
00832      cache_entry_t *entry,
00833      cache_inode_dir_entry_t **dir_entry,
00834      cache_inode_status_t *status);
00835 cache_entry_t *cache_inode_make_root(cache_inode_fsal_data_t *fsdata,
00836                                      fsal_op_context_t *context,
00837                                      cache_inode_status_t *status);
00838 
00839 cache_inode_status_t cache_inode_check_trust(cache_entry_t *entry,
00840                                              fsal_op_context_t *context);
00841 
00842 cache_inode_file_type_t cache_inode_fsal_type_convert(fsal_nodetype_t type);
00843 
00844 int cache_inode_types_are_rename_compatible(cache_entry_t *src,
00845                                             cache_entry_t *dest);
00846 
00847 void cache_inode_print_dir(cache_entry_t *cache_entry_root);
00848 
00849 cache_inode_status_t cache_inode_statfs(cache_entry_t *entry,
00850                                         fsal_dynamicfsinfo_t *dynamicinfo,
00851                                         fsal_op_context_t *context,
00852                                         cache_inode_status_t *status);
00853 
00854 cache_inode_status_t cache_inode_is_dir_empty(cache_entry_t *entry);
00855 cache_inode_status_t cache_inode_is_dir_empty_WithLock(cache_entry_t *entry);
00856 
00857 cache_inode_status_t cache_inode_invalidate_all_cached_dirent(
00858      cache_entry_t *entry,
00859      cache_inode_status_t *status);
00860 
00861 void cache_inode_release_dirents(cache_entry_t *entry,
00862                                  cache_inode_avl_which_t which);
00863 
00864 void cache_inode_kill_entry(cache_entry_t *entry);
00865 
00866 cache_inode_status_t cache_inode_invalidate(
00867      cache_inode_fsal_data_t *fsal_data,
00868      cache_inode_status_t *status,
00869      uint32_t flags);
00870 
00871 /* Parsing functions */
00872 cache_inode_status_t cache_inode_read_conf_hash_parameter(
00873      config_file_t in_config,
00874      cache_inode_parameter_t *pparam);
00875 cache_inode_status_t cache_inode_read_conf_parameter(
00876      config_file_t in_config,
00877      cache_inode_parameter_t *pparam);
00878 cache_inode_status_t cache_inode_read_conf_gc_policy(
00879      config_file_t in_config,
00880      cache_inode_gc_policy_t *ppolicy);
00881 void cache_inode_print_conf_hash_parameter(FILE *output,
00882                                            cache_inode_parameter_t *param);
00883 void cache_inode_print_conf_parameter(
00884      FILE *output,
00885      cache_inode_parameter_t *param);
00886 void cache_inode_print_conf_gc_policy(FILE *output,
00887                                       cache_inode_gc_policy_t *gcpolicy);
00888 void cache_inode_expire_to_str(cache_inode_expire_type_t type,
00889                                time_t value,
00890                                char *out);
00891 inline bool_t cache_inode_file_holds_state(cache_entry_t *entry);
00892 
00893 inline int cache_inode_set_time_current(fsal_time_t *ptime);
00894 
00895 /* Hash functions for hashtables and RBT */
00896 uint32_t cache_inode_fsal_hash_func(hash_parameter_t *p_hparam,
00897                                          hash_buffer_t *buffclef);
00898 uint64_t cache_inode_fsal_rbt_func(hash_parameter_t *p_hparam,
00899                                         hash_buffer_t *buffclef);
00900 int cache_inode_fsal_rbt_both(hash_parameter_t *p_hparam,
00901                               hash_buffer_t *buffclef,
00902                               uint32_t *phashval,
00903                               uint64_t *prbtval);
00904 int display_key(hash_buffer_t *pbuff, char *str);
00905 int display_not_implemented(hash_buffer_t *pbuff,
00906                             char *str);
00907 int display_value(hash_buffer_t *pbuff, char *str);
00908 
00919 static inline void
00920 cache_inode_fixup_md(cache_entry_t *entry)
00921 {
00922      /* Set the refresh time for the cache entry */
00923      entry->attr_time = time(NULL);
00924      /* TODO: This should really be changed to use sub-second time
00925         resolution when it's available. */
00926      entry->change_time = entry->attributes.chgtime.seconds;
00927      /* Almost certainly not necessary */
00928      entry->type = cache_inode_fsal_type_convert(entry->attributes.type);
00929      /* We have just loaded the attributes from the FSAL. */
00930      entry->flags |= CACHE_INODE_TRUST_ATTRS;
00931 }
00932 
00944 static inline cache_inode_status_t
00945 cache_inode_refresh_attrs(cache_entry_t *entry,
00946                           fsal_op_context_t *context)
00947 {
00948      fsal_status_t fsal_status = {ERR_FSAL_NO_ERROR, 0};
00949      cache_inode_status_t cache_status = CACHE_INODE_SUCCESS;
00950 
00951 #ifdef _USE_NFS4_ACL
00952      if (entry->attributes.acl) {
00953          fsal_acl_status_t acl_status = 0;
00954 
00955          nfs4_acl_release_entry(entry->attributes.acl, &acl_status);
00956          if (acl_status != NFS_V4_ACL_SUCCESS) {
00957               LogEvent(COMPONENT_CACHE_INODE,
00958                        "Failed to release old acl, status=%d",
00959                        acl_status);
00960          }
00961          entry->attributes.acl = NULL;
00962      }
00963 #endif /* _USE_NFS4_ACL */
00964 
00965      memset(&entry->attributes, 0, sizeof(fsal_attrib_list_t));
00966      entry->attributes.asked_attributes = cache_inode_params.attrmask;
00967 
00968      /* I assume this function will go away in the Lieb
00969         Rearchitecture. */
00970      fsal_status = FSAL_getattrs_descriptor(cache_inode_fd(entry),
00971                                             &entry->handle,
00972                                             context,
00973                                             &entry->attributes);
00974      if (FSAL_IS_ERROR(fsal_status) &&
00975          (fsal_status.major == ERR_FSAL_NOT_OPENED)) {
00976           fsal_status = FSAL_getattrs(&entry->handle,
00977                                       context,
00978                                       &entry->attributes);
00979      }
00980      if (FSAL_IS_ERROR(fsal_status)) {
00981           cache_inode_kill_entry(entry);
00982           cache_status
00983                = cache_inode_error_convert(fsal_status);
00984           goto out;
00985      }
00986 
00987      cache_inode_fixup_md(entry);
00988 
00989      cache_status = CACHE_INODE_SUCCESS;
00990 
00991 out:
00992      return cache_status;
00993 }
00994 
01005 static inline changeid4
01006 cache_inode_get_changeid4(cache_entry_t *entry)
01007 {
01008      return (changeid4) entry->change_time;
01009 }
01010 
01028 static inline cache_inode_status_t
01029 cache_inode_lock_trust_attrs(cache_entry_t *entry,
01030                              fsal_op_context_t *context)
01031 {
01032      cache_inode_status_t cache_status = CACHE_INODE_SUCCESS;
01033 
01034 
01035      pthread_rwlock_rdlock(&entry->attr_lock);
01036      /* Do we need to refresh? */
01037      if (!(entry->flags & CACHE_INODE_TRUST_ATTRS) ||
01038          FSAL_TEST_MASK(entry->attributes.asked_attributes,
01039                         FSAL_ATTR_RDATTR_ERR)) {
01040           pthread_rwlock_unlock(&entry->attr_lock);
01041           pthread_rwlock_wrlock(&entry->attr_lock);
01042           /* Has someone else done it for us? */
01043           if (!(entry->flags & CACHE_INODE_TRUST_ATTRS) ||
01044               FSAL_TEST_MASK(entry->attributes.asked_attributes,
01045                              FSAL_ATTR_RDATTR_ERR)) {
01046                /* Release the lock on error */
01047                if ((cache_status =
01048                     cache_inode_refresh_attrs(entry,
01049                                               context))
01050                    != CACHE_INODE_SUCCESS) {
01051                     pthread_rwlock_unlock(&entry->attr_lock);
01052                }
01053           }
01054      }
01055 
01056      return cache_status;
01057 }
01058 
01059 #endif /*  _CACHE_INODE_H */