/* Covert GPFS NFS4 ACLs to FSAL ACLs, and set the ACL
 * pointer of attribute. */
static int gpfs_acl_2_fsal_acl(struct attrlist * p_object_attributes,
	                      gpfs_acl_t *p_gpfsacl)
{
  fsal_acl_status_t status;
  fsal_acl_data_t acldata;
  fsal_ace_t *pace;
  fsal_acl_t *pacl;
  gpfs_ace_v4_t *pace_gpfs;

  /* sanity checks */
  if(!p_object_attributes || !p_gpfsacl)
    return ERR_FSAL_FAULT;

  /* Create fsal acl data. */
  acldata.naces = p_gpfsacl->acl_nace;
  acldata.aces = (fsal_ace_t *)nfs4_ace_alloc(acldata.naces);

  /* Fill fsal acl data from gpfs acl. */
  for(pace = acldata.aces, pace_gpfs = p_gpfsacl->ace_v4;
      pace < acldata.aces + acldata.naces; pace++, pace_gpfs++)
    {
      pace->type = pace_gpfs->aceType;
      pace->flag = pace_gpfs->aceFlags;
      pace->iflag = pace_gpfs->aceIFlags;
      pace->perm = pace_gpfs->aceMask;

      if(IS_FSAL_ACE_SPECIAL_ID(*pace))  /* Record special user. */
        {
          pace->who.uid = pace_gpfs->aceWho;
        }
        else
        {
          if(IS_FSAL_ACE_GROUP_ID(*pace))  /* Record group. */
            pace->who.gid = pace_gpfs->aceWho;
          else  /* Record user. */
            pace->who.uid = pace_gpfs->aceWho;
        }

        LogDebug(COMPONENT_FSAL,
                 "gpfs_acl_2_fsal_acl: fsal ace: type = 0x%x, flag = 0x%x, perm = 0x%x, special = %d, %s = 0x%x",
                 pace->type, pace->flag, pace->perm, IS_FSAL_ACE_SPECIAL_ID(*pace),
                 GET_FSAL_ACE_WHO_TYPE(*pace), GET_FSAL_ACE_WHO(*pace));
    }

  /* Create a new hash table entry for fsal acl. */
  pacl = nfs4_acl_new_entry(&acldata, &status);
  LogDebug(COMPONENT_FSAL, "fsal acl = %p, fsal_acl_status = %u", pacl, status);

  if(pacl == NULL)
    {
      LogCrit(COMPONENT_FSAL, "gpfs_acl_2_fsal_acl: failed to create a new acl entry");
      return ERR_FSAL_FAULT;
    }

  /* Add fsal acl to attribute. */
  p_object_attributes->acl = pacl;

  return ERR_FSAL_NO_ERROR;
}
Esempio n. 2
0
int display_fsal_ace(struct display_buffer *dspbuf, int ace_number,
		     fsal_ace_t *pace, bool is_dir)
{
	int b_left;

	if (!pace)
		return display_cat(dspbuf, "ACE: <NULL>");

	/* Print the entire ACE. */
	b_left = display_printf(dspbuf, "ACE %d:", ace_number);

	/* ACE type. */
	if (b_left > 0)
		b_left =
		    display_cat(dspbuf,
				IS_FSAL_ACE_ALLOW(*pace) ? " allow" :
				IS_FSAL_ACE_DENY(*pace) ? " deny" :
				IS_FSAL_ACE_AUDIT(*pace) ? " audit" : " ?");

	/* ACE who and its type. */
	if (b_left > 0 && IS_FSAL_ACE_SPECIAL_ID(*pace))
		b_left =
		    display_cat(dspbuf,
				IS_FSAL_ACE_SPECIAL_OWNER(*pace) ? " owner@" :
				IS_FSAL_ACE_SPECIAL_GROUP(*pace) ? " group@" :
				IS_FSAL_ACE_SPECIAL_EVERYONE(*pace) ?
				" everyone@" : "");

	if (b_left > 0 && !IS_FSAL_ACE_SPECIAL_ID(*pace)) {
		if (IS_FSAL_ACE_SPECIAL_ID(*pace))
			b_left =
			    display_printf(dspbuf, " gid %d", pace->who.gid);
		else
			b_left =
			    display_printf(dspbuf, " uid %d", pace->who.uid);
	}

	/* ACE mask. */
	if (b_left > 0)
		b_left = display_fsal_v4mask(dspbuf, pace->perm, is_dir);

	/* ACE Inherit flags. */
	if (b_left > 0 && IS_FSAL_ACE_INHERIT(*pace))
		b_left = display_fsal_inherit_flags(dspbuf, pace);

	return b_left;
}
Esempio n. 3
0
static void fsal_print_ace(int ace_number, fsal_ace_t *pace, char *p_acebuf)
{
  char inherit_flags[ACL_DEBUG_BUF_SIZE];

  if(!pace || !p_acebuf)
    return;

  memset(p_acebuf, 0, ACL_DEBUG_BUF_SIZE);
  memset(inherit_flags, 0, ACL_DEBUG_BUF_SIZE);

  /* Get inherit flags if any. */
  fsal_print_inherit_flags(pace, inherit_flags);

  /* Print the entire ACE. */
  sprintf(p_acebuf, "ACE %d %s %s %d %c%c%c%c%c%c%c%c%c%c%c%c%c%c %s",
          ace_number,
          /* ACE type. */
          IS_FSAL_ACE_ALLOW(*pace)? "allow":
          IS_FSAL_ACE_DENY(*pace) ? "deny":
          IS_FSAL_ACE_AUDIT(*pace)? "audit": "?",
          /* ACE who and its type. */
          (IS_FSAL_ACE_SPECIAL_ID(*pace) && IS_FSAL_ACE_SPECIAL_OWNER(*pace))    ? "owner@":
          (IS_FSAL_ACE_SPECIAL_ID(*pace) && IS_FSAL_ACE_SPECIAL_GROUP(*pace))    ? "group@":
          (IS_FSAL_ACE_SPECIAL_ID(*pace) && IS_FSAL_ACE_SPECIAL_EVERYONE(*pace)) ? "everyone@":
          IS_FSAL_ACE_SPECIAL_ID(*pace)						 ? "specialid":
          IS_FSAL_ACE_GROUP_ID(*pace) 						 ? "gid": "uid",
          GET_FSAL_ACE_WHO(*pace),
          /* ACE mask. */
          IS_FSAL_ACE_READ_DATA(*pace)		 ? 'r':'-',
          IS_FSAL_ACE_WRITE_DATA(*pace)		 ? 'w':'-',
          IS_FSAL_ACE_EXECUTE(*pace)		 ? 'x':'-',
          IS_FSAL_ACE_ADD_SUBDIRECTORY(*pace)    ? 'm':'-',
          IS_FSAL_ACE_READ_NAMED_ATTR(*pace)	 ? 'n':'-',
          IS_FSAL_ACE_WRITE_NAMED_ATTR(*pace) 	 ? 'N':'-',
          IS_FSAL_ACE_DELETE_CHILD(*pace) 	 ? 'p':'-',
          IS_FSAL_ACE_READ_ATTR(*pace)		 ? 't':'-',
          IS_FSAL_ACE_WRITE_ATTR(*pace)		 ? 'T':'-',
          IS_FSAL_ACE_DELETE(*pace)		 ? 'd':'-',
          IS_FSAL_ACE_READ_ACL(*pace) 		 ? 'c':'-',
          IS_FSAL_ACE_WRITE_ACL(*pace)		 ? 'C':'-',
          IS_FSAL_ACE_WRITE_OWNER(*pace)	 ? 'o':'-',
          IS_FSAL_ACE_SYNCHRONIZE(*pace)	 ? 'z':'-',
          /* ACE Inherit flags. */
          IS_FSAL_ACE_INHERIT(*pace)? inherit_flags: "");
}
Esempio n. 4
0
fsal_acl_t *lzfs_int_convert_lzfs_acl(const liz_acl_t *lzfs_acl) {
	fsal_acl_data_t acl_data;
	fsal_acl_status_t acl_status;
	fsal_acl_t *fsal_acl = NULL;

	if (!lzfs_acl) {
		return NULL;
	}

	acl_data.naces = liz_get_acl_size(lzfs_acl);
	acl_data.aces = (fsal_ace_t *)nfs4_ace_alloc(acl_data.naces);

	if (!acl_data.aces) {
		return NULL;
	}

	for (unsigned i = 0; i < acl_data.naces; ++i) {
		fsal_ace_t *fsal_ace = acl_data.aces + i;
		liz_acl_ace_t lzfs_ace;

		int rc = liz_get_acl_entry(lzfs_acl, i, &lzfs_ace);
		(void)rc;
		assert(rc == 0);

		fsal_ace->type = lzfs_ace.type;
		fsal_ace->flag = lzfs_ace.flags & 0xFF;
		fsal_ace->iflag = (lzfs_ace.flags & LIZ_ACL_SPECIAL_WHO) ? FSAL_ACE_IFLAG_SPECIAL_ID : 0;

		if (IS_FSAL_ACE_GROUP_ID(*fsal_ace)) {
			fsal_ace->who.gid = lzfs_ace.id;
		} else {
			fsal_ace->who.uid = lzfs_ace.id;
		}

		if (IS_FSAL_ACE_SPECIAL_ID(*fsal_ace)) {
			switch (lzfs_ace.id) {
			case LIZ_ACL_OWNER_SPECIAL_ID:
				fsal_ace->who.uid = FSAL_ACE_SPECIAL_OWNER;
				break;
			case LIZ_ACL_GROUP_SPECIAL_ID:
				fsal_ace->who.uid = FSAL_ACE_SPECIAL_GROUP;
				break;
			case LIZ_ACL_EVERYONE_SPECIAL_ID:
				fsal_ace->who.uid = FSAL_ACE_SPECIAL_EVERYONE;
				break;
			default:
				fsal_ace->who.uid = FSAL_ACE_NORMAL_WHO;
				LogWarn(COMPONENT_FSAL, "Invalid LizardFS ACE special id type (%u)",
				        (unsigned)lzfs_ace.id);
			}
		}
	}

	fsal_acl = nfs4_acl_new_entry(&acl_data, &acl_status);
	LogDebug(COMPONENT_FSAL, "fsal acl = %p, fsal_acl_status = %u", fsal_acl, acl_status);
	return fsal_acl;
}
Esempio n. 5
0
liz_acl_t *lzfs_int_convert_fsal_acl(const fsal_acl_t *fsal_acl) {
	liz_acl_t *lzfs_acl = NULL;

	if (!fsal_acl || (!fsal_acl->aces && fsal_acl->naces > 0)) {
		return NULL;
	}

	int count = 0;
	for (unsigned i = 0; i < fsal_acl->naces; ++i) {
		fsal_ace_t *fsal_ace = fsal_acl->aces + i;
		count += (IS_FSAL_ACE_ALLOW(*fsal_ace) || IS_FSAL_ACE_DENY(*fsal_ace)) ? 1 : 0;
	}

	lzfs_acl = liz_create_acl();
	if (!lzfs_acl) {
		return NULL;
	}

	for (unsigned i = 0; i < fsal_acl->naces; ++i) {
		fsal_ace_t *fsal_ace = fsal_acl->aces + i;
		if (!(IS_FSAL_ACE_ALLOW(*fsal_ace) || IS_FSAL_ACE_DENY(*fsal_ace))) {
			continue;
		}

		liz_acl_ace_t ace;
		ace.flags = fsal_ace->flag & 0xFF;
		ace.mask = fsal_ace->perm;
		ace.type = fsal_ace->type;
		if (IS_FSAL_ACE_GROUP_ID(*fsal_ace)) {
			ace.id = GET_FSAL_ACE_GROUP(*fsal_ace);
		} else {
			ace.id = GET_FSAL_ACE_USER(*fsal_ace);
		}
		if (IS_FSAL_ACE_SPECIAL_ID(*fsal_ace)) {
			ace.flags |= LIZ_ACL_SPECIAL_WHO;
			switch (GET_FSAL_ACE_USER(*fsal_ace)) {
			case FSAL_ACE_SPECIAL_OWNER:
				ace.id = LIZ_ACL_OWNER_SPECIAL_ID;
				break;
			case FSAL_ACE_SPECIAL_GROUP:
				ace.id = LIZ_ACL_GROUP_SPECIAL_ID;
				break;
			case FSAL_ACE_SPECIAL_EVERYONE:
				ace.id = LIZ_ACL_EVERYONE_SPECIAL_ID;
				break;
			default:
				LogFullDebug(COMPONENT_FSAL, "Invalid FSAL ACE special id type (%d)",
				             (int)GET_FSAL_ACE_USER(*fsal_ace));
				continue;
			}
		}

		liz_add_acl_entry(lzfs_acl, &ace);
	}

	return lzfs_acl;
}
Esempio n. 6
0
/* Covert FSAL ACLs to PTFS NFS4 ACLs. */
fsal_status_t
fsal_acl_2_ptfs_acl(fsal_acl_t     * p_fsalacl,
		    ptfsal_xstat_t * p_buffxstat)
{
  int i;
  fsal_ace_t *pace;
  gpfs_acl_t *p_ptfsacl;

  p_ptfsacl = (gpfs_acl_t *) p_buffxstat->buffacl;

  p_ptfsacl->acl_level   =  0;
  p_ptfsacl->acl_version =  PTFS_ACL_VERSION_NFS4;
  p_ptfsacl->acl_type    =  PTFS_ACL_TYPE_NFS4;
  p_ptfsacl->acl_nace = p_fsalacl->naces;
  p_ptfsacl->acl_len = ((int)(signed long)&(((gpfs_acl_t *) 0)->ace_v1)) 
                       + p_ptfsacl->acl_nace * sizeof(ptfs_ace_v4_t);

  for(pace = p_fsalacl->aces, i = 0; 
      pace < p_fsalacl->aces + p_fsalacl->naces; 
      pace++, i++)
    {
      p_ptfsacl->ace_v4[i].aceType = pace->type;
      p_ptfsacl->ace_v4[i].aceFlags = pace->flag;
      p_ptfsacl->ace_v4[i].aceIFlags = pace->iflag;
      p_ptfsacl->ace_v4[i].aceMask = pace->perm;

      if(IS_FSAL_ACE_SPECIAL_ID(*pace))
        p_ptfsacl->ace_v4[i].aceWho = pace->who.uid;
      else
        {
          if(IS_FSAL_ACE_GROUP_ID(*pace))
            p_ptfsacl->ace_v4[i].aceWho = pace->who.gid;
          else
            p_ptfsacl->ace_v4[i].aceWho = pace->who.uid;
        }

      LogDebug(COMPONENT_FSAL, "fsal_acl_2_ptfs_acl: ptfs ace: " 
               "type = 0x%x, flag = 0x%x, perm = 0x%x, special = %d, %s = 0x%x",
               p_ptfsacl->ace_v4[i].aceType, p_ptfsacl->ace_v4[i].aceFlags, 
               p_ptfsacl->ace_v4[i].aceMask,
               (p_ptfsacl->ace_v4[i].aceIFlags 
               & FSAL_ACE_IFLAG_SPECIAL_ID) ? 1 : 0,
               (p_ptfsacl->ace_v4[i].aceFlags 
               & FSAL_ACE_FLAG_GROUP_ID) ? "gid" : "uid",
               p_ptfsacl->ace_v4[i].aceWho);

    }

  ReturnCode(ERR_FSAL_NO_ERROR, 0);
}
Esempio n. 7
0
static bool fsal_check_ace_matches(fsal_ace_t *pace, struct user_cred *creds,
				   bool is_owner, bool is_group)
{
	bool result = false;
	char *cause = "";

	if (IS_FSAL_ACE_SPECIAL_ID(*pace))
		switch (pace->who.uid) {
		case FSAL_ACE_SPECIAL_OWNER:
			if (is_owner) {
				result = true;
				cause = "special owner";
			}
			break;

		case FSAL_ACE_SPECIAL_GROUP:
			if (is_group) {
				result = true;
				cause = "special group";
			}
			break;

		case FSAL_ACE_SPECIAL_EVERYONE:
			result = true;
			cause = "special everyone";
			break;

		default:
			break;
	} else if (IS_FSAL_ACE_GROUP_ID(*pace)) {
		if (fsal_check_ace_group(pace->who.gid, creds)) {
			result = true;
			cause = "group";
		}
	} else {
		if (fsal_check_ace_owner(pace->who.uid, creds)) {
			result = true;
			cause = "owner";
		}
	}

	LogFullDebug(COMPONENT_NFS_V4_ACL,
		     "result: %d, cause: %s, flag: 0x%X, who: %d", result,
		     cause, pace->flag, GET_FSAL_ACE_WHO(*pace));

	return result;
}
Esempio n. 8
0
static fsal_boolean_t fsal_check_ace_matches(fsal_ace_t *pace,
                                             fsal_op_context_t *p_context,
                                             fsal_boolean_t is_owner,
                                             fsal_boolean_t is_group)
{
  int matches = 0;

  if (IS_FSAL_ACE_SPECIAL_ID(*pace))
    switch(pace->who.uid)
      {
        case FSAL_ACE_SPECIAL_OWNER:
          if(is_owner)
            matches = 1;
        break;

        case FSAL_ACE_SPECIAL_GROUP:
          if(is_group)
            matches = 2;
        break;

        case FSAL_ACE_SPECIAL_EVERYONE:
          matches = 3;
        break;

        default:
        break;
      }
  else if (IS_FSAL_ACE_GROUP_ID(*pace))
    {
      if(fsal_check_ace_group(pace->who.gid, p_context))
        matches = 4;
    }
  else
    {
      if(fsal_check_ace_owner(pace->who.uid, p_context))
        matches = 5;
    }

  LogDebug(COMPONENT_FSAL,
           "fsal_check_ace_matches: matches %d flag 0x%X who %d",
           matches, pace->flag, GET_FSAL_ACE_WHO(*pace));

  return (matches != 0);
}
Esempio n. 9
0
/* XXX dang - This will lose PANFS specific types (PAN_IDENTITY_PAN_* and
 * PAN_IDENTITY_WIN_*), since those were consolidated into the FSAL types */
void fsal_id_to_panace_id(fsal_ace_t *ace, pan_identity_t *pan_id)
{
	if (IS_FSAL_ACE_SPECIAL_ID(*ace)) {
		if (IS_FSAL_ACE_SPECIAL_EVERYONE(*ace)) {
			pan_id->type = PAN_IDENTITY_PAN_GROUP;
			pan_id->u.pan_gid = PAN_IDENTITY_EVERYONE_GROUP_ID;
		} else {
			pan_id->type = PAN_IDENTITY_UNKNOWN;
			pan_id->u.uid = ace->who.uid;
		}
	} else {
		if (IS_FSAL_ACE_GROUP_ID(*ace)) {
			pan_id->type = PAN_IDENTITY_UNIX_GROUP;
			pan_id->u.gid = ace->who.gid;
		} else {
			pan_id->type = PAN_IDENTITY_UNIX_USER;
			pan_id->u.uid = ace->who.uid;
		}
	}
}
Esempio n. 10
0
/* Covert FSAL ACLs to GPFS NFS4 ACLs. */
fsal_status_t fsal_acl_2_gpfs_acl(struct fsal_obj_handle *dir_hdl,
				  fsal_acl_t *p_fsalacl,
				  gpfsfsal_xstat_t *p_buffxstat)
{
	int i;
	fsal_ace_t *pace;
	gpfs_acl_t *p_gpfsacl;

	p_gpfsacl = (gpfs_acl_t *) p_buffxstat->buffacl;

	p_gpfsacl->acl_level = 0;
	p_gpfsacl->acl_version = GPFS_ACL_VERSION_NFS4;
	p_gpfsacl->acl_type = GPFS_ACL_TYPE_NFS4;
	p_gpfsacl->acl_nace = p_fsalacl->naces;
	p_gpfsacl->acl_len =
	    ((int)(signed long)&(((gpfs_acl_t *) 0)->ace_v1)) +
	    p_gpfsacl->acl_nace * sizeof(gpfs_ace_v4_t);

	for (pace = p_fsalacl->aces, i = 0;
	     pace < p_fsalacl->aces + p_fsalacl->naces; pace++, i++) {
		p_gpfsacl->ace_v4[i].aceType = pace->type;
		p_gpfsacl->ace_v4[i].aceFlags = pace->flag;
		p_gpfsacl->ace_v4[i].aceIFlags = pace->iflag;
		p_gpfsacl->ace_v4[i].aceMask = pace->perm;

		if (IS_FSAL_ACE_SPECIAL_ID(*pace))
			p_gpfsacl->ace_v4[i].aceWho = pace->who.uid;
		else {
			if (IS_FSAL_ACE_GROUP_ID(*pace))
				p_gpfsacl->ace_v4[i].aceWho = pace->who.gid;
			else
				p_gpfsacl->ace_v4[i].aceWho = pace->who.uid;
		}

		LogMidDebug(COMPONENT_FSAL,
			 "fsal_acl_2_gpfs_acl: gpfs ace: type = 0x%x, flag = 0x%x, perm = 0x%x, special = %d, %s = 0x%x",
			 p_gpfsacl->ace_v4[i].aceType,
			 p_gpfsacl->ace_v4[i].aceFlags,
			 p_gpfsacl->ace_v4[i].aceMask,
			 (p_gpfsacl->ace_v4[i].
			  aceIFlags & FSAL_ACE_IFLAG_SPECIAL_ID) ? 1 : 0,
			 (p_gpfsacl->ace_v4[i].
			  aceFlags & FSAL_ACE_FLAG_GROUP_ID) ? "gid" : "uid",
			 p_gpfsacl->ace_v4[i].aceWho);

		/* It is invalid to set inherit flags on non dir objects */
		if (dir_hdl->type != DIRECTORY &&
		    (p_gpfsacl->ace_v4[i].aceFlags &
		    FSAL_ACE_FLAG_INHERIT) != 0) {
			LogMidDebug(COMPONENT_FSAL,
			   "attempt to set inherit flag to non dir object");
			return fsalstat(ERR_FSAL_INVAL, 0);
		}

		/* It is invalid to set inherit only with
		 * out an actual inherit flag */
		if ((p_gpfsacl->ace_v4[i].aceFlags & FSAL_ACE_FLAG_INHERIT) ==
			FSAL_ACE_FLAG_INHERIT_ONLY) {
			LogMidDebug(COMPONENT_FSAL,
			   "attempt to set inherit only without an inherit flag");
			return fsalstat(ERR_FSAL_INVAL, 0);
		}

	}

	return fsalstat(ERR_FSAL_NO_ERROR, 0);
}
Esempio n. 11
0
/**
 *
 * cache_inode_getattr: Gets the attributes for a cached entry.
 *
 * Gets the attributes for a cached entry. The FSAL attributes are kept in a structure when the entry
 * is added to the cache.
 *
 * @param pentry [IN] entry to be managed.
 * @param pattr [OUT] pointer to the results
 * @param ht [IN] hash table used for the cache, unused in this call.
 * @param pclient [INOUT] ressource allocated by the client for the nfs management.
 * @param pcontext [IN] FSAL credentials
 * @param pstatus [OUT] returned status.
 *
 * @return CACHE_INODE_SUCCESS if operation is a success \n
 * @return CACHE_INODE_LRU_ERROR if allocation error occured when validating the entry
 *
 */
cache_inode_status_t
cache_inode_getattr(cache_entry_t * pentry,
                    fsal_attrib_list_t * pattr,
                    hash_table_t * ht, /* Unused, kept for protototype's homogeneity */
                    cache_inode_client_t * pclient,
                    fsal_op_context_t * pcontext,
                    cache_inode_status_t * pstatus)
{
    cache_inode_status_t status;
    fsal_handle_t *pfsal_handle = NULL;
    fsal_status_t fsal_status;

    /* sanity check */
    if(pentry == NULL || pattr == NULL ||
       ht == NULL || pclient == NULL || pcontext == NULL)
        {
            *pstatus = CACHE_INODE_INVALID_ARGUMENT;
            LogDebug(COMPONENT_CACHE_INODE,
                     "cache_inode_getattr: returning CACHE_INODE_INVALID_ARGUMENT because of bad arg");
            return *pstatus;
        }

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

    /* stats */
    pclient->stat.nb_call_total += 1;
    inc_func_call(pclient, CACHE_INODE_GETATTR);

    /* Lock the entry */
    P_w(&pentry->lock);
    status = cache_inode_renew_entry(pentry, pattr, ht,
                                     pclient, pcontext, pstatus);
    if(status != CACHE_INODE_SUCCESS)
        {
            V_w(&pentry->lock);
            inc_func_err_retryable(pclient, CACHE_INODE_GETATTR);
            LogFullDebug(COMPONENT_CACHE_INODE,
                         "cache_inode_getattr: returning %d(%s) from cache_inode_renew_entry",
                         *pstatus, cache_inode_err_str(*pstatus));
            return *pstatus;
        }

    /* RW Lock goes for writer to reader */
    rw_lock_downgrade(&pentry->lock);

    cache_inode_get_attributes(pentry, pattr);

    if(FSAL_TEST_MASK(pattr->asked_attributes,
                      FSAL_ATTR_RDATTR_ERR))
        {
            switch (pentry->internal_md.type)
                {
                case REGULAR_FILE:
                    pfsal_handle = &pentry->object.file.handle;
                    break;

                case SYMBOLIC_LINK:
                    assert(pentry->object.symlink);
                    pfsal_handle = &pentry->object.symlink->handle;
                    break;

                case DIRECTORY:
                    pfsal_handle = &pentry->object.dir.handle;
                    break;
                case SOCKET_FILE:
                case FIFO_FILE:
                case BLOCK_FILE:
                case CHARACTER_FILE:
                    pfsal_handle = &pentry->object.special_obj.handle;
                    break;
                case FS_JUNCTION:
                case UNASSIGNED:
                case RECYCLED:
                    *pstatus = CACHE_INODE_INVALID_ARGUMENT;
                    LogFullDebug(COMPONENT_CACHE_INODE,
                                 "cache_inode_getattr: returning %d(%s) from cache_inode_renew_entry - unexpected md_type",
                                 *pstatus, cache_inode_err_str(*pstatus));
                    return *pstatus;
                }

            /*
             * An error occured when trying to get
             * the attributes, they have to be renewed
             */
#ifdef _USE_MFSL
            fsal_status = FSAL_getattrs_descriptor(&(cache_inode_fd(pentry)->fsal_file), pfsal_handle, pcontext, pattr);
#else
            fsal_status = FSAL_getattrs_descriptor(cache_inode_fd(pentry), pfsal_handle, pcontext, pattr);
#endif
            if(FSAL_IS_ERROR(fsal_status))
                {
                    *pstatus = cache_inode_error_convert(fsal_status);
                    
                    V_r(&pentry->lock);

                    if(fsal_status.major == ERR_FSAL_STALE)
                        {
                            cache_inode_status_t kill_status;

                            LogEvent(COMPONENT_CACHE_INODE,
                                     "cache_inode_getattr: Stale FSAL File Handle detected for pentry = %p",
                                     pentry);

                            /* Locked flag is set to true to show entry has a read lock */
                            cache_inode_kill_entry( pentry, WT_LOCK, ht,
                                                    pclient, &kill_status);
                            if(kill_status != CACHE_INODE_SUCCESS)
                                LogCrit(COMPONENT_CACHE_INODE,
                                        "cache_inode_getattr: Could not kill entry %p, status = %u",
                                        pentry, kill_status);

                            *pstatus = CACHE_INODE_FSAL_ESTALE;
                        }

                    /* stat */
                    inc_func_err_unrecover(pclient, CACHE_INODE_GETATTR);
                    LogDebug(COMPONENT_CACHE_INODE,
                             "cache_inode_getattr: returning %d(%s) from FSAL_getattrs_descriptor",
                             *pstatus, cache_inode_err_str(*pstatus));
                    return *pstatus;
                }

            /* Set the new attributes */
            cache_inode_set_attributes(pentry, pattr);
        }
    *pstatus = cache_inode_valid(pentry, CACHE_INODE_OP_GET, pclient);

    V_r(&pentry->lock);

    /* stat */
    if(*pstatus != CACHE_INODE_SUCCESS)
        inc_func_err_retryable(pclient, CACHE_INODE_GETATTR);
    else
        inc_func_success(pclient, CACHE_INODE_GETATTR);

#ifdef _USE_NFS4_ACL
    if(isDebug(COMPONENT_NFS_V4_ACL))
      {
        LogDebug(COMPONENT_CACHE_INODE,
                 "cache_inode_getattr: pentry = %p, acl = %p",
                 pentry, pattr->acl);

        if(pattr->acl)
          {
            fsal_ace_t *pace;
            for(pace = pattr->acl->aces; pace < pattr->acl->aces + pattr->acl->naces; pace++)
              {
                LogDebug(COMPONENT_CACHE_INODE,
                         "cache_inode_getattr: ace type = 0x%x, flag = 0x%x, perm = 0x%x, special = %d, %s = 0x%x",
                         pace->type, pace->flag, pace->perm, IS_FSAL_ACE_SPECIAL_ID(*pace),
                         GET_FSAL_ACE_WHO_TYPE(*pace), GET_FSAL_ACE_WHO(*pace));
              }
          }
      }
#endif                          /* _USE_NFS4_ACL */

    LogFullDebug(COMPONENT_CACHE_INODE,
                 "cache_inode_getattr: returning %d(%s) from cache_inode_valid",
                 *pstatus, cache_inode_err_str(*pstatus));
    return *pstatus;
}