cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

ioctl.c (5098B)


      1/*
      2 * Copyright 2000 by Hans Reiser, licensing governed by reiserfs/README
      3 */
      4
      5#include <linux/capability.h>
      6#include <linux/fs.h>
      7#include <linux/mount.h>
      8#include "reiserfs.h"
      9#include <linux/time.h>
     10#include <linux/uaccess.h>
     11#include <linux/pagemap.h>
     12#include <linux/compat.h>
     13#include <linux/fileattr.h>
     14
     15int reiserfs_fileattr_get(struct dentry *dentry, struct fileattr *fa)
     16{
     17	struct inode *inode = d_inode(dentry);
     18
     19	if (!reiserfs_attrs(inode->i_sb))
     20		return -ENOTTY;
     21
     22	fileattr_fill_flags(fa, REISERFS_I(inode)->i_attrs);
     23
     24	return 0;
     25}
     26
     27int reiserfs_fileattr_set(struct user_namespace *mnt_userns,
     28			  struct dentry *dentry, struct fileattr *fa)
     29{
     30	struct inode *inode = d_inode(dentry);
     31	unsigned int flags = fa->flags;
     32	int err;
     33
     34	reiserfs_write_lock(inode->i_sb);
     35
     36	err = -ENOTTY;
     37	if (!reiserfs_attrs(inode->i_sb))
     38		goto unlock;
     39
     40	err = -EOPNOTSUPP;
     41	if (fileattr_has_fsx(fa))
     42		goto unlock;
     43
     44	/*
     45	 * Is it quota file? Do not allow user to mess with it
     46	 */
     47	err = -EPERM;
     48	if (IS_NOQUOTA(inode))
     49		goto unlock;
     50
     51	if ((flags & REISERFS_NOTAIL_FL) && S_ISREG(inode->i_mode)) {
     52		err = reiserfs_unpack(inode);
     53		if (err)
     54			goto unlock;
     55	}
     56	sd_attrs_to_i_attrs(flags, inode);
     57	REISERFS_I(inode)->i_attrs = flags;
     58	inode->i_ctime = current_time(inode);
     59	mark_inode_dirty(inode);
     60	err = 0;
     61unlock:
     62	reiserfs_write_unlock(inode->i_sb);
     63
     64	return err;
     65}
     66
     67/*
     68 * reiserfs_ioctl - handler for ioctl for inode
     69 * supported commands:
     70 *  1) REISERFS_IOC_UNPACK - try to unpack tail from direct item into indirect
     71 *                           and prevent packing file (argument arg has t
     72 *			      be non-zero)
     73 *  2) REISERFS_IOC_[GS]ETFLAGS, REISERFS_IOC_[GS]ETVERSION
     74 *  3) That's all for a while ...
     75 */
     76long reiserfs_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
     77{
     78	struct inode *inode = file_inode(filp);
     79	int err = 0;
     80
     81	reiserfs_write_lock(inode->i_sb);
     82
     83	switch (cmd) {
     84	case REISERFS_IOC_UNPACK:
     85		if (S_ISREG(inode->i_mode)) {
     86			if (arg)
     87				err = reiserfs_unpack(inode);
     88		} else
     89			err = -ENOTTY;
     90		break;
     91		/*
     92		 * following two cases are taken from fs/ext2/ioctl.c by Remy
     93		 * Card (card@masi.ibp.fr)
     94		 */
     95	case REISERFS_IOC_GETVERSION:
     96		err = put_user(inode->i_generation, (int __user *)arg);
     97		break;
     98	case REISERFS_IOC_SETVERSION:
     99		if (!inode_owner_or_capable(&init_user_ns, inode)) {
    100			err = -EPERM;
    101			break;
    102		}
    103		err = mnt_want_write_file(filp);
    104		if (err)
    105			break;
    106		if (get_user(inode->i_generation, (int __user *)arg)) {
    107			err = -EFAULT;
    108			goto setversion_out;
    109		}
    110		inode->i_ctime = current_time(inode);
    111		mark_inode_dirty(inode);
    112setversion_out:
    113		mnt_drop_write_file(filp);
    114		break;
    115	default:
    116		err = -ENOTTY;
    117	}
    118
    119	reiserfs_write_unlock(inode->i_sb);
    120
    121	return err;
    122}
    123
    124#ifdef CONFIG_COMPAT
    125long reiserfs_compat_ioctl(struct file *file, unsigned int cmd,
    126				unsigned long arg)
    127{
    128	/*
    129	 * These are just misnamed, they actually
    130	 * get/put from/to user an int
    131	 */
    132	switch (cmd) {
    133	case REISERFS_IOC32_UNPACK:
    134		cmd = REISERFS_IOC_UNPACK;
    135		break;
    136	case REISERFS_IOC32_GETVERSION:
    137		cmd = REISERFS_IOC_GETVERSION;
    138		break;
    139	case REISERFS_IOC32_SETVERSION:
    140		cmd = REISERFS_IOC_SETVERSION;
    141		break;
    142	default:
    143		return -ENOIOCTLCMD;
    144	}
    145
    146	return reiserfs_ioctl(file, cmd, (unsigned long) compat_ptr(arg));
    147}
    148#endif
    149
    150int reiserfs_commit_write(struct file *f, struct page *page,
    151			  unsigned from, unsigned to);
    152/*
    153 * reiserfs_unpack
    154 * Function try to convert tail from direct item into indirect.
    155 * It set up nopack attribute in the REISERFS_I(inode)->nopack
    156 */
    157int reiserfs_unpack(struct inode *inode)
    158{
    159	int retval = 0;
    160	int index;
    161	struct page *page;
    162	struct address_space *mapping;
    163	unsigned long write_from;
    164	unsigned long blocksize = inode->i_sb->s_blocksize;
    165
    166	if (inode->i_size == 0) {
    167		REISERFS_I(inode)->i_flags |= i_nopack_mask;
    168		return 0;
    169	}
    170	/* ioctl already done */
    171	if (REISERFS_I(inode)->i_flags & i_nopack_mask) {
    172		return 0;
    173	}
    174
    175	/* we need to make sure nobody is changing the file size beneath us */
    176	{
    177		int depth = reiserfs_write_unlock_nested(inode->i_sb);
    178
    179		inode_lock(inode);
    180		reiserfs_write_lock_nested(inode->i_sb, depth);
    181	}
    182
    183	reiserfs_write_lock(inode->i_sb);
    184
    185	write_from = inode->i_size & (blocksize - 1);
    186	/* if we are on a block boundary, we are already unpacked.  */
    187	if (write_from == 0) {
    188		REISERFS_I(inode)->i_flags |= i_nopack_mask;
    189		goto out;
    190	}
    191
    192	/*
    193	 * we unpack by finding the page with the tail, and calling
    194	 * __reiserfs_write_begin on that page.  This will force a
    195	 * reiserfs_get_block to unpack the tail for us.
    196	 */
    197	index = inode->i_size >> PAGE_SHIFT;
    198	mapping = inode->i_mapping;
    199	page = grab_cache_page(mapping, index);
    200	retval = -ENOMEM;
    201	if (!page) {
    202		goto out;
    203	}
    204	retval = __reiserfs_write_begin(page, write_from, 0);
    205	if (retval)
    206		goto out_unlock;
    207
    208	/* conversion can change page contents, must flush */
    209	flush_dcache_page(page);
    210	retval = reiserfs_commit_write(NULL, page, write_from, write_from);
    211	REISERFS_I(inode)->i_flags |= i_nopack_mask;
    212
    213out_unlock:
    214	unlock_page(page);
    215	put_page(page);
    216
    217out:
    218	inode_unlock(inode);
    219	reiserfs_write_unlock(inode->i_sb);
    220	return retval;
    221}