Commit 1f26b062 authored by Miklos Szeredi's avatar Miklos Szeredi
Browse files

orangefs: convert to fileattr



Use the fileattr API to let the VFS handle locking, permission checking and
conversion.

Signed-off-by: default avatarMiklos Szeredi <mszeredi@redhat.com>
Cc: Mike Marshall <hubcap@omnibond.com>
parent 88b631cb
Loading
Loading
Loading
Loading
+0 −79
Original line number Diff line number Diff line
@@ -375,84 +375,6 @@ static ssize_t orangefs_file_write_iter(struct kiocb *iocb,
	return ret;
}

static int orangefs_getflags(struct inode *inode, unsigned long *uval)
{
	__u64 val = 0;
	int ret;

	ret = orangefs_inode_getxattr(inode,
				      "user.pvfs2.meta_hint",
				      &val, sizeof(val));
	if (ret < 0 && ret != -ENODATA)
		return ret;
	else if (ret == -ENODATA)
		val = 0;
	*uval = val;
	return 0;
}

/*
 * Perform a miscellaneous operation on a file.
 */
static long orangefs_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
	struct inode *inode = file_inode(file);
	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) {
		ret = orangefs_getflags(inode, &uval);
		if (ret)
			return ret;
		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) {
		unsigned long old_uval;

		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;
		}
		ret = orangefs_getflags(inode, &old_uval);
		if (ret)
			return ret;
		ret = vfs_ioc_setflags_prepare(inode, old_uval, uval);
		if (ret)
			return ret;
		val = uval;
		gossip_debug(GOSSIP_FILE_DEBUG,
			     "orangefs_ioctl: FS_IOC_SETFLAGS: %llu\n",
			     (unsigned long long)val);
		ret = orangefs_inode_setxattr(inode,
					      "user.pvfs2.meta_hint",
					      &val, sizeof(val), 0);
	}

	return ret;
}

static vm_fault_t orangefs_fault(struct vm_fault *vmf)
{
	struct file *file = vmf->vma->vm_file;
@@ -657,7 +579,6 @@ const struct file_operations orangefs_file_operations = {
	.read_iter	= orangefs_file_read_iter,
	.write_iter	= orangefs_file_write_iter,
	.lock		= orangefs_lock,
	.unlocked_ioctl	= orangefs_ioctl,
	.mmap		= orangefs_file_mmap,
	.open		= generic_file_open,
	.splice_read    = generic_file_splice_read,
+50 −0
Original line number Diff line number Diff line
@@ -11,6 +11,7 @@
 */

#include <linux/bvec.h>
#include <linux/fileattr.h>
#include "protocol.h"
#include "orangefs-kernel.h"
#include "orangefs-bufmap.h"
@@ -954,6 +955,53 @@ int orangefs_update_time(struct inode *inode, struct timespec64 *time, int flags
	return __orangefs_setattr(inode, &iattr);
}

static int orangefs_fileattr_get(struct dentry *dentry, struct fileattr *fa)
{
	u64 val = 0;
	int ret;

	gossip_debug(GOSSIP_FILE_DEBUG, "%s: called on %pd\n", __func__,
		     dentry);

	ret = orangefs_inode_getxattr(d_inode(dentry),
				      "user.pvfs2.meta_hint",
				      &val, sizeof(val));
	if (ret < 0 && ret != -ENODATA)
		return ret;

	gossip_debug(GOSSIP_FILE_DEBUG, "%s: flags=%u\n", __func__, (u32) val);

	fileattr_fill_flags(fa, val);
	return 0;
}

static int orangefs_fileattr_set(struct user_namespace *mnt_userns,
				 struct dentry *dentry, struct fileattr *fa)
{
	u64 val = 0;

	gossip_debug(GOSSIP_FILE_DEBUG, "%s: called on %pd\n", __func__,
		     dentry);
	/*
	 * 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 (fileattr_has_fsx(fa) ||
	    (fa->flags & ~(FS_IMMUTABLE_FL | FS_APPEND_FL | FS_NOATIME_FL | ORANGEFS_MIRROR_FL))) {
		gossip_err("%s: only supports setting one of FS_IMMUTABLE_FL|FS_APPEND_FL|FS_NOATIME_FL\n",
			   __func__);
		return -EOPNOTSUPP;
	}
	val = fa->flags;
	gossip_debug(GOSSIP_FILE_DEBUG, "%s: flags=%u\n", __func__, (u32) val);
	return orangefs_inode_setxattr(d_inode(dentry),
				       "user.pvfs2.meta_hint",
				       &val, sizeof(val), 0);
}

/* ORANGEFS2 implementation of VFS inode operations for files */
static const struct inode_operations orangefs_file_inode_operations = {
	.get_acl = orangefs_get_acl,
@@ -963,6 +1011,8 @@ static const struct inode_operations orangefs_file_inode_operations = {
	.listxattr = orangefs_listxattr,
	.permission = orangefs_permission,
	.update_time = orangefs_update_time,
	.fileattr_get = orangefs_fileattr_get,
	.fileattr_set = orangefs_fileattr_set,
};

static int orangefs_init_iops(struct inode *inode)