Beispiel #1
0
int nfs4_op_rename(struct nfs_argop4 *op, compound_data_t * data, struct nfs_resop4 *resp)
{
  char __attribute__ ((__unused__)) funcname[] = "nfs4_op_rename";

  cache_entry_t        * dst_entry = NULL;
  cache_entry_t        * src_entry = NULL;
  cache_entry_t        * tst_entry_dst = NULL;
  cache_entry_t        * tst_entry_src = NULL;
  fsal_attrib_list_t     attr_dst;
  fsal_attrib_list_t     attr_src;
  fsal_attrib_list_t     attr_tst_dst;
  fsal_attrib_list_t     attr_tst_src;
  cache_inode_status_t   cache_status;
  fsal_status_t          fsal_status;
  fsal_handle_t        * handlenew = NULL;
  fsal_handle_t        * handleold = NULL;
  fsal_name_t            oldname;
  fsal_name_t            newname;

  resp->resop = NFS4_OP_RENAME;
  res_RENAME4.status = NFS4_OK;

  /* Do basic checks on a filehandle */
  res_RENAME4.status = nfs4_sanity_check_FH(data, 0LL);
  if(res_RENAME4.status != NFS4_OK)
    return res_RENAME4.status;

  /* Do basic checks on saved filehandle */

  /* If there is no FH */
  if(nfs4_Is_Fh_Empty(&(data->savedFH)))
    {
      res_RENAME4.status = NFS4ERR_NOFILEHANDLE;
      return res_RENAME4.status;
    }

  /* If the filehandle is invalid */
  if(nfs4_Is_Fh_Invalid(&(data->savedFH)))
    {
      res_RENAME4.status = NFS4ERR_BADHANDLE;
      return res_RENAME4.status;
    }

  /* Tests if the Filehandle is expired (for volatile filehandle) */
  if(nfs4_Is_Fh_Expired(&(data->savedFH)))
    {
      res_RENAME4.status = NFS4ERR_FHEXPIRED;
      return res_RENAME4.status;
    }

  /* Pseudo Fs is explictely a Read-Only File system */
  if(nfs4_Is_Fh_Pseudo(&(data->savedFH)))
    {
      res_RENAME4.status = NFS4ERR_ROFS;
      return res_RENAME4.status;
    }

  if (nfs_in_grace())
    {
      res_RENAME4.status = NFS4ERR_GRACE;
      return res_RENAME4.status;
    }

  /* get the names from the RPC input */
  cache_status = utf8_to_name(&arg_RENAME4.oldname, &oldname);

  if(cache_status != CACHE_INODE_SUCCESS)
    {
      res_RENAME4.status = nfs4_Errno(cache_status);
      return res_RENAME4.status;
    }

  cache_status = utf8_to_name(&arg_RENAME4.newname, &newname);

  if(cache_status != CACHE_INODE_SUCCESS)
    {
      res_RENAME4.status = nfs4_Errno(cache_status);
      return res_RENAME4.status;
    }

  /* Sanuty check: never rename to '.' or '..' */
  if(!FSAL_namecmp(&newname, (fsal_name_t *) & FSAL_DOT)
     || !FSAL_namecmp(&newname, (fsal_name_t *) & FSAL_DOT_DOT))
    {
      res_RENAME4.status = NFS4ERR_BADNAME;
      return res_RENAME4.status;
    }

  /* Sanuty check: never rename to '.' or '..' */
  if(!FSAL_namecmp(&oldname, (fsal_name_t *) & FSAL_DOT)
     || !FSAL_namecmp(&oldname, (fsal_name_t *) & FSAL_DOT_DOT))
    {
      res_RENAME4.status = NFS4ERR_BADNAME;
      return res_RENAME4.status;
    }

  /*
   * This operation renames 
   *             - the object in directory pointed by savedFH, named arg_RENAME4.oldname
   *       into
   *             - an object in directory pointed by currentFH, named arg_RENAME4.newname
   *
   * Because of this, we will use 2 entry and we have verified both currentFH and savedFH */

  /* No Cross Device */
  if(((file_handle_v4_t *) (data->currentFH.nfs_fh4_val))->exportid !=
     ((file_handle_v4_t *) (data->savedFH.nfs_fh4_val))->exportid)
    {
      res_RENAME4.status = NFS4ERR_XDEV;
      return res_RENAME4.status;
    }

  /* destination must be a directory */
  dst_entry = data->current_entry;

  if(data->current_filetype != DIRECTORY)
    {
      res_RENAME4.status = NFS4ERR_NOTDIR;
      return res_RENAME4.status;
    }

  /* Convert saved FH into a vnode */
  src_entry = data->saved_entry;

  /* Source must be a directory */
  if(data->saved_filetype != DIRECTORY)
    {
      res_RENAME4.status = NFS4ERR_NOTDIR;
      return res_RENAME4.status;
    }

  /* Renaming a file to himself is allowed, returns NFS4_OK */
  if(src_entry == dst_entry)
    {
      if(!FSAL_namecmp(&oldname, &newname))
        {
          res_RENAME4.status = NFS4_OK;
          return res_RENAME4.status;
        }
    }

  /* For the change_info4, get the 'change' attributes for both directories */
  if((cache_status = cache_inode_getattr(src_entry,
                                         &attr_src,
                                         data->pcontext,
                                         &cache_status)) != CACHE_INODE_SUCCESS)
    {
      res_RENAME4.status = nfs4_Errno(cache_status);
      return res_RENAME4.status;
    }
#ifdef BUGAZOMEU
  /* Ne devrait pas se produire dans le cas de exportid differents */

  /* Both object must resides on the same filesystem, return NFS4ERR_XDEV if not */
  if(attr_src.va_rdev != attr_dst.va_rdev)
    {
      res_RENAME4.status = NFS4ERR_XDEV;
      return res_RENAME4.status;
    }
#endif
  /* Lookup oldfile to see if it exists (refcount +1) */
  if((tst_entry_src = cache_inode_lookup(src_entry,
                                         &oldname,
                                         &attr_tst_src,
                                         data->pcontext,
                                         &cache_status)) == NULL)
    {
      res_RENAME4.status = nfs4_Errno(cache_status);
      goto release;
    }

  /* Lookup file with new name to see if it already exists (refcount +1),
   * I expect to get NO_ERROR or ENOENT, anything else means an error */
  tst_entry_dst = cache_inode_lookup(dst_entry,
                                     &newname,
                                     &attr_tst_dst,
                                     data->pcontext,
                                     &cache_status);
  if((cache_status != CACHE_INODE_SUCCESS) &&
     (cache_status != CACHE_INODE_NOT_FOUND))
    {
        /* Unexpected status at this step, exit with an error */
        res_RENAME4.status = nfs4_Errno(cache_status);
        goto release;
    }

  if(cache_status == CACHE_INODE_NOT_FOUND)
    tst_entry_dst = NULL;       /* Just to make sure */

  /* Renaming a file to one of its own hardlink is allowed, return NFS4_OK */
  if(tst_entry_src == tst_entry_dst) {
      res_RENAME4.status = NFS4_OK;
      goto release;
    }

  /* Renaming dir into existing file should return NFS4ERR_EXIST */
  if ((tst_entry_src->type == DIRECTORY) &&
      ((tst_entry_dst != NULL) &&
       (tst_entry_dst->type == REGULAR_FILE)))
    {
      res_RENAME4.status = NFS4ERR_EXIST;
      goto release;
    }

  /* Renaming file into existing dir should return NFS4ERR_EXIST */
  if(tst_entry_src->type == REGULAR_FILE)
    {
      if(tst_entry_dst != NULL)
        {
          if(tst_entry_dst->type == DIRECTORY)
            {
              res_RENAME4.status = NFS4ERR_EXIST;
              goto release;
            }
        }
    }

  /* Renaming dir1 into existing, nonempty dir2 should return NFS4ERR_EXIST
   * Renaming file into existing, nonempty dir should return NFS4ERR_EXIST */
  if(tst_entry_dst != NULL)
    {
      if((tst_entry_dst->type == DIRECTORY)
         && ((tst_entry_src->type == DIRECTORY)
             || (tst_entry_src->type == REGULAR_FILE)))
        {
          if(cache_inode_is_dir_empty_WithLock(tst_entry_dst) ==
             CACHE_INODE_DIR_NOT_EMPTY)
            {
              res_RENAME4.status = NFS4ERR_EXIST;
              goto release;
            }
        }
    }

  res_RENAME4.RENAME4res_u.resok4.source_cinfo.before
       = cache_inode_get_changeid4(src_entry);
  res_RENAME4.RENAME4res_u.resok4.target_cinfo.before
       = cache_inode_get_changeid4(dst_entry);

  if(cache_status == CACHE_INODE_SUCCESS)
    {
      /* New entry already exists, its attributes are in attr_tst_*,
         check for old entry to see if types are compatible */
      handlenew = &tst_entry_dst->handle;
      handleold = &tst_entry_src->handle;

      if(!FSAL_handlecmp(handlenew, handleold, &fsal_status))
        {
          /* For the change_info4, get the 'change' attributes for both directories */
          res_RENAME4.RENAME4res_u.resok4.source_cinfo.before
            = cache_inode_get_changeid4(src_entry);
          res_RENAME4.RENAME4res_u.resok4.target_cinfo.before
            = cache_inode_get_changeid4(dst_entry);
          res_RENAME4.RENAME4res_u.resok4.target_cinfo.atomic = FALSE;
          res_RENAME4.RENAME4res_u.resok4.source_cinfo.atomic = FALSE;

          res_RENAME4.status = NFS4_OK;
          goto release;
        }
      else
        {
          /* Destination exists and is something different from source */
          if(( tst_entry_src->type == REGULAR_FILE &&
              tst_entry_dst->type == REGULAR_FILE ) ||
              ( tst_entry_src->type == DIRECTORY &&
              tst_entry_dst->type == DIRECTORY ))
            {
              if(cache_inode_rename(src_entry,
                                    &oldname,
                                    dst_entry,
                                    &newname,
                                    &attr_src,
                                    &attr_dst,
                                    data->pcontext, &cache_status) != CACHE_INODE_SUCCESS)
               {

                 res_RENAME4.status = nfs4_Errno(cache_status);
                 goto release;
               }
            }
          else
            { 
              res_RENAME4.status = NFS4ERR_EXIST;
              goto release;
            }
        }
    }
  else
    {
      /* New entry does not already exist, call cache_entry_rename */
      if(cache_inode_rename(src_entry,
                            &oldname,
                            dst_entry,
                            &newname,
                            &attr_src,
                            &attr_dst,
                            data->pcontext, &cache_status) != CACHE_INODE_SUCCESS)
        {
          res_RENAME4.status = nfs4_Errno(cache_status);
          goto release;
        }
    }

  /* If you reach this point, then everything was alright */
  /* For the change_info4, get the 'change' attributes for both directories */

  res_RENAME4.RENAME4res_u.resok4.source_cinfo.after =
       cache_inode_get_changeid4(src_entry);
  res_RENAME4.RENAME4res_u.resok4.target_cinfo.after =
       cache_inode_get_changeid4(dst_entry);
  res_RENAME4.RENAME4res_u.resok4.target_cinfo.atomic = FALSE;
  res_RENAME4.RENAME4res_u.resok4.source_cinfo.atomic = FALSE;
  res_RENAME4.status = nfs4_Errno(cache_status);

release:
  if (tst_entry_src)
      (void) cache_inode_put(tst_entry_src);
  if (tst_entry_dst)
      (void) cache_inode_put(tst_entry_dst);

  return (res_RENAME4.status);
}                               /* nfs4_op_rename */
Beispiel #2
0
int nfs41_op_open(struct nfs_argop4 *op, compound_data_t * data, struct nfs_resop4 *resp)
{
    cache_entry_t *pentry_parent = NULL;
    cache_entry_t *pentry_lookup = NULL;
    cache_entry_t *pentry_newfile = NULL;
    fsal_handle_t *pnewfsal_handle = NULL;
    fsal_attrib_list_t attr_parent;
    fsal_attrib_list_t attr;
    fsal_attrib_list_t attr_newfile;
    fsal_attrib_list_t sattr;
    fsal_openflags_t openflags = 0;
    cache_inode_status_t cache_status;
    nfsstat4 rc;
    int retval;
    fsal_name_t filename;
    bool_t AttrProvided = FALSE;
    fsal_accessmode_t mode = 0600;
    nfs_fh4 newfh4;
    nfs_client_id_t nfs_clientid;
    nfs_worker_data_t *pworker = NULL;
    int convrc = 0;
    char __attribute__ ((__unused__)) funcname[] = "nfs4_op_open";

    cache_inode_state_data_t candidate_data;
    cache_inode_state_type_t candidate_type;
    cache_inode_state_t *pfile_state = NULL;
    cache_inode_state_t *pstate_found_iterate = NULL;
    cache_inode_state_t *pstate_previous_iterate = NULL;
    cache_inode_state_t *pstate_found_same_owner = NULL;

    cache_inode_open_owner_name_t owner_name;
    cache_inode_open_owner_name_t *powner_name = NULL;
    cache_inode_open_owner_t *powner = NULL;
    bool_t open_owner_known = FALSE;

    resp->resop = NFS4_OP_OPEN;
    res_OPEN4.status = NFS4_OK;

    uint32_t tmp_attr[2];
    uint_t tmp_int = 2;

    int pnfs_status;
    cache_inode_create_arg_t create_arg;

    pworker = (nfs_worker_data_t *) data->pclient->pworker;

    /* If there is no FH */
    if(nfs4_Is_Fh_Empty(&(data->currentFH)))
    {
        res_OPEN4.status = NFS4ERR_NOFILEHANDLE;
        return res_OPEN4.status;
    }

    /* If the filehandle is invalid */
    if(nfs4_Is_Fh_Invalid(&(data->currentFH)))
    {
        res_OPEN4.status = NFS4ERR_BADHANDLE;
        return res_OPEN4.status;
    }

    /* Tests if the Filehandle is expired (for volatile filehandle) */
    if(nfs4_Is_Fh_Expired(&(data->currentFH)))
    {
        res_OPEN4.status = NFS4ERR_FHEXPIRED;
        return res_OPEN4.status;
    }

    /* This can't be done on the pseudofs */
    if(nfs4_Is_Fh_Pseudo(&(data->currentFH)))
    {
        res_OPEN4.status = NFS4ERR_ROFS;
        return res_OPEN4.status;
    }

    /* If Filehandle points to a xattr object, manage it via the xattrs specific functions */
    if(nfs4_Is_Fh_Xattr(&(data->currentFH)))
        return nfs4_op_open_xattr(op, data, resp);

    /* If data->current_entry is empty, repopulate it */
    if(data->current_entry == NULL)
    {
        if((data->current_entry = nfs_FhandleToCache(NFS_V4,
                                  NULL,
                                  NULL,
                                  &(data->currentFH),
                                  NULL,
                                  NULL,
                                  &(res_OPEN4.status),
                                  &attr,
                                  data->pcontext,
                                  data->pclient,
                                  data->ht, &retval)) == NULL)
        {
            res_OPEN4.status = NFS4ERR_SERVERFAULT;
            return res_OPEN4.status;
        }
    }

    /* Set parent */
    pentry_parent = data->current_entry;

    /* First switch is based upon claim type */
    switch (arg_OPEN4.claim.claim)
    {
    case CLAIM_DELEGATE_CUR:
    case CLAIM_DELEGATE_PREV:
        /* Check for name length */
        if(arg_OPEN4.claim.open_claim4_u.file.utf8string_len > FSAL_MAX_NAME_LEN)
        {
            res_OPEN4.status = NFS4ERR_NAMETOOLONG;
            return res_OPEN4.status;
        }

        /* get the filename from the argument, it should not be empty */
        if(arg_OPEN4.claim.open_claim4_u.file.utf8string_len == 0)
        {
            res_OPEN4.status = NFS4ERR_INVAL;
            return res_OPEN4.status;
        }

        res_OPEN4.status = NFS4ERR_NOTSUPP;
        return res_OPEN4.status;
        break;

    case CLAIM_NULL:
        /* Check for name length */
        if(arg_OPEN4.claim.open_claim4_u.file.utf8string_len > FSAL_MAX_NAME_LEN)
        {
            res_OPEN4.status = NFS4ERR_NAMETOOLONG;
            return res_OPEN4.status;
        }

        /* get the filename from the argument, it should not be empty */
        if(arg_OPEN4.claim.open_claim4_u.file.utf8string_len == 0)
        {
            res_OPEN4.status = NFS4ERR_INVAL;
            return res_OPEN4.status;
        }

        /* Check if asked attributes are correct */
        if(arg_OPEN4.openhow.openflag4_u.how.mode == GUARDED4 ||
                arg_OPEN4.openhow.openflag4_u.how.mode == UNCHECKED4)
        {
            if(!nfs4_Fattr_Supported
                    (&arg_OPEN4.openhow.openflag4_u.how.createhow4_u.createattrs))
            {
                res_OPEN4.status = NFS4ERR_ATTRNOTSUPP;
                return res_OPEN4.status;
            }

            /* Do not use READ attr, use WRITE attr */
            if(!nfs4_Fattr_Check_Access
                    (&arg_OPEN4.openhow.openflag4_u.how.createhow4_u.createattrs,
                     FATTR4_ATTR_WRITE))
            {
                res_OPEN4.status = NFS4ERR_INVAL;
                return res_OPEN4.status;
            }
        }

        /* Check if filename is correct */
        if((cache_status =
                    cache_inode_error_convert(FSAL_buffdesc2name
                                              ((fsal_buffdesc_t *) & arg_OPEN4.claim.open_claim4_u.
                                               file, &filename))) != CACHE_INODE_SUCCESS)
        {
            res_OPEN4.status = nfs4_Errno(cache_status);
            return res_OPEN4.status;
        }

        /* Check parent */
        pentry_parent = data->current_entry;

        /* Parent must be a directory */
        if((pentry_parent->internal_md.type != DIR_BEGINNING) &&
                (pentry_parent->internal_md.type != DIR_CONTINUE))
        {
            /* Parent object is not a directory... */
            if(pentry_parent->internal_md.type == SYMBOLIC_LINK)
                res_OPEN4.status = NFS4ERR_SYMLINK;
            else
                res_OPEN4.status = NFS4ERR_NOTDIR;

            return res_OPEN4.status;
        }

        /* What kind of open is it ? */

        LogFullDebug(COMPONENT_NFS_V4,
                     "     OPEN: Claim type = %d   Open Type = %d  Share Deny = %d   Share Access = %d \n",
                     arg_OPEN4.claim.claim, arg_OPEN4.openhow.opentype, arg_OPEN4.share_deny,
                     arg_OPEN4.share_access);


        /* It this a known client id ? */
        LogDebug(COMPONENT_NFS_V4, "OPEN Client id = %llx", arg_OPEN4.owner.clientid);

        /* Is this open_owner known ? */
        if(!nfs_convert_open_owner(&arg_OPEN4.owner, &owner_name))
        {
            res_OPEN4.status = NFS4ERR_SERVERFAULT;
            return res_OPEN4.status;
        }

        if(!nfs_open_owner_Get_Pointer(&owner_name, &powner))
        {
            /* This open owner is not known yet, allocated and set up a new one */
            GET_PREALLOC(powner,
                         data->pclient->pool_open_owner,
                         data->pclient->nb_pre_state_v4, cache_inode_open_owner_t, next);

            GET_PREALLOC(powner_name,
                         data->pclient->pool_open_owner_name,
                         data->pclient->nb_pre_state_v4,
                         cache_inode_open_owner_name_t, next);

            if(powner == NULL || powner_name == NULL)
            {
                res_OPEN4.status = NFS4ERR_SERVERFAULT;
                return res_OPEN4.status;
            }

            memcpy((char *)powner_name, (char *)&owner_name,
                   sizeof(cache_inode_open_owner_name_t));

            /* set up the content of the open_owner */
            powner->confirmed = FALSE;
            powner->seqid = 1;    /* NFSv4.1 specific, initial seqid is 1 */
            powner->related_owner = NULL;
            powner->next = NULL;
            powner->clientid = arg_OPEN4.owner.clientid;
            powner->owner_len = arg_OPEN4.owner.owner.owner_len;
            memcpy((char *)powner->owner_val, (char *)arg_OPEN4.owner.owner.owner_val,
                   arg_OPEN4.owner.owner.owner_len);
            powner->owner_val[powner->owner_len] = '\0';

            pthread_mutex_init(&powner->lock, NULL);

            if(!nfs_open_owner_Set(powner_name, powner))
            {
                res_OPEN4.status = NFS4ERR_SERVERFAULT;
                return res_OPEN4.status;
            }

        }

        /* Status of parent directory before the operation */
        if((cache_status = cache_inode_getattr(pentry_parent,
                                               &attr_parent,
                                               data->ht,
                                               data->pclient,
                                               data->pcontext,
                                               &cache_status)) != CACHE_INODE_SUCCESS)
        {
            res_OPEN4.status = nfs4_Errno(cache_status);
            return res_OPEN4.status;
        }
        memset(&(res_OPEN4.OPEN4res_u.resok4.cinfo.before), 0, sizeof(changeid4));
        res_OPEN4.OPEN4res_u.resok4.cinfo.before =
            (changeid4) pentry_parent->internal_md.mod_time;

        /* CLient may have provided fattr4 to set attributes at creation time */
        if(arg_OPEN4.openhow.openflag4_u.how.mode == GUARDED4 ||
                arg_OPEN4.openhow.openflag4_u.how.mode == UNCHECKED4)
        {
            if(arg_OPEN4.openhow.openflag4_u.how.createhow4_u.createattrs.attrmask.
                    bitmap4_len != 0)
            {
                /* Convert fattr4 so nfs4_sattr */
                convrc =
                    nfs4_Fattr_To_FSAL_attr(&sattr,
                                            &(arg_OPEN4.openhow.openflag4_u.how.
                                              createhow4_u.createattrs));

                if(convrc == 0)
                {
                    res_OPEN4.status = NFS4ERR_ATTRNOTSUPP;
                    return res_OPEN4.status;
                }

                if(convrc == -1)
                {
                    res_OPEN4.status = NFS4ERR_BADXDR;
                    return res_OPEN4.status;
                }

                AttrProvided = TRUE;
            }

        }

        /* Second switch is based upon "openhow" */
        switch (arg_OPEN4.openhow.opentype)
        {
        case OPEN4_CREATE:
            /* a new file is to be created */

            /* Does a file with this name already exist ? */
            pentry_lookup = cache_inode_lookup(pentry_parent,
                                               &filename,
                                               &attr_newfile,
                                               data->ht,
                                               data->pclient,
                                               data->pcontext, &cache_status);

            if(cache_status != CACHE_INODE_NOT_FOUND)
            {
                /* if open is UNCHECKED, return NFS4_OK (RFC3530 page 172) */
                if(arg_OPEN4.openhow.openflag4_u.how.mode == UNCHECKED4
                        && (cache_status == CACHE_INODE_SUCCESS))
                {
                    /* If the file is opened for write, OPEN4 while deny share write access,
                     * in this case, check caller has write access to the file */
                    if(arg_OPEN4.share_deny & OPEN4_SHARE_DENY_WRITE)
                    {
                        if(cache_inode_access(pentry_lookup,
                                              FSAL_W_OK,
                                              data->ht,
                                              data->pclient,
                                              data->pcontext,
                                              &cache_status) != CACHE_INODE_SUCCESS)
                        {
                            res_OPEN4.status = NFS4ERR_ACCESS;
                            return res_OPEN4.status;
                        }
                        openflags = FSAL_O_WRONLY;
                    }

                    /* Same check on read: check for readability of a file before opening it for read */
                    if(arg_OPEN4.share_access & OPEN4_SHARE_ACCESS_READ)
                    {
                        if(cache_inode_access(pentry_lookup,
                                              FSAL_R_OK,
                                              data->ht,
                                              data->pclient,
                                              data->pcontext,
                                              &cache_status) != CACHE_INODE_SUCCESS)
                        {
                            res_OPEN4.status = NFS4ERR_ACCESS;
                            return res_OPEN4.status;
                        }
                        openflags = FSAL_O_RDONLY;
                    }

                    if(AttrProvided == TRUE)      /* Set the attribute if provided */
                    {
                        if((cache_status = cache_inode_setattr(pentry_lookup,
                                                               &sattr,
                                                               data->ht,
                                                               data->pclient,
                                                               data->pcontext,
                                                               &cache_status)) !=
                                CACHE_INODE_SUCCESS)
                        {
                            res_OPEN4.status = nfs4_Errno(cache_status);
                            return res_OPEN4.status;
                        }

                        res_OPEN4.OPEN4res_u.resok4.attrset =
                            arg_OPEN4.openhow.openflag4_u.how.createhow4_u.createattrs.
                            attrmask;
                    }
                    else
                        res_OPEN4.OPEN4res_u.resok4.attrset.bitmap4_len = 0;

                    /* Same check on write */
                    if(arg_OPEN4.share_access & OPEN4_SHARE_ACCESS_WRITE)
                    {
                        if(cache_inode_access(pentry_lookup,
                                              FSAL_W_OK,
                                              data->ht,
                                              data->pclient,
                                              data->pcontext,
                                              &cache_status) != CACHE_INODE_SUCCESS)
                        {
                            res_OPEN4.status = NFS4ERR_ACCESS;
                            return res_OPEN4.status;
                        }
                        openflags = FSAL_O_RDWR;
                    }

                    /* Set the state for the related file */

                    /* Prepare state management structure */
                    candidate_type = CACHE_INODE_STATE_SHARE;
                    candidate_data.share.share_deny = arg_OPEN4.share_deny;
                    candidate_data.share.share_access = arg_OPEN4.share_access;

                    if(cache_inode_add_state(pentry_lookup,
                                             candidate_type,
                                             &candidate_data,
                                             powner,
                                             data->pclient,
                                             data->pcontext,
                                             &pfile_state,
                                             &cache_status) != CACHE_INODE_SUCCESS)
                    {
                        /* Seqid has to be incremented even in this case */
                        P(powner->lock);
                        powner->seqid += 1;
                        V(powner->lock);

                        res_OPEN4.status = NFS4ERR_SHARE_DENIED;
                        return res_OPEN4.status;
                    }

                    /* Open the file */
                    if(cache_inode_open_by_name(pentry_parent,
                                                &filename,
                                                pentry_lookup,
                                                data->pclient,
                                                openflags,
                                                data->pcontext,
                                                &cache_status) != CACHE_INODE_SUCCESS)
                    {
                        /* Seqid has to be incremented even in this case */
                        P(powner->lock);
                        powner->seqid += 1;
                        V(powner->lock);

                        res_OPEN4.status = NFS4ERR_SHARE_DENIED;
                        res_OPEN4.status = NFS4ERR_ACCESS;
                        return res_OPEN4.status;
                    }

                    res_OPEN4.OPEN4res_u.resok4.attrset.bitmap4_len = 2;
                    if((res_OPEN4.OPEN4res_u.resok4.attrset.bitmap4_val =
                                (uint32_t *) Mem_Alloc(res_OPEN4.OPEN4res_u.resok4.attrset.
                                                       bitmap4_len * sizeof(uint32_t))) == NULL)
                    {
                        res_OPEN4.status = NFS4ERR_SERVERFAULT;
                        return res_OPEN4.status;
                    }

                    memset(&(res_OPEN4.OPEN4res_u.resok4.cinfo.after), 0,
                           sizeof(changeid4));
                    res_OPEN4.OPEN4res_u.resok4.cinfo.after =
                        (changeid4) pentry_parent->internal_md.mod_time;
                    res_OPEN4.OPEN4res_u.resok4.cinfo.atomic = TRUE;

                    res_OPEN4.OPEN4res_u.resok4.stateid.seqid = pfile_state->seqid;
                    memcpy(res_OPEN4.OPEN4res_u.resok4.stateid.other,
                           pfile_state->stateid_other, 12);

                    /* No delegation */
                    res_OPEN4.OPEN4res_u.resok4.delegation.delegation_type =
                        OPEN_DELEGATE_NONE;
                    res_OPEN4.OPEN4res_u.resok4.rflags = OPEN4_RESULT_LOCKTYPE_POSIX;

                    /* Now produce the filehandle to this file */
                    if((pnewfsal_handle =
                                cache_inode_get_fsal_handle(pentry_lookup, &cache_status)) == NULL)
                    {
                        res_OPEN4.status = nfs4_Errno(cache_status);
                        return res_OPEN4.status;
                    }

                    /* Allocation of a new file handle */
                    if((rc = nfs4_AllocateFH(&newfh4)) != NFS4_OK)
                    {
                        res_OPEN4.status = rc;
                        return res_OPEN4.status;
                    }

                    /* Building a new fh */
                    if(!nfs4_FSALToFhandle(&newfh4, pnewfsal_handle, data))
                    {
                        res_OPEN4.status = NFS4ERR_SERVERFAULT;
                        return res_OPEN4.status;
                    }

                    /* This new fh replaces the current FH */
                    data->currentFH.nfs_fh4_len = newfh4.nfs_fh4_len;
                    memcpy(data->currentFH.nfs_fh4_val, newfh4.nfs_fh4_val,
                           newfh4.nfs_fh4_len);

                    data->current_entry = pentry_lookup;
                    data->current_filetype = REGULAR_FILE;

                    res_OPEN4.status = NFS4_OK;
                    return res_OPEN4.status;
                }

                /* if open is EXCLUSIVE, but verifier is the same, return NFS4_OK (RFC3530 page 173) */
                if(arg_OPEN4.openhow.openflag4_u.how.mode == EXCLUSIVE4)
                {
                    if((pentry_lookup != NULL)
                            && (pentry_lookup->internal_md.type == REGULAR_FILE))
                    {
                        pstate_found_iterate = NULL;
                        pstate_previous_iterate = NULL;

                        do
                        {
                            cache_inode_state_iterate(pentry_lookup,
                                                      &pstate_found_iterate,
                                                      pstate_previous_iterate,
                                                      data->pclient,
                                                      data->pcontext, &cache_status);
                            if(cache_status == CACHE_INODE_STATE_ERROR)
                                break;

                            if(cache_status == CACHE_INODE_INVALID_ARGUMENT)
                            {
                                /* Seqid has to be incremented even in this case */
                                P(powner->lock);
                                powner->seqid += 1;
                                V(powner->lock);

                                res_OPEN4.status = NFS4ERR_INVAL;
                                return res_OPEN4.status;
                            }

                            /* Check is open_owner is the same */
                            if(pstate_found_iterate != NULL)
                            {
                                if((pstate_found_iterate->state_type ==
                                        CACHE_INODE_STATE_SHARE)
                                        && !memcmp(arg_OPEN4.owner.owner.owner_val,
                                                   pstate_found_iterate->powner->owner_val,
                                                   pstate_found_iterate->powner->owner_len)
                                        && !memcmp(pstate_found_iterate->state_data.share.
                                                   oexcl_verifier,
                                                   arg_OPEN4.openhow.openflag4_u.how.
                                                   createhow4_u.createverf, NFS4_VERIFIER_SIZE))
                                {

                                    /* A former open EXCLUSIVE with same owner and verifier was found, resend it */
                                    res_OPEN4.OPEN4res_u.resok4.stateid.seqid =
                                        pstate_found_iterate->seqid;
                                    memcpy(res_OPEN4.OPEN4res_u.resok4.stateid.other,
                                           pstate_found_iterate->stateid_other, 12);

                                    memset(&(res_OPEN4.OPEN4res_u.resok4.cinfo.after), 0,
                                           sizeof(changeid4));
                                    res_OPEN4.OPEN4res_u.resok4.cinfo.after =
                                        (changeid4) pentry_parent->internal_md.mod_time;
                                    res_OPEN4.OPEN4res_u.resok4.cinfo.atomic = TRUE;

                                    /* No delegation */
                                    res_OPEN4.OPEN4res_u.resok4.delegation.delegation_type =
                                        OPEN_DELEGATE_NONE;
                                    res_OPEN4.OPEN4res_u.resok4.rflags =
                                        OPEN4_RESULT_LOCKTYPE_POSIX;

                                    /* Now produce the filehandle to this file */
                                    if((pnewfsal_handle =
                                                cache_inode_get_fsal_handle(pentry_lookup,
                                                                            &cache_status)) == NULL)
                                    {
                                        res_OPEN4.status = nfs4_Errno(cache_status);
                                        return res_OPEN4.status;
                                    }

                                    /* Allocation of a new file handle */
                                    if((rc = nfs4_AllocateFH(&newfh4)) != NFS4_OK)
                                    {
                                        res_OPEN4.status = rc;
                                        return res_OPEN4.status;
                                    }

                                    /* Building a new fh */
                                    if(!nfs4_FSALToFhandle(&newfh4, pnewfsal_handle, data))
                                    {
                                        res_OPEN4.status = NFS4ERR_SERVERFAULT;
                                        return res_OPEN4.status;
                                    }

                                    /* This new fh replaces the current FH */
                                    data->currentFH.nfs_fh4_len = newfh4.nfs_fh4_len;
                                    memcpy(data->currentFH.nfs_fh4_val, newfh4.nfs_fh4_val,
                                           newfh4.nfs_fh4_len);

                                    data->current_entry = pentry_lookup;
                                    data->current_filetype = REGULAR_FILE;

                                    /* regular exit */
                                    res_OPEN4.status = NFS4_OK;
                                    return res_OPEN4.status;
                                }

                            }
                            /* if( pstate_found_iterate != NULL ) */
                            pstate_previous_iterate = pstate_found_iterate;
                        }
                        while(pstate_found_iterate != NULL);
                    }
                }

                /* Managing GUARDED4 mode */
                if(cache_status != CACHE_INODE_SUCCESS)
                    res_OPEN4.status = nfs4_Errno(cache_status);
                else
                    res_OPEN4.status = NFS4ERR_EXIST;       /* File already exists */
                return res_OPEN4.status;
            }

            /*  if( cache_status != CACHE_INODE_NOT_FOUND ), if file already exists basically */
            LogFullDebug(COMPONENT_NFS_V4, "    OPEN open.how = %d\n", arg_OPEN4.openhow.openflag4_u.how.mode);

            create_arg.use_pnfs = FALSE;
#ifdef _USE_PNFS
            /*  set the file has "managed via pNFS" */
            if(data->pexport->options & EXPORT_OPTION_USE_PNFS)
                create_arg.use_pnfs = TRUE;
#endif                          /* _USE_PNFS */

            /* Create the file, if we reach this point, it does not exist, we can create it */
            if((pentry_newfile = cache_inode_create(pentry_parent,
                                                    &filename,
                                                    REGULAR_FILE,
                                                    mode,
                                                    &create_arg,
                                                    &attr_newfile,
                                                    data->ht,
                                                    data->pclient,
                                                    data->pcontext, &cache_status)) == NULL)
            {
                /* If the file already exists, this is not an error if open mode is UNCHECKED */
                if(cache_status != CACHE_INODE_ENTRY_EXISTS)
                {
                    res_OPEN4.status = nfs4_Errno(cache_status);
                    return res_OPEN4.status;
                }
                else
                {
                    /* If this point is reached, then the file already exists, cache_status == CACHE_INODE_ENTRY_EXISTS and pentry_newfile == NULL
                       This probably means EXCLUSIVE4 mode is used and verifier matches. pentry_newfile is then set to pentry_lookup */
                    pentry_newfile = pentry_lookup;
                }
            }

            /* Prepare state management structure */
            candidate_type = CACHE_INODE_STATE_SHARE;
            candidate_data.share.share_deny = arg_OPEN4.share_deny;
            candidate_data.share.share_access = arg_OPEN4.share_access;
            candidate_data.share.lockheld = 0;

            /* If file is opened under mode EXCLUSIVE4, open verifier should be kept to detect non vicious double open */
            if(arg_OPEN4.openhow.openflag4_u.how.mode == EXCLUSIVE4)
            {
                strncpy(candidate_data.share.oexcl_verifier,
                        arg_OPEN4.openhow.openflag4_u.how.createhow4_u.createverf,
                        NFS4_VERIFIER_SIZE);
            }

            if(cache_inode_add_state(pentry_newfile,
                                     candidate_type,
                                     &candidate_data,
                                     powner,
                                     data->pclient,
                                     data->pcontext,
                                     &pfile_state, &cache_status) != CACHE_INODE_SUCCESS)
            {
                /* Seqid has to be incremented even in this case */
                P(powner->lock);
                powner->seqid += 1;
                V(powner->lock);

                res_OPEN4.status = NFS4ERR_SHARE_DENIED;
                return res_OPEN4.status;
            }

            if(AttrProvided == TRUE)      /* Set the attribute if provided */
            {
                if((cache_status = cache_inode_setattr(pentry_newfile,
                                                       &sattr,
                                                       data->ht,
                                                       data->pclient,
                                                       data->pcontext,
                                                       &cache_status)) !=
                        CACHE_INODE_SUCCESS)
                {
                    res_OPEN4.status = nfs4_Errno(cache_status);
                    return res_OPEN4.status;
                }

            }

            /* Set the openflags variable */
            if(arg_OPEN4.share_deny & OPEN4_SHARE_DENY_WRITE)
                openflags |= FSAL_O_RDONLY;
            if(arg_OPEN4.share_deny & OPEN4_SHARE_DENY_READ)
                openflags |= FSAL_O_WRONLY;
            if(arg_OPEN4.share_access & OPEN4_SHARE_ACCESS_WRITE)
                openflags = FSAL_O_RDWR;
            if(arg_OPEN4.share_access != 0)
                openflags = FSAL_O_RDWR;    /* @todo : BUGAZOMEU : Something better later */

            /* Open the file */
            if(cache_inode_open_by_name(pentry_parent,
                                        &filename,
                                        pentry_newfile,
                                        data->pclient,
                                        openflags,
                                        data->pcontext,
                                        &cache_status) != CACHE_INODE_SUCCESS)
            {
                /* Seqid has to be incremented even in this case */
                P(powner->lock);
                powner->seqid += 1;
                V(powner->lock);

                res_OPEN4.status = NFS4ERR_ACCESS;
                return res_OPEN4.status;
            }

            break;

        case OPEN4_NOCREATE:
            /* It was not a creation, but a regular open */
            /* The filehandle to the new file replaces the current filehandle */
            if(pentry_newfile == NULL)
            {
                if((pentry_newfile = cache_inode_lookup(pentry_parent,
                                                        &filename,
                                                        &attr_newfile,
                                                        data->ht,
                                                        data->pclient,
                                                        data->pcontext,
                                                        &cache_status)) == NULL)
                {
                    res_OPEN4.status = nfs4_Errno(cache_status);
                    return res_OPEN4.status;
                }
            }

            /* OPEN4 is to be done on a file */
            if(pentry_newfile->internal_md.type != REGULAR_FILE)
            {
                if(pentry_newfile->internal_md.type == DIR_BEGINNING
                        || pentry_newfile->internal_md.type == DIR_CONTINUE)
                {
                    res_OPEN4.status = NFS4ERR_ISDIR;
                    return res_OPEN4.status;
                }
                else if(pentry_newfile->internal_md.type == SYMBOLIC_LINK)
                {
                    res_OPEN4.status = NFS4ERR_SYMLINK;
                    return res_OPEN4.status;
                }
                else
                {
                    res_OPEN4.status = NFS4ERR_INVAL;
                    return res_OPEN4.status;
                }
            }

            /* If the file is opened for write, OPEN4 while deny share write access,
             * in this case, check caller has write access to the file */
            if(arg_OPEN4.share_deny & OPEN4_SHARE_DENY_WRITE)
            {
                if(cache_inode_access(pentry_newfile,
                                      FSAL_W_OK,
                                      data->ht,
                                      data->pclient,
                                      data->pcontext, &cache_status) != CACHE_INODE_SUCCESS)
                {
                    res_OPEN4.status = NFS4ERR_ACCESS;
                    return res_OPEN4.status;
                }
                openflags = FSAL_O_WRONLY;
            }

            /* Same check on read: check for readability of a file before opening it for read */
            if(arg_OPEN4.share_access & OPEN4_SHARE_ACCESS_READ)
            {
                if(cache_inode_access(pentry_newfile,
                                      FSAL_R_OK,
                                      data->ht,
                                      data->pclient,
                                      data->pcontext, &cache_status) != CACHE_INODE_SUCCESS)
                {
                    res_OPEN4.status = NFS4ERR_ACCESS;
                    return res_OPEN4.status;
                }
                openflags = FSAL_O_RDONLY;
            }

            /* Same check on write */
            if(arg_OPEN4.share_access & OPEN4_SHARE_ACCESS_WRITE)
            {
                if(cache_inode_access(pentry_newfile,
                                      FSAL_W_OK,
                                      data->ht,
                                      data->pclient,
                                      data->pcontext, &cache_status) != CACHE_INODE_SUCCESS)
                {
                    res_OPEN4.status = NFS4ERR_ACCESS;
                    return res_OPEN4.status;
                }
                openflags = FSAL_O_RDWR;
            }

            /* Try to find if the same open_owner already has acquired a stateid for this file */
            pstate_found_iterate = NULL;
            pstate_previous_iterate = NULL;
            do
            {
                cache_inode_state_iterate(pentry_newfile,
                                          &pstate_found_iterate,
                                          pstate_previous_iterate,
                                          data->pclient, data->pcontext, &cache_status);
                if(cache_status == CACHE_INODE_STATE_ERROR)
                    break;          /* Get out of the loop */

                if(cache_status == CACHE_INODE_INVALID_ARGUMENT)
                {
                    res_OPEN4.status = NFS4ERR_INVAL;
                    return res_OPEN4.status;
                }

                /* Check is open_owner is the same */
                if(pstate_found_iterate != NULL)
                {
                    if((pstate_found_iterate->state_type == CACHE_INODE_STATE_SHARE) &&
                            (pstate_found_iterate->powner->clientid == arg_OPEN4.owner.clientid)
                            &&
                            ((pstate_found_iterate->powner->owner_len ==
                              arg_OPEN4.owner.owner.owner_len)
                             &&
                             (!memcmp
                              (arg_OPEN4.owner.owner.owner_val,
                               pstate_found_iterate->powner->owner_val,
                               pstate_found_iterate->powner->owner_len))))
                    {
                        /* We'll be re-using the found state */
                        pstate_found_same_owner = pstate_found_iterate;
                    }
                    else
                    {

                        /* This is a different owner, check for possible conflicts */

                        if(memcmp(arg_OPEN4.owner.owner.owner_val,
                                  pstate_found_iterate->powner->owner_val,
                                  pstate_found_iterate->powner->owner_len))
                        {
                            switch (pstate_found_iterate->state_type)
                            {
                            case CACHE_INODE_STATE_SHARE:
                                if((pstate_found_iterate->state_data.share.
                                        share_access & OPEN4_SHARE_ACCESS_WRITE)
                                        && (arg_OPEN4.share_deny & OPEN4_SHARE_DENY_WRITE))
                                {
                                    res_OPEN4.status = NFS4ERR_SHARE_DENIED;
                                    return res_OPEN4.status;
                                }

                                break;
                            }
                        }

                    }

                    /* In all cases opening in read access a read denied file or write access to a write denied file
                     * should fail, even if the owner is the same, see discussion in 14.2.16 and 8.9 */
                    if(pstate_found_iterate->state_type == CACHE_INODE_STATE_SHARE)
                    {
                        /* deny read access on read denied file */
                        if((pstate_found_iterate->state_data.share.
                                share_deny & OPEN4_SHARE_DENY_READ)
                                && (arg_OPEN4.share_access & OPEN4_SHARE_ACCESS_READ))
                        {
                            /* Seqid has to be incremented even in this case */
                            P(powner->lock);
                            powner->seqid += 1;
                            V(powner->lock);

                            powner->seqid += 1;
                            res_OPEN4.status = NFS4ERR_SHARE_DENIED;
                            return res_OPEN4.status;
                        }

                        /* deny write access on write denied file */
                        if((pstate_found_iterate->state_data.share.
                                share_deny & OPEN4_SHARE_DENY_WRITE)
                                && (arg_OPEN4.share_access & OPEN4_SHARE_ACCESS_WRITE))
                        {
                            /* Seqid has to be incremented even in this case */
                            P(powner->lock);
                            powner->seqid += 1;
                            V(powner->lock);

                            res_OPEN4.status = NFS4ERR_SHARE_DENIED;
                            return res_OPEN4.status;
                        }

                    }

                }
                /*  if( pstate_found_iterate != NULL ) */
                pstate_previous_iterate = pstate_found_iterate;
            }
            while(pstate_found_iterate != NULL);

            if(pstate_found_same_owner != NULL)
            {
                pfile_state = pstate_found_same_owner;
                pfile_state->seqid += 1;

                P(powner->lock);
                powner->seqid += 1;
                V(powner->lock);

            }
            else
            {
                /* Set the state for the related file */
                /* Prepare state management structure */
                candidate_type = CACHE_INODE_STATE_SHARE;
                candidate_data.share.share_deny = arg_OPEN4.share_deny;
                candidate_data.share.share_access = arg_OPEN4.share_access;

                if(cache_inode_add_state(pentry_newfile,
                                         candidate_type,
                                         &candidate_data,
                                         powner,
                                         data->pclient,
                                         data->pcontext,
                                         &pfile_state,
                                         &cache_status) != CACHE_INODE_SUCCESS)
                {
                    /* Seqid has to be incremented even in this case */
                    P(powner->lock);
                    powner->seqid += 1;
                    V(powner->lock);

                    res_OPEN4.status = NFS4ERR_SHARE_DENIED;
                    return res_OPEN4.status;
                }
            }

            /* Open the file */
            if(cache_inode_open_by_name(pentry_parent,
                                        &filename,
                                        pentry_newfile,
                                        data->pclient,
                                        openflags,
                                        data->pcontext,
                                        &cache_status) != CACHE_INODE_SUCCESS)
            {
                /* Seqid has to be incremented even in this case */
                P(powner->lock);
                powner->seqid += 1;
                V(powner->lock);

                res_OPEN4.status = NFS4ERR_ACCESS;
                return res_OPEN4.status;
            }
            break;

        default:
            /* Seqid has to be incremented even in this case */
            if(powner != NULL)
            {
                P(powner->lock);
                powner->seqid += 1;
                V(powner->lock);
            }

            res_OPEN4.status = NFS4ERR_INVAL;
            return res_OPEN4.status;
            break;
        }                       /* switch( arg_OPEN4.openhow.opentype ) */

        break;

    case CLAIM_PREVIOUS:
        break;

    default:
        /* Seqid has to be incremented even in this case */
        if(powner != NULL)
        {
            P(powner->lock);
            powner->seqid += 1;
            V(powner->lock);
        }

        res_OPEN4.status = NFS4ERR_INVAL;
        return res_OPEN4.status;
        break;
    }                           /*  switch(  arg_OPEN4.claim.claim ) */

    /* Now produce the filehandle to this file */
    if((pnewfsal_handle =
                cache_inode_get_fsal_handle(pentry_newfile, &cache_status)) == NULL)
    {
        res_OPEN4.status = nfs4_Errno(cache_status);
        return res_OPEN4.status;
    }

    /* Allocation of a new file handle */
    if((rc = nfs4_AllocateFH(&newfh4)) != NFS4_OK)
    {
        res_OPEN4.status = rc;
        return res_OPEN4.status;
    }

    /* Building a new fh */
    if(!nfs4_FSALToFhandle(&newfh4, pnewfsal_handle, data))
    {
        res_OPEN4.status = NFS4ERR_SERVERFAULT;
        return res_OPEN4.status;
    }

    /* This new fh replaces the current FH */
    data->currentFH.nfs_fh4_len = newfh4.nfs_fh4_len;
    memcpy(data->currentFH.nfs_fh4_val, newfh4.nfs_fh4_val, newfh4.nfs_fh4_len);

    data->current_entry = pentry_newfile;
    data->current_filetype = REGULAR_FILE;

    /* No do not need newfh any more */
    Mem_Free((char *)newfh4.nfs_fh4_val);

    /* Status of parent directory after the operation */
    if((cache_status = cache_inode_getattr(pentry_parent,
                                           &attr_parent,
                                           data->ht,
                                           data->pclient,
                                           data->pcontext,
                                           &cache_status)) != CACHE_INODE_SUCCESS)
    {
        res_OPEN4.status = nfs4_Errno(cache_status);
        return res_OPEN4.status;
    }

    res_OPEN4.OPEN4res_u.resok4.attrset.bitmap4_len = 2;
    if((res_OPEN4.OPEN4res_u.resok4.attrset.bitmap4_val =
                (uint32_t *) Mem_Alloc(res_OPEN4.OPEN4res_u.resok4.attrset.bitmap4_len *
                                       sizeof(uint32_t))) == NULL)
    {
        res_OPEN4.status = NFS4ERR_SERVERFAULT;
        return res_OPEN4.status;
    }
    res_OPEN4.OPEN4res_u.resok4.attrset.bitmap4_val[0] = 0;       /* No Attributes set */
    res_OPEN4.OPEN4res_u.resok4.attrset.bitmap4_val[1] = 0;       /* No Attributes set */

    if(arg_OPEN4.openhow.opentype == OPEN4_CREATE)
    {
        tmp_int = 2;
        tmp_attr[0] = FATTR4_SIZE;
        tmp_attr[1] = FATTR4_MODE;
        nfs4_list_to_bitmap4(&(res_OPEN4.OPEN4res_u.resok4.attrset), &tmp_int, tmp_attr);
        res_OPEN4.OPEN4res_u.resok4.attrset.bitmap4_len = 2;
    }

    res_OPEN4.OPEN4res_u.resok4.cinfo.after =
        (changeid4) pentry_parent->internal_md.mod_time;
    res_OPEN4.OPEN4res_u.resok4.cinfo.atomic = TRUE;

    res_OPEN4.OPEN4res_u.resok4.stateid.seqid = powner->seqid;
    memcpy(res_OPEN4.OPEN4res_u.resok4.stateid.other, pfile_state->stateid_other, 12);

    /* No delegation */
    res_OPEN4.OPEN4res_u.resok4.delegation.delegation_type = OPEN_DELEGATE_NONE;

    res_OPEN4.OPEN4res_u.resok4.rflags = OPEN4_RESULT_LOCKTYPE_POSIX;

    /* regular exit */
    res_OPEN4.status = NFS4_OK;
    return res_OPEN4.status;
}                               /* nfs41_op_open */
Beispiel #3
0
int nfs4_op_lookupp(struct nfs_argop4 *op,
                    compound_data_t * data, struct nfs_resop4 *resp)
{
  fsal_name_t name;
  cache_entry_t *dir_pentry = NULL;
  cache_entry_t *file_pentry = NULL;
  fsal_attrib_list_t attrlookup;
  cache_inode_status_t cache_status;
  int error = 0;
  fsal_handle_t *pfsal_handle = NULL;

  char __attribute__ ((__unused__)) funcname[] = "nfs4_op_lookupp";

  resp->resop = NFS4_OP_LOOKUPP;
  resp->nfs_resop4_u.oplookupp.status = NFS4_OK;

  /* If there is no FH */
  if(nfs4_Is_Fh_Empty(&(data->currentFH)))
    {
      res_LOOKUPP4.status = NFS4ERR_NOFILEHANDLE;
      return res_LOOKUPP4.status;
    }

  /* If the filehandle is invalid */
  if(nfs4_Is_Fh_Invalid(&(data->currentFH)))
    {
      res_LOOKUPP4.status = NFS4ERR_BADHANDLE;
      return res_LOOKUPP4.status;
    }

  /* Tests if the Filehandle is expired (for volatile filehandle) */
  if(nfs4_Is_Fh_Expired(&(data->currentFH)))
    {
      res_LOOKUPP4.status = NFS4ERR_FHEXPIRED;
      return res_LOOKUPP4.status;
    }

  /* looking up for parent directory from ROOTFH return NFS4ERR_NOENT (RFC3530, page 166) */
  if(data->currentFH.nfs_fh4_len == data->rootFH.nfs_fh4_len
     && memcmp(data->currentFH.nfs_fh4_val, data->rootFH.nfs_fh4_val,
               data->currentFH.nfs_fh4_len) == 0)
    {
      /* Nothing to do, just reply with success */
      res_LOOKUPP4.status = NFS4ERR_NOENT;
      return res_LOOKUPP4.status;
    }

  /* If in pseudoFS, proceed with pseudoFS specific functions */
  if(nfs4_Is_Fh_Pseudo(&(data->currentFH)))
    return nfs4_op_lookupp_pseudo(op, data, resp);

  /* If Filehandle points to a xattr object, manage it via the xattrs specific functions */
  if(nfs4_Is_Fh_Xattr(&(data->currentFH)))
    return nfs4_op_lookupp_xattr(op, data, resp);

  /* If data->exportp is null, a junction from pseudo fs was traversed, credp and exportp have to be updated */
  if(data->pexport == NULL)
    {
      if((error = nfs4_SetCompoundExport(data)) != NFS4_OK)
        {
          res_LOOKUPP4.status = error;
          return res_LOOKUPP4.status;
        }
    }

  /* Preparying for cache_inode_lookup ".." */
  file_pentry = NULL;
  dir_pentry = data->current_entry;
  name = FSAL_DOT_DOT;

  /* BUGAZOMEU: Faire la gestion des cross junction traverse */
  if((file_pentry = cache_inode_lookup(dir_pentry,
                                       &name,
                                       data->pexport->cache_inode_policy,
                                       &attrlookup,
                                       data->ht,
                                       data->pclient,
                                       data->pcontext, &cache_status)) != NULL)
    {
      /* Extract the fsal attributes from the cache inode pentry */
      pfsal_handle = cache_inode_get_fsal_handle(file_pentry, &cache_status);
      if(cache_status != CACHE_INODE_SUCCESS)
        {
          res_LOOKUPP4.status = NFS4ERR_SERVERFAULT;
          return res_LOOKUPP4.status;
        }

      /* Convert it to a file handle */
      if(!nfs4_FSALToFhandle(&data->currentFH, pfsal_handle, data))
        {
          res_LOOKUPP4.status = NFS4ERR_SERVERFAULT;
          return res_LOOKUPP4.status;
        }

      /* Copy this to the mounted on FH (if no junction is traversed */
      memcpy((char *)(data->mounted_on_FH.nfs_fh4_val),
             (char *)(data->currentFH.nfs_fh4_val), data->currentFH.nfs_fh4_len);
      data->mounted_on_FH.nfs_fh4_len = data->currentFH.nfs_fh4_len;

      /* Keep the pointer within the compound data */
      data->current_entry = file_pentry;
      data->current_filetype = file_pentry->internal_md.type;

      /* Return successfully */
      res_LOOKUPP4.status = NFS4_OK;
      return NFS4_OK;

    }

  /* If the part of the code is reached, then something wrong occured in the lookup process, status is not HPSS_E_NOERROR 
   * and contains the code for the error */

  /* If NFS4ERR_SYMLINK should be returned for a symlink instead of ENOTDIR */
  if((cache_status == CACHE_INODE_NOT_A_DIRECTORY) &&
     (dir_pentry->internal_md.type == SYMBOLIC_LINK))
    res_LOOKUPP4.status = NFS4ERR_SYMLINK;
  else
    res_LOOKUPP4.status = nfs4_Errno(cache_status);

  return res_LOOKUPP4.status;
}                               /* nfs4_op_lookupp */
cache_inode_status_t
cache_inode_create(cache_entry_t *parent,
                   const char *name,
                   object_file_type_t type,
                   uint32_t mode,
                   cache_inode_create_arg_t *create_arg,
                   struct req_op_context *req_ctx,
                   cache_entry_t **entry)
{
     cache_inode_status_t status = CACHE_INODE_SUCCESS;
     fsal_status_t fsal_status = {0, 0};
     struct fsal_obj_handle *object_handle;
     struct attrlist object_attributes;
     struct fsal_obj_handle *dir_handle;
     cache_inode_create_arg_t zero_create_arg;
     fsal_accessflags_t access_mask = 0;

     memset(&zero_create_arg, 0, sizeof(zero_create_arg));
     memset(&object_attributes, 0, sizeof(object_attributes));

     if (create_arg == NULL) {
          create_arg = &zero_create_arg;
     }

     if ((type != REGULAR_FILE) && (type != DIRECTORY) &&
         (type != SYMBOLIC_LINK) && (type != SOCKET_FILE) &&
         (type != FIFO_FILE) && (type != CHARACTER_FILE) &&
         (type != BLOCK_FILE)) {
          status = CACHE_INODE_BAD_TYPE;

          *entry = NULL;
          goto out;
        }

    /*
     * Check if caller is allowed to perform the operation
     */
    access_mask = FSAL_MODE_MASK_SET(FSAL_W_OK) |
                  FSAL_ACE4_MASK_SET(FSAL_ACE_PERM_ADD_FILE |
                                     FSAL_ACE_PERM_ADD_SUBDIRECTORY);
    status = cache_inode_access(parent,
                                access_mask,
                                req_ctx);
    if (status != CACHE_INODE_SUCCESS)
        {
          *entry = NULL;
          goto out;
        }

    /* Try to create it first */

    dir_handle = parent->obj_handle;
/* we pass in attributes to the create.  We will get them back below */
    FSAL_SET_MASK(object_attributes.mask, ATTR_MODE|ATTR_OWNER|ATTR_GROUP);
    object_attributes.owner = req_ctx->creds->caller_uid;
    object_attributes.group = req_ctx->creds->caller_gid; /* be more selective? */
    object_attributes.mode = mode;

    switch (type) {
    case REGULAR_FILE:
            fsal_status = dir_handle->ops->create(dir_handle, req_ctx,
                                                  name,
                                                  &object_attributes,
                                                  &object_handle);
            break;

    case DIRECTORY:
            fsal_status = dir_handle->ops->mkdir(dir_handle, req_ctx,
                                                 name,
                                                 &object_attributes,
                                                 &object_handle);
            break;

    case SYMBOLIC_LINK:
            fsal_status = dir_handle->ops->symlink(dir_handle, req_ctx,
                                                   name,
                                                   create_arg->link_content,
                                                   &object_attributes,
                                                   &object_handle);
            break;

        case SOCKET_FILE:
        case FIFO_FILE:
            fsal_status = dir_handle->ops->mknode(dir_handle, req_ctx,
                                                  name,
                                                  type,
                                                  NULL, /* no dev_t needed */
                                                  &object_attributes,
                                                  &object_handle);
            break;

        case BLOCK_FILE:
        case CHARACTER_FILE:
            fsal_status = dir_handle->ops->mknode(dir_handle, req_ctx,
                                                  name,
                                                  type,
                                                  &create_arg->dev_spec,
                                                  &object_attributes,
                                                  &object_handle);
            break;

    default:
            /* we should never go there */
            status = CACHE_INODE_INCONSISTENT_ENTRY;
            *entry = NULL;
            goto out;
            break;
    }

     cache_inode_refresh_attrs_locked(parent, req_ctx);

     /* Check for the result */
     if (FSAL_IS_ERROR(fsal_status)) {
          if (fsal_status.major == ERR_FSAL_STALE) {
               LogEvent(COMPONENT_CACHE_INODE,
                        "FSAL returned STALE on create type %d", type);
               cache_inode_kill_entry(parent);
          } else if (fsal_status.major == ERR_FSAL_EXIST) {
               /* Already exists. Check if type if correct */
               status = cache_inode_lookup(parent,
                                           name,
                                           req_ctx,
                                           entry);
               if (*entry != NULL) {
                    status = CACHE_INODE_ENTRY_EXISTS;
                    if ((*entry)->type != type) {
                         /* Incompatible types, returns NULL */
                         cache_inode_put(*entry);
                         *entry = NULL;
                    }
                    goto out;
               }

               if (status == CACHE_INODE_NOT_FOUND) {
                    /* Too bad, FSAL insist the file exists when we try to
                     * create it, but lookup couldn't find it, retry. */
                    status = CACHE_INODE_INCONSISTENT_ENTRY;
                    goto out;
               }
          }

          status = cache_inode_error_convert(fsal_status);
          *entry = NULL;
          goto out;
     }
     status = cache_inode_new_entry(object_handle,
				    CACHE_INODE_FLAG_CREATE,
				    entry);
     if (*entry == NULL) {
          goto out;
     }

     PTHREAD_RWLOCK_wrlock(&parent->content_lock);
     /* Add this entry to the directory (also takes an internal ref) */
     status = cache_inode_add_cached_dirent(parent,
					    name,
					    *entry,
					    NULL);
     PTHREAD_RWLOCK_unlock(&parent->content_lock);
     if (status != CACHE_INODE_SUCCESS) {
          cache_inode_put(*entry);
          *entry = NULL;
          goto out;
     }

out:
     return status;
}
/**
 * nfs4_op_readdir: The NFS4_OP_READDIR.
 * 
 * Implements the NFS4_OP_READDIR. If fh is a pseudo FH, then call is routed to routine nfs4_op_readdir_pseudo
 *
 * @param op    [IN]    pointer to nfs4_op arguments
 * @param data  [INOUT] Pointer to the compound request's data
 * @param resp  [IN]    Pointer to nfs4_op results
 * 
 * @return NFS4_OK if ok, any other value show an error.
 *
 */
int nfs4_op_readdir(struct nfs_argop4 *op,
                    compound_data_t * data, struct nfs_resop4 *resp)
{
  cache_entry_t *dir_pentry = NULL;
  cache_entry_t *pentry = NULL;

  cache_inode_endofdir_t eod_met;
  fsal_attrib_list_t attrlookup;
  cache_inode_status_t cache_status;
  cache_inode_status_t cache_status_attr;

  char __attribute__ ((__unused__)) funcname[] = "nfs4_op_readdir";

  unsigned long dircount;
  unsigned long maxcount;
  entry4 *entry_nfs_array;
  cache_inode_dir_entry_t *dirent_array;
  verifier4 cookie_verifier;
  unsigned int cookie = 0;
  unsigned int end_cookie = 0;
  unsigned int *cookie_array;
  fsal_handle_t *entry_FSALhandle;
  nfs_fh4 entryFH;
  char val_fh[NFS4_FHSIZE];
  entry_name_array_item_t *entry_name_array;
  unsigned long space_used;
  unsigned int estimated_num_entries;
  unsigned int num_entries;

  unsigned int i = 0;

  bitmap4 RdAttrErrorBitmap;
  attrlist4 RdAttrErrorVals;

  resp->resop = NFS4_OP_READDIR;
  res_READDIR4.status = NFS4_OK;

  entryFH.nfs_fh4_len = 0;
  entryFH.nfs_fh4_val = val_fh;

  /* If there is no FH */
  if(nfs4_Is_Fh_Empty(&(data->currentFH)))
    {
      res_READDIR4.status = NFS4ERR_NOFILEHANDLE;
      return res_READDIR4.status;
    }

  /* If the filehandle is invalid */
  if(nfs4_Is_Fh_Invalid(&(data->currentFH)))
    {
      res_READDIR4.status = NFS4ERR_BADHANDLE;
      return res_READDIR4.status;
    }

  /* Tests if the Filehandle is expired (for volatile filehandle) */
  if(nfs4_Is_Fh_Expired(&(data->currentFH)))
    {
      res_READDIR4.status = NFS4ERR_FHEXPIRED;
      return res_READDIR4.status;
    }

  /* Pseudo Fs management */
  if(nfs4_Is_Fh_Pseudo(&(data->currentFH)))
    return nfs4_op_readdir_pseudo(op, data, resp);

  /* Xattrs management */
  if(nfs4_Is_Fh_Xattr(&(data->currentFH)))
    return nfs4_op_readdir_xattr(op, data, resp);

  /* You can readdir only within a directory */
  dir_pentry = data->current_entry;
  if(data->current_filetype != DIR_BEGINNING && data->current_filetype != DIR_CONTINUE)
    {
      res_READDIR4.status = NFS4ERR_NOTDIR;
      return res_READDIR4.status;
    }

  /* get the caracteristic value for readdir operation */
  dircount = arg_READDIR4.dircount;
  maxcount = arg_READDIR4.maxcount;
  cookie = (unsigned int)arg_READDIR4.cookie;
  space_used = sizeof(entry4);

  /* dircount is considered meaningless by many nfsv4 client (like the CITI one). we use maxcount instead */
  estimated_num_entries = maxcount / sizeof(entry4);    /* Estimated_num_entries is probably far too big */

  LogFullDebug(COMPONENT_NFS_V4,
      "--- nfs4_op_readdir ---> dircount=%u maxcount=%u arg_cookie=%llu cookie=%d estimated_num_entries=%u\n",
       dircount, maxcount, arg_READDIR4.cookie, cookie, estimated_num_entries);

  /* Do not use a cookie of 1 or 2 (reserved values) */
  if(cookie == 1 || cookie == 2)
    {
      res_READDIR4.status = NFS4ERR_BAD_COOKIE;
      return res_READDIR4.status;
    }

  if(cookie != 0)
    cookie = cookie - 2;        /* 0,1 and 2 are reserved, there is a delta of '3' because of this */

  /* Get only attributes that are allowed to be read */
  if(!nfs4_Fattr_Check_Access_Bitmap(&arg_READDIR4.attr_request, FATTR4_ATTR_READ))
    {
      res_READDIR4.status = NFS4ERR_INVAL;
      return res_READDIR4.status;
    }

  /* If maxcount is too short, return NFS4ERR_TOOSMALL */
  if(maxcount < sizeof(entry4) || estimated_num_entries == 0)
    {
      res_READDIR4.status = NFS4ERR_TOOSMALL;
      return res_READDIR4.status;
    }

  /*
   * If cookie verifier is used, then an non-trivial value is
   * returned to the client         This value is the mtime of
   * the pentry. If verifier is unused (as in many NFS
   * Servers) then only a set of zeros is returned (trivial
   * value) 
   */
  memset(cookie_verifier, 0, NFS4_VERIFIER_SIZE);
  if(data->pexport->UseCookieVerifier == 1)
    memcpy(cookie_verifier, &dir_pentry->internal_md.mod_time, sizeof(time_t));

  /* Cookie delivered by the server and used by the client SHOULD not ne 0, 1 or 2 (cf RFC3530, page192)
   * because theses value are reserved for special use.
   *      0 - cookie for first READDIR
   *      1 - reserved for . on client handside
   *      2 - reserved for .. on client handside
   * Entries '.' and '..' are not returned also
   * For these reason, there will be an offset of 3 between NFS4 cookie and HPSS cookie */

  if((cookie != 0) && (data->pexport->UseCookieVerifier == 1))
    {
      if(memcmp(cookie_verifier, arg_READDIR4.cookieverf, NFS4_VERIFIER_SIZE) != 0)
        {

          res_READDIR4.status = NFS4ERR_BAD_COOKIE;
          return res_READDIR4.status;
        }
    }

  /* The default behaviour is to consider that eof is not reached, the returned values by cache_inode_readdir 
   * will let us know if eod was reached or not */
  res_READDIR4.READDIR4res_u.resok4.reply.eof = FALSE;

  /* Get prepared for readdir */
  if((dirent_array =
      (cache_inode_dir_entry_t *) Mem_Alloc(estimated_num_entries *
                                            sizeof(cache_inode_dir_entry_t))) == NULL)
    {
      res_READDIR4.status = NFS4ERR_SERVERFAULT;
      return res_READDIR4.status;
    }

  if((cookie_array =
      (unsigned int *)Mem_Alloc(estimated_num_entries * sizeof(unsigned int))) == NULL)
    {
      Mem_Free((char *)dirent_array);

      res_READDIR4.status = NFS4ERR_SERVERFAULT;
      return res_READDIR4.status;
    }

  /* Perform the readdir operation */
  if(cache_inode_readdir(dir_pentry,
                         cookie,
                         estimated_num_entries,
                         &num_entries,
                         &end_cookie,
                         &eod_met,
                         dirent_array,
                         cookie_array,
                         data->ht,
                         data->pclient,
                         data->pcontext, &cache_status) != CACHE_INODE_SUCCESS)
    {
      res_READDIR4.status = nfs4_Errno(cache_status);
      return res_READDIR4.status;
    }

  /* For an empty directory, we will find only . and .., so reply af if the end if reached */
  if(num_entries == 0)
    {
      /* only . and .. */
      res_READDIR4.READDIR4res_u.resok4.reply.entries = NULL;
      res_READDIR4.READDIR4res_u.resok4.reply.eof = TRUE;
      memcpy(res_READDIR4.READDIR4res_u.resok4.cookieverf, cookie_verifier,
             NFS4_VERIFIER_SIZE);
    }
  else
    {
      /* Allocation of reply structures */
      if((entry_name_array =
          (entry_name_array_item_t *) Mem_Alloc(num_entries *
                                                (FSAL_MAX_NAME_LEN + 1))) == NULL)
        {
          LogError(COMPONENT_NFS_V4, ERR_SYS, ERR_MALLOC, errno);
          res_READDIR4.status = NFS4ERR_SERVERFAULT;
          return res_READDIR4.status;
        }
      memset((char *)entry_name_array, 0, num_entries * (FSAL_MAX_NAME_LEN + 1));

      if((entry_nfs_array = (entry4 *) Mem_Alloc(num_entries * sizeof(entry4))) == NULL)
        {
          LogError(COMPONENT_NFS_V4, ERR_SYS, ERR_MALLOC, errno);
          res_READDIR4.status = NFS4ERR_SERVERFAULT;
          return res_READDIR4.status;
        }

      for(i = 0; i < num_entries; i++)
        {
          entry_nfs_array[i].name.utf8string_val = entry_name_array[i];

          if(str2utf8(dirent_array[i].name.name, &entry_nfs_array[i].name) == -1)
            {
              res_READDIR4.status = NFS4ERR_SERVERFAULT;
              return res_READDIR4.status;
            }

          /* Set the cookie value */
          if(i != num_entries - 1)
            entry_nfs_array[i].cookie = cookie_array[i + 1] + 2;        /* 0, 1 and 2 are reserved */
          else
            entry_nfs_array[i].cookie = end_cookie + 2;

          LogFullDebug(COMPONENT_NFS_V4, " === nfs4_op_readdir ===>   i=%d name=%s cookie=%llu\n",
                 i, dirent_array[i].name.name, entry_nfs_array[i].cookie);

          /* Get the pentry for the object's attributes and filehandle */
          if((pentry = cache_inode_lookup(dir_pentry,
                                          &dirent_array[i].name,
                                          &attrlookup,
                                          data->ht,
                                          data->pclient,
                                          data->pcontext, &cache_status)) == NULL)
            {
              Mem_Free((char *)entry_nfs_array);
              Mem_Free((char *)dirent_array);
              Mem_Free((char *)cookie_array);
              /* Return the fattr4_rdattr_error , cf RFC3530, page 192 */
              entry_nfs_array[i].attrs.attrmask = RdAttrErrorBitmap;
              entry_nfs_array[i].attrs.attr_vals = RdAttrErrorVals;
              res_READDIR4.status = NFS4ERR_SERVERFAULT;
              return res_READDIR4.status;
            }

          /* If file handle is asked in the attributes, provide it */
          if(arg_READDIR4.attr_request.bitmap4_val != NULL
             && (arg_READDIR4.attr_request.bitmap4_val[0] & FATTR4_FILEHANDLE))
            {
              if((entry_FSALhandle =
                  cache_inode_get_fsal_handle(pentry, &cache_status_attr)) == NULL)
                {
                  /* Faulty Handle or pentry */
                  Mem_Free((char *)entry_nfs_array);
                  Mem_Free((char *)dirent_array);
                  Mem_Free((char *)cookie_array);
                  res_READDIR4.status = NFS4ERR_SERVERFAULT;
                  return res_READDIR4.status;
                }

              if(!nfs4_FSALToFhandle(&entryFH, entry_FSALhandle, data))
                {
                  /* Faulty type */
                  Mem_Free((char *)entry_nfs_array);
                  Mem_Free((char *)dirent_array);
                  Mem_Free((char *)cookie_array);
                  res_READDIR4.status = NFS4ERR_SERVERFAULT;
                  return res_READDIR4.status;
                }
            }

          if(nfs4_FSALattr_To_Fattr(data->pexport,
                                    &attrlookup,
                                    &(entry_nfs_array[i].attrs),
                                    data, &entryFH, &(arg_READDIR4.attr_request)) != 0)
            {
              /* Return the fattr4_rdattr_error , cf RFC3530, page 192 */
              entry_nfs_array[i].attrs.attrmask = RdAttrErrorBitmap;
              entry_nfs_array[i].attrs.attr_vals = RdAttrErrorVals;
            }

          /* Chain the entries together */
          entry_nfs_array[i].nextentry = NULL;
          if(i != 0)
            entry_nfs_array[i - 1].nextentry = &(entry_nfs_array[i]);

          /* This test is there to avoid going further than the buffer provided by the client 
           * the factor "9/10" is there for safety. Its value could be change as beta tests will be done */
          if((caddr_t)
             ((caddr_t) (&entry_nfs_array[i]) - (caddr_t) (&entry_nfs_array[0])) >
             (caddr_t) (maxcount * 9 / 10))
            break;
        }                       /* for i */

      if((eod_met == END_OF_DIR) && (i == num_entries))
        {
          /* This is the end of the directory */
          res_READDIR4.READDIR4res_u.resok4.reply.eof = TRUE;
          memcpy(res_READDIR4.READDIR4res_u.resok4.cookieverf, cookie_verifier,
                 NFS4_VERIFIER_SIZE);
        }

      /* Put the entry's list in the READDIR reply */
      res_READDIR4.READDIR4res_u.resok4.reply.entries = entry_nfs_array;
    }

  /* Do not forget to set the verifier */
  memcpy((char *)res_READDIR4.READDIR4res_u.resok4.cookieverf, cookie_verifier,
         NFS4_VERIFIER_SIZE);

  Mem_Free((char *)dirent_array);
  Mem_Free((char *)cookie_array);
  res_READDIR4.status = NFS4_OK;

  return res_READDIR4.status;
}                               /* nfs4_op_readdir */
main(int argc, char *argv[])
{
  char localmachine[256];

  cache_inode_client_t client;
  LRU_parameter_t lru_param;
  LRU_status_t lru_status;
  cache_inode_fsal_data_t fsdata;

  fsal_status_t status;
  fsal_parameter_t init_param;
  fsal_name_t name;
  fsal_path_t path;
  fsal_attrib_mask_t mask;
  fsal_path_t pathroot;
  fsal_attrib_list_t attribs;
  fsal_handle_t root_handle;

  cache_inode_endofdir_t eod_met;
  cache_inode_dir_entry_t dirent_array[100];
  cache_inode_dir_entry_t dirent_array_loop[5];
  unsigned int nbfound;

  unsigned int begin_cookie = 0;
  hash_buffer_t key, value;

  uid_t uid;
  fsal_cred_t cred;

  cache_inode_status_t cache_status;
  cache_inode_parameter_t cache_param;
  cache_inode_client_parameter_t cache_client_param;

  hash_table_t *ht = NULL;
  fsal_attrib_list_t attrlookup;
  cache_entry_t *cache_entry_root = NULL;
  cache_entry_t *cache_entry_lookup = NULL;
  cache_entry_t *cache_entry_lookup2 = NULL;
  cache_entry_t *cache_entry_lookup3 = NULL;
  cache_entry_t *cache_entry_lookup4 = NULL;
  cache_entry_t *cache_entry_dircont = NULL;

  cache_inode_gc_policy_t gcpol;

  char *configfile = argv[1];
  int i = 0;
  int rc = 0;

  /* Init the Buddy System allocation */
  if((rc = BuddyInit(NULL)) != BUDDY_SUCCESS)
    {
      LogTest("Error initializing memory allocator");
      exit(1);
    }


  /* init debug */
  SetDefaultLogging("TEST");
  SetNamePgm("test_cache_inode");
  SetNameFunction("main");
  InitLogging();

#if defined( _USE_GHOSTFS )
  if(argc != 2)
    {
      LogTest("Please set the configuration file as parameter");
      exit(1);
    }
#endif

  /* Obtention du nom de la machine */
  if(gethostname(localmachine, sizeof(localmachine)) != 0)
    {
      LogError(COMPONENT_STDOUT,ERR_SYS, ERR_GETHOSTNAME, errno);
      exit(1);
    }
  else
    SetNameHost(localmachine);

  AddFamilyError(ERR_FSAL, "FSAL related Errors", tab_errstatus_FSAL);
  AddFamilyError(ERR_CACHE_INODE, "FSAL related Errors", tab_errstatus_cache_inode);

  /* creating log */
  LogTest( "Starting the test");
  LogTest( "-----------------");

#if defined( _USE_GHOSTFS )
  if(FSAL_IS_ERROR(status = FSAL_str2path(configfile,
                                          strlen(configfile) + 1,
                                          &(init_param.fs_specific_info.
                                            definition_file))))
    {
      LogError(COMPONENT_STDOUT,ERR_FSAL, status.major, status.minor);
    }
#elif defined( _USE_HPSS )

  FSAL_SET_INIT_DEFAULT(init_param.fs_specific_info, Flags);
  FSAL_SET_INIT_DEFAULT(init_param.fs_specific_info, DebugValue);
  FSAL_SET_INIT_DEFAULT(init_param.fs_specific_info, TransferType);
  FSAL_SET_INIT_DEFAULT(init_param.fs_specific_info, NumRetries);
  FSAL_SET_INIT_DEFAULT(init_param.fs_specific_info, BusyDelay);
  FSAL_SET_INIT_DEFAULT(init_param.fs_specific_info, BusyRetries);
  FSAL_SET_INIT_DEFAULT(init_param.fs_specific_info, TotalDelay);
  FSAL_SET_INIT_DEFAULT(init_param.fs_specific_info, GKTotalDelay);
  FSAL_SET_INIT_DEFAULT(init_param.fs_specific_info, LimitedRetries);
  FSAL_SET_INIT_DEFAULT(init_param.fs_specific_info, MaxConnections);
  FSAL_SET_INIT_DEFAULT(init_param.fs_specific_info, ReuseDataConnections);
  FSAL_SET_INIT_DEFAULT(init_param.fs_specific_info, UsePortRange);
  FSAL_SET_INIT_DEFAULT(init_param.fs_specific_info, RetryStageInp);
  FSAL_SET_INIT_DEFAULT(init_param.fs_specific_info, DMAPWriteUpdates);
  FSAL_SET_INIT_DEFAULT(init_param.fs_specific_info, ServerName);
  FSAL_SET_INIT_DEFAULT(init_param.fs_specific_info, DescName);

  init_param.fs_specific_info.behaviors.PrincipalName = FSAL_INIT_FORCE_VALUE;
  strncpy(init_param.fs_specific_info.hpss_config.PrincipalName,
          HPSS_SSM, HPSS_MAX_PRINCIPAL_NAME);

  init_param.fs_specific_info.behaviors.KeytabPath = FSAL_INIT_FORCE_VALUE;
  strncpy(init_param.fs_specific_info.hpss_config.KeytabPath,
          HPSS_KEYTAB, HPSS_MAX_PATH_NAME);

  FSAL_SET_INIT_DEFAULT(init_param.fs_specific_info, DebugPath);
  FSAL_SET_INIT_DEFAULT(init_param.fs_specific_info, HostName);
  FSAL_SET_INIT_DEFAULT(init_param.fs_specific_info, RegistrySiteName);

#endif

  /* 2-common info (default) */
  FSAL_SET_INIT_DEFAULT(init_param.fs_common_info, maxfilesize);
  FSAL_SET_INIT_DEFAULT(init_param.fs_common_info, maxlink);
  FSAL_SET_INIT_DEFAULT(init_param.fs_common_info, maxnamelen);
  FSAL_SET_INIT_DEFAULT(init_param.fs_common_info, maxpathlen);
  FSAL_SET_INIT_DEFAULT(init_param.fs_common_info, no_trunc);
  FSAL_SET_INIT_DEFAULT(init_param.fs_common_info, chown_restricted);
  FSAL_SET_INIT_DEFAULT(init_param.fs_common_info, case_insensitive);
  FSAL_SET_INIT_DEFAULT(init_param.fs_common_info, case_preserving);
  FSAL_SET_INIT_DEFAULT(init_param.fs_common_info, fh_expire_type);
  FSAL_SET_INIT_DEFAULT(init_param.fs_common_info, link_support);
  FSAL_SET_INIT_DEFAULT(init_param.fs_common_info, symlink_support);
  FSAL_SET_INIT_DEFAULT(init_param.fs_common_info, named_attr);
  FSAL_SET_INIT_DEFAULT(init_param.fs_common_info, unique_handles);
  FSAL_SET_INIT_DEFAULT(init_param.fs_common_info, lease_time);
  FSAL_SET_INIT_DEFAULT(init_param.fs_common_info, acl_support);
  FSAL_SET_INIT_DEFAULT(init_param.fs_common_info, cansettime);
  FSAL_SET_INIT_DEFAULT(init_param.fs_common_info, homogenous);
  FSAL_SET_INIT_DEFAULT(init_param.fs_common_info, maxread);
  FSAL_SET_INIT_DEFAULT(init_param.fs_common_info, maxwrite);

  /* Init */
  if(FSAL_IS_ERROR(status = FSAL_Init(&init_param)))
    {
      LogError(COMPONENT_STDOUT,ERR_FSAL, status.major, status.minor);
    }

  /* getting creds */
  uid = getuid();

  if(FSAL_IS_ERROR(status = FSAL_GetUserCred(uid, NULL, &cred)))
    {
      LogError(COMPONENT_STDOUT,ERR_FSAL, status.major, status.minor);
    }

  /* Init of the cache inode module */
  cache_param.hparam.index_size = 31;
  cache_param.hparam.alphabet_length = 10;      /* Buffer seen as a decimal polynom */
  cache_param.hparam.nb_node_prealloc = 100;
  cache_param.hparam.hash_func_key = cache_inode_fsal_hash_func;
  cache_param.hparam.hash_func_rbt = cache_inode_fsal_rbt_func;
  cache_param.hparam.hash_func_both = NULL ; /* BUGAZOMEU */
  cache_param.hparam.compare_key = cache_inode_compare_key_fsal;
  cache_param.hparam.key_to_str = display_key;
  cache_param.hparam.val_to_str = display_value;

  if((ht = cache_inode_init(cache_param, &cache_status)) == NULL)
    {
      LogTest( "Error %d while init hash ", cache_status);
    }
  else
    LogTest( "Hash Table address = %p", ht);

  /* We need a cache_client to acces the cache */
  cache_client_param.attrmask =
      FSAL_ATTRS_MANDATORY | FSAL_ATTR_MTIME | FSAL_ATTR_CTIME | FSAL_ATTR_ATIME;
  cache_client_param.nb_prealloc_entry = 1000;
  cache_client_param.nb_pre_dir_data = 200;
  cache_client_param.nb_pre_parent = 1200;
  cache_client_param.nb_pre_state_v4 = 100;

  cache_client_param.lru_param.nb_entry_prealloc = 1000;
  cache_client_param.lru_param.entry_to_str = lru_entry_to_str;
  cache_client_param.lru_param.clean_entry = lru_clean_entry;

  cache_client_param.grace_period_attr   = 0;
  cache_client_param.grace_period_link   = 0;
  cache_client_param.grace_period_dirent = 0;
  cache_client_param.expire_type_attr    = CACHE_INODE_EXPIRE_NEVER;
  cache_client_param.expire_type_link    = CACHE_INODE_EXPIRE_NEVER;
  cache_client_param.expire_type_dirent  = CACHE_INODE_EXPIRE_NEVER;

  /* Init the cache_inode client */
  if(cache_inode_client_init(&client, &cache_client_param, 0, NULL) != 0)
    exit(1);

  /* Init the gc */
  gcpol.file_expiration_delay = 3;
  gcpol.directory_expiration_delay = 4;
  gcpol.hwmark_nb_entries = 6;
  gcpol.lwmark_nb_entries = 3;
  gcpol.run_interval = 4;

  cache_inode_set_gc_policy(gcpol);

  /* Getting the root of the FS */
  if((FSAL_IS_ERROR(status = FSAL_str2path("/", 2, &pathroot))))
    {
      LogError(COMPONENT_STDOUT,ERR_FSAL, status.major, status.minor);
      exit(1);
    }

  if((FSAL_IS_ERROR(status = FSAL_lookupPath(&pathroot, &cred, &root_handle, &attribs))))
    {
      LogError(COMPONENT_STDOUT,ERR_FSAL, status.major, status.minor);
      exit(1);
    }
  fsdata.cookie = 0;
  fsdata.handle = root_handle;

  /* Cache the root of the FS */
  if((cache_entry_root =
      cache_inode_make_root(&fsdata, 1, ht, &client, &cred, &cache_status)) == NULL)
    {
      LogTest( "Error: can't init fs's root");
      exit(1);
    }

  /* A lookup in the root fsal */
  if((FSAL_IS_ERROR(status = FSAL_str2name("cea", 10, &name))))
    {
      LogError(COMPONENT_STDOUT,ERR_FSAL, status.major, status.minor);
      exit(1);
    }

  if((cache_entry_lookup = cache_inode_lookup(cache_entry_root,
                                              &name,
                                              &attrlookup,
                                              ht, &client, &cred, &cache_status)) == NULL)
    {
      LogTest( "Error: can't lookup");
      exit(1);
    }

  /* Lookup a second time (entry should now be cached) */
  if((cache_entry_lookup2 = cache_inode_lookup(cache_entry_root,
                                               &name,
                                               &attrlookup,
                                               ht,
                                               &client, &cred, &cache_status)) == NULL)
    {
      LogTest( "Error: can't lookup");
      exit(1);
    }

  if(cache_entry_lookup2 != cache_entry_lookup)
    {
      LogTest("Error: lookup results should be the same");
      exit(1);
    }

  /* A lookup in the root fsal */
  if((FSAL_IS_ERROR(status = FSAL_str2name("log", 10, &name))))
    {
      LogError(COMPONENT_STDOUT,ERR_FSAL, status.major, status.minor);
      exit(1);
    }

  if((cache_entry_lookup3 = cache_inode_lookup(cache_entry_root,
                                               &name,
                                               &attrlookup,
                                               ht,
                                               &client, &cred, &cache_status)) == NULL)
    {
      LogTest( "Error: can't lookup");
      exit(1);
    }

  if((cache_entry_lookup4 = cache_inode_lookup(cache_entry_root,
                                               &name,
                                               &attrlookup,
                                               ht,
                                               &client, &cred, &cache_status)) == NULL)
    {
      LogTest( "Error: can't lookup");
      exit(1);
    }

  if(cache_entry_lookup3 != cache_entry_lookup4)
    {
      LogTest("Error: lookup results should be the same");
      exit(1);
    }

  /* A lookup in the root fsal */
  if((FSAL_IS_ERROR(status = FSAL_str2name("SunOS_5", 10, &name))))
    {
      LogError(COMPONENT_STDOUT,ERR_FSAL, status.major, status.minor);
      exit(1);
    }

  cache_inode_print_dir(cache_entry_root);

  /* Test readdir */
  if(cache_inode_readdir(cache_entry_root,
                         0,
                         100,
                         &nbfound,
                         &eod_met,
                         dirent_array,
                         ht, &client, &cred, &cache_status) != CACHE_INODE_SUCCESS)
    {
      LogTest( "Error: cache_inode_readdir failed");
      exit(1);
    }

  LogTest( "Readdir nbfound=%d, eod_met=%d", nbfound, eod_met);
  for(i = 0; i < nbfound; i++)
    LogTest( "dirent_array[%d] ==> %s | %p", i,
                 dirent_array[i].name.name, dirent_array[i].pentry);

  cache_inode_print_dir(cache_entry_root);

  /* looping on readir */
  LogTest( "Loop directory in several pass");

  eod_met = TO_BE_CONTINUED;
  begin_cookie = 0;

  do
    {

      if(cache_inode_readdir(cache_entry_root,
                             begin_cookie,
                             2,
                             &nbfound,
                             &eod_met,
                             dirent_array_loop,
                             ht, &client, &cred, &cache_status) != CACHE_INODE_SUCCESS)
        {
          LogTest("Error: cache_inode_readdir failed: %d", cache_status);
          exit(1);
        }

      for(i = 0; i < nbfound; i++)
        LogTest( " ==> %s | %p", dirent_array_loop[i].name.name,
                     dirent_array_loop[i].pentry);

      begin_cookie += nbfound;

    }
  while(eod_met == TO_BE_CONTINUED);

  LogTest( "---------------------------------");

  /* A lookup in the root fsal */
  if((FSAL_IS_ERROR(status = FSAL_str2name("cea", 10, &name))))
    {
      LogError(COMPONENT_STDOUT,ERR_FSAL, status.major, status.minor);
      exit(1);
    }

  if((cache_entry_lookup = cache_inode_lookup(cache_entry_root,
                                              &name,
                                              &attrlookup,
                                              ht, &client, &cred, &cache_status)) == NULL)
    {
      LogTest( "Error: can't lookup");
      exit(1);
    }

  /* A lookup in the root fsal */
  if((FSAL_IS_ERROR(status = FSAL_str2name("log", 10, &name))))
    {
      LogError(COMPONENT_STDOUT,ERR_FSAL, status.major, status.minor);
      exit(1);
    }

  if((cache_entry_lookup = cache_inode_lookup(cache_entry_root,
                                              &name,
                                              &attrlookup,
                                              ht, &client, &cred, &cache_status)) == NULL)
    {
      LogTest( "Error: can't lookup");
      exit(1);
    }
  /* Print the Hash Table */
  HashTable_Log(COMPONENT_STDOUT, ht);

  LogTest( "Readdir nbfound=%d, eod_met=%d", nbfound, eod_met);
  for(i = 0; i < nbfound; i++)
    LogTest( "dirent_array[%d] ==> %s | %p ", i,
                 dirent_array[i].name.name, dirent_array[i].pentry);

  /* Call the GC */
  LogTest( "Sleeping %d second before gc (for gc invalidation)",
               gcpol.file_expiration_delay + 2);
  sleep(gcpol.file_expiration_delay + 2);

  if(cache_inode_gc(ht, &client, &cache_status) != CACHE_INODE_SUCCESS)
    {
      LogTest( "Error: cache_inode_gc failed");
      exit(1);
    }
  LogTest( "GC performed successfully");

  /* Print the Hash Table */
  HashTable_Log(COMPONENT_STDOUT, ht);

  /* Another readdir, after gc is made */
  eod_met = TO_BE_CONTINUED;
  begin_cookie = 0;

  LogTest( "ANOTHER READDIR AFTER GC");

  do
    {

      if(cache_inode_readdir(cache_entry_root,
                             begin_cookie,
                             2,
                             &nbfound,
                             &eod_met,
                             dirent_array_loop,
                             ht, &client, &cred, &cache_status) != CACHE_INODE_SUCCESS)
        {
          LogTest("Error: cache_inode_readdir failed: %d", cache_status);
          exit(1);
        }

      for(i = 0; i < nbfound; i++)
        LogTest( " ==> %s | %p", dirent_array_loop[i].name.name,
                     dirent_array_loop[i].pentry);

      begin_cookie += nbfound;

    }
  while(eod_met == TO_BE_CONTINUED);

  LogTest( "---------------------------------");

  /* Print the Hash Table */
  HashTable_Log(COMPONENT_STDOUT, ht);

  LogTest( "---------------------------------");

  /* The end of all the tests */
  LogTest( "All tests exited successfully");

  exit(0);
}                               /* main */
Beispiel #7
0
int nfs_Mkdir(nfs_arg_t * parg,
              exportlist_t * pexport,
              fsal_op_context_t * pcontext,
              cache_inode_client_t * pclient,
              hash_table_t * ht, struct svc_req *preq, nfs_res_t * pres)
{
  static char __attribute__ ((__unused__)) funcName[] = "nfs_Mkdir";

  char *str_dir_name = NULL;
  fsal_accessmode_t mode = 0;
  cache_entry_t *dir_pentry = NULL;
  cache_entry_t *parent_pentry = NULL;
  int rc = 0;
  fsal_attrib_list_t parent_attr;
  fsal_attrib_list_t attr;
  fsal_attrib_list_t *ppre_attr;
  fsal_attrib_list_t attr_parent_after;
  cache_inode_file_type_t parent_filetype;
  fsal_handle_t *pfsal_handle;
  fsal_name_t dir_name;
  cache_inode_status_t cache_status = CACHE_INODE_SUCCESS;
  cache_inode_status_t cache_status_lookup;

  if(isDebug(COMPONENT_NFSPROTO))
    {
      char str[LEN_FH_STR];

      switch (preq->rq_vers)
        {
        case NFS_V2:
          str_dir_name = parg->arg_mkdir2.where.name;
          break;
        case NFS_V3:
          str_dir_name = parg->arg_mkdir3.where.name;
          break;
        }

      nfs_FhandleToStr(preq->rq_vers,
                       &(parg->arg_mkdir2.where.dir),
                       &(parg->arg_mkdir3.where.dir),
                       NULL,
                       str);
      LogDebug(COMPONENT_NFSPROTO,
               "REQUEST PROCESSING: Calling nfs_Mkdir handle: %s name: %s",
               str, str_dir_name);
    }

  if(preq->rq_vers == NFS_V3)
    {
      /* to avoid setting it on each error case */
      pres->res_mkdir3.MKDIR3res_u.resfail.dir_wcc.before.attributes_follow = FALSE;
      pres->res_mkdir3.MKDIR3res_u.resfail.dir_wcc.after.attributes_follow = FALSE;
      ppre_attr = NULL;
    }

  if((parent_pentry = nfs_FhandleToCache(preq->rq_vers,
                                         &(parg->arg_mkdir2.where.dir),
                                         &(parg->arg_mkdir3.where.dir),
                                         NULL,
                                         &(pres->res_dirop2.status),
                                         &(pres->res_mkdir3.status),
                                         NULL,
                                         &parent_attr,
                                         pcontext, pclient, ht, &rc)) == NULL)
    {
      /* Stale NFS FH ? */
      return rc;
    }

  /* get directory attributes before action (for V3 reply) */
  ppre_attr = &parent_attr;

  /* Extract the filetype */
  parent_filetype = cache_inode_fsal_type_convert(parent_attr.type);

  /*
   * Sanity checks: 
   */
  if(parent_filetype != DIRECTORY)
    {
      switch (preq->rq_vers)
        {
        case NFS_V2:
          pres->res_dirop2.status = NFSERR_NOTDIR;
          break;

        case NFS_V3:
          pres->res_mkdir3.status = NFS3ERR_NOTDIR;
          break;
        }

      return NFS_REQ_OK;
    }

  switch (preq->rq_vers)
    {
    case NFS_V2:
      str_dir_name = parg->arg_mkdir2.where.name;

      if(parg->arg_mkdir2.attributes.mode != (unsigned int)-1)
        {
          mode = (fsal_accessmode_t) parg->arg_mkdir2.attributes.mode;
        }
      else
        {
          mode = (fsal_accessmode_t) 0;
        }
      break;

    case NFS_V3:
      str_dir_name = parg->arg_mkdir3.where.name;

      if(parg->arg_mkdir3.attributes.mode.set_it == TRUE)
        mode = (fsal_accessmode_t) parg->arg_mkdir3.attributes.mode.set_mode3_u.mode;
      else
        mode = (fsal_accessmode_t) 0;
      break;
    }

  //if(str_dir_name == NULL || strlen(str_dir_name) == 0)
  if(str_dir_name == NULL || *str_dir_name == '\0' )
    {
      if(preq->rq_vers == NFS_V2)
        pres->res_dirop2.status = NFSERR_IO;
      if(preq->rq_vers == NFS_V3)
        pres->res_mkdir3.status = NFS3ERR_INVAL;
    }
  else
    {
      /* Make the directory */
      if((cache_status = cache_inode_error_convert(FSAL_str2name(str_dir_name,
                                                                 FSAL_MAX_NAME_LEN,
                                                                 &dir_name))) ==
         CACHE_INODE_SUCCESS)
        {
          /*
           * Lookup file to see if it exists.  If so, use it.  Otherwise
           * create a new one.  
           */
          dir_pentry = cache_inode_lookup( parent_pentry,
                                           &dir_name,
                                           pexport->cache_inode_policy,
                                           &attr,
                                           ht, 
                                           pclient, 
                                           pcontext, 
                                           &cache_status_lookup);

          if(cache_status_lookup == CACHE_INODE_NOT_FOUND)
            {
              /* Create the directory */
              if((dir_pentry = cache_inode_create(parent_pentry,
                                                  &dir_name,
                                                  DIRECTORY,
                                                  pexport->cache_inode_policy,
                                                  mode,
                                                  NULL,
                                                  &attr,
                                                  ht,
                                                  pclient,
                                                  pcontext, &cache_status)) != NULL)
                {
                  /*
                   * Get the FSAL handle for this entry 
                   */
                  pfsal_handle = cache_inode_get_fsal_handle(dir_pentry, &cache_status);

                  if(cache_status == CACHE_INODE_SUCCESS)
                    {
                      switch (preq->rq_vers)
                        {
                        case NFS_V2:
                          /* Build file handle */
                          if(!nfs2_FSALToFhandle
                             (&(pres->res_dirop2.DIROP2res_u.diropok.file), pfsal_handle,
                              pexport))
                            pres->res_dirop2.status = NFSERR_IO;
                          else
                            {
                              /*
                               * Build entry
                               * attributes 
                               */
                              if(nfs2_FSALattr_To_Fattr(pexport, &attr,
                                                        &(pres->res_dirop2.DIROP2res_u.
                                                          diropok.attributes)) == 0)
                                pres->res_dirop2.status = NFSERR_IO;
                              else
                                pres->res_dirop2.status = NFS_OK;
                            }
                          break;

                        case NFS_V3:
                          /* Build file handle */
                          if((pres->res_mkdir3.MKDIR3res_u.resok.obj.post_op_fh3_u.
                              handle.data.data_val = Mem_Alloc_Label(NFS3_FHSIZE,
                                                                     "Filehandle V3 in nfs3_mkdir")) == NULL)
                            {
                              pres->res_mkdir3.status = NFS3ERR_IO;
                              return NFS_REQ_OK;
                            }

                          if(nfs3_FSALToFhandle
                             (&pres->res_mkdir3.MKDIR3res_u.resok.obj.post_op_fh3_u.
                              handle, pfsal_handle, pexport) == 0)
                            {
                              Mem_Free((char *)pres->res_mkdir3.MKDIR3res_u.resok.obj.
                                       post_op_fh3_u.handle.data.data_val);
                              pres->res_mkdir3.status = NFS3ERR_INVAL;
                              return NFS_REQ_OK;
                            }
                          else
                            {
                              /* Set Post Op Fh3 structure */
                              pres->res_mkdir3.MKDIR3res_u.resok.obj.handle_follows =
                                  TRUE;
                              pres->res_mkdir3.MKDIR3res_u.resok.obj.post_op_fh3_u.handle.
                                  data.data_len = sizeof(file_handle_v3_t);

                              /*
                               * Build entry
                               * attributes 
                               */
                              nfs_SetPostOpAttr(pcontext, pexport,
                                                dir_pentry,
                                                &attr,
                                                &(pres->res_mkdir3.MKDIR3res_u.resok.
                                                  obj_attributes));

                              /* Get the attributes of the parent after the operation */
                              cache_inode_get_attributes(parent_pentry,
                                                         &attr_parent_after);

                              /*
                               * Build Weak Cache
                               * Coherency data 
                               */
                              nfs_SetWccData(pcontext, pexport,
                                             parent_pentry,
                                             ppre_attr,
                                             &attr_parent_after,
                                             &(pres->res_mkdir3.MKDIR3res_u.resok.
                                               dir_wcc));

                              pres->res_mkdir3.status = NFS3_OK;
                            }

                          break;
                        }
                      return NFS_REQ_OK;
                    }
                }
            }                   /* If( cache_status_lookup == CACHE_INODE_NOT_FOUND ) */
          else
            {
              /* object already exists or failure during lookup */
              if(cache_status_lookup == CACHE_INODE_SUCCESS)
                {
                  /* Trying to create a file that already exists */
                  cache_status = CACHE_INODE_ENTRY_EXISTS;

                  switch (preq->rq_vers)
                    {
                    case NFS_V2:
                      pres->res_dirop2.status = NFSERR_EXIST;
                      break;

                    case NFS_V3:
                      pres->res_mkdir3.status = NFS3ERR_EXIST;
                      break;
                    }
                }
              else
                {
                  /* Server fault */
                  cache_status = cache_status_lookup;

                  switch (preq->rq_vers)
                    {
                    case NFS_V2:
                      pres->res_dirop2.status = NFSERR_IO;
                      break;

                    case NFS_V3:
                      pres->res_mkdir3.status = NFS3ERR_INVAL;
                      break;
                    }
                }

              nfs_SetFailedStatus(pcontext, pexport,
                                  preq->rq_vers,
                                  cache_status,
                                  &pres->res_dirop2.status,
                                  &pres->res_mkdir3.status,
                                  NULL, NULL,
                                  parent_pentry,
                                  ppre_attr,
                                  &(pres->res_mkdir3.MKDIR3res_u.resfail.dir_wcc),
                                  NULL, NULL, NULL);

              return NFS_REQ_OK;
            }
        }
    }

  /* If we are here, there was an error */
  if(nfs_RetryableError(cache_status))
    {
      return NFS_REQ_DROP;

    }
  nfs_SetFailedStatus(pcontext, pexport,
                      preq->rq_vers,
                      cache_status,
                      &pres->res_dirop2.status,
                      &pres->res_mkdir3.status,
                      NULL, NULL,
                      parent_pentry,
                      ppre_attr,
                      &(pres->res_mkdir3.MKDIR3res_u.resfail.dir_wcc), NULL, NULL, NULL);

  return NFS_REQ_OK;

}
Beispiel #8
0
int nfs_Rename(nfs_arg_t * parg /* IN  */ ,
               exportlist_t * pexport /* IN  */ ,
               fsal_op_context_t * pcontext /* IN  */ ,
               cache_inode_client_t * pclient /* IN  */ ,
               hash_table_t * ht /* INOUT */ ,
               struct svc_req *preq /* IN  */ ,
               nfs_res_t * pres /* OUT */ )
{
  static char __attribute__ ((__unused__)) funcName[] = "nfs_Rename";

  char *str_entry_name = NULL;
  fsal_name_t entry_name;
  char *str_new_entry_name = NULL;
  fsal_name_t new_entry_name;
  cache_entry_t *pentry = NULL;
  cache_entry_t *new_pentry = NULL;
  cache_entry_t *parent_pentry = NULL;
  cache_entry_t *new_parent_pentry = NULL;
  cache_entry_t *should_not_exists = NULL;
  cache_entry_t *should_exists = NULL;
  cache_inode_status_t cache_status;
  int rc;
  fsal_attrib_list_t *ppre_attr;
  fsal_attrib_list_t pre_attr;
  fsal_attrib_list_t *pnew_pre_attr;
  fsal_attrib_list_t new_attr;
  fsal_attrib_list_t new_parent_attr;
  fsal_attrib_list_t attr;
  fsal_attrib_list_t tst_attr;
  cache_inode_file_type_t parent_filetype;
  cache_inode_file_type_t new_parent_filetype;

  if(preq->rq_vers == NFS_V3)
    {
      /* to avoid setting it on each error case */
      pres->res_rename3.RENAME3res_u.resfail.fromdir_wcc.before.attributes_follow = FALSE;
      pres->res_rename3.RENAME3res_u.resfail.fromdir_wcc.after.attributes_follow = FALSE;
      pres->res_rename3.RENAME3res_u.resfail.todir_wcc.before.attributes_follow = FALSE;
      pres->res_rename3.RENAME3res_u.resfail.todir_wcc.after.attributes_follow = FALSE;
      ppre_attr = NULL;
      pnew_pre_attr = NULL;
    }

  /* Convert fromdir file handle into a cache_entry */
  if((parent_pentry = nfs_FhandleToCache(preq->rq_vers,
                                         &(parg->arg_rename2.from.dir),
                                         &(parg->arg_rename3.from.dir),
                                         NULL,
                                         &(pres->res_dirop2.status),
                                         &(pres->res_create3.status),
                                         NULL,
                                         &pre_attr, pcontext, pclient, ht, &rc)) == NULL)
    {
      /* Stale NFS FH ? */
      return rc;
    }

  /* Convert todir file handle into a cache_entry */
  if((new_parent_pentry = nfs_FhandleToCache(preq->rq_vers,
                                             &(parg->arg_rename2.to.dir),
                                             &(parg->arg_rename3.to.dir),
                                             NULL,
                                             &(pres->res_dirop2.status),
                                             &(pres->res_create3.status),
                                             NULL,
                                             &new_parent_attr,
                                             pcontext, pclient, ht, &rc)) == NULL)
    {
      /* Stale NFS FH ? */
      return rc;
    }

  /* get the attr pointers */
  ppre_attr = &pre_attr;
  pnew_pre_attr = &new_parent_attr;

  /* Get the filetypes */
  parent_filetype = cache_inode_fsal_type_convert(pre_attr.type);
  new_parent_filetype = cache_inode_fsal_type_convert(new_parent_attr.type);

  /*
   * Sanity checks: we must manage directories
   */
  if((parent_filetype != DIR_BEGINNING && parent_filetype != DIR_CONTINUE) ||
     (new_parent_filetype != DIR_BEGINNING && new_parent_filetype != DIR_CONTINUE))
    {
      switch (preq->rq_vers)
        {
        case NFS_V2:
          pres->res_stat2 = NFSERR_NOTDIR;
          break;

        case NFS_V3:
          pres->res_rename3.status = NFS3ERR_NOTDIR;
          break;
        }

      return NFS_REQ_OK;
    }

  switch (preq->rq_vers)
    {
    case NFS_V2:
      str_entry_name = parg->arg_rename2.from.name;
      str_new_entry_name = parg->arg_rename2.to.name;
      break;

    case NFS_V3:
      str_entry_name = parg->arg_rename3.from.name;
      str_new_entry_name = parg->arg_rename3.to.name;
      break;
    }

  pentry = new_pentry = NULL;

  if(str_entry_name == NULL ||
     strlen(str_entry_name) == 0 ||
     str_new_entry_name == NULL ||
     strlen(str_new_entry_name) == 0 ||
     FSAL_IS_ERROR(FSAL_str2name(str_entry_name, FSAL_MAX_NAME_LEN, &entry_name)) ||
     FSAL_IS_ERROR(FSAL_str2name(str_new_entry_name, FSAL_MAX_NAME_LEN, &new_entry_name)))
    {
      cache_status = CACHE_INODE_INVALID_ARGUMENT;
    }
  else
    {
      /*
       * Lookup file to see if new entry exists
       *
       */
      should_not_exists = cache_inode_lookup(new_parent_pentry,
                                             &new_entry_name,
                                             &tst_attr,
                                             ht, pclient, pcontext, &cache_status);

      if(cache_status == CACHE_INODE_NOT_FOUND)
        {
          /* We need to lookup over the old entry also */
          should_exists = cache_inode_lookup(parent_pentry,
                                             &entry_name,
                                             &tst_attr,
                                             ht, pclient, pcontext, &cache_status);

          /* Rename entry */
          if(cache_status == CACHE_INODE_SUCCESS)
            cache_inode_rename(parent_pentry,
                               &entry_name,
                               new_parent_pentry,
                               &new_entry_name,
                               &attr, &new_attr, ht, pclient, pcontext, &cache_status);

          if(cache_status == CACHE_INODE_SUCCESS)
            {
              switch (preq->rq_vers)
                {
                case NFS_V2:
                  pres->res_stat2 = NFS_OK;
                  break;

                case NFS_V3:
                  /*
                   * Build Weak Cache Coherency
                   * data 
                   */
                  nfs_SetWccData(pcontext, pexport,
                                 parent_pentry,
                                 ppre_attr,
                                 &attr,
                                 &(pres->res_rename3.RENAME3res_u.resok.fromdir_wcc));

                  nfs_SetWccData(pcontext, pexport,
                                 new_parent_pentry,
                                 pnew_pre_attr,
                                 &new_attr,
                                 &(pres->res_rename3.RENAME3res_u.resok.todir_wcc));

                  pres->res_rename3.status = NFS3_OK;
                  break;

                }

              return NFS_REQ_OK;
            }
        }
      else
        {
          /* If name are the same (basically renaming a/file1 to a/file1, this is a non-erroneous situation to be managed */
          if(new_parent_pentry == parent_pentry)
            {
              if(!FSAL_namecmp(&new_entry_name, &entry_name))
                {
                  /* trying to rename a file to himself, this is allowed */
                  cache_status = CACHE_INODE_SUCCESS;
                  switch (preq->rq_vers)
                    {
                    case NFS_V2:
                      pres->res_stat2 = NFS_OK;
                      break;

                    case NFS_V3:
                      /*
                       * Build Weak Cache Coherency
                       * data 
                       */
                      nfs_SetWccData(pcontext, pexport,
                                     parent_pentry,
                                     ppre_attr,
                                     &attr,
                                     &(pres->res_rename3.RENAME3res_u.resok.fromdir_wcc));

                      nfs_SetWccData(pcontext, pexport,
                                     parent_pentry,
                                     ppre_attr,
                                     &attr,
                                     &(pres->res_rename3.RENAME3res_u.resok.todir_wcc));

                      pres->res_rename3.status = NFS3_OK;
                      break;

                    }

                  return NFS_REQ_OK;
                }

            }

          /* New entry already exists. In this case (see RFC), entry should be compatible: Both are non-directories or 
           * both are directories and 'todir' is empty. If compatible, old 'todir' entry is scratched, if not returns EEXISTS */
          if(should_not_exists != NULL)
            {
              /* We need to lookup over the old entry also */
              if((should_exists = cache_inode_lookup(parent_pentry,
                                                     &entry_name,
                                                     &tst_attr,
                                                     ht,
                                                     pclient,
                                                     pcontext, &cache_status)) != NULL)
                {
                  if(cache_inode_type_are_rename_compatible
                     (should_exists, should_not_exists))
                    {
                      /* Remove the old entry before renaming it */
                      if(cache_inode_remove(new_parent_pentry,
                                            &new_entry_name,
                                            &tst_attr,
                                            ht,
                                            pclient,
                                            pcontext,
                                            &cache_status) == CACHE_INODE_SUCCESS)
                        {
                          if(cache_inode_rename(parent_pentry,
                                                &entry_name,
                                                new_parent_pentry,
                                                &new_entry_name,
                                                &attr,
                                                &new_attr,
                                                ht,
                                                pclient,
                                                pcontext,
                                                &cache_status) == CACHE_INODE_SUCCESS)
                            {
                              /* trying to rename a file to himself, this is allowed */
                              switch (preq->rq_vers)
                                {
                                case NFS_V2:
                                  pres->res_stat2 = NFS_OK;
                                  break;

                                case NFS_V3:
                                  /*
                                   * Build Weak Cache Coherency
                                   * data 
                                   */
                                  nfs_SetWccData(pcontext, pexport,
                                                 parent_pentry,
                                                 ppre_attr,
                                                 &attr,
                                                 &(pres->res_rename3.RENAME3res_u.resok.
                                                   fromdir_wcc));

                                  nfs_SetWccData(pcontext, pexport,
                                                 parent_pentry,
                                                 ppre_attr,
                                                 &attr,
                                                 &(pres->res_rename3.RENAME3res_u.resok.
                                                   todir_wcc));

                                  pres->res_rename3.status = NFS3_OK;
                                  break;

                                }

                              return NFS_REQ_OK;
                            }
                        }

                    }
                }               /*  if( cache_inode_type_are_rename_compatible( should_exists, should_not_exists ) ) */
            }

          /* if( ( should_exists = cache_inode_lookup( parent_pentry, .... */
          /* If this point is reached, then destination object already exists with that name in the directory 
             and types are not compatible, we should return that the file exists */
          cache_status = CACHE_INODE_ENTRY_EXISTS;
        }                       /* if( should_not_exists != NULL ) */
    }

  /* If we are here, there was an error */
  if(nfs_RetryableError(cache_status))
    {
      return NFS_REQ_DROP;
    }

  nfs_SetFailedStatus(pcontext, pexport,
                      preq->rq_vers,
                      cache_status,
                      &pres->res_stat2,
                      &pres->res_rename3.status,
                      NULL, NULL,
                      parent_pentry,
                      ppre_attr,
                      &(pres->res_rename3.RENAME3res_u.resfail.fromdir_wcc),
                      new_parent_pentry,
                      pnew_pre_attr, &(pres->res_rename3.RENAME3res_u.resfail.todir_wcc));

  return NFS_REQ_OK;

}                               /* nfs_Rename */
Beispiel #9
0
int nfs_Rmdir(nfs_arg_t *parg,
              exportlist_t *pexport,
              fsal_op_context_t *pcontext,
              nfs_worker_data_t *pworker,
              struct svc_req *preq,
              nfs_res_t *pres)
{
  cache_entry_t *parent_pentry = NULL;
  cache_entry_t *pentry_child = NULL;
  fsal_attrib_list_t pre_parent_attr;
  fsal_attrib_list_t parent_attr;
  fsal_attrib_list_t *ppre_attr;
  fsal_attrib_list_t pentry_child_attr;
  cache_inode_file_type_t filetype;
  cache_inode_file_type_t childtype;
  cache_inode_status_t cache_status;
  fsal_name_t name;
  char *dir_name = NULL;
  int rc = NFS_REQ_OK;

  if(isDebug(COMPONENT_NFSPROTO))
    {
      char str[LEN_FH_STR];

      switch (preq->rq_vers)
        {
        case NFS_V2:
          dir_name = parg->arg_rmdir2.name;
          break;
        case NFS_V3:
          dir_name = parg->arg_rmdir3.object.name;
          break;
        }

      nfs_FhandleToStr(preq->rq_vers,
                       &(parg->arg_rmdir2.dir),
                       &(parg->arg_rmdir3.object.dir),
                       NULL,
                       str);
      LogDebug(COMPONENT_NFSPROTO,
               "REQUEST PROCESSING: Calling nfs_Rmdir handle: %s name: %s",
               str, dir_name);
    }

  if(preq->rq_vers == NFS_V3)
    {
      /* to avoid setting it on each error case */
      pres->res_rmdir3.RMDIR3res_u.resfail.dir_wcc.before.attributes_follow = FALSE;
      pres->res_rmdir3.RMDIR3res_u.resfail.dir_wcc.after.attributes_follow = FALSE;
      ppre_attr = NULL;
    }

  /* Convert file handle into a pentry */
  if((parent_pentry = nfs_FhandleToCache(preq->rq_vers,
                                         &(parg->arg_rmdir2.dir),
                                         &(parg->arg_rmdir3.object.dir),
                                         NULL,
                                         &(pres->res_stat2),
                                         &(pres->res_rmdir3.status),
                                         NULL,
                                         &pre_parent_attr,
                                         pcontext, &rc)) == NULL)
    {
      /* Stale NFS FH ? */
      goto out;
    }

  /* get directory attributes before action (for V3 reply) */
  ppre_attr = &pre_parent_attr;

  /* Extract the filetype */
  filetype = cache_inode_fsal_type_convert(pre_parent_attr.type);

  /*
   * Sanity checks: new directory name must be non-null; parent must be
   * a directory. 
   */
  if(filetype != DIRECTORY)
    {
      switch (preq->rq_vers)
        {
        case NFS_V2:
          pres->res_stat2 = NFSERR_NOTDIR;
          break;
        case NFS_V3:
          pres->res_rmdir3.status = NFS3ERR_NOTDIR;
          break;
        }

      rc = NFS_REQ_OK;
      goto out;
    }

  switch (preq->rq_vers)
    {
    case NFS_V2:
      dir_name = parg->arg_rmdir2.name;
      break;

    case NFS_V3:
      dir_name = parg->arg_rmdir3.object.name;
      break;

    }

  //if(dir_name == NULL || strlen(dir_name) == 0)
  if(dir_name == NULL || *dir_name == '\0' )
    {
      cache_status = CACHE_INODE_INVALID_ARGUMENT;      /* for lack of better... */
    }
  else
    {
      if((cache_status = cache_inode_error_convert(FSAL_str2name(dir_name,
                                                                 FSAL_MAX_NAME_LEN,
                                                                 &name))) ==
         CACHE_INODE_SUCCESS)
        {
          /*
           * Lookup to the entry to be removed to check if it is a directory
           */
          if((pentry_child = cache_inode_lookup(parent_pentry,
                                                &name,
                                                &pentry_child_attr,
                                                pcontext,
                                                &cache_status)) != NULL)
            {
              /* Extract the filetype */
              childtype = cache_inode_fsal_type_convert(pentry_child_attr.type);

              /*
               * Sanity check: make sure we are about to remove a directory
               */
              if(childtype != DIRECTORY)
                {
                  switch (preq->rq_vers)
                    {
                    case NFS_V2:
                      pres->res_stat2 = NFSERR_NOTDIR;
                      break;

                    case NFS_V3:
                      pres->res_rmdir3.status = NFS3ERR_NOTDIR;
                      break;
                    }
                  rc = NFS_REQ_OK;
                  goto out;
                }

              /*
               * Remove the directory.  Use NULL vnode for the directory
               * that's being removed because we know the directory's name. 
               */

              if(cache_inode_remove(parent_pentry,
                                    &name,
                                    &parent_attr,
                                    pcontext, &cache_status) == CACHE_INODE_SUCCESS)
                {
                  switch (preq->rq_vers)
                    {
                    case NFS_V2:
                      pres->res_stat2 = NFS_OK;
                      break;

                    case NFS_V3:
                      /* Build Weak Cache Coherency data */
                      nfs_SetWccData(pexport,
                                     ppre_attr,
                                     &parent_attr,
                                     &(pres->res_rmdir3.RMDIR3res_u.resok.dir_wcc));

                      pres->res_rmdir3.status = NFS3_OK;
                      break;
                    }
                  rc = NFS_REQ_OK;
                  goto out;
                }
            }
        }
    }

  /* If we are here, there was an error */
  if(nfs_RetryableError(cache_status))
    {
      rc = NFS_REQ_DROP;
      goto out;
    }

  nfs_SetFailedStatus(pcontext, pexport,
                      preq->rq_vers,
                      cache_status,
                      &pres->res_stat2,
                      &pres->res_rmdir3.status,
                      NULL, NULL,
                      parent_pentry,
                      ppre_attr,
                      &(pres->res_rmdir3.RMDIR3res_u.resfail.dir_wcc), NULL, NULL, NULL);

  rc = NFS_REQ_OK;

out:
  /* return references */
  if (pentry_child)
      cache_inode_put(pentry_child);

  if (parent_pentry)
      cache_inode_put(parent_pentry);

  return (rc);

}                               /* nfs_Rmdir */
int nfs4_op_lookup(struct nfs_argop4 *op, compound_data_t * data, struct nfs_resop4 *resp)
{
  char __attribute__ ((__unused__)) funcname[] = "nfs4_op_lookup";

  char strname[MAXNAMLEN];
#ifndef _NO_XATTRD
  char objname[MAXNAMLEN];
#endif
  fsal_name_t            name;
  unsigned int           xattr_found = FALSE;
  cache_entry_t        * dir_pentry = NULL;
  cache_entry_t        * file_pentry = NULL;
  fsal_attrib_list_t     attrlookup;
  cache_inode_status_t   cache_status;
  fsal_handle_t        * pfsal_handle = NULL;

  resp->resop = NFS4_OP_LOOKUP;
  res_LOOKUP4.status = NFS4_OK;

  /* Do basic checks on a filehandle */
  res_LOOKUP4.status = nfs4_sanity_check_FH(data, 0LL);
  if(res_LOOKUP4.status != NFS4_OK)
    return res_LOOKUP4.status;

  /* Check for empty name */
  if(op->nfs_argop4_u.oplookup.objname.utf8string_len == 0 ||
     op->nfs_argop4_u.oplookup.objname.utf8string_val == NULL)
    {
      res_LOOKUP4.status = NFS4ERR_INVAL;
      return res_LOOKUP4.status;
    }

  /* Check for name too long */
  if(op->nfs_argop4_u.oplookup.objname.utf8string_len > FSAL_MAX_NAME_LEN)
    {
      res_LOOKUP4.status = NFS4ERR_NAMETOOLONG;
      return res_LOOKUP4.status;
    }

  /* If Filehandle points to a pseudo fs entry, manage it via pseudofs specific functions */
  if(nfs4_Is_Fh_Pseudo(&(data->currentFH)))
    return nfs4_op_lookup_pseudo(op, data, resp);

  if (nfs_export_check_security(data->reqp, data->pexport) == FALSE)
    {
      res_LOOKUP4.status = NFS4ERR_PERM;
      return res_LOOKUP4.status;
    }

#ifndef _NO_XATTRD
  /* If Filehandle points to a xattr object, manage it via the xattrs specific functions */
  if(nfs4_Is_Fh_Xattr(&(data->currentFH)))
    return nfs4_op_lookup_xattr(op, data, resp);
#endif

  /* UTF8 strings may not end with \0, but they carry their length */
  utf82str(strname, sizeof(strname), &arg_LOOKUP4.objname);

#ifndef _NO_XATTRD
  /* Is this a .xattr.d.<object> name ? */
  if(nfs_XattrD_Name(strname, objname))
    {
      strcpy(strname, objname);
      xattr_found = TRUE;
    }
#endif

  if((cache_status = cache_inode_error_convert(FSAL_str2name(strname,
                                                             MAXNAMLEN,
                                                             &name))) !=
     CACHE_INODE_SUCCESS)
    {
      res_LOOKUP4.status = nfs4_Errno(cache_status);
      return res_LOOKUP4.status;
    }

  /* No 'cd .' is allowed return NFS4ERR_BADNAME in this case */
  /* No 'cd .. is allowed, return EINVAL in this case. NFS4_OP_LOOKUPP should be use instead */
  if(!FSAL_namecmp(&name, (fsal_name_t *) & FSAL_DOT)
     || !FSAL_namecmp(&name, (fsal_name_t *) & FSAL_DOT_DOT))
    {
      res_LOOKUP4.status = NFS4ERR_BADNAME;
      return res_LOOKUP4.status;
    }

  /* Do the lookup in the HPSS Namespace */
  file_pentry = NULL;
  dir_pentry = data->current_entry;

  /* Sanity check: dir_pentry should be ACTUALLY a directory */
  if(dir_pentry->type != DIRECTORY)
    {
      /* This is not a directory */
      if(dir_pentry->type == SYMBOLIC_LINK)
        res_LOOKUP4.status = NFS4ERR_SYMLINK;
      else
        res_LOOKUP4.status = NFS4ERR_NOTDIR;

      /* Return failed status */
      return res_LOOKUP4.status;
    }

  /* BUGAZOMEU: Faire la gestion des cross junction traverse */
  if((file_pentry = cache_inode_lookup(dir_pentry,
                                       &name,
                                       &attrlookup,
                                       data->pcontext, &cache_status)) != NULL)
    {
      /* Extract the fsal attributes from the cache inode pentry */
      pfsal_handle = &file_pentry->handle;

      /* Convert it to a file handle */
      if(!nfs4_FSALToFhandle(&data->currentFH, pfsal_handle, data))
        {
          res_LOOKUP4.status = NFS4ERR_SERVERFAULT;
          cache_inode_put(file_pentry);
          return res_LOOKUP4.status;
        }

      /* Copy this to the mounted on FH (if no junction is traversed */
      memcpy((char *)(data->mounted_on_FH.nfs_fh4_val),
             (char *)(data->currentFH.nfs_fh4_val), data->currentFH.nfs_fh4_len);
      data->mounted_on_FH.nfs_fh4_len = data->currentFH.nfs_fh4_len;

#if 0
      print_buff((char *)cache_inode_get_fsal_handle(file_pentry, &cache_status),
                 sizeof(fsal_handle_t));
      print_buff((char *)cache_inode_get_fsal_handle(dir_pentry, &cache_status),
                 sizeof(fsal_handle_t));
#endif
      if(isFullDebug(COMPONENT_NFS_V4))
        {
          LogFullDebug(COMPONENT_NFS_V4,
                       "----> nfs4_op_lookup: name=%s  dir_pentry=%p  looked up pentry=%p",
                       strname, dir_pentry, file_pentry);
          LogFullDebug(COMPONENT_NFS_V4,
                       "----> FSAL handle parent and children in nfs4_op_lookup");
          print_buff(COMPONENT_NFS_V4,
                     (char *)&file_pentry->handle,
                     sizeof(fsal_handle_t));
          print_buff(COMPONENT_NFS_V4,
                     (char *)&dir_pentry->handle,
                     sizeof(fsal_handle_t));
        }
      LogHandleNFS4("NFS4 LOOKUP CURRENT FH: ", &data->currentFH);

      /* Release dir_pentry, as it is not reachable from anywhere in
         compound after this function returns.  Count on later
         operations or nfs4_Compound to clean up current_entry. */

      if (dir_pentry)
        cache_inode_put(dir_pentry);

      /* Keep the pointer within the compound data */
      data->current_entry = file_pentry;
      data->current_filetype = file_pentry->type;

      /* Return successfully */
      res_LOOKUP4.status = NFS4_OK;

#ifndef _NO_XATTRD
      /* If this is a xattr ghost directory name, update the FH */
      if(xattr_found == TRUE)
        res_LOOKUP4.status = nfs4_fh_to_xattrfh(&(data->currentFH), &(data->currentFH));
#endif

      if((data->current_entry->type == DIRECTORY) &&
         (data->current_entry->object.dir.referral != NULL))
        {
          if(!nfs4_Set_Fh_Referral(&(data->currentFH)))
            {
              res_LOOKUP4.status = NFS4ERR_SERVERFAULT;
              return res_LOOKUP4.status;
            }
        }

      return NFS4_OK;

    }

  /* If the part of the code is reached, then something wrong occured in the lookup process, status is not HPSS_E_NOERROR 
   * and contains the code for the error */

  res_LOOKUP4.status = nfs4_Errno(cache_status);

  return res_LOOKUP4.status;
}                               /* nfs4_op_lookup */