nfs-ganesha 1.4

cache_inode_open_close.c

Go to the documentation of this file.
00001 
00033 #ifdef HAVE_CONFIG_H
00034 #include "config.h"
00035 #endif
00036 
00037 #ifdef _SOLARIS
00038 #include "solaris_port.h"
00039 #endif                          /* _SOLARIS */
00040 
00041 #include "fsal.h"
00042 
00043 #include "abstract_atomic.h"
00044 #include "log.h"
00045 #include "HashData.h"
00046 #include "HashTable.h"
00047 #include "cache_inode.h"
00048 #include "cache_inode_lru.h"
00049 
00050 #include <unistd.h>
00051 #include <string.h>
00052 #include <sys/types.h>
00053 #include <sys/stat.h>
00054 #include <sys/param.h>
00055 #include <time.h>
00056 #include <pthread.h>
00057 #include <strings.h>
00058 #include <assert.h>
00059 
00072 fsal_file_t *
00073 cache_inode_fd(cache_entry_t *entry)
00074 {
00075      if (entry == NULL) {
00076           return NULL;
00077      }
00078 
00079      if (entry->type != REGULAR_FILE) {
00080           return NULL;
00081      }
00082 
00083      if (entry->object.file.open_fd.openflags != FSAL_O_CLOSED) {
00084           return &entry->object.file.open_fd.fd;
00085      }
00086 
00087      return NULL;
00088 }
00089 
00101 bool_t
00102 is_open_for_write(cache_entry_t *entry)
00103 {
00104      return
00105           (entry &&
00106            (entry->type == REGULAR_FILE) &&
00107            ((entry->object.file.open_fd.openflags == FSAL_O_RDWR) ||
00108             (entry->object.file.open_fd.openflags == FSAL_O_WRONLY)));
00109 }
00110 
00122 bool_t
00123 is_open_for_read(cache_entry_t *entry)
00124 {
00125      return
00126           (entry &&
00127            (entry->type == REGULAR_FILE) &&
00128            ((entry->object.file.open_fd.openflags == FSAL_O_RDWR) ||
00129             (entry->object.file.open_fd.openflags == FSAL_O_RDONLY)));
00130 }
00131 
00147 cache_inode_status_t
00148 cache_inode_open(cache_entry_t *entry,
00149                  fsal_openflags_t openflags,
00150                  fsal_op_context_t *context,
00151                  uint32_t flags,
00152                  cache_inode_status_t *status)
00153 {
00154      /* Error return from FSAL */
00155      fsal_status_t fsal_status = {0, 0};
00156 
00157      if ((entry == NULL) || (context == NULL) ||
00158          (status == NULL)) {
00159           *status = CACHE_INODE_INVALID_ARGUMENT;
00160           goto out;
00161      }
00162 
00163      if (entry->type != REGULAR_FILE) {
00164           *status = CACHE_INODE_BAD_TYPE;
00165           goto out;
00166      }
00167 
00168      if (!cache_inode_lru_fds_available()) {
00169           /* This seems the best idea, let the client try again later
00170              after the reap. */
00171           *status = CACHE_INODE_DELAY;
00172           goto out;
00173      }
00174 
00175      if (!(flags & CACHE_INODE_FLAG_CONTENT_HAVE)) {
00176           pthread_rwlock_wrlock(&entry->content_lock);
00177      }
00178 
00179      /* Open file need to be closed, unless it is already open as read/write */
00180      if ((entry->object.file.open_fd.openflags != FSAL_O_RDWR) &&
00181          (entry->object.file.open_fd.openflags != 0) &&
00182          (entry->object.file.open_fd.openflags != openflags)) {
00183           fsal_status = FSAL_close(&(entry->object.file.open_fd.fd));
00184           if (FSAL_IS_ERROR(fsal_status) &&
00185               (fsal_status.major != ERR_FSAL_NOT_OPENED)) {
00186                *status = cache_inode_error_convert(fsal_status);
00187                if (fsal_status.major == ERR_FSAL_STALE) {
00188                     cache_inode_kill_entry(entry);
00189                }
00190 
00191                LogDebug(COMPONENT_CACHE_INODE,
00192                         "cache_inode_open: returning %d(%s) from FSAL_close",
00193                         *status, cache_inode_err_str(*status));
00194 
00195                goto unlock;
00196           }
00197 
00198           if (!FSAL_IS_ERROR(fsal_status))
00199               atomic_dec_size_t(&open_fd_count);
00200 
00201           /* Force re-openning */
00202           entry->object.file.open_fd.openflags = FSAL_O_CLOSED;
00203      }
00204 
00205      if ((entry->object.file.open_fd.openflags == FSAL_O_CLOSED)) {
00206           fsal_status = FSAL_open(&(entry->handle),
00207                                   context,
00208                                   openflags,
00209                                   &entry->object.file.open_fd.fd,
00210                                   NULL);
00211           if (FSAL_IS_ERROR(fsal_status)) {
00212                *status = cache_inode_error_convert(fsal_status);
00213                LogDebug(COMPONENT_CACHE_INODE,
00214                         "cache_inode_open: returning %d(%s) from FSAL_open",
00215                         *status, cache_inode_err_str(*status));
00216                if (fsal_status.major == ERR_FSAL_STALE) {
00217                     cache_inode_kill_entry(entry);
00218                }
00219                goto unlock;
00220           }
00221 
00222           entry->object.file.open_fd.openflags = openflags;
00223           /* This is temporary code, until Jim Lieb makes FSALs cache
00224              their own file descriptors.  Under that regime, the LRU
00225              thread will interrogate FSALs for their FD use. */
00226           atomic_inc_size_t(&open_fd_count);
00227 
00228           LogDebug(COMPONENT_CACHE_INODE,
00229                    "cache_inode_open: pentry %p: openflags = %d, "
00230                    "open_fd_count = %zd", entry, openflags,
00231                    open_fd_count);
00232      }
00233 
00234      *status = CACHE_INODE_SUCCESS;
00235 
00236 unlock:
00237 
00238      if (!(flags & CACHE_INODE_FLAG_CONTENT_HOLD)) {
00239           pthread_rwlock_unlock(&entry->content_lock);
00240      }
00241 
00242 out:
00243 
00244      return *status;
00245 
00246 } /* cache_inode_open */
00247 
00260 cache_inode_status_t
00261 cache_inode_close(cache_entry_t *entry,
00262                   uint32_t flags,
00263                   cache_inode_status_t *status)
00264 {
00265      /* Error return from the FSAL */
00266      fsal_status_t fsal_status;
00267 
00268      if ((entry == NULL) || (status == NULL)) {
00269           *status = CACHE_INODE_INVALID_ARGUMENT;
00270           goto out;
00271      }
00272 
00273      if (entry->type != REGULAR_FILE) {
00274           *status = CACHE_INODE_BAD_TYPE;
00275           goto out;
00276      }
00277 
00278      if (!(flags & CACHE_INODE_FLAG_CONTENT_HAVE)) {
00279           pthread_rwlock_wrlock(&entry->content_lock);
00280      }
00281 
00282      /* If nothing is opened, do nothing */
00283      if (entry->object.file.open_fd.openflags == FSAL_O_CLOSED) {
00284           if (!(flags & CACHE_INODE_FLAG_CONTENT_HOLD)) {
00285                pthread_rwlock_unlock(&entry->content_lock);
00286           }
00287           *status = CACHE_INODE_SUCCESS;
00288           return *status;
00289      }
00290 
00291      /* If state is held in the file, do not close it.  This should
00292         be refined.  (A non return_on_close layout should not prevent
00293         the file from closing.)  The caller should hold the state
00294         lock. */
00295      if (cache_inode_file_holds_state(entry)) {
00296           *status = CACHE_INODE_SUCCESS;
00297           goto unlock;
00298      }
00299 
00300      if (!cache_inode_lru_caching_fds() ||
00301          (flags & CACHE_INODE_FLAG_REALLYCLOSE)) {
00302           LogDebug(COMPONENT_CACHE_INODE,
00303                    "cache_inode_close: entry %p", entry);
00304           fsal_status = FSAL_close(&(entry->object.file.open_fd.fd));
00305 
00306           entry->object.file.open_fd.openflags = FSAL_O_CLOSED;
00307           if (FSAL_IS_ERROR(fsal_status) &&
00308               (fsal_status.major != ERR_FSAL_NOT_OPENED)) {
00309                *status = cache_inode_error_convert(fsal_status);
00310                if (fsal_status.major == ERR_FSAL_STALE) {
00311                     cache_inode_kill_entry(entry);
00312                }
00313                LogCrit(COMPONENT_CACHE_INODE,
00314                        "cache_inode_close: returning %d(%s) from FSAL_close",
00315                        *status, cache_inode_err_str(*status));
00316                goto unlock;
00317           }
00318           if (!FSAL_IS_ERROR(fsal_status))
00319               atomic_dec_size_t(&open_fd_count);
00320      }
00321 
00322      *status = CACHE_INODE_SUCCESS;
00323 
00324 unlock:
00325 
00326      if (!(flags & CACHE_INODE_FLAG_CONTENT_HOLD)) {
00327           pthread_rwlock_unlock(&entry->content_lock);
00328      }
00329 
00330 out:
00331 
00332      return *status;
00333 }