/* * Perform a miscellaneous operation on a file. */ static long orangefs_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { int ret = -ENOTTY; __u64 val = 0; unsigned long uval; gossip_debug(GOSSIP_FILE_DEBUG, "orangefs_ioctl: called with cmd %d\n", cmd); /* * we understand some general ioctls on files, such as the immutable * and append flags */ if (cmd == FS_IOC_GETFLAGS) { val = 0; ret = orangefs_inode_getxattr(file_inode(file), ORANGEFS_XATTR_NAME_DEFAULT_PREFIX, "user.pvfs2.meta_hint", &val, sizeof(val)); if (ret < 0 && ret != -ENODATA) return ret; else if (ret == -ENODATA) val = 0; uval = val; gossip_debug(GOSSIP_FILE_DEBUG, "orangefs_ioctl: FS_IOC_GETFLAGS: %llu\n", (unsigned long long)uval); return put_user(uval, (int __user *)arg); } else if (cmd == FS_IOC_SETFLAGS) { ret = 0; if (get_user(uval, (int __user *)arg)) return -EFAULT; /* * ORANGEFS_MIRROR_FL is set internally when the mirroring mode * is turned on for a file. The user is not allowed to turn * on this bit, but the bit is present if the user first gets * the flags and then updates the flags with some new * settings. So, we ignore it in the following edit. bligon. */ if ((uval & ~ORANGEFS_MIRROR_FL) & (~(FS_IMMUTABLE_FL | FS_APPEND_FL | FS_NOATIME_FL))) { gossip_err("orangefs_ioctl: the FS_IOC_SETFLAGS only supports setting one of FS_IMMUTABLE_FL|FS_APPEND_FL|FS_NOATIME_FL\n"); return -EINVAL; } val = uval; gossip_debug(GOSSIP_FILE_DEBUG, "orangefs_ioctl: FS_IOC_SETFLAGS: %llu\n", (unsigned long long)val); ret = orangefs_inode_setxattr(file_inode(file), ORANGEFS_XATTR_NAME_DEFAULT_PREFIX, "user.pvfs2.meta_hint", &val, sizeof(val), 0); } return ret; }
static int orangefs_xattr_set_default(const struct xattr_handler *handler, struct dentry *unused, struct inode *inode, const char *name, const void *buffer, size_t size, int flags) { return orangefs_inode_setxattr(inode, name, buffer, size, flags); }
static int __orangefs_set_acl(struct inode *inode, struct posix_acl *acl, int type) { int error = 0; void *value = NULL; size_t size = 0; const char *name = NULL; switch (type) { case ACL_TYPE_ACCESS: name = XATTR_NAME_POSIX_ACL_ACCESS; break; case ACL_TYPE_DEFAULT: name = XATTR_NAME_POSIX_ACL_DEFAULT; break; default: gossip_err("%s: invalid type %d!\n", __func__, type); return -EINVAL; } gossip_debug(GOSSIP_ACL_DEBUG, "%s: inode %pU, key %s type %d\n", __func__, get_khandle_from_ino(inode), name, type); if (acl) { size = posix_acl_xattr_size(acl->a_count); value = kmalloc(size, GFP_KERNEL); if (!value) return -ENOMEM; error = posix_acl_to_xattr(&init_user_ns, acl, value, size); if (error < 0) goto out; } gossip_debug(GOSSIP_ACL_DEBUG, "%s: name %s, value %p, size %zd, acl %p\n", __func__, name, value, size, acl); /* * Go ahead and set the extended attribute now. NOTE: Suppose acl * was NULL, then value will be NULL and size will be 0 and that * will xlate to a removexattr. However, we don't want removexattr * complain if attributes does not exist. */ error = orangefs_inode_setxattr(inode, name, value, size, 0); out: kfree(value); if (!error) set_cached_acl(inode, type, acl); return error; }
static int orangefs_xattr_set_trusted(const struct xattr_handler *handler, struct dentry *dentry, const char *name, const void *buffer, size_t size, int flags) { return orangefs_inode_setxattr(dentry->d_inode, ORANGEFS_XATTR_NAME_TRUSTED_PREFIX, name, buffer, size, flags); }
static int orangefs_xattr_set_default(const struct xattr_handler *handler, struct dentry *unused, struct inode *inode, const char *name, const void *buffer, size_t size, int flags) { return orangefs_inode_setxattr(inode, ORANGEFS_XATTR_NAME_DEFAULT_PREFIX, name, buffer, size, flags); }