// SPDX-License-Identifier: GPL-2.0 /* * (C) 2001 Clemson University and The University of Chicago * Copyright 2018 Omnibond Systems, L.L.C. * * See COPYING in top-level directory.
*/ #include <linux/kernel.h> #include"protocol.h" #include"orangefs-kernel.h" #include"orangefs-dev-proto.h" #include"orangefs-bufmap.h"
/* * ORANGEFS cannot set size with a setattr operation. Probably not * likely to be requested through the VFS, but just in case, don't * worry about ATTR_SIZE
*/
staticvoid orangefs_make_bad_inode(struct inode *inode)
{ if (is_root_handle(inode)) { /* * if this occurs, the pvfs2-client-core was killed but we * can't afford to lose the inode operations and such * associated with the root handle in any case.
*/
gossip_debug(GOSSIP_UTILS_DEBUG, "*** NOT making bad root inode %pU\n",
get_khandle_from_ino(inode));
} else {
gossip_debug(GOSSIP_UTILS_DEBUG, "*** making bad inode %pU\n",
get_khandle_from_ino(inode));
make_bad_inode(inode);
}
}
staticint orangefs_inode_is_stale(struct inode *inode, struct ORANGEFS_sys_attr_s *attrs, char *link_target)
{ struct orangefs_inode_s *orangefs_inode = ORANGEFS_I(inode); int type = orangefs_inode_type(attrs->objtype); /* * If the inode type or symlink target have changed then this * inode is stale.
*/ if (type == -1 || inode_wrong_type(inode, type)) {
orangefs_make_bad_inode(inode); return 1;
} if (type == S_IFLNK && strncmp(orangefs_inode->link_target,
link_target, ORANGEFS_NAME_MAX)) {
orangefs_make_bad_inode(inode); return 1;
} return 0;
}
int orangefs_inode_getattr(struct inode *inode, int flags)
{ struct orangefs_inode_s *orangefs_inode = ORANGEFS_I(inode); struct orangefs_kernel_op_s *new_op;
loff_t inode_size; int ret, type;
gossip_debug(GOSSIP_UTILS_DEBUG, "%s: called on inode %pU flags %d\n",
__func__, get_khandle_from_ino(inode), flags);
again:
spin_lock(&inode->i_lock); /* Must have all the attributes in the mask and be within cache time. */ if ((!flags && time_before(jiffies, orangefs_inode->getattr_time)) ||
orangefs_inode->attr_valid || inode->i_state & I_DIRTY_PAGES) { if (orangefs_inode->attr_valid) {
spin_unlock(&inode->i_lock);
write_inode_now(inode, 1); goto again;
}
spin_unlock(&inode->i_lock); return 0;
}
spin_unlock(&inode->i_lock);
new_op = op_alloc(ORANGEFS_VFS_OP_GETATTR); if (!new_op) return -ENOMEM;
new_op->upcall.req.getattr.refn = orangefs_inode->refn; /* * Size is the hardest attribute to get. The incremental cost of any * other attribute is essentially zero.
*/ if (flags)
new_op->upcall.req.getattr.mask = ORANGEFS_ATTR_SYS_ALL_NOHINT; else
new_op->upcall.req.getattr.mask =
ORANGEFS_ATTR_SYS_ALL_NOHINT & ~ORANGEFS_ATTR_SYS_SIZE;
ret = service_operation(new_op, __func__,
get_interruptible_flag(inode)); if (ret != 0) goto out;
again2:
spin_lock(&inode->i_lock); /* Must have all the attributes in the mask and be within cache time. */ if ((!flags && time_before(jiffies, orangefs_inode->getattr_time)) ||
orangefs_inode->attr_valid || inode->i_state & I_DIRTY_PAGES) { if (orangefs_inode->attr_valid) {
spin_unlock(&inode->i_lock);
write_inode_now(inode, 1); goto again2;
} if (inode->i_state & I_DIRTY_PAGES) {
ret = 0; goto out_unlock;
}
gossip_debug(GOSSIP_UTILS_DEBUG, "%s: in cache or dirty\n",
__func__);
ret = 0; goto out_unlock;
}
if (!(flags & ORANGEFS_GETATTR_NEW)) {
ret = orangefs_inode_is_stale(inode,
&new_op->downcall.resp.getattr.attributes,
new_op->downcall.resp.getattr.link_target); if (ret) {
ret = -ESTALE; goto out_unlock;
}
}
type = orangefs_inode_type(new_op->
downcall.resp.getattr.attributes.objtype); switch (type) { case S_IFREG:
inode->i_flags = orangefs_inode_flags(&new_op->
downcall.resp.getattr.attributes); if (flags) {
inode_size = (loff_t)new_op->
downcall.resp.getattr.attributes.size;
inode->i_size = inode_size;
inode->i_blkbits = ffs(new_op->downcall.resp.getattr.
attributes.blksize);
inode->i_bytes = inode_size;
inode->i_blocks =
(inode_size + 512 - inode_size % 512)/512;
} break; case S_IFDIR: if (flags) {
inode->i_size = PAGE_SIZE;
inode_set_bytes(inode, inode->i_size);
}
set_nlink(inode, 1); break; case S_IFLNK: if (flags & ORANGEFS_GETATTR_NEW) {
inode->i_size = (loff_t)strlen(new_op->
downcall.resp.getattr.link_target);
ret = strscpy(orangefs_inode->link_target,
new_op->downcall.resp.getattr.link_target,
ORANGEFS_NAME_MAX); if (ret == -E2BIG) {
ret = -EIO; goto out_unlock;
}
inode->i_link = orangefs_inode->link_target;
} break; /* i.e. -1 */ default: /* XXX: ESTALE? This is what is done if it is not new. */
orangefs_make_bad_inode(inode);
ret = -ESTALE; goto out_unlock;
}
/* special case: mark the root inode as sticky */
inode->i_mode = type | (is_root_handle(inode) ? S_ISVTX : 0) |
orangefs_inode_perms(&new_op->downcall.resp.getattr.attributes);
ret = service_operation(new_op, __func__,
get_interruptible_flag(inode)); if (ret != 0) goto out;
ret = orangefs_inode_is_stale(inode,
&new_op->downcall.resp.getattr.attributes,
new_op->downcall.resp.getattr.link_target);
out:
op_release(new_op); return ret;
}
/* * issues a orangefs setattr request to make sure the new attribute values * take effect if successful. returns 0 on success; -errno otherwise
*/ int orangefs_inode_setattr(struct inode *inode)
{ struct orangefs_inode_s *orangefs_inode = ORANGEFS_I(inode); struct orangefs_kernel_op_s *new_op; int ret;
new_op = op_alloc(ORANGEFS_VFS_OP_SETATTR); if (!new_op) return -ENOMEM;
int orangefs_normalize_to_errno(__s32 error_code)
{
__u32 i;
/* Success */ if (error_code == 0) { return 0; /* * This shouldn't ever happen. If it does it should be fixed on the * server.
*/
} elseif (error_code > 0) {
gossip_err("orangefs: error status received.\n");
gossip_err("orangefs: assuming error code is inverted.\n");
error_code = -error_code;
}
/* * XXX: This is very bad since error codes from ORANGEFS may not be * suitable for return into userspace.
*/
/* * Convert ORANGEFS error values into errno values suitable for return * from the kernel.
*/ if ((-error_code) & ORANGEFS_NON_ERRNO_ERROR_BIT) { if (((-error_code) &
(ORANGEFS_ERROR_NUMBER_BITS|ORANGEFS_NON_ERRNO_ERROR_BIT|
ORANGEFS_ERROR_BIT)) == ORANGEFS_ECANCEL) { /* * cancellation error codes generally correspond to * a timeout from the client's perspective
*/
error_code = -ETIMEDOUT;
} else { /* assume a default error code */
gossip_err("%s: bad error code :%d:.\n",
__func__,
error_code);
error_code = -EINVAL;
}
/* Convert ORANGEFS encoded errno values into regular errno values. */
} elseif ((-error_code) & ORANGEFS_ERROR_BIT) {
i = (-error_code) & ~(ORANGEFS_ERROR_BIT|ORANGEFS_ERROR_CLASS_BITS); if (i < ARRAY_SIZE(PINT_errno_mapping))
error_code = -PINT_errno_mapping[i]; else
error_code = -EINVAL;
/* * Only ORANGEFS protocol error codes should ever come here. Otherwise * there is a bug somewhere.
*/
} else {
gossip_err("%s: unknown error code.\n", __func__);
error_code = -EINVAL;
} return error_code;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.