Blame view

fs/reiserfs/ioctl.c 5.28 KB
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1
2
3
  /*
   * Copyright 2000 by Hans Reiser, licensing governed by reiserfs/README
   */
16f7e0fe2   Randy Dunlap   [PATCH] capable/c...
4
  #include <linux/capability.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5
  #include <linux/fs.h>
42a74f206   Dave Hansen   [PATCH] r/o bind ...
6
  #include <linux/mount.h>
f466c6fdb   Al Viro   move private bits...
7
  #include "reiserfs.h"
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
8
  #include <linux/time.h>
17093991a   Fabian Frederick   fs/reiserfs: use ...
9
  #include <linux/uaccess.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
10
  #include <linux/pagemap.h>
52b499c43   David Howells   [PATCH] BLOCK: Mo...
11
  #include <linux/compat.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
12

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
13
  /*
ac78a0789   Frederic Weisbecker   kill-the-bkl/reis...
14
15
16
   * reiserfs_ioctl - handler for ioctl for inode
   * supported commands:
   *  1) REISERFS_IOC_UNPACK - try to unpack tail from direct item into indirect
098297b27   Jeff Mahoney   reiserfs: cleanup...
17
18
   *                           and prevent packing file (argument arg has t
   *			      be non-zero)
ac78a0789   Frederic Weisbecker   kill-the-bkl/reis...
19
20
21
   *  2) REISERFS_IOC_[GS]ETFLAGS, REISERFS_IOC_[GS]ETVERSION
   *  3) That's all for a while ...
   */
205cb37b8   Frederic Weisbecker   kill-the-bkl/reis...
22
  long reiserfs_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
23
  {
496ad9aa8   Al Viro   new helper: file_...
24
  	struct inode *inode = file_inode(filp);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
25
  	unsigned int flags;
42a74f206   Dave Hansen   [PATCH] r/o bind ...
26
  	int err = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
27

ac78a0789   Frederic Weisbecker   kill-the-bkl/reis...
28
  	reiserfs_write_lock(inode->i_sb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
29
  	switch (cmd) {
bd4c625c0   Linus Torvalds   reiserfs: run scr...
30
31
32
  	case REISERFS_IOC_UNPACK:
  		if (S_ISREG(inode->i_mode)) {
  			if (arg)
ac78a0789   Frederic Weisbecker   kill-the-bkl/reis...
33
  				err = reiserfs_unpack(inode, filp);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
34
  		} else
ac78a0789   Frederic Weisbecker   kill-the-bkl/reis...
35
36
37
38
39
40
  			err = -ENOTTY;
  		break;
  		/*
  		 * following two cases are taken from fs/ext2/ioctl.c by Remy
  		 * Card (card@masi.ibp.fr)
  		 */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
41
  	case REISERFS_IOC_GETFLAGS:
ac78a0789   Frederic Weisbecker   kill-the-bkl/reis...
42
43
44
45
  		if (!reiserfs_attrs(inode->i_sb)) {
  			err = -ENOTTY;
  			break;
  		}
869eb76e7   Jeff Mahoney   [PATCH] reiserfs:...
46

bd4c625c0   Linus Torvalds   reiserfs: run scr...
47
  		flags = REISERFS_I(inode)->i_attrs;
ac78a0789   Frederic Weisbecker   kill-the-bkl/reis...
48
49
  		err = put_user(flags, (int __user *)arg);
  		break;
bd4c625c0   Linus Torvalds   reiserfs: run scr...
50
  	case REISERFS_IOC_SETFLAGS:{
ac78a0789   Frederic Weisbecker   kill-the-bkl/reis...
51
52
53
54
  			if (!reiserfs_attrs(inode->i_sb)) {
  				err = -ENOTTY;
  				break;
  			}
869eb76e7   Jeff Mahoney   [PATCH] reiserfs:...
55

a561be710   Al Viro   switch a bunch of...
56
  			err = mnt_want_write_file(filp);
42a74f206   Dave Hansen   [PATCH] r/o bind ...
57
  			if (err)
ac78a0789   Frederic Weisbecker   kill-the-bkl/reis...
58
  				break;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
59

2e1496707   Serge E. Hallyn   userns: rename is...
60
  			if (!inode_owner_or_capable(inode)) {
42a74f206   Dave Hansen   [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;
  			}
5aca28421   Darrick J. Wong   vfs: create a gen...
75
76
77
78
  			err = vfs_ioc_setflags_prepare(inode,
  						     REISERFS_I(inode)->i_attrs,
  						     flags);
  			if (err)
42a74f206   Dave Hansen   [PATCH] r/o bind ...
79
  				goto setflags_out;
bd4c625c0   Linus Torvalds   reiserfs: run scr...
80
81
  			if ((flags & REISERFS_NOTAIL_FL) &&
  			    S_ISREG(inode->i_mode)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
82
  				int result;
bd4c625c0   Linus Torvalds   reiserfs: run scr...
83
  				result = reiserfs_unpack(inode, filp);
42a74f206   Dave Hansen   [PATCH] r/o bind ...
84
85
86
87
  				if (result) {
  					err = result;
  					goto setflags_out;
  				}
bd4c625c0   Linus Torvalds   reiserfs: run scr...
88
89
90
  			}
  			sd_attrs_to_i_attrs(flags, inode);
  			REISERFS_I(inode)->i_attrs = flags;
02027d42c   Deepa Dinamani   fs: Replace CURRE...
91
  			inode->i_ctime = current_time(inode);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
92
  			mark_inode_dirty(inode);
42a74f206   Dave Hansen   [PATCH] r/o bind ...
93
  setflags_out:
2a79f17e4   Al Viro   vfs: mnt_drop_wri...
94
  			mnt_drop_write_file(filp);
ac78a0789   Frederic Weisbecker   kill-the-bkl/reis...
95
  			break;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
96
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
97
  	case REISERFS_IOC_GETVERSION:
ac78a0789   Frederic Weisbecker   kill-the-bkl/reis...
98
99
  		err = put_user(inode->i_generation, (int __user *)arg);
  		break;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
100
  	case REISERFS_IOC_SETVERSION:
2e1496707   Serge E. Hallyn   userns: rename is...
101
  		if (!inode_owner_or_capable(inode)) {
ac78a0789   Frederic Weisbecker   kill-the-bkl/reis...
102
103
  			err = -EPERM;
  			break;
e0baec1b6   Jiri Slaby   reiserfs: Fix unr...
104
  		}
a561be710   Al Viro   switch a bunch of...
105
  		err = mnt_want_write_file(filp);
42a74f206   Dave Hansen   [PATCH] r/o bind ...
106
  		if (err)
ac78a0789   Frederic Weisbecker   kill-the-bkl/reis...
107
  			break;
42a74f206   Dave Hansen   [PATCH] r/o bind ...
108
109
110
111
  		if (get_user(inode->i_generation, (int __user *)arg)) {
  			err = -EFAULT;
  			goto setversion_out;
  		}
02027d42c   Deepa Dinamani   fs: Replace CURRE...
112
  		inode->i_ctime = current_time(inode);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
113
  		mark_inode_dirty(inode);
42a74f206   Dave Hansen   [PATCH] r/o bind ...
114
  setversion_out:
2a79f17e4   Al Viro   vfs: mnt_drop_wri...
115
  		mnt_drop_write_file(filp);
ac78a0789   Frederic Weisbecker   kill-the-bkl/reis...
116
  		break;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
117
  	default:
ac78a0789   Frederic Weisbecker   kill-the-bkl/reis...
118
  		err = -ENOTTY;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
119
  	}
ac78a0789   Frederic Weisbecker   kill-the-bkl/reis...
120
121
122
123
  
  	reiserfs_write_unlock(inode->i_sb);
  
  	return err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
124
  }
52b499c43   David Howells   [PATCH] BLOCK: Mo...
125
126
127
128
  #ifdef CONFIG_COMPAT
  long reiserfs_compat_ioctl(struct file *file, unsigned int cmd,
  				unsigned long arg)
  {
098297b27   Jeff Mahoney   reiserfs: cleanup...
129
130
131
132
  	/*
  	 * These are just misnamed, they actually
  	 * get/put from/to user an int
  	 */
52b499c43   David Howells   [PATCH] BLOCK: Mo...
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
  	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   Frederic Weisbecker   reiserfs: kill-th...
152

205cb37b8   Frederic Weisbecker   kill-the-bkl/reis...
153
  	return reiserfs_ioctl(file, cmd, (unsigned long) compat_ptr(arg));
52b499c43   David Howells   [PATCH] BLOCK: Mo...
154
155
  }
  #endif
ba9d8cec6   Vladimir Saveliev   reiserfs: convert...
156
157
  int reiserfs_commit_write(struct file *f, struct page *page,
  			  unsigned from, unsigned to);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
158
  /*
098297b27   Jeff Mahoney   reiserfs: cleanup...
159
160
161
162
   * reiserfs_unpack
   * Function try to convert tail from direct item into indirect.
   * It set up nopack attribute in the REISERFS_I(inode)->nopack
   */
d5dee5c39   Jan Kara   reiserfs: unpack ...
163
  int reiserfs_unpack(struct inode *inode, struct file *filp)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
164
  {
bd4c625c0   Linus Torvalds   reiserfs: run scr...
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
  	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;
  	}
bd4c625c0   Linus Torvalds   reiserfs: run scr...
180

da905873e   Frederic Weisbecker   reiserfs: fix ino...
181
  	/* we need to make sure nobody is changing the file size beneath us */
1ae1f3f64   Al Viro   reiserfs: open-co...
182
183
184
185
186
  {
  	int depth = reiserfs_write_unlock_nested(inode->i_sb);
  	inode_lock(inode);
  	reiserfs_write_lock_nested(inode->i_sb, depth);
  }
da905873e   Frederic Weisbecker   reiserfs: fix ino...
187

278f6679f   Jeff Mahoney   reiserfs: locking...
188
  	reiserfs_write_lock(inode->i_sb);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
189
190
191
192
193
194
  	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;
  	}
098297b27   Jeff Mahoney   reiserfs: cleanup...
195
196
197
198
  	/*
  	 * 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.
bd4c625c0   Linus Torvalds   reiserfs: run scr...
199
  	 */
09cbfeaf1   Kirill A. Shutemov   mm, fs: get rid o...
200
  	index = inode->i_size >> PAGE_SHIFT;
bd4c625c0   Linus Torvalds   reiserfs: run scr...
201
202
203
204
205
206
  	mapping = inode->i_mapping;
  	page = grab_cache_page(mapping, index);
  	retval = -ENOMEM;
  	if (!page) {
  		goto out;
  	}
ebdec241d   Christoph Hellwig   fs: kill block_pr...
207
  	retval = __reiserfs_write_begin(page, write_from, 0);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
208
209
210
211
212
  	if (retval)
  		goto out_unlock;
  
  	/* conversion can change page contents, must flush */
  	flush_dcache_page(page);
ba9d8cec6   Vladimir Saveliev   reiserfs: convert...
213
  	retval = reiserfs_commit_write(NULL, page, write_from, write_from);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
214
  	REISERFS_I(inode)->i_flags |= i_nopack_mask;
bd4c625c0   Linus Torvalds   reiserfs: run scr...
215

cf776a7a4   Jeff Mahoney   reiserfs: cleanup...
216
  out_unlock:
bd4c625c0   Linus Torvalds   reiserfs: run scr...
217
  	unlock_page(page);
09cbfeaf1   Kirill A. Shutemov   mm, fs: get rid o...
218
  	put_page(page);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
219

cf776a7a4   Jeff Mahoney   reiserfs: cleanup...
220
  out:
5955102c9   Al Viro   wrappers for ->i_...
221
  	inode_unlock(inode);
278f6679f   Jeff Mahoney   reiserfs: locking...
222
  	reiserfs_write_unlock(inode->i_sb);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
223
  	return retval;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
224
  }