brintos

brintos / linux-shallow public Read only

0
0
Text · 5.0 KiB · dd33f8c Raw
222 lines · c
1/*2 * Copyright 2000 by Hans Reiser, licensing governed by reiserfs/README3 */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 mnt_idmap *idmap,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 it46	 */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_set_ctime_current(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 inode69 * supported commands:70 *  1) REISERFS_IOC_UNPACK - try to unpack tail from direct item into indirect71 *                           and prevent packing file (argument arg has t72 *			      be non-zero)73 *  2) REISERFS_IOC_[GS]ETFLAGS, REISERFS_IOC_[GS]ETVERSION74 *  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		} else89			err = -ENOTTY;90		break;91		/*92		 * following two cases are taken from fs/ext2/ioctl.c by Remy93		 * 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(&nop_mnt_idmap, 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_set_ctime_current(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_COMPAT125long reiserfs_compat_ioctl(struct file *file, unsigned int cmd,126				unsigned long arg)127{128	/*129	 * These are just misnamed, they actually130	 * get/put from/to user an int131	 */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#endif149 150int reiserfs_commit_write(struct file *f, struct page *page,151			  unsigned from, unsigned to);152/*153 * reiserfs_unpack154 * Function try to convert tail from direct item into indirect.155 * It set up nopack attribute in the REISERFS_I(inode)->nopack156 */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 calling194	 * __reiserfs_write_begin on that page.  This will force a195	 * 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}222