nfs-ganesha 1.4

cache_inode_create.c

Go to the documentation of this file.
00001 /*
00002  * vim:expandtab:shiftwidth=8:tabstop=8:
00003  *
00004  * Copyright CEA/DAM/DIF  (2008)
00005  * contributeur : Philippe DENIEL   philippe.deniel@cea.fr
00006  *                Thomas LEIBOVICI  thomas.leibovici@cea.fr
00007  *
00008  *
00009  * This program is free software; you can redistribute it and/or
00010  * modify it under the terms of the GNU Lesser General Public
00011  * License as published by the Free Software Foundation; either
00012  * version 3 of the License, or (at your option) any later version.
00013  *
00014  * This program is distributed in the hope that it will be useful,
00015  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00016  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00017  * Lesser General Public License for more details.
00018  *
00019  * You should have received a copy of the GNU Lesser General Public
00020  * License along with this library; if not, write to the Free Software
00021  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
00022  *
00023  * ---------------------------------------
00024  */
00025 
00037 #ifdef HAVE_CONFIG_H
00038 #include "config.h"
00039 #endif
00040 
00041 #ifdef _SOLARIS
00042 #include "solaris_port.h"
00043 #endif                          /* _SOLARIS */
00044 
00045 #include "LRU_List.h"
00046 #include "log.h"
00047 #include "HashData.h"
00048 #include "HashTable.h"
00049 #include "fsal.h"
00050 #include "cache_inode.h"
00051 #include "cache_inode_lru.h"
00052 #include "cache_inode_weakref.h"
00053 #include <unistd.h>
00054 #include <sys/types.h>
00055 #include <sys/param.h>
00056 #include <time.h>
00057 #include <pthread.h>
00058 #include <assert.h>
00059 
00079 cache_entry_t *
00080 cache_inode_create(cache_entry_t *parent,
00081                    fsal_name_t *name,
00082                    cache_inode_file_type_t type,
00083                    fsal_accessmode_t mode,
00084                    cache_inode_create_arg_t *create_arg,
00085                    fsal_attrib_list_t *attr,
00086                    fsal_op_context_t *context,
00087                    cache_inode_status_t *status)
00088 {
00089      cache_entry_t *entry = NULL;
00090      fsal_status_t fsal_status = {0, 0};
00091      fsal_handle_t object_handle;
00092      fsal_attrib_list_t object_attributes;
00093      cache_inode_fsal_data_t fsal_data;
00094      cache_inode_create_arg_t zero_create_arg;
00095 
00096      memset(&zero_create_arg, 0, sizeof(zero_create_arg));
00097      memset(&fsal_data, 0, sizeof(fsal_data));
00098      memset(&object_handle, 0, sizeof(object_handle));
00099 
00100      if (create_arg == NULL) {
00101           create_arg = &zero_create_arg;
00102      }
00103 
00104      /* Set the return default to CACHE_INODE_SUCCESS */
00105      *status = CACHE_INODE_SUCCESS;
00106 
00107      if ((type != REGULAR_FILE) && (type != DIRECTORY) &&
00108          (type != SYMBOLIC_LINK) && (type != SOCKET_FILE) &&
00109          (type != FIFO_FILE) && (type != CHARACTER_FILE) &&
00110          (type != BLOCK_FILE)) {
00111           *status = CACHE_INODE_BAD_TYPE;
00112 
00113           entry = NULL;
00114           goto out;
00115         }
00116 
00117      /* Check if an entry of the same name exists */
00118      entry = cache_inode_lookup(parent,
00119                                 name,
00120                                 attr,
00121                                 context,
00122                                 status);
00123      if (entry != NULL) {
00124           *status = CACHE_INODE_ENTRY_EXISTS;
00125           if (entry->type != type) {
00126                /* Incompatible types, returns NULL */
00127                cache_inode_lru_unref(entry, LRU_FLAG_NONE);
00128                entry = NULL;
00129                goto out;
00130           } else {
00131                goto out;
00132           }
00133      }
00134 
00135      /* The entry doesn't exist, so we can create it. */
00136 
00137      object_attributes.asked_attributes = cache_inode_params.attrmask;
00138      switch (type) {
00139      case REGULAR_FILE:
00140           fsal_status = FSAL_create(&parent->handle,
00141                                     name, context, mode,
00142                                     &object_handle, &object_attributes);
00143           break;
00144 
00145      case DIRECTORY:
00146           fsal_status = FSAL_mkdir(&parent->handle,
00147                                    name, context, mode,
00148                                    &object_handle, &object_attributes);
00149           break;
00150 
00151      case SYMBOLIC_LINK:
00152           fsal_status = FSAL_symlink(&parent->handle,
00153                                      name, &create_arg->link_content,
00154                                      context, mode, &object_handle,
00155                                      &object_attributes);
00156           break;
00157 
00158      case SOCKET_FILE:
00159           fsal_status = FSAL_mknode(&parent->handle, name, context,
00160                                     mode, FSAL_TYPE_SOCK, NULL,
00161                                     &object_handle, &object_attributes);
00162           break;
00163 
00164      case FIFO_FILE:
00165           fsal_status = FSAL_mknode(&parent->handle, name, context,
00166                                     mode, FSAL_TYPE_FIFO, NULL,
00167                                     &object_handle, &object_attributes);
00168           break;
00169 
00170      case BLOCK_FILE:
00171           fsal_status = FSAL_mknode(&parent->handle,
00172                                     name, context,
00173                                     mode, FSAL_TYPE_BLK,
00174                                     &create_arg->dev_spec,
00175                                     &object_handle, &object_attributes);
00176              break;
00177 
00178      case CHARACTER_FILE:
00179           fsal_status = FSAL_mknode(&parent->handle,
00180                                     name, context,
00181                                     mode, FSAL_TYPE_CHR,
00182                                     &create_arg->dev_spec,
00183                                     &object_handle,
00184                                     &object_attributes);
00185           break;
00186 
00187      default:
00188           /* we should never go there */
00189           *status = CACHE_INODE_INCONSISTENT_ENTRY;
00190           entry = NULL;
00191           goto out;
00192           break;
00193         }
00194 
00195      /* Check for the result */
00196      if (FSAL_IS_ERROR(fsal_status)) {
00197           if (fsal_status.major == ERR_FSAL_STALE) {
00198                cache_inode_kill_entry(parent);
00199           }
00200           *status = cache_inode_error_convert(fsal_status);
00201           entry = NULL;
00202           goto out;
00203      }
00204      fsal_data.fh_desc.start = (caddr_t) &object_handle;
00205      fsal_data.fh_desc.len = 0;
00206      FSAL_ExpandHandle(context->export_context,
00207                        FSAL_DIGEST_SIZEOF,
00208                        &fsal_data.fh_desc);
00209 
00210      entry = cache_inode_new_entry(&fsal_data,
00211                                    &object_attributes,
00212                                    type,
00213                                    create_arg,
00214                                    status);
00215      if (entry == NULL) {
00216           *status = CACHE_INODE_INSERT_ERROR;
00217 
00218           return NULL;
00219      }
00220 
00221      pthread_rwlock_wrlock(&parent->content_lock);
00222      /* Add this entry to the directory (also takes an internal ref) */
00223      cache_inode_add_cached_dirent(parent,
00224                                    name, entry,
00225                                    NULL,
00226                                    status);
00227      pthread_rwlock_unlock(&parent->content_lock);
00228      if (*status != CACHE_INODE_SUCCESS) {
00229           cache_inode_lru_unref(entry, LRU_FLAG_NONE);
00230           entry = NULL;
00231           goto out;
00232      }
00233 
00234      pthread_rwlock_wrlock(&parent->attr_lock);
00235      /* Update the parent cached attributes */
00236      cache_inode_set_time_current(&parent->attributes.mtime);
00237      parent->attributes.ctime = parent->attributes.mtime;
00238      /* if the created object is a directory, it contains a link
00239         to its parent : '..'. Thus the numlink attr must be increased. */
00240      if (type == DIRECTORY) {
00241           ++(parent->attributes.numlinks);
00242      }
00243      pthread_rwlock_unlock(&parent->attr_lock);
00244 
00245      /* Copy up the child attributes */
00246      *attr = object_attributes;
00247 
00248      *status = CACHE_INODE_SUCCESS;
00249 
00250 out:
00251 
00252      return entry;
00253 }