Blame view
fs/reiserfs/ioctl.c
5.38 KB
1da177e4c Linux-2.6.12-rc2 |
1 2 3 |
/* * Copyright 2000 by Hans Reiser, licensing governed by reiserfs/README */ |
16f7e0fe2 [PATCH] capable/c... |
4 |
#include <linux/capability.h> |
1da177e4c Linux-2.6.12-rc2 |
5 |
#include <linux/fs.h> |
42a74f206 [PATCH] r/o bind ... |
6 |
#include <linux/mount.h> |
1da177e4c Linux-2.6.12-rc2 |
7 8 9 10 |
#include <linux/reiserfs_fs.h> #include <linux/time.h> #include <asm/uaccess.h> #include <linux/pagemap.h> |
52b499c43 [PATCH] BLOCK: Mo... |
11 |
#include <linux/compat.h> |
1da177e4c Linux-2.6.12-rc2 |
12 |
|
1da177e4c Linux-2.6.12-rc2 |
13 |
/* |
ac78a0789 kill-the-bkl/reis... |
14 15 16 17 18 19 20 |
* 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 to be non-zero) * 2) REISERFS_IOC_[GS]ETFLAGS, REISERFS_IOC_[GS]ETVERSION * 3) That's all for a while ... */ |
205cb37b8 kill-the-bkl/reis... |
21 |
long reiserfs_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) |
1da177e4c Linux-2.6.12-rc2 |
22 |
{ |
205cb37b8 kill-the-bkl/reis... |
23 |
struct inode *inode = filp->f_path.dentry->d_inode; |
1da177e4c Linux-2.6.12-rc2 |
24 |
unsigned int flags; |
42a74f206 [PATCH] r/o bind ... |
25 |
int err = 0; |
1da177e4c Linux-2.6.12-rc2 |
26 |
|
ac78a0789 kill-the-bkl/reis... |
27 |
reiserfs_write_lock(inode->i_sb); |
1da177e4c Linux-2.6.12-rc2 |
28 |
switch (cmd) { |
bd4c625c0 reiserfs: run scr... |
29 30 31 |
case REISERFS_IOC_UNPACK: if (S_ISREG(inode->i_mode)) { if (arg) |
ac78a0789 kill-the-bkl/reis... |
32 |
err = reiserfs_unpack(inode, filp); |
1da177e4c Linux-2.6.12-rc2 |
33 |
} else |
ac78a0789 kill-the-bkl/reis... |
34 35 36 37 38 39 |
err = -ENOTTY; break; /* * following two cases are taken from fs/ext2/ioctl.c by Remy * Card (card@masi.ibp.fr) */ |
1da177e4c Linux-2.6.12-rc2 |
40 |
case REISERFS_IOC_GETFLAGS: |
ac78a0789 kill-the-bkl/reis... |
41 42 43 44 |
if (!reiserfs_attrs(inode->i_sb)) { err = -ENOTTY; break; } |
869eb76e7 [PATCH] reiserfs:... |
45 |
|
bd4c625c0 reiserfs: run scr... |
46 47 |
flags = REISERFS_I(inode)->i_attrs; i_attrs_to_sd_attrs(inode, (__u16 *) & flags); |
ac78a0789 kill-the-bkl/reis... |
48 49 |
err = put_user(flags, (int __user *)arg); break; |
bd4c625c0 reiserfs: run scr... |
50 |
case REISERFS_IOC_SETFLAGS:{ |
ac78a0789 kill-the-bkl/reis... |
51 52 53 54 |
if (!reiserfs_attrs(inode->i_sb)) { err = -ENOTTY; break; } |
869eb76e7 [PATCH] reiserfs:... |
55 |
|
a561be710 switch a bunch of... |
56 |
err = mnt_want_write_file(filp); |
42a74f206 [PATCH] r/o bind ... |
57 |
if (err) |
ac78a0789 kill-the-bkl/reis... |
58 |
break; |
1da177e4c Linux-2.6.12-rc2 |
59 |
|
2e1496707 userns: rename is... |
60 |
if (!inode_owner_or_capable(inode)) { |
42a74f206 [PATCH] r/o bind ... |
61 62 63 64 65 66 67 68 69 70 71 72 73 74 |
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; } |
bd4c625c0 reiserfs: run scr... |
75 76 77 |
if (((flags ^ REISERFS_I(inode)-> i_attrs) & (REISERFS_IMMUTABLE_FL | REISERFS_APPEND_FL)) |
42a74f206 [PATCH] r/o bind ... |
78 79 80 81 |
&& !capable(CAP_LINUX_IMMUTABLE)) { err = -EPERM; goto setflags_out; } |
bd4c625c0 reiserfs: run scr... |
82 83 |
if ((flags & REISERFS_NOTAIL_FL) && S_ISREG(inode->i_mode)) { |
1da177e4c Linux-2.6.12-rc2 |
84 |
int result; |
bd4c625c0 reiserfs: run scr... |
85 |
result = reiserfs_unpack(inode, filp); |
42a74f206 [PATCH] r/o bind ... |
86 87 88 89 |
if (result) { err = result; goto setflags_out; } |
bd4c625c0 reiserfs: run scr... |
90 91 92 93 94 |
} sd_attrs_to_i_attrs(flags, inode); REISERFS_I(inode)->i_attrs = flags; inode->i_ctime = CURRENT_TIME_SEC; mark_inode_dirty(inode); |
42a74f206 [PATCH] r/o bind ... |
95 |
setflags_out: |
2a79f17e4 vfs: mnt_drop_wri... |
96 |
mnt_drop_write_file(filp); |
ac78a0789 kill-the-bkl/reis... |
97 |
break; |
1da177e4c Linux-2.6.12-rc2 |
98 |
} |
1da177e4c Linux-2.6.12-rc2 |
99 |
case REISERFS_IOC_GETVERSION: |
ac78a0789 kill-the-bkl/reis... |
100 101 |
err = put_user(inode->i_generation, (int __user *)arg); break; |
1da177e4c Linux-2.6.12-rc2 |
102 |
case REISERFS_IOC_SETVERSION: |
2e1496707 userns: rename is... |
103 |
if (!inode_owner_or_capable(inode)) { |
ac78a0789 kill-the-bkl/reis... |
104 105 |
err = -EPERM; break; |
e0baec1b6 reiserfs: Fix unr... |
106 |
} |
a561be710 switch a bunch of... |
107 |
err = mnt_want_write_file(filp); |
42a74f206 [PATCH] r/o bind ... |
108 |
if (err) |
ac78a0789 kill-the-bkl/reis... |
109 |
break; |
42a74f206 [PATCH] r/o bind ... |
110 111 112 113 |
if (get_user(inode->i_generation, (int __user *)arg)) { err = -EFAULT; goto setversion_out; } |
1da177e4c Linux-2.6.12-rc2 |
114 115 |
inode->i_ctime = CURRENT_TIME_SEC; mark_inode_dirty(inode); |
42a74f206 [PATCH] r/o bind ... |
116 |
setversion_out: |
2a79f17e4 vfs: mnt_drop_wri... |
117 |
mnt_drop_write_file(filp); |
ac78a0789 kill-the-bkl/reis... |
118 |
break; |
1da177e4c Linux-2.6.12-rc2 |
119 |
default: |
ac78a0789 kill-the-bkl/reis... |
120 |
err = -ENOTTY; |
1da177e4c Linux-2.6.12-rc2 |
121 |
} |
ac78a0789 kill-the-bkl/reis... |
122 123 124 125 |
reiserfs_write_unlock(inode->i_sb); return err; |
1da177e4c Linux-2.6.12-rc2 |
126 |
} |
52b499c43 [PATCH] BLOCK: Mo... |
127 128 129 130 |
#ifdef CONFIG_COMPAT long reiserfs_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { |
52b499c43 [PATCH] BLOCK: Mo... |
131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 |
/* 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; } |
8ebc42323 reiserfs: kill-th... |
151 |
|
205cb37b8 kill-the-bkl/reis... |
152 |
return reiserfs_ioctl(file, cmd, (unsigned long) compat_ptr(arg)); |
52b499c43 [PATCH] BLOCK: Mo... |
153 154 |
} #endif |
ba9d8cec6 reiserfs: convert... |
155 156 |
int reiserfs_commit_write(struct file *f, struct page *page, unsigned from, unsigned to); |
1da177e4c Linux-2.6.12-rc2 |
157 158 159 160 161 |
/* ** reiserfs_unpack ** Function try to convert tail from direct item into indirect. ** It set up nopack attribute in the REISERFS_I(inode)->nopack */ |
d5dee5c39 reiserfs: unpack ... |
162 |
int reiserfs_unpack(struct inode *inode, struct file *filp) |
1da177e4c Linux-2.6.12-rc2 |
163 |
{ |
bd4c625c0 reiserfs: run scr... |
164 |
int retval = 0; |
9d8117e72 reiserfs: fix unw... |
165 |
int depth; |
bd4c625c0 reiserfs: run scr... |
166 167 168 169 170 171 172 173 174 175 176 177 178 179 |
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; } |
bd4c625c0 reiserfs: run scr... |
180 |
|
9d8117e72 reiserfs: fix unw... |
181 |
depth = reiserfs_write_lock_once(inode->i_sb); |
bd4c625c0 reiserfs: run scr... |
182 |
|
da905873e reiserfs: fix ino... |
183 184 |
/* we need to make sure nobody is changing the file size beneath us */ reiserfs_mutex_lock_safe(&inode->i_mutex, inode->i_sb); |
bd4c625c0 reiserfs: run scr... |
185 186 187 188 189 190 191 192 |
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 |
ebdec241d fs: kill block_pr... |
193 |
** __reiserfs_write_begin on that page. This will force a |
bd4c625c0 reiserfs: run scr... |
194 195 196 197 198 199 200 201 202 |
** reiserfs_get_block to unpack the tail for us. */ index = inode->i_size >> PAGE_CACHE_SHIFT; mapping = inode->i_mapping; page = grab_cache_page(mapping, index); retval = -ENOMEM; if (!page) { goto out; } |
ebdec241d fs: kill block_pr... |
203 |
retval = __reiserfs_write_begin(page, write_from, 0); |
bd4c625c0 reiserfs: run scr... |
204 205 206 207 208 |
if (retval) goto out_unlock; /* conversion can change page contents, must flush */ flush_dcache_page(page); |
ba9d8cec6 reiserfs: convert... |
209 |
retval = reiserfs_commit_write(NULL, page, write_from, write_from); |
1da177e4c Linux-2.6.12-rc2 |
210 |
REISERFS_I(inode)->i_flags |= i_nopack_mask; |
bd4c625c0 reiserfs: run scr... |
211 212 213 214 215 216 |
out_unlock: unlock_page(page); page_cache_release(page); out: |
1b1dcc1b5 [PATCH] mutex sub... |
217 |
mutex_unlock(&inode->i_mutex); |
9d8117e72 reiserfs: fix unw... |
218 |
reiserfs_write_unlock_once(inode->i_sb, depth); |
bd4c625c0 reiserfs: run scr... |
219 |
return retval; |
1da177e4c Linux-2.6.12-rc2 |
220 |
} |