linux/fs/reiserfs/ioctl.c
Kirill A. Shutemov 09cbfeaf1a mm, fs: get rid of PAGE_CACHE_* and page_cache_{get,release} macros
PAGE_CACHE_{SIZE,SHIFT,MASK,ALIGN} macros were introduced *long* time
ago with promise that one day it will be possible to implement page
cache with bigger chunks than PAGE_SIZE.

This promise never materialized.  And unlikely will.

We have many places where PAGE_CACHE_SIZE assumed to be equal to
PAGE_SIZE.  And it's constant source of confusion on whether
PAGE_CACHE_* or PAGE_* constant should be used in a particular case,
especially on the border between fs and mm.

Global switching to PAGE_CACHE_SIZE != PAGE_SIZE would cause to much
breakage to be doable.

Let's stop pretending that pages in page cache are special.  They are
not.

The changes are pretty straight-forward:

 - <foo> << (PAGE_CACHE_SHIFT - PAGE_SHIFT) -> <foo>;

 - <foo> >> (PAGE_CACHE_SHIFT - PAGE_SHIFT) -> <foo>;

 - PAGE_CACHE_{SIZE,SHIFT,MASK,ALIGN} -> PAGE_{SIZE,SHIFT,MASK,ALIGN};

 - page_cache_get() -> get_page();

 - page_cache_release() -> put_page();

This patch contains automated changes generated with coccinelle using
script below.  For some reason, coccinelle doesn't patch header files.
I've called spatch for them manually.

The only adjustment after coccinelle is revert of changes to
PAGE_CAHCE_ALIGN definition: we are going to drop it later.

There are few places in the code where coccinelle didn't reach.  I'll
fix them manually in a separate patch.  Comments and documentation also
will be addressed with the separate patch.

virtual patch

@@
expression E;
@@
- E << (PAGE_CACHE_SHIFT - PAGE_SHIFT)
+ E

@@
expression E;
@@
- E >> (PAGE_CACHE_SHIFT - PAGE_SHIFT)
+ E

@@
@@
- PAGE_CACHE_SHIFT
+ PAGE_SHIFT

@@
@@
- PAGE_CACHE_SIZE
+ PAGE_SIZE

@@
@@
- PAGE_CACHE_MASK
+ PAGE_MASK

@@
expression E;
@@
- PAGE_CACHE_ALIGN(E)
+ PAGE_ALIGN(E)

@@
expression E;
@@
- page_cache_get(E)
+ get_page(E)

@@
expression E;
@@
- page_cache_release(E)
+ put_page(E)

Signed-off-by: Kirill A. Shutemov <kirill.shutemov@linux.intel.com>
Acked-by: Michal Hocko <mhocko@suse.com>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2016-04-04 10:41:08 -07:00

231 lines
5.3 KiB
C

/*
* Copyright 2000 by Hans Reiser, licensing governed by reiserfs/README
*/
#include <linux/capability.h>
#include <linux/fs.h>
#include <linux/mount.h>
#include "reiserfs.h"
#include <linux/time.h>
#include <linux/uaccess.h>
#include <linux/pagemap.h>
#include <linux/compat.h>
/*
* reiserfs_ioctl - handler for ioctl for inode
* supported commands:
* 1) REISERFS_IOC_UNPACK - try to unpack tail from direct item into indirect
* and prevent packing file (argument arg has t
* be non-zero)
* 2) REISERFS_IOC_[GS]ETFLAGS, REISERFS_IOC_[GS]ETVERSION
* 3) That's all for a while ...
*/
long reiserfs_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
{
struct inode *inode = file_inode(filp);
unsigned int flags;
int err = 0;
reiserfs_write_lock(inode->i_sb);
switch (cmd) {
case REISERFS_IOC_UNPACK:
if (S_ISREG(inode->i_mode)) {
if (arg)
err = reiserfs_unpack(inode, filp);
} else
err = -ENOTTY;
break;
/*
* following two cases are taken from fs/ext2/ioctl.c by Remy
* Card (card@masi.ibp.fr)
*/
case REISERFS_IOC_GETFLAGS:
if (!reiserfs_attrs(inode->i_sb)) {
err = -ENOTTY;
break;
}
flags = REISERFS_I(inode)->i_attrs;
i_attrs_to_sd_attrs(inode, (__u16 *) & flags);
err = put_user(flags, (int __user *)arg);
break;
case REISERFS_IOC_SETFLAGS:{
if (!reiserfs_attrs(inode->i_sb)) {
err = -ENOTTY;
break;
}
err = mnt_want_write_file(filp);
if (err)
break;
if (!inode_owner_or_capable(inode)) {
err = -EPERM;
goto setflags_out;
}
if (get_user(flags, (int __user *)arg)) {
err = -EFAULT;
goto setflags_out;
}
/*
* Is it quota file? Do not allow user to mess with it
*/
if (IS_NOQUOTA(inode)) {
err = -EPERM;
goto setflags_out;
}
if (((flags ^ REISERFS_I(inode)->
i_attrs) & (REISERFS_IMMUTABLE_FL |
REISERFS_APPEND_FL))
&& !capable(CAP_LINUX_IMMUTABLE)) {
err = -EPERM;
goto setflags_out;
}
if ((flags & REISERFS_NOTAIL_FL) &&
S_ISREG(inode->i_mode)) {
int result;
result = reiserfs_unpack(inode, filp);
if (result) {
err = result;
goto setflags_out;
}
}
sd_attrs_to_i_attrs(flags, inode);
REISERFS_I(inode)->i_attrs = flags;
inode->i_ctime = CURRENT_TIME_SEC;
mark_inode_dirty(inode);
setflags_out:
mnt_drop_write_file(filp);
break;
}
case REISERFS_IOC_GETVERSION:
err = put_user(inode->i_generation, (int __user *)arg);
break;
case REISERFS_IOC_SETVERSION:
if (!inode_owner_or_capable(inode)) {
err = -EPERM;
break;
}
err = mnt_want_write_file(filp);
if (err)
break;
if (get_user(inode->i_generation, (int __user *)arg)) {
err = -EFAULT;
goto setversion_out;
}
inode->i_ctime = CURRENT_TIME_SEC;
mark_inode_dirty(inode);
setversion_out:
mnt_drop_write_file(filp);
break;
default:
err = -ENOTTY;
}
reiserfs_write_unlock(inode->i_sb);
return err;
}
#ifdef CONFIG_COMPAT
long reiserfs_compat_ioctl(struct file *file, unsigned int cmd,
unsigned long arg)
{
/*
* These are just misnamed, they actually
* get/put from/to user an int
*/
switch (cmd) {
case REISERFS_IOC32_UNPACK:
cmd = REISERFS_IOC_UNPACK;
break;
case REISERFS_IOC32_GETFLAGS:
cmd = REISERFS_IOC_GETFLAGS;
break;
case REISERFS_IOC32_SETFLAGS:
cmd = REISERFS_IOC_SETFLAGS;
break;
case REISERFS_IOC32_GETVERSION:
cmd = REISERFS_IOC_GETVERSION;
break;
case REISERFS_IOC32_SETVERSION:
cmd = REISERFS_IOC_SETVERSION;
break;
default:
return -ENOIOCTLCMD;
}
return reiserfs_ioctl(file, cmd, (unsigned long) compat_ptr(arg));
}
#endif
int reiserfs_commit_write(struct file *f, struct page *page,
unsigned from, unsigned to);
/*
* reiserfs_unpack
* Function try to convert tail from direct item into indirect.
* It set up nopack attribute in the REISERFS_I(inode)->nopack
*/
int reiserfs_unpack(struct inode *inode, struct file *filp)
{
int retval = 0;
int index;
struct page *page;
struct address_space *mapping;
unsigned long write_from;
unsigned long blocksize = inode->i_sb->s_blocksize;
if (inode->i_size == 0) {
REISERFS_I(inode)->i_flags |= i_nopack_mask;
return 0;
}
/* ioctl already done */
if (REISERFS_I(inode)->i_flags & i_nopack_mask) {
return 0;
}
/* we need to make sure nobody is changing the file size beneath us */
reiserfs_mutex_lock_safe(&inode->i_mutex, inode->i_sb);
reiserfs_write_lock(inode->i_sb);
write_from = inode->i_size & (blocksize - 1);
/* if we are on a block boundary, we are already unpacked. */
if (write_from == 0) {
REISERFS_I(inode)->i_flags |= i_nopack_mask;
goto out;
}
/*
* we unpack by finding the page with the tail, and calling
* __reiserfs_write_begin on that page. This will force a
* reiserfs_get_block to unpack the tail for us.
*/
index = inode->i_size >> PAGE_SHIFT;
mapping = inode->i_mapping;
page = grab_cache_page(mapping, index);
retval = -ENOMEM;
if (!page) {
goto out;
}
retval = __reiserfs_write_begin(page, write_from, 0);
if (retval)
goto out_unlock;
/* conversion can change page contents, must flush */
flush_dcache_page(page);
retval = reiserfs_commit_write(NULL, page, write_from, write_from);
REISERFS_I(inode)->i_flags |= i_nopack_mask;
out_unlock:
unlock_page(page);
put_page(page);
out:
inode_unlock(inode);
reiserfs_write_unlock(inode->i_sb);
return retval;
}