Example #1
0
fsal_status_t MFSL_close(mfsl_file_t * file_descriptor, /* IN */
                         mfsl_context_t * p_mfsl_context,        /* IN */
			 void * pextra
    )
{
  return FSAL_close(&file_descriptor->fsal_file);
}                               /* MFSL_close */
Example #2
0
fsal_status_t MFSL_close(mfsl_file_t * file_descriptor, /* IN */
                         mfsl_context_t * p_mfsl_context,        /* IN */
			 void * pextra
    )
{
  struct timeval start, stop, delta ;
  fsal_status_t fsal_status = { ERR_FSAL_NO_ERROR, 0 } ;
  
  gettimeofday( &start, 0 ) ; 
  fsal_status = FSAL_close(&file_descriptor->fsal_file);
  gettimeofday( &stop, 0 ) ; 
  delta = mfsl_timer_diff( &stop, &start ) ;
  LogFullDebug( COMPONENT_MFSL, "%s: duration=%ld.%06ld", __FUNCTION__, delta.tv_sec, delta.tv_usec ) ;
  return fsal_status ;
}                               /* MFSL_close */
Example #3
0
cache_inode_status_t cache_inode_rdwr(cache_entry_t * pentry,
                                      cache_inode_io_direction_t read_or_write,
                                      fsal_seek_t * seek_descriptor,
                                      fsal_size_t buffer_size,
                                      fsal_size_t * pio_size,
                                      fsal_attrib_list_t * pfsal_attr,
                                      caddr_t buffer,
                                      fsal_boolean_t * p_fsal_eof,
                                      hash_table_t * ht,
                                      cache_inode_client_t * pclient,
                                      fsal_op_context_t * pcontext,
                                      uint64_t stable, 
				      cache_inode_status_t * pstatus)
{
  int statindex = 0;
  cache_content_io_direction_t io_direction;
  cache_content_status_t cache_content_status;
  fsal_status_t fsal_status;
  fsal_openflags_t openflags;
  fsal_size_t io_size;
  fsal_attrib_list_t post_write_attr;
  fsal_status_t fsal_status_getattr;
  struct stat buffstat;

  /* Set the return default to CACHE_INODE_SUCCESS */
  *pstatus = CACHE_INODE_SUCCESS;

  /* For now, only FSAL_SEEK_SET is supported */
  if(seek_descriptor->whence != FSAL_SEEK_SET)
    {
      LogCrit(COMPONENT_CACHE_INODE,
              "Implementation trouble: seek_descriptor was not a 'FSAL_SEEK_SET' cursor");
      *pstatus = CACHE_INODE_INVALID_ARGUMENT;
      return *pstatus;
    }

  io_size = buffer_size;

  LogDebug(COMPONENT_CACHE_INODE,
           "cache_inode_rdwr: INODE : IO Size = %llu fdsize =%zu seeksize=%zu",
           buffer_size, sizeof(fsal_file_t), sizeof(fsal_seek_t));

  /* stat */
  pclient->stat.nb_call_total += 1;
  if(read_or_write == CACHE_INODE_READ)
    {
      statindex = CACHE_INODE_READ_DATA;
      io_direction = CACHE_CONTENT_READ;
      openflags = FSAL_O_RDONLY;
      pclient->stat.func_stats.nb_call[CACHE_INODE_READ_DATA] += 1;
    }
  else
    {
      statindex = CACHE_INODE_WRITE_DATA;
      io_direction = CACHE_CONTENT_WRITE;
      openflags = FSAL_O_WRONLY;
      pclient->stat.func_stats.nb_call[CACHE_INODE_WRITE_DATA] += 1;
    }

  P_w(&pentry->lock);

  /* IO are done only on REGULAR_FILEs */
  if(pentry->internal_md.type != REGULAR_FILE)
    {
      *pstatus = CACHE_INODE_BAD_TYPE;
      V_w(&pentry->lock);

      /* stats */
      pclient->stat.func_stats.nb_err_unrecover[statindex] += 1;

      return *pstatus;
    }

  /* Non absolute address within the file are not supported (we act only like pread/pwrite) */
  if(seek_descriptor->whence != FSAL_SEEK_SET)
    {
      *pstatus = CACHE_INODE_INVALID_ARGUMENT;
      V_w(&pentry->lock);

      /* stats */
      pclient->stat.func_stats.nb_err_unrecover[statindex] += 1;

      return *pstatus;
    }

  /* Do we use stable or unstable storage ? */
  if(stable == FSAL_UNSAFE_WRITE_TO_GANESHA_BUFFER)
    {
      /* Data will be stored in memory and not flush to FSAL */

      /* If the unstable_data buffer allocated ? */
      if(pentry->object.file.unstable_data.buffer == NULL)
        {
          if((pentry->object.file.unstable_data.buffer =
              Mem_Alloc_Label(CACHE_INODE_UNSTABLE_BUFFERSIZE,
                              "Cache_Inode Unstable Buffer")) == NULL)
            {
              *pstatus = CACHE_INODE_MALLOC_ERROR;
              V_w(&pentry->lock);

              /* stats */
              pclient->stat.func_stats.nb_err_unrecover[statindex] += 1;

              return *pstatus;
            }

          pentry->object.file.unstable_data.offset = seek_descriptor->offset;
          pentry->object.file.unstable_data.length = buffer_size;

          memcpy(pentry->object.file.unstable_data.buffer, buffer, buffer_size);

          /* Set mtime and ctime */
          cache_inode_set_time_current( &pentry->attributes.mtime ) ;  

          /* BUGAZOMEU : write operation must NOT modify file's ctime */
          pentry->attributes.ctime = pentry->attributes.mtime;

          *pio_size = buffer_size;
        }                       /* if( pentry->object.file.unstable_data.buffer == NULL ) */
      else
        {
          if((pentry->object.file.unstable_data.offset < seek_descriptor->offset) &&
             (buffer_size + seek_descriptor->offset < CACHE_INODE_UNSTABLE_BUFFERSIZE))
            {
              pentry->object.file.unstable_data.length =
                  buffer_size + seek_descriptor->offset;
              memcpy((char *)(pentry->object.file.unstable_data.buffer +
                              seek_descriptor->offset), buffer, buffer_size);

              /* Set mtime and ctime */
              cache_inode_set_time_current( &pentry->attributes.mtime ) ;

              /* BUGAZOMEU : write operation must NOT modify file's ctime */
              pentry->attributes.ctime = pentry->attributes.mtime;

              *pio_size = buffer_size;
            }
          else
            {
              /* Go back to regular situation */
              stable = FSAL_SAFE_WRITE_TO_FS;
            }
        }

    }
  /* if( stable == FALSE ) */
  if(stable == FSAL_SAFE_WRITE_TO_FS ||
     stable == FSAL_UNSAFE_WRITE_TO_FS_BUFFER)
    {
      /* Calls file content cache to operate on the cache */
      if(pentry->object.file.pentry_content != NULL)
        {
          /* Entry is data cached */
          cache_content_rdwr(pentry->object.file.pentry_content,
                             io_direction,
                             seek_descriptor,
                             &io_size,
                             pio_size,
                             buffer,
                             p_fsal_eof,
                             &buffstat,
                             (cache_content_client_t *) pclient->pcontent_client,
                             pcontext, &cache_content_status);

          /* If the entry under resync */
          if(cache_content_status == CACHE_CONTENT_LOCAL_CACHE_NOT_FOUND)
            {
              /* Data cache gc has removed this entry */
              if(cache_content_new_entry(pentry,
                                         NULL,
                                         (cache_content_client_t *)pclient->pcontent_client, 
                                         RENEW_ENTRY, pcontext,
                                         &cache_content_status) == NULL)
                {
                  /* Entry could not be recoverd, cache_content_status contains an error, let it be managed by the next block */
                  LogCrit(COMPONENT_CACHE_INODE,
                          "Read/Write Operation through cache failed with status %d (renew process failed)",
                          cache_content_status);

		  /* Will go to the end of the function on the error clause with cache_content_status describing the error */
                }
              else
                {
                  /* Entry was successfully renewed */
                  LogInfo(COMPONENT_CACHE_INODE,
                          "----> File Content Entry %p was successfully renewed",
                          pentry);

                  /* Try to access the content of the file again */
                  cache_content_rdwr(pentry->object.file.pentry_content,
                                     io_direction,
                                     seek_descriptor,
                                     &io_size,
                                     pio_size,
                                     buffer,
                                     p_fsal_eof,
                                     &buffstat,
                                     (cache_content_client_t *) pclient->pcontent_client,
                                     pcontext, &cache_content_status);

                  /* No management of cache_content_status in case of failure, this will be done
                   * within the next block */
                }

            }

          if(cache_content_status != CACHE_CONTENT_SUCCESS)
            {
              *pstatus = cache_content_error_convert(cache_content_status);

              V_w(&pentry->lock);

              LogCrit(COMPONENT_CACHE_INODE,
                      "Read/Write Operation through cache failed with status %d",
                      cache_content_status);

              /* stats */
              pclient->stat.func_stats.nb_err_unrecover[statindex] += 1;

              return *pstatus;
            }

          LogFullDebug(COMPONENT_CACHE_INODE,
                       "cache_inode_rdwr: inode/dc: io_size=%llu, pio_size=%llu,  eof=%d, seek=%d.%"PRIu64,
                       io_size, *pio_size, *p_fsal_eof, seek_descriptor->whence,
                       seek_descriptor->offset);

          LogMidDebug(COMPONENT_CACHE_INODE,
                       "cache_inode_rdwr: INODE  AFTER : IO Size = %llu %llu",
                       io_size, *pio_size);

          /* Use information from the buffstat to update the file metadata */
          pentry->attributes.filesize = buffstat.st_size;
          pentry->attributes.spaceused =
              buffstat.st_blksize * buffstat.st_blocks;

        }
      else
        {
          /* No data cache entry, we operated directly on FSAL */
          pentry->attributes.asked_attributes = pclient->attrmask;

          /* We need to open if we don't have a cached
           * descriptor or our open flags differs.
           */
          if(cache_inode_open(pentry,
                              pclient,
                              openflags, pcontext, pstatus) != CACHE_INODE_SUCCESS)
            {
              V_w(&pentry->lock);

              /* stats */
              pclient->stat.func_stats.nb_err_unrecover[statindex] += 1;

              return *pstatus;
            }

          /* Call FSAL_read or FSAL_write */

          if(read_or_write == CACHE_INODE_READ)
            {
#ifdef _USE_MFSL
              fsal_status = MFSL_read(&(pentry->object.file.open_fd.mfsl_fd),
                                      seek_descriptor,
                                      io_size,
                                      buffer,
                                      pio_size, p_fsal_eof, &pclient->mfsl_context, NULL);
#else
              fsal_status = FSAL_read(&(pentry->object.file.open_fd.fd),
                                      seek_descriptor,
                                      io_size, buffer, pio_size, p_fsal_eof);
#endif
            }
          else
            {
#ifdef _USE_MFSL
              fsal_status = MFSL_write(&(pentry->object.file.open_fd.mfsl_fd),
                                       seek_descriptor,
                                       io_size, buffer, pio_size, &pclient->mfsl_context, NULL);
#else
              fsal_status = FSAL_write(&(pentry->object.file.open_fd.fd),
                                       seek_descriptor, io_size, buffer, pio_size);
#endif

#if 0
              /* Alright, the unstable write is complete. Now if it was supposed to be a stable write
               * we can sync to the hard drive. */
              if(stable == FSAL_SAFE_WRITE_TO_FS)
                {
#ifdef _USE_MFSL
                  fsal_status = MFSL_commit(&(pentry->object.file.open_fd.mfsl_fd), NULL);
#else
                  fsal_status = FSAL_commit(&(pentry->object.file.open_fd.fd));
#endif
#endif

            }

          LogFullDebug(COMPONENT_FSAL,
                       "cache_inode_rdwr: FSAL IO operation returned %d, asked_size=%llu, effective_size=%llu",
                       fsal_status.major, (unsigned long long)io_size,
                       (unsigned long long)*pio_size);

          if(FSAL_IS_ERROR(fsal_status))
            {

              if(fsal_status.major == ERR_FSAL_DELAY)
                LogEvent(COMPONENT_CACHE_INODE,
                         "cache_inode_rdwr: FSAL_write returned EBUSY");
              else
                LogDebug(COMPONENT_CACHE_INODE,
                         "cache_inode_rdwr: fsal_status.major = %d",
                         fsal_status.major);

              if((fsal_status.major != ERR_FSAL_NOT_OPENED)
                 && (pentry->object.file.open_fd.fileno != 0))
                {

                  LogDebug(COMPONENT_CACHE_INODE,
                               "cache_inode_rdwr: CLOSING pentry %p: fd=%d",
                               pentry, pentry->object.file.open_fd.fileno);

#ifdef _USE_MFSL
                  MFSL_close(&(pentry->object.file.open_fd.mfsl_fd), &pclient->mfsl_context, NULL);
#else
                  FSAL_close(&(pentry->object.file.open_fd.fd));
#endif

                  *pstatus = cache_inode_error_convert(fsal_status);
                }
              else
                {
                  /* the fd has been close by another thread.
                   * return CACHE_INODE_FSAL_DELAY so the client will
                   * retry with a new fd.
                   */
                  *pstatus = CACHE_INODE_FSAL_DELAY;
                }

              pentry->object.file.open_fd.last_op = 0;
              pentry->object.file.open_fd.fileno = 0;

              V_w(&pentry->lock);

              /* stats */
              pclient->stat.func_stats.nb_err_unrecover[statindex] += 1;

              return *pstatus;
            }

          LogFullDebug(COMPONENT_CACHE_INODE,
                       "cache_inode_rdwr: inode/direct: io_size=%llu, pio_size=%llu, eof=%d, seek=%d.%"PRIu64,
                       io_size, *pio_size, *p_fsal_eof, seek_descriptor->whence,
                       seek_descriptor->offset);

          if(cache_inode_close(pentry, pclient, pstatus) != CACHE_INODE_SUCCESS)
            {
              LogEvent(COMPONENT_CACHE_INODE,
                       "cache_inode_rdwr: cache_inode_close = %d", *pstatus);

              V_w(&pentry->lock);

              /* stats */
              pclient->stat.func_stats.nb_err_unrecover[statindex] += 1;

              return *pstatus;
            }

          if(read_or_write == CACHE_INODE_WRITE)
            {
              /* Do a getattr in order to have update information on filesize
               * This query is done directly on FSAL (object is not data cached), and result
               * will be propagated to cache Inode */

              /* WARNING: This operation is to be done AFTER FSAL_close (some FSAL, like POSIX,
               * may not flush data until the file is closed */

              /*post_write_attr.asked_attributes =  pclient->attrmask ; */
              post_write_attr.asked_attributes = FSAL_ATTR_SIZE | FSAL_ATTR_SPACEUSED;
              fsal_status_getattr =
                  FSAL_getattrs(&(pentry->handle), pcontext,
                                &post_write_attr);

              /* if failed, the next block will handle the error */
              if(FSAL_IS_ERROR(fsal_status_getattr))
                fsal_status = fsal_status_getattr;
              else
                {
                  /* Update Cache Inode attributes */
                  pentry->attributes.filesize = post_write_attr.filesize;
                  pentry->attributes.spaceused = post_write_attr.spaceused;
                }
            }

        }

      /* IO was successfull (through cache content or not), we manually update the times in the attributes */

      switch (read_or_write)
        {
        case CACHE_INODE_READ:
          /* Set the atime */
          cache_inode_set_time_current( & pentry->attributes.atime ) ;
          break;

        case CACHE_INODE_WRITE:
          /* Set mtime and ctime */
          cache_inode_set_time_current( & pentry->attributes.mtime ) ;

          /* BUGAZOMEU : write operation must NOT modify file's ctime */
          pentry->attributes.ctime = pentry->attributes.mtime;

          break;
        }
    }

  /* if(stable == TRUE ) */
  /* Return attributes to caller */
  if(pfsal_attr != NULL)
    *pfsal_attr = pentry->attributes;

  *pstatus = CACHE_INODE_SUCCESS;

  /* stat */
  if(read_or_write == CACHE_INODE_READ)
    {
      *pstatus = cache_inode_valid(pentry, CACHE_INODE_OP_GET, pclient);

      if(*pstatus != CACHE_INODE_SUCCESS)
        pclient->stat.func_stats.nb_err_unrecover[CACHE_INODE_READ] += 1;
      else
        pclient->stat.func_stats.nb_success[CACHE_INODE_READ] += 1;
    }
  else
    {
      *pstatus = cache_inode_valid(pentry, CACHE_INODE_OP_SET, pclient);

      if(*pstatus != CACHE_INODE_SUCCESS)
        pclient->stat.func_stats.nb_err_unrecover[CACHE_INODE_WRITE] += 1;
      else
        pclient->stat.func_stats.nb_success[CACHE_INODE_WRITE] += 1;
    }

  V_w(&pentry->lock);

  return *pstatus;
}                               /* cache_inode_rdwr */
/**
 *
 * cache_inode_close: closes the local fd in the FSAL.
 *
 * Closes the local fd in the FSAL.
 *
 * No lock management is done in this layer: the related pentry in the cache inode layer is
 * locked and will prevent from concurent accesses.
 *
 * @param pentry  [IN] entry in file content layer whose content is to be accessed.
 * @param pclient [IN]  ressource allocated by the client for the nfs management.
 * @pstatus       [OUT] returned status.
 *
 * @return CACHE_CONTENT_SUCCESS is successful .
 *
 */
cache_inode_status_t cache_inode_close(cache_entry_t * pentry,
                                       cache_inode_client_t * pclient,
                                       cache_inode_status_t * pstatus)
{
  fsal_status_t fsal_status;

  if((pentry == NULL) || (pclient == NULL) || (pstatus == NULL))
    return CACHE_CONTENT_INVALID_ARGUMENT;

  if(pentry->internal_md.type != REGULAR_FILE)
    {
      *pstatus = CACHE_INODE_BAD_TYPE;
      return *pstatus;
    }

  /* if nothing is opened, do nothing */
  if(pentry->object.file.open_fd.fileno < 0)
    {
      *pstatus = CACHE_INODE_SUCCESS;
      return *pstatus;
    }

  /* if locks are held in the file, do not close */
  if( cache_inode_file_holds_state( pentry ) )
    {
      *pstatus = CACHE_INODE_SUCCESS; /** @todo : PhD : May be CACHE_INODE_STATE_CONFLICTS would be better ? */
      return *pstatus;
    }

  if((pclient->use_fd_cache == 0) ||
     (time(NULL) - pentry->object.file.open_fd.last_op > pclient->retention) ||
     (pentry->object.file.open_fd.fileno > (int)(pclient->max_fd)))
    {

      LogDebug(COMPONENT_CACHE_INODE,
               "cache_inode_close: pentry %p, fileno = %d, lastop=%d ago",
               pentry, pentry->object.file.open_fd.fileno,
               (int)(time(NULL) - pentry->object.file.open_fd.last_op));

#ifdef _USE_MFSL
      fsal_status = MFSL_close(&(pentry->object.file.open_fd.mfsl_fd), &pclient->mfsl_context, NULL);
#else
      fsal_status = FSAL_close(&(pentry->object.file.open_fd.fd));
#endif

      pentry->object.file.open_fd.fileno = 0;
      pentry->object.file.open_fd.last_op = 0;

      if(FSAL_IS_ERROR(fsal_status) && (fsal_status.major != ERR_FSAL_NOT_OPENED))
        {
          *pstatus = cache_inode_error_convert(fsal_status);

          LogDebug(COMPONENT_CACHE_INODE,
                   "cache_inode_close: returning %d(%s) from FSAL_close",
                   *pstatus, cache_inode_err_str(*pstatus));

          return *pstatus;
        }
    }
#ifdef _USE_PROXY
  /* If proxy if used, free the name if needed */
  if(pentry->object.file.pname != NULL)
    {
      Mem_Free((char *)(pentry->object.file.pname));
      pentry->object.file.pname = NULL;
    }
  pentry->object.file.pentry_parent_open = NULL;
#endif

  *pstatus = CACHE_CONTENT_SUCCESS;

  return *pstatus;
}                               /* cache_content_close */
cache_inode_status_t cache_inode_open_by_name(cache_entry_t * pentry_dir,
                                              fsal_name_t * pname,
                                              cache_entry_t * pentry_file,
                                              cache_inode_client_t * pclient,
                                              fsal_openflags_t openflags,
                                              fsal_op_context_t * pcontext,
                                              cache_inode_status_t * pstatus)
{
  fsal_status_t fsal_status;
  fsal_size_t save_filesize = 0;
  fsal_size_t save_spaceused = 0;
  fsal_time_t save_mtime = {
    .seconds = 0,
    .nseconds = 0
  };

  if((pentry_dir == NULL) || (pname == NULL) || (pentry_file == NULL) ||
     (pclient == NULL) || (pcontext == NULL) || (pstatus == NULL))
    return CACHE_INODE_INVALID_ARGUMENT;

  if((pentry_dir->internal_md.type != DIRECTORY))
    {
      *pstatus = CACHE_INODE_BAD_TYPE;
      return *pstatus;
    }

  if(pentry_file->internal_md.type != REGULAR_FILE)
    {
      *pstatus = CACHE_INODE_BAD_TYPE;
      return *pstatus;
    }

  /* Open file need to be closed, unless it is already open as read/write */
  if((pentry_file->object.file.open_fd.openflags != FSAL_O_RDWR) &&
     (pentry_file->object.file.open_fd.openflags != 0) &&
     (pentry_file->object.file.open_fd.fileno >= 0) &&
     (pentry_file->object.file.open_fd.openflags != openflags))
    {
#ifdef _USE_MFSL
      fsal_status =
          MFSL_close(&(pentry_file->object.file.open_fd.mfsl_fd), &pclient->mfsl_context, NULL);
#else
      fsal_status = FSAL_close(&(pentry_file->object.file.open_fd.fd));
#endif
      if(FSAL_IS_ERROR(fsal_status) && (fsal_status.major != ERR_FSAL_NOT_OPENED))
        {
          *pstatus = cache_inode_error_convert(fsal_status);

          LogDebug(COMPONENT_CACHE_INODE,
                   "cache_inode_open_by_name: returning %d(%s) from FSAL_close",
                   *pstatus, cache_inode_err_str(*pstatus));

          return *pstatus;
        }

      pentry_file->object.file.open_fd.last_op = 0;
      pentry_file->object.file.open_fd.fileno = 0;
    }

  if(pentry_file->object.file.open_fd.last_op == 0
     || pentry_file->object.file.open_fd.fileno == 0)
    {
      LogDebug(COMPONENT_FSAL,
               "cache_inode_open_by_name: pentry %p: lastop=0", pentry_file);

      /* Keep coherency with the cache_content */
      if(pentry_file->object.file.pentry_content != NULL)
        {
          save_filesize = pentry_file->object.file.attributes.filesize;
          save_spaceused = pentry_file->object.file.attributes.spaceused;
          save_mtime = pentry_file->object.file.attributes.mtime;
        }

      /* opened file is not preserved yet */
#ifdef _USE_MFSL
      fsal_status = MFSL_open_by_name(&(pentry_dir->mobject),
                                      pname,
                                      pcontext,
                                      &pclient->mfsl_context,
                                      openflags,
                                      &pentry_file->object.file.open_fd.mfsl_fd,
                                      &(pentry_file->object.file.attributes),
#ifdef _USE_PNFS
                                      &pentry_file->object.file.pnfs_file ) ;
#else
                                      NULL );
#endif /* _USE_PNFS */

#else
      fsal_status = FSAL_open_by_name(&(pentry_dir->object.file.handle),
                                      pname,
                                      pcontext,
                                      openflags,
                                      &pentry_file->object.file.open_fd.fd,
                                      &(pentry_file->object.file.attributes));
#endif

      if(FSAL_IS_ERROR(fsal_status))
        {
          *pstatus = cache_inode_error_convert(fsal_status);

          LogDebug(COMPONENT_CACHE_INODE,
                   "cache_inode_open_by_name: returning %d(%s) from FSAL_open_by_name",
                   *pstatus, cache_inode_err_str(*pstatus));

          return *pstatus;
        }

#ifdef _USE_PROXY

      /* If proxy if used, we should keep the name of the file to do FSAL_rcp if needed */
      if((pentry_file->object.file.pname =
          (fsal_name_t *) Mem_Alloc_Label(sizeof(fsal_name_t), "fsal_name_t")) == NULL)
        {
          *pstatus = CACHE_INODE_MALLOC_ERROR;

          return *pstatus;
        }

      pentry_file->object.file.pentry_parent_open = pentry_dir;
      pentry_file->object.file.pname->len = pname->len;
      memcpy((char *)(pentry_file->object.file.pname->name), (char *)(pname->name),
             FSAL_MAX_NAME_LEN);

#endif

      /* Keep coherency with the cache_content */
      if(pentry_file->object.file.pentry_content != NULL)
        {
          pentry_file->object.file.attributes.filesize = save_filesize;
          pentry_file->object.file.attributes.spaceused = save_spaceused;
          pentry_file->object.file.attributes.mtime = save_mtime;
        }

#ifdef _USE_MFSL
      pentry_file->object.file.open_fd.fileno =
          (int)FSAL_FILENO(&(pentry_file->object.file.open_fd.mfsl_fd.fsal_file));
#else
      pentry_file->object.file.open_fd.fileno =
          (int)FSAL_FILENO(&(pentry_file->object.file.open_fd.fd));
#endif
      pentry_file->object.file.open_fd.last_op = time(NULL);
      pentry_file->object.file.open_fd.openflags = openflags;

      LogDebug(COMPONENT_FSAL,
               "cache_inode_open_by_name: pentry %p: fd=%u",
               pentry_file, pentry_file->object.file.open_fd.fileno);

    }

  /* regular exit */
  pentry_file->object.file.open_fd.last_op = time(NULL);

  /* if file descriptor is too high, garbage collect FDs */
  if(pclient->use_fd_cache
     && (pentry_file->object.file.open_fd.fileno > pclient->max_fd))
    {
      if(cache_inode_gc_fd(pclient, pstatus) != CACHE_INODE_SUCCESS)
        {
          LogCrit(COMPONENT_CACHE_INODE_GC,
                  "FAILURE performing FD garbage collection");
          return *pstatus;
        }
    }

  *pstatus = CACHE_INODE_SUCCESS;
  return *pstatus;

}                               /* cache_inode_open_by_name */
cache_inode_status_t cache_inode_open(cache_entry_t * pentry,
                                      cache_inode_client_t * pclient,
                                      fsal_openflags_t openflags,
                                      fsal_op_context_t * pcontext,
                                      cache_inode_status_t * pstatus)
{
  fsal_status_t fsal_status;

  if((pentry == NULL) || (pclient == NULL) || (pcontext == NULL) || (pstatus == NULL))
    return CACHE_INODE_INVALID_ARGUMENT;

  if(pentry->internal_md.type != REGULAR_FILE)
    {
      *pstatus = CACHE_INODE_BAD_TYPE;
      return *pstatus;
    }

  /* Open file need to be closed, unless it is already open as read/write */
  if((pentry->object.file.open_fd.openflags != FSAL_O_RDWR) &&
     (pentry->object.file.open_fd.openflags != 0) &&
     (pentry->object.file.open_fd.fileno != 0) &&
     (pentry->object.file.open_fd.openflags != openflags))
    {
#ifdef _USE_MFSL
      fsal_status = MFSL_close(&(pentry->object.file.open_fd.mfsl_fd), &pclient->mfsl_context, NULL);
#else
      fsal_status = FSAL_close(&(pentry->object.file.open_fd.fd));
#endif
      if(FSAL_IS_ERROR(fsal_status) && (fsal_status.major != ERR_FSAL_NOT_OPENED))
        {
          *pstatus = cache_inode_error_convert(fsal_status);

          LogDebug(COMPONENT_CACHE_INODE,
                   "cache_inode_open: returning %d(%s) from FSAL_close",
                   *pstatus, cache_inode_err_str(*pstatus));

          return *pstatus;
        }

      /* force re-openning */
      pentry->object.file.open_fd.last_op = 0;
      pentry->object.file.open_fd.fileno = 0;

    }

  if((pentry->object.file.open_fd.last_op == 0)
     || (pentry->object.file.open_fd.fileno == 0))
    {
      /* opened file is not preserved yet */
#ifdef _USE_MFSL
      fsal_status = MFSL_open(&(pentry->mobject),
                              pcontext,
                              &pclient->mfsl_context,
                              openflags,
                              &pentry->object.file.open_fd.mfsl_fd,
                              &(pentry->object.file.attributes),
                              NULL );
#else
      fsal_status = FSAL_open(&(pentry->object.file.handle),
                              pcontext,
                              openflags,
                              &pentry->object.file.open_fd.fd,
                              &(pentry->object.file.attributes));
#endif

      if(FSAL_IS_ERROR(fsal_status))
        {
          *pstatus = cache_inode_error_convert(fsal_status);

          LogDebug(COMPONENT_CACHE_INODE,
                   "cache_inode_open: returning %d(%s) from FSAL_open",
                   *pstatus, cache_inode_err_str(*pstatus));

          return *pstatus;
        }

#ifdef _USE_MFSL
      pentry->object.file.open_fd.fileno = FSAL_FILENO(&(pentry->object.file.open_fd.mfsl_fd.fsal_file));
#else
      pentry->object.file.open_fd.fileno = FSAL_FILENO(&(pentry->object.file.open_fd.fd));
#endif
      pentry->object.file.open_fd.openflags = openflags;

      LogDebug(COMPONENT_CACHE_INODE,
               "cache_inode_open: pentry %p: lastop=0, fileno = %d, openflags = %d",
               pentry, pentry->object.file.open_fd.fileno, (int) openflags);
    }

  /* regular exit */
  pentry->object.file.open_fd.last_op = time(NULL);

  /* if file descriptor is too high, garbage collect FDs */
  if(pclient->use_fd_cache
     && (pentry->object.file.open_fd.fileno > pclient->max_fd))
    {
      if(cache_inode_gc_fd(pclient, pstatus) != CACHE_INODE_SUCCESS)
        {
          LogCrit(COMPONENT_CACHE_INODE_GC,
                  "FAILURE performing FD garbage collection");
          return *pstatus;
        }
    }

  *pstatus = CACHE_INODE_SUCCESS;
  return *pstatus;

}                               /* cache_inode_open */
Example #7
0
fsal_status_t PROXYFSAL_rcp_by_fileid(proxyfsal_handle_t * filehandle,  /* IN */
                                      fsal_u64_t fileid,        /* IN */
                                      proxyfsal_op_context_t * p_context,       /* IN */
                                      fsal_path_t * p_local_path,       /* IN */
                                      fsal_rcpflag_t transfer_opt       /* IN */
    )
{

  int local_fd;
  int local_flags;

  proxyfsal_file_t fs_fd;
  fsal_openflags_t fs_flags;

  fsal_status_t st = FSAL_STATUS_NO_ERROR;

/* >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
 * This is a template implementation of rcp based on FSAL_read and FSAL_write
 * function. You may chose keeping it or doing your own implementation
 * that is optimal for your filesystems.
 * <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
 */

  caddr_t IObuffer;

  int to_local = FALSE;
  int to_fs = FALSE;

  int eof = FALSE;

  ssize_t local_size;
  fsal_size_t fs_size;

  /* sanity checks. */

  if(!filehandle || !p_context || !p_local_path)
    Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_rcp);

  to_local = ((transfer_opt & FSAL_RCP_FS_TO_LOCAL) == FSAL_RCP_FS_TO_LOCAL);
  to_fs = ((transfer_opt & FSAL_RCP_LOCAL_TO_FS) == FSAL_RCP_LOCAL_TO_FS);

  if(to_local)
    LogFullDebug(COMPONENT_FSAL,
                      "FSAL_rcp: FSAL -> local file (%s)", p_local_path->path);

  if(to_fs)
    LogFullDebug(COMPONENT_FSAL,
                      "FSAL_rcp: local file -> FSAL (%s)", p_local_path->path);

  /* must give the sens of transfert (exactly one) */

  if((!to_local && !to_fs) || (to_local && to_fs))
    Return(ERR_FSAL_INVAL, 0, INDEX_FSAL_rcp);

  /* first, open local file with the correct flags */

  if(to_fs)
    {
      local_flags = O_RDONLY;
    }
  else
    {
      local_flags = O_WRONLY | O_TRUNC;

      if((transfer_opt & FSAL_RCP_LOCAL_CREAT) == FSAL_RCP_LOCAL_CREAT)
        local_flags |= O_CREAT;

      if((transfer_opt & FSAL_RCP_LOCAL_EXCL) == FSAL_RCP_LOCAL_EXCL)
        local_flags |= O_EXCL;

    }

  if(isFullDebug(COMPONENT_FSAL))
    {
      char msg[1024];

      msg[0] = '\0';

      if((local_flags & O_RDONLY) == O_RDONLY)
        strcat(msg, "O_RDONLY ");

      if((local_flags & O_WRONLY) == O_WRONLY)
        strcat(msg, "O_WRONLY ");

      if((local_flags & O_TRUNC) == O_TRUNC)
        strcat(msg, "O_TRUNC ");

      if((local_flags & O_CREAT) == O_CREAT)
        strcat(msg, "O_CREAT ");

      if((local_flags & O_EXCL) == O_EXCL)
        strcat(msg, "O_EXCL ");

      LogFullDebug(COMPONENT_FSAL, "Openning local file %s with flags: %s",
                        p_local_path->path, msg);
    }

  local_fd = open(p_local_path->path, local_flags, 0644);

  if(local_fd == -1)
    {
    /** @todo : put a function in fsal_convert.c that convert your local
     * filesystem errors to an FSAL error code.
     * So you will have a call like :
     * Return( unix2fsal_error(errno) , errno , INDEX_FSAL_rcp );
     */

      Return(ERR_FSAL_SERVERFAULT, errno, INDEX_FSAL_rcp);
    }

  /* call FSAL_open with the correct flags */

  if(to_fs)
    {
      fs_flags = FSAL_O_WRONLY | FSAL_O_TRUNC;

      /* invalid flags for local to filesystem */

      if(((transfer_opt & FSAL_RCP_LOCAL_CREAT) == FSAL_RCP_LOCAL_CREAT)
         || ((transfer_opt & FSAL_RCP_LOCAL_EXCL) == FSAL_RCP_LOCAL_EXCL))
        {
          /* clean & return */
          close(local_fd);
          Return(ERR_FSAL_INVAL, 0, INDEX_FSAL_rcp);
        }
    }
  else
    {
      fs_flags = FSAL_O_RDONLY;
    }

  if(isFullDebug(COMPONENT_FSAL))
    {
      char msg[1024];

      msg[0] = '\0';

      if((fs_flags & FSAL_O_RDONLY) == FSAL_O_RDONLY)
        strcat(msg, "FSAL_O_RDONLY ");

      if((fs_flags & FSAL_O_WRONLY) == FSAL_O_WRONLY)
        strcat(msg, "FSAL_O_WRONLY ");

      if((fs_flags & FSAL_O_TRUNC) == FSAL_O_TRUNC)
        strcat(msg, "FSAL_O_TRUNC ");

      LogFullDebug(COMPONENT_FSAL, "Openning FSAL file with flags: %s", msg);
    }

  st = FSAL_open_by_fileid(filehandle, fileid, p_context, fs_flags, &fs_fd, NULL);

  if(FSAL_IS_ERROR(st))
    {
      /* clean & return */
      close(local_fd);
      Return(st.major, st.minor, INDEX_FSAL_rcp);
    }
  LogFullDebug(COMPONENT_FSAL,
               "Allocating IO buffer of size %llu",
               (unsigned long long)RCP_BUFFER_SIZE);

  /* Allocates buffer */

  IObuffer = (caddr_t) Mem_Alloc(RCP_BUFFER_SIZE);

  if(IObuffer == NULL)
    {
      /* clean & return */
      close(local_fd);
      FSAL_close(&fs_fd);
      Return(ERR_FSAL_NOMEM, Mem_Errno, INDEX_FSAL_rcp);
    }

  /* read/write loop */

  while(!eof)
    {
      /* initialize error code */
      st = FSAL_STATUS_NO_ERROR;

      LogFullDebug(COMPONENT_FSAL, "Read a block from source");

      /* read */

      if(to_fs)                 /* from local filesystem */
        {
          local_size = read(local_fd, IObuffer, RCP_BUFFER_SIZE);

          if(local_size == -1)
            {
              st.major = ERR_FSAL_IO;
              st.minor = errno;
              break;            /* exit loop */
            }

          eof = (local_size == 0);

        }
      else                      /* from FSAL filesystem */
        {
          fs_size = 0;
          st = FSAL_read(&fs_fd, NULL, RCP_BUFFER_SIZE, IObuffer, &fs_size, &eof);

          if(FSAL_IS_ERROR(st))
            break;              /* exit loop */

        }

      /* write (if not eof) */

      if(!eof || ((!to_fs) && (fs_size > 0)))
        {

          LogFullDebug(COMPONENT_FSAL, "Write a block to destination");

          if(to_fs)             /* to FSAL filesystem */
            {

              st = FSAL_write(&fs_fd, NULL, local_size, IObuffer, &fs_size);

              if(FSAL_IS_ERROR(st))
                break;          /* exit loop */

            }
          else                  /* to local filesystem */
            {

              local_size = write(local_fd, IObuffer, fs_size);

              if(local_size == -1)
                {
                  st.major = ERR_FSAL_IO;
                  st.minor = errno;
                  break;        /* exit loop */
                }

            }                   /* if to_fs */

        }                       /* if eof */
      else
        LogFullDebug(COMPONENT_FSAL, "End of source file reached");

    }                           /* while !eof */

  /* Clean */

  Mem_Free(IObuffer);
  close(local_fd);
  FSAL_close_by_fileid(&fs_fd, fileid);

  /* return status. */

  Return(st.major, st.minor, INDEX_FSAL_rcp);

}                               /* FSAL_rcp_by_name */
cache_inode_status_t cache_inode_open_by_name(cache_entry_t * pentry_dir,
                                              fsal_name_t * pname,
                                              cache_entry_t * pentry_file,
                                              cache_inode_client_t * pclient,
                                              fsal_openflags_t openflags,
                                              fsal_op_context_t * pcontext,
                                              cache_inode_status_t * pstatus)
{
  fsal_status_t fsal_status;
  fsal_size_t save_filesize = 0;
  fsal_size_t save_spaceused = 0;
  fsal_time_t save_mtime = {
    .seconds = 0,
    .nseconds = 0
  };

  if((pentry_dir == NULL) || (pname == NULL) || (pentry_file == NULL) ||
     (pclient == NULL) || (pcontext == NULL) || (pstatus == NULL))
    return CACHE_INODE_INVALID_ARGUMENT;

  if((pentry_dir->internal_md.type != DIRECTORY))
    {
      *pstatus = CACHE_INODE_BAD_TYPE;
      return *pstatus;
    }

  if(pentry_file->internal_md.type != REGULAR_FILE)
    {
      *pstatus = CACHE_INODE_BAD_TYPE;
      return *pstatus;
    }

  /* Open file need to be closed, unless it is already open as read/write */
  if((pentry_file->object.file.open_fd.openflags != FSAL_O_RDWR) &&
     (pentry_file->object.file.open_fd.openflags != 0) &&
     (pentry_file->object.file.open_fd.fileno != 0) &&
     (pentry_file->object.file.open_fd.openflags != openflags))
    {
#ifdef _USE_MFSL
      fsal_status =
          MFSL_close(&(pentry_file->object.file.open_fd.mfsl_fd), &pclient->mfsl_context, NULL);
#else
      fsal_status = FSAL_close(&(pentry_file->object.file.open_fd.fd));
#endif
      if(FSAL_IS_ERROR(fsal_status) && (fsal_status.major != ERR_FSAL_NOT_OPENED))
        {
          *pstatus = cache_inode_error_convert(fsal_status);

          LogDebug(COMPONENT_CACHE_INODE,
                   "cache_inode_open_by_name: returning %d(%s) from FSAL_close",
                   *pstatus, cache_inode_err_str(*pstatus));

          return *pstatus;
        }

      pentry_file->object.file.open_fd.last_op = 0;
      pentry_file->object.file.open_fd.fileno = 0;
    }

  if(pentry_file->object.file.open_fd.last_op == 0
     || pentry_file->object.file.open_fd.fileno == 0)
    {
      LogFullDebug(COMPONENT_FSAL,
               "cache_inode_open_by_name: pentry %p: lastop=0", pentry_file);

      /* Keep coherency with the cache_content */
      if(pentry_file->object.file.pentry_content != NULL)
        {
          save_filesize = pentry_file->attributes.filesize;
          save_spaceused = pentry_file->attributes.spaceused;
          save_mtime = pentry_file->attributes.mtime;
        }

      /* opened file is not preserved yet */
#ifdef _USE_MFSL
      fsal_status = MFSL_open_by_name(&(pentry_dir->mobject),
                                      pname,
                                      pcontext,
                                      &pclient->mfsl_context,
                                      openflags,
                                      &pentry_file->object.file.open_fd.mfsl_fd,
                                      &(pentry_file->attributes),
                                      NULL );

#else
      fsal_status = FSAL_open_by_name(&(pentry_dir->handle),
                                      pname,
                                      pcontext,
                                      openflags,
                                      &pentry_file->object.file.open_fd.fd,
                                      &(pentry_file->attributes));
#endif

      if(FSAL_IS_ERROR(fsal_status))
        {
          *pstatus = cache_inode_error_convert(fsal_status);

          LogDebug(COMPONENT_CACHE_INODE,
                   "cache_inode_open_by_name: returning %d(%s) from FSAL_open_by_name",
                   *pstatus, cache_inode_err_str(*pstatus));

          return *pstatus;
        }

#ifdef _USE_PROXY

      /* If proxy if used, we should keep the name of the file to do FSAL_rcp if needed */
      if((pentry_file->object.file.pname =
          (fsal_name_t *) Mem_Alloc_Label(sizeof(fsal_name_t), "fsal_name_t")) == NULL)
        {
          *pstatus = CACHE_INODE_MALLOC_ERROR;

          return *pstatus;
        }

      pentry_file->object.file.pentry_parent_open = pentry_dir;
      pentry_file->object.file.pname->len = pname->len;
      memcpy((char *)(pentry_file->object.file.pname->name), (char *)(pname->name),
             FSAL_MAX_NAME_LEN);

#endif

      /* Keep coherency with the cache_content */
      if(pentry_file->object.file.pentry_content != NULL)
        {
          pentry_file->attributes.filesize = save_filesize;
          pentry_file->attributes.spaceused = save_spaceused;
          pentry_file->attributes.mtime = save_mtime;
        }

#ifdef _USE_MFSL
      pentry_file->object.file.open_fd.fileno =
          (int)FSAL_FILENO(&(pentry_file->object.file.open_fd.mfsl_fd.fsal_file));
#else
      pentry_file->object.file.open_fd.fileno =
          (int)FSAL_FILENO(&(pentry_file->object.file.open_fd.fd));
#endif
      pentry_file->object.file.open_fd.last_op = time(NULL);
      pentry_file->object.file.open_fd.openflags = openflags;

      LogFullDebug(COMPONENT_FSAL,
               "cache_inode_open_by_name: pentry %p: fd=%u",
               pentry_file, pentry_file->object.file.open_fd.fileno);

    }

  /* regular exit */
  pentry_file->object.file.open_fd.last_op = time(NULL);

  /* if file descriptor is too high, garbage collect FDs */
  if(pclient->use_fd_cache
     && (pentry_file->object.file.open_fd.fileno > pclient->max_fd))
    {
      if(cache_inode_gc_fd(pclient, pstatus) != CACHE_INODE_SUCCESS)
        {
          LogCrit(COMPONENT_CACHE_INODE_GC,
                  "FAILURE performing FD garbage collection");
          return *pstatus;
        }
    }

  *pstatus = CACHE_INODE_SUCCESS;
  return *pstatus;

}                               /* cache_inode_open_by_name */

/**
 *
 * cache_inode_close: closes the local fd in the FSAL.
 *
 * Closes the local fd in the FSAL.
 *
 * No lock management is done in this layer: the related pentry in the cache inode layer is
 * locked and will prevent from concurent accesses.
 *
 * @param pentry  [IN] entry in file content layer whose content is to be accessed.
 * @param pclient [IN]  ressource allocated by the client for the nfs management.
 * @pstatus       [OUT] returned status.
 *
 * @return CACHE_CONTENT_SUCCESS is successful .
 *
 */
cache_inode_status_t cache_inode_close(cache_entry_t * pentry,
                                       cache_inode_client_t * pclient,
                                       cache_inode_status_t * pstatus)
{
  fsal_status_t fsal_status;

  if((pentry == NULL) || (pclient == NULL) || (pstatus == NULL))
    return CACHE_CONTENT_INVALID_ARGUMENT;

  if(pentry->internal_md.type != REGULAR_FILE)
    {
      *pstatus = CACHE_INODE_BAD_TYPE;
      return *pstatus;
    }

  /* if nothing is opened, do nothing */
  if(pentry->object.file.open_fd.fileno < 0)
    {
      *pstatus = CACHE_INODE_SUCCESS;
      return *pstatus;
    }

  /* if locks are held in the file, do not close */
  if( cache_inode_file_holds_state( pentry ) )
    {
      *pstatus = CACHE_INODE_SUCCESS; /** @todo : PhD : May be CACHE_INODE_STATE_CONFLICTS would be better ? */
      return *pstatus;
    }

  if((pclient->use_fd_cache == 0) ||
     (time(NULL) - pentry->object.file.open_fd.last_op > pclient->retention) ||
     (pentry->object.file.open_fd.fileno > (int)(pclient->max_fd)))
    {

      LogFullDebug(COMPONENT_CACHE_INODE,
               "cache_inode_close: pentry %p, fileno = %d, lastop=%d ago",
               pentry, pentry->object.file.open_fd.fileno,
               (int)(time(NULL) - pentry->object.file.open_fd.last_op));

#ifdef _USE_MFSL
      fsal_status = MFSL_close(&(pentry->object.file.open_fd.mfsl_fd), &pclient->mfsl_context, NULL);
#else
      fsal_status = FSAL_close(&(pentry->object.file.open_fd.fd));
#endif

      pentry->object.file.open_fd.fileno = 0;
      pentry->object.file.open_fd.last_op = 0;

      if(FSAL_IS_ERROR(fsal_status) && (fsal_status.major != ERR_FSAL_NOT_OPENED))
        {
          *pstatus = cache_inode_error_convert(fsal_status);

          LogDebug(COMPONENT_CACHE_INODE,
                   "cache_inode_close: returning %d(%s) from FSAL_close",
                   *pstatus, cache_inode_err_str(*pstatus));

          return *pstatus;
        }
    }
#ifdef _USE_PROXY
  /* If proxy if used, free the name if needed */
  if(pentry->object.file.pname != NULL)
    {
      Mem_Free((char *)(pentry->object.file.pname));
      pentry->object.file.pname = NULL;
    }
  pentry->object.file.pentry_parent_open = NULL;
#endif

  *pstatus = CACHE_CONTENT_SUCCESS;

  return *pstatus;
}                               /* cache_content_close */
fsal_status_t MFSL_close(fsal_file_t * file_descriptor, /* IN */
                         mfsl_context_t * p_mfsl_context        /* IN */
    )
{
  return FSAL_close(file_descriptor);
}                               /* MFSL_close */
Example #10
0
fsal_status_t GPFSFSAL_rcp(fsal_handle_t * filehandle,      /* IN */
                           fsal_op_context_t * p_context,   /* IN */
                           fsal_path_t * p_local_path,      /* IN */
                           fsal_rcpflag_t transfer_opt      /* IN */
                          )
{

    int local_fd;
    int local_flags;
    int errsv;

    fsal_file_t fs_fd;
    fsal_openflags_t fs_flags;

    fsal_status_t st = FSAL_STATUS_NO_ERROR;

    /* default buffer size for RCP: 10MB */
#define RCP_BUFFER_SIZE 10485760
    caddr_t IObuffer;

    int to_local = FALSE;
    int to_fs = FALSE;

    int eof = FALSE;

    ssize_t local_size;
    fsal_size_t fs_size;

    /* sanity checks. */

    if(!filehandle || !p_context || !p_local_path)
        Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_rcp);

    to_local = ((transfer_opt & FSAL_RCP_FS_TO_LOCAL) == FSAL_RCP_FS_TO_LOCAL);
    to_fs = ((transfer_opt & FSAL_RCP_LOCAL_TO_FS) == FSAL_RCP_LOCAL_TO_FS);

    if(to_local)
        LogFullDebug(COMPONENT_FSAL,
                     "FSAL_rcp: FSAL -> local file (%s)", p_local_path->path);

    if(to_fs)
        LogFullDebug(COMPONENT_FSAL,
                     "FSAL_rcp: local file -> FSAL (%s)", p_local_path->path);

    /* must give the sens of transfert (exactly one) */

    if((!to_local && !to_fs) || (to_local && to_fs))
        Return(ERR_FSAL_INVAL, 0, INDEX_FSAL_rcp);

    /* first, open local file with the correct flags */

    if(to_fs)
    {
        local_flags = O_RDONLY;
    }
    else
    {
        local_flags = O_WRONLY | O_TRUNC;

        if((transfer_opt & FSAL_RCP_LOCAL_CREAT) == FSAL_RCP_LOCAL_CREAT)
            local_flags |= O_CREAT;

        if((transfer_opt & FSAL_RCP_LOCAL_EXCL) == FSAL_RCP_LOCAL_EXCL)
            local_flags |= O_EXCL;

    }

    if(isFullDebug(COMPONENT_FSAL))
    {
        char msg[1024];

        msg[0] = '\0';

        if((local_flags & O_RDONLY) == O_RDONLY)
            strcat(msg, "O_RDONLY ");

        if((local_flags & O_WRONLY) == O_WRONLY)
            strcat(msg, "O_WRONLY ");

        if((local_flags & O_TRUNC) == O_TRUNC)
            strcat(msg, "O_TRUNC ");

        if((local_flags & O_CREAT) == O_CREAT)
            strcat(msg, "O_CREAT ");

        if((local_flags & O_EXCL) == O_EXCL)
            strcat(msg, "O_EXCL ");

        LogFullDebug(COMPONENT_FSAL, "Openning local file %s with flags: %s",
                     p_local_path->path, msg);
    }

    local_fd = open(p_local_path->path, local_flags);
    errsv = errno;

    if(local_fd == -1)
    {
        Return(posix2fsal_error(errsv), errsv, INDEX_FSAL_rcp);
    }

    /* call FSAL_open with the correct flags */

    if(to_fs)
    {
        fs_flags = FSAL_O_WRONLY | FSAL_O_TRUNC;

        /* invalid flags for local to filesystem */

        if(((transfer_opt & FSAL_RCP_LOCAL_CREAT) == FSAL_RCP_LOCAL_CREAT)
                || ((transfer_opt & FSAL_RCP_LOCAL_EXCL) == FSAL_RCP_LOCAL_EXCL))
        {
            /* clean & return */
            close(local_fd);
            Return(ERR_FSAL_INVAL, 0, INDEX_FSAL_rcp);
        }
    }
    else
    {
        fs_flags = FSAL_O_RDONLY;
    }

    if(isFullDebug(COMPONENT_FSAL))
    {
        char msg[1024];

        msg[0] = '\0';

        if((fs_flags & FSAL_O_RDONLY) == FSAL_O_RDONLY)
            strcat(msg, "FSAL_O_RDONLY ");

        if((fs_flags & FSAL_O_WRONLY) == FSAL_O_WRONLY)
            strcat(msg, "FSAL_O_WRONLY ");

        if((fs_flags & FSAL_O_TRUNC) == FSAL_O_TRUNC)
            strcat(msg, "FSAL_O_TRUNC ");

        LogFullDebug(COMPONENT_FSAL, "Openning FSAL file with flags: %s", msg);
    }


    st = FSAL_open(filehandle, p_context, fs_flags, &fs_fd, NULL);

    if(FSAL_IS_ERROR(st))
    {
        /* clean & return */
        close(local_fd);
        Return(st.major, st.minor, INDEX_FSAL_rcp);
    }
    LogFullDebug(COMPONENT_FSAL,
                 "Allocating IO buffer of size %llu",
                 (unsigned long long)RCP_BUFFER_SIZE);

    /* Allocates buffer */

    IObuffer = gsh_malloc(RCP_BUFFER_SIZE);

    if(IObuffer == NULL)
    {
        /* clean & return */
        close(local_fd);
        FSAL_close(&fs_fd, p_context);
        Return(ERR_FSAL_NOMEM, ENOMEM, INDEX_FSAL_rcp);
    }

    /* read/write loop */

    while(!eof)
    {
        /* initialize error code */
        st = FSAL_STATUS_NO_ERROR;

        LogFullDebug(COMPONENT_FSAL, "Read a block from source");

        /* read */

        if(to_fs)                 /* from local filesystem */
        {
            LogFullDebug(COMPONENT_FSAL,
                         "Read a block from local file system");
            local_size = read(local_fd, IObuffer, RCP_BUFFER_SIZE);

            if(local_size == -1)
            {
                st.major = ERR_FSAL_IO;
                st.minor = errno;
                break;            /* exit loop */
            }

            eof = (local_size == 0);
            if(!eof)
            {
                LogFullDebug(COMPONENT_FSAL,
                             "Write a block (%llu bytes) to FSAL",
                             (unsigned long long)local_size);

                st = FSAL_write(&fs_fd, p_context, NULL, local_size, IObuffer, &fs_size);
                if(FSAL_IS_ERROR(st))
                {
                    LogFullDebug(COMPONENT_FSAL,
                                 "Error writing to FSAL");
                    break;          /* exit loop */
                }
            }
            else
            {
                LogFullDebug(COMPONENT_FSAL,
                             "End of file on local file system");
            }
        }
        else                      /* from FSAL filesystem */
        {
            LogFullDebug(COMPONENT_FSAL,
                         "Read a block from FSAL");
            fs_size = 0;
            st = FSAL_read(&fs_fd, p_context, NULL, RCP_BUFFER_SIZE, IObuffer, &fs_size, &eof);

            if(FSAL_IS_ERROR(st))
                break;              /* exit loop */

            if(fs_size > 0)
            {
                LogFullDebug(COMPONENT_FSAL,
                             "Write a block (%llu bytes) to local file system",
                             (unsigned long long)fs_size);

                local_size = write(local_fd, IObuffer, fs_size);

                if(local_size == -1)
                {
                    st.major = ERR_FSAL_IO;
                    st.minor = errno;
                    break;        /* exit loop */
                }
            }
            else
            {
                LogFullDebug(COMPONENT_FSAL,
                             "End of file on FSAL");
                break;
            }

            LogFullDebug(COMPONENT_FSAL, "Size read from source: %llu",
                         (unsigned long long)fs_size);
        }
    }                           /* while !eof */

    /* Clean */

    gsh_free(IObuffer);
    close(local_fd);
    FSAL_close(&fs_fd, p_context);

    /* return status. */

    Return(st.major, st.minor, INDEX_FSAL_rcp);

}
Example #11
0
/**
 * FSAL_create:
 * Create a regular file.
 *
 * \param parent_directory_handle (input):
 *        Handle of the parent directory where the file is to be created.
 * \param p_filename (input):
 *        Pointer to the name of the file to be created.
 * \param cred (input):
 *        Authentication context for the operation (user, export...).
 * \param accessmode (input):
 *        Mode for the file to be created.
 *        (the umask defined into the FSAL configuration file
 *        will be applied on it).
 * \param object_handle (output):
 *        Pointer to the handle of the created file.
 * \param object_attributes (optionnal input/output): 
 *        The postop attributes of the created file.
 *        As input, it defines the attributes that the caller
 *        wants to retrieve (by positioning flags into this structure)
 *        and the output is built considering this input
 *        (it fills the structure according to the flags it contains).
 *        Can be NULL.
 *
 * \return Major error codes :
 *        - ERR_FSAL_NO_ERROR     (no error)
 *        - ERR_FSAL_STALE        (parent_directory_handle does not address an existing object)
 *        - ERR_FSAL_FAULT        (a NULL pointer was passed as mandatory argument)
 *        - Other error codes can be returned :
 *          ERR_FSAL_ACCESS, ERR_FSAL_EXIST, ERR_FSAL_IO, ...
 *            
 *        NB: if getting postop attributes failed,
 *        the function does not return an error
 *        but the FSAL_ATTR_RDATTR_ERR bit is set in
 *        the object_attributes->asked_attributes field.
 */
fsal_status_t PROXYFSAL_create(proxyfsal_handle_t * parent_directory_handle,    /* IN */
                               fsal_name_t * p_filename,        /* IN */
                               proxyfsal_op_context_t * p_context,      /* IN */
                               fsal_accessmode_t accessmode,    /* IN */
                               proxyfsal_handle_t * object_handle,      /* OUT */
                               fsal_attrib_list_t * object_attributes   /* [ IN/OUT ] */
    )
{
  int rc;
  COMPOUND4args argnfs4;
  COMPOUND4res resnfs4;
  nfs_fh4 nfs4fh;
  bitmap4 bitmap;
  uint32_t bitmap_val[2];
  uint32_t bitmap_res[2];
  uint32_t bitmap_conv_val[2];
  uint32_t bitmap_create[2];
  uint32_t bitmap_getattr_res[2];
  fattr4 input_attr;
  bitmap4 convert_bitmap;
  component4 name;
  char nameval[MAXNAMLEN];
  char padfilehandle[FSAL_PROXY_FILEHANDLE_MAX_LEN];
  fsal_status_t fsal_status;
  proxyfsal_file_t fd;

#define FSAL_CREATE_NB_OP_ALLOC 4
#define FSAL_CREATE_VAL_BUFFER  1024

  fsal_proxy_internal_fattr_t fattr_internal;
  fsal_attrib_list_t create_mode_attr;
  fsal_attrib_list_t attributes;
  nfs_argop4 argoparray[FSAL_CREATE_NB_OP_ALLOC];
  nfs_resop4 resoparray[FSAL_CREATE_NB_OP_ALLOC];
  char fattr_val[FSAL_CREATE_VAL_BUFFER];
  struct timeval timeout = { 25, 0 };
  char owner_val[FSAL_PROXY_OWNER_LEN];
  unsigned int owner_len = 0;

  /* sanity checks.
   * note : object_attributes is optional.
   */
  if(!parent_directory_handle || !p_context || !object_handle || !p_filename)
    Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_create);

  PRINT_HANDLE("FSAL_create", parent_directory_handle);

  /* Create the owner */
  snprintf(owner_val, FSAL_PROXY_OWNER_LEN, "GANESHA/PROXY: pid=%u ctx=%p file=%llu",
           getpid(), p_context, (unsigned long long int)p_context->file_counter);
  owner_len = strnlen(owner_val, FSAL_PROXY_OWNER_LEN);
  p_context->file_counter += 1;

  /* Setup results structures */
  argnfs4.argarray.argarray_val = argoparray;
  resnfs4.resarray.resarray_val = resoparray;
  argnfs4.minorversion = 0;
  /* argnfs4.tag.utf8string_val = "GANESHA NFSv4 Proxy: Mkdir" ; */
  argnfs4.tag.utf8string_val = NULL;
  argnfs4.tag.utf8string_len = 0;
  argnfs4.argarray.argarray_len = 0;

  input_attr.attrmask.bitmap4_val = bitmap_val;
  input_attr.attrmask.bitmap4_len = 2;

  input_attr.attr_vals.attrlist4_val = fattr_val;
  input_attr.attr_vals.attrlist4_len = FSAL_CREATE_VAL_BUFFER;

  fsal_internal_proxy_setup_fattr(&fattr_internal);

  convert_bitmap.bitmap4_val = bitmap_conv_val;
  convert_bitmap.bitmap4_len = 2;

  memset((char *)&name, 0, sizeof(component4));
  name.utf8string_val = nameval;
  if(fsal_internal_proxy_fsal_name_2_utf8(p_filename, &name) == FALSE)
    Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_create);

  /* Get NFSv4 File handle */
  if(fsal_internal_proxy_extract_fh(&nfs4fh, parent_directory_handle) == FALSE)
    Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_create);

  if(isFullDebug(COMPONENT_FSAL))
    {
      char outstr[1024];

      nfs4_sprint_fhandle(&nfs4fh, outstr);
      LogFullDebug(COMPONENT_FSAL, "FSAL_CREATE: extracted server (as client) parent handle=%s\n",
                   outstr);
    }

  bitmap.bitmap4_val = bitmap_create;
  bitmap.bitmap4_len = 2;
  fsal_internal_proxy_create_fattr_bitmap(&bitmap);

  create_mode_attr.asked_attributes = FSAL_ATTR_MODE;
  create_mode_attr.mode = accessmode;
  fsal_interval_proxy_fsalattr2bitmap4(&create_mode_attr, &convert_bitmap);

  if(nfs4_FSALattr_To_Fattr(NULL,       /* no exportlist required here */
                            &create_mode_attr, &input_attr, NULL,       /* no compound data required here */
                            NULL,       /* No fh here, filehandle is not a settable attribute */
                            &convert_bitmap) == -1)
    Return(ERR_FSAL_INVAL, -1, INDEX_FSAL_create);

#define FSAL_CREATE_IDX_OP_PUTFH       0
#define FSAL_CREATE_IDX_OP_OPEN_CREATE 1
#define FSAL_CREATE_IDX_OP_GETFH       2
#define FSAL_CREATE_IDX_OP_GETATTR     3
  COMPOUNDV4_ARG_ADD_OP_PUTFH(argnfs4, nfs4fh);
  COMPOUNDV4_ARG_ADD_OP_OPEN_CREATE(argnfs4, name, input_attr, p_context->clientid,
                                    owner_val, owner_len);
  COMPOUNDV4_ARG_ADD_OP_GETFH(argnfs4);
  COMPOUNDV4_ARG_ADD_OP_GETATTR(argnfs4, bitmap);

  resnfs4.resarray.resarray_val[FSAL_CREATE_IDX_OP_OPEN_CREATE].nfs_resop4_u.opopen.
      OPEN4res_u.resok4.attrset.bitmap4_val = bitmap_res;
  resnfs4.resarray.resarray_val[FSAL_CREATE_IDX_OP_OPEN_CREATE].nfs_resop4_u.opopen.
      OPEN4res_u.resok4.attrset.bitmap4_len = 2;

  resnfs4.resarray.resarray_val[FSAL_CREATE_IDX_OP_GETFH].nfs_resop4_u.opgetfh.
      GETFH4res_u.resok4.object.nfs_fh4_val = (char *)padfilehandle;
  resnfs4.resarray.resarray_val[FSAL_CREATE_IDX_OP_GETFH].nfs_resop4_u.opgetfh.
      GETFH4res_u.resok4.object.nfs_fh4_len = FSAL_PROXY_FILEHANDLE_MAX_LEN;

  resnfs4.resarray.resarray_val[FSAL_CREATE_IDX_OP_GETATTR].nfs_resop4_u.opgetattr.
      GETATTR4res_u.resok4.obj_attributes.attrmask.bitmap4_val = bitmap_getattr_res;
  resnfs4.resarray.resarray_val[FSAL_CREATE_IDX_OP_GETATTR].nfs_resop4_u.opgetattr.
      GETATTR4res_u.resok4.obj_attributes.attrmask.bitmap4_len = 2;

  resnfs4.resarray.resarray_val[FSAL_CREATE_IDX_OP_GETATTR].nfs_resop4_u.opgetattr.
      GETATTR4res_u.resok4.obj_attributes.attr_vals.attrlist4_val =
      (char *)&fattr_internal;
  resnfs4.resarray.resarray_val[FSAL_CREATE_IDX_OP_GETATTR].nfs_resop4_u.opgetattr.
      GETATTR4res_u.resok4.obj_attributes.attr_vals.attrlist4_len =
      sizeof(fattr_internal);

  TakeTokenFSCall();

  /* Call the NFSv4 function */
  COMPOUNDV4_EXECUTE(p_context, argnfs4, resnfs4, rc);
  if(rc != RPC_SUCCESS)
    {
      ReleaseTokenFSCall();

      Return(ERR_FSAL_IO, rc, INDEX_FSAL_create);
    }

  ReleaseTokenFSCall();

  /* >> convert error code, and return on error << */
  if(resnfs4.status != NFS4_OK)
    return fsal_internal_proxy_error_convert(resnfs4.status, INDEX_FSAL_create);

  /* Use NFSv4 service function to build the FSAL_attr */
  if(nfs4_Fattr_To_FSAL_attr(&attributes,
                             &resnfs4.resarray.resarray_val[FSAL_CREATE_IDX_OP_GETATTR].
                             nfs_resop4_u.opgetattr.GETATTR4res_u.resok4.
                             obj_attributes) != 1)
    {
      FSAL_CLEAR_MASK(attributes.asked_attributes);
      FSAL_SET_MASK(attributes.asked_attributes, FSAL_ATTR_RDATTR_ERR);

      Return(ERR_FSAL_INVAL, 0, INDEX_FSAL_create);

    }

  /* Return attributes if asked */
  if(object_attributes)
    {
      memcpy(object_attributes, &attributes, sizeof(attributes));
    }

  if(isFullDebug(COMPONENT_FSAL))
    {
      char outstr[1024];

      nfs4_sprint_fhandle(&nfs4fh, outstr);
      LogFullDebug(COMPONENT_FSAL, "FSAL_CREATE: extracted server (as client) created file handle=%s\n",
           outstr);
    }

  if(fsal_internal_proxy_create_fh
     (&
      (resnfs4.resarray.resarray_val[FSAL_CREATE_IDX_OP_GETFH].nfs_resop4_u.opgetfh.
       GETFH4res_u.resok4.object), FSAL_TYPE_FILE, attributes.fileid,
      object_handle) == FALSE)
    Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_create);

  /* Keep the information into the file descriptor as well */
  memcpy((char *)&fd.fhandle, (char *)object_handle, sizeof(fd.fhandle));

  fd.openflags = FSAL_O_RDWR;
  fd.current_offset = 0;
  fd.pcontext = p_context;

  /* Keep the returned stateid for later use */
  fd.stateid.seqid =
      resnfs4.resarray.resarray_val[FSAL_CREATE_IDX_OP_OPEN_CREATE].nfs_resop4_u.opopen.
      OPEN4res_u.resok4.stateid.seqid;
  memcpy((char *)fd.stateid.other,
         resnfs4.resarray.resarray_val[FSAL_CREATE_IDX_OP_OPEN_CREATE].nfs_resop4_u.
         opopen.OPEN4res_u.resok4.stateid.other, 12);

  /* See if a OPEN_CONFIRM is required */
  if(resnfs4.resarray.resarray_val[FSAL_CREATE_IDX_OP_OPEN_CREATE].nfs_resop4_u.opopen.
     OPEN4res_u.resok4.rflags & OPEN4_RESULT_CONFIRM)
    {
      fsal_status = FSAL_proxy_open_confirm(&fd);
      if(FSAL_IS_ERROR(fsal_status))
        Return(fsal_status.major, fsal_status.minor, INDEX_FSAL_create);
    }
#ifdef _FSAL_CREATE_CLOSE_FILE
  /* The craeted file is still opened, to preserve the correct seqid for later use, we close it */
  fsal_status = FSAL_close(&fd);
  if(FSAL_IS_ERROR(fsal_status))
    Return(fsal_status.major, fsal_status.minor, INDEX_FSAL_create);
#endif

  /* OK */
  Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_create);
}                               /* FSAL_create */