diff options
Diffstat (limited to 'fs/reiserfs/ioctl.c')
-rw-r--r-- | fs/reiserfs/ioctl.c | 197 |
1 files changed, 101 insertions, 96 deletions
diff --git a/fs/reiserfs/ioctl.c b/fs/reiserfs/ioctl.c index 76caedf737f2..81fc00285f60 100644 --- a/fs/reiserfs/ioctl.c +++ b/fs/reiserfs/ioctl.c | |||
@@ -9,7 +9,7 @@ | |||
9 | #include <linux/pagemap.h> | 9 | #include <linux/pagemap.h> |
10 | #include <linux/smp_lock.h> | 10 | #include <linux/smp_lock.h> |
11 | 11 | ||
12 | static int reiserfs_unpack (struct inode * inode, struct file * filp); | 12 | static int reiserfs_unpack(struct inode *inode, struct file *filp); |
13 | 13 | ||
14 | /* | 14 | /* |
15 | ** reiserfs_ioctl - handler for ioctl for inode | 15 | ** reiserfs_ioctl - handler for ioctl for inode |
@@ -19,69 +19,72 @@ static int reiserfs_unpack (struct inode * inode, struct file * filp); | |||
19 | ** 2) REISERFS_IOC_[GS]ETFLAGS, REISERFS_IOC_[GS]ETVERSION | 19 | ** 2) REISERFS_IOC_[GS]ETFLAGS, REISERFS_IOC_[GS]ETVERSION |
20 | ** 3) That's all for a while ... | 20 | ** 3) That's all for a while ... |
21 | */ | 21 | */ |
22 | int reiserfs_ioctl (struct inode * inode, struct file * filp, unsigned int cmd, | 22 | int reiserfs_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, |
23 | unsigned long arg) | 23 | unsigned long arg) |
24 | { | 24 | { |
25 | unsigned int flags; | 25 | unsigned int flags; |
26 | 26 | ||
27 | switch (cmd) { | 27 | switch (cmd) { |
28 | case REISERFS_IOC_UNPACK: | 28 | case REISERFS_IOC_UNPACK: |
29 | if( S_ISREG( inode -> i_mode ) ) { | 29 | if (S_ISREG(inode->i_mode)) { |
30 | if (arg) | 30 | if (arg) |
31 | return reiserfs_unpack (inode, filp); | 31 | return reiserfs_unpack(inode, filp); |
32 | else | 32 | else |
33 | return 0; | 33 | return 0; |
34 | } else | 34 | } else |
35 | return -ENOTTY; | 35 | return -ENOTTY; |
36 | /* following two cases are taken from fs/ext2/ioctl.c by Remy | 36 | /* following two cases are taken from fs/ext2/ioctl.c by Remy |
37 | Card (card@masi.ibp.fr) */ | 37 | Card (card@masi.ibp.fr) */ |
38 | case REISERFS_IOC_GETFLAGS: | 38 | case REISERFS_IOC_GETFLAGS: |
39 | if (!reiserfs_attrs (inode->i_sb)) | 39 | if (!reiserfs_attrs(inode->i_sb)) |
40 | return -ENOTTY; | 40 | return -ENOTTY; |
41 | 41 | ||
42 | flags = REISERFS_I(inode) -> i_attrs; | 42 | flags = REISERFS_I(inode)->i_attrs; |
43 | i_attrs_to_sd_attrs( inode, ( __u16 * ) &flags ); | 43 | i_attrs_to_sd_attrs(inode, (__u16 *) & flags); |
44 | return put_user(flags, (int __user *) arg); | 44 | return put_user(flags, (int __user *)arg); |
45 | case REISERFS_IOC_SETFLAGS: { | 45 | case REISERFS_IOC_SETFLAGS:{ |
46 | if (!reiserfs_attrs (inode->i_sb)) | 46 | if (!reiserfs_attrs(inode->i_sb)) |
47 | return -ENOTTY; | 47 | return -ENOTTY; |
48 | 48 | ||
49 | if (IS_RDONLY(inode)) | 49 | if (IS_RDONLY(inode)) |
50 | return -EROFS; | 50 | return -EROFS; |
51 | 51 | ||
52 | if ((current->fsuid != inode->i_uid) && !capable(CAP_FOWNER)) | 52 | if ((current->fsuid != inode->i_uid) |
53 | return -EPERM; | 53 | && !capable(CAP_FOWNER)) |
54 | return -EPERM; | ||
54 | 55 | ||
55 | if (get_user(flags, (int __user *) arg)) | 56 | if (get_user(flags, (int __user *)arg)) |
56 | return -EFAULT; | 57 | return -EFAULT; |
57 | 58 | ||
58 | if ( ( ( flags ^ REISERFS_I(inode) -> i_attrs) & ( REISERFS_IMMUTABLE_FL | REISERFS_APPEND_FL)) && | 59 | if (((flags ^ REISERFS_I(inode)-> |
59 | !capable( CAP_LINUX_IMMUTABLE ) ) | 60 | i_attrs) & (REISERFS_IMMUTABLE_FL | |
60 | return -EPERM; | 61 | REISERFS_APPEND_FL)) |
61 | 62 | && !capable(CAP_LINUX_IMMUTABLE)) | |
62 | if( ( flags & REISERFS_NOTAIL_FL ) && | 63 | return -EPERM; |
63 | S_ISREG( inode -> i_mode ) ) { | 64 | |
65 | if ((flags & REISERFS_NOTAIL_FL) && | ||
66 | S_ISREG(inode->i_mode)) { | ||
64 | int result; | 67 | int result; |
65 | 68 | ||
66 | result = reiserfs_unpack( inode, filp ); | 69 | result = reiserfs_unpack(inode, filp); |
67 | if( result ) | 70 | if (result) |
68 | return result; | 71 | return result; |
72 | } | ||
73 | sd_attrs_to_i_attrs(flags, inode); | ||
74 | REISERFS_I(inode)->i_attrs = flags; | ||
75 | inode->i_ctime = CURRENT_TIME_SEC; | ||
76 | mark_inode_dirty(inode); | ||
77 | return 0; | ||
69 | } | 78 | } |
70 | sd_attrs_to_i_attrs( flags, inode ); | ||
71 | REISERFS_I(inode) -> i_attrs = flags; | ||
72 | inode->i_ctime = CURRENT_TIME_SEC; | ||
73 | mark_inode_dirty(inode); | ||
74 | return 0; | ||
75 | } | ||
76 | case REISERFS_IOC_GETVERSION: | 79 | case REISERFS_IOC_GETVERSION: |
77 | return put_user(inode->i_generation, (int __user *) arg); | 80 | return put_user(inode->i_generation, (int __user *)arg); |
78 | case REISERFS_IOC_SETVERSION: | 81 | case REISERFS_IOC_SETVERSION: |
79 | if ((current->fsuid != inode->i_uid) && !capable(CAP_FOWNER)) | 82 | if ((current->fsuid != inode->i_uid) && !capable(CAP_FOWNER)) |
80 | return -EPERM; | 83 | return -EPERM; |
81 | if (IS_RDONLY(inode)) | 84 | if (IS_RDONLY(inode)) |
82 | return -EROFS; | 85 | return -EROFS; |
83 | if (get_user(inode->i_generation, (int __user *) arg)) | 86 | if (get_user(inode->i_generation, (int __user *)arg)) |
84 | return -EFAULT; | 87 | return -EFAULT; |
85 | inode->i_ctime = CURRENT_TIME_SEC; | 88 | inode->i_ctime = CURRENT_TIME_SEC; |
86 | mark_inode_dirty(inode); | 89 | mark_inode_dirty(inode); |
87 | return 0; | 90 | return 0; |
@@ -95,63 +98,65 @@ int reiserfs_ioctl (struct inode * inode, struct file * filp, unsigned int cmd, | |||
95 | ** Function try to convert tail from direct item into indirect. | 98 | ** Function try to convert tail from direct item into indirect. |
96 | ** It set up nopack attribute in the REISERFS_I(inode)->nopack | 99 | ** It set up nopack attribute in the REISERFS_I(inode)->nopack |
97 | */ | 100 | */ |
98 | static int reiserfs_unpack (struct inode * inode, struct file * filp) | 101 | static int reiserfs_unpack(struct inode *inode, struct file *filp) |
99 | { | 102 | { |
100 | int retval = 0; | 103 | int retval = 0; |
101 | int index ; | 104 | int index; |
102 | struct page *page ; | 105 | struct page *page; |
103 | struct address_space *mapping ; | 106 | struct address_space *mapping; |
104 | unsigned long write_from ; | 107 | unsigned long write_from; |
105 | unsigned long blocksize = inode->i_sb->s_blocksize ; | 108 | unsigned long blocksize = inode->i_sb->s_blocksize; |
106 | 109 | ||
107 | if (inode->i_size == 0) { | 110 | if (inode->i_size == 0) { |
108 | REISERFS_I(inode)->i_flags |= i_nopack_mask; | 111 | REISERFS_I(inode)->i_flags |= i_nopack_mask; |
109 | return 0 ; | 112 | return 0; |
110 | } | 113 | } |
111 | /* ioctl already done */ | 114 | /* ioctl already done */ |
112 | if (REISERFS_I(inode)->i_flags & i_nopack_mask) { | 115 | if (REISERFS_I(inode)->i_flags & i_nopack_mask) { |
113 | return 0 ; | 116 | return 0; |
114 | } | 117 | } |
115 | reiserfs_write_lock(inode->i_sb); | 118 | reiserfs_write_lock(inode->i_sb); |
116 | 119 | ||
117 | /* we need to make sure nobody is changing the file size beneath | 120 | /* we need to make sure nobody is changing the file size beneath |
118 | ** us | 121 | ** us |
119 | */ | 122 | */ |
120 | down(&inode->i_sem) ; | 123 | down(&inode->i_sem); |
121 | 124 | ||
122 | write_from = inode->i_size & (blocksize - 1) ; | 125 | write_from = inode->i_size & (blocksize - 1); |
123 | /* if we are on a block boundary, we are already unpacked. */ | 126 | /* if we are on a block boundary, we are already unpacked. */ |
124 | if ( write_from == 0) { | 127 | if (write_from == 0) { |
128 | REISERFS_I(inode)->i_flags |= i_nopack_mask; | ||
129 | goto out; | ||
130 | } | ||
131 | |||
132 | /* we unpack by finding the page with the tail, and calling | ||
133 | ** reiserfs_prepare_write on that page. This will force a | ||
134 | ** reiserfs_get_block to unpack the tail for us. | ||
135 | */ | ||
136 | index = inode->i_size >> PAGE_CACHE_SHIFT; | ||
137 | mapping = inode->i_mapping; | ||
138 | page = grab_cache_page(mapping, index); | ||
139 | retval = -ENOMEM; | ||
140 | if (!page) { | ||
141 | goto out; | ||
142 | } | ||
143 | retval = | ||
144 | mapping->a_ops->prepare_write(NULL, page, write_from, write_from); | ||
145 | if (retval) | ||
146 | goto out_unlock; | ||
147 | |||
148 | /* conversion can change page contents, must flush */ | ||
149 | flush_dcache_page(page); | ||
150 | retval = | ||
151 | mapping->a_ops->commit_write(NULL, page, write_from, write_from); | ||
125 | REISERFS_I(inode)->i_flags |= i_nopack_mask; | 152 | REISERFS_I(inode)->i_flags |= i_nopack_mask; |
126 | goto out ; | 153 | |
127 | } | 154 | out_unlock: |
128 | 155 | unlock_page(page); | |
129 | /* we unpack by finding the page with the tail, and calling | 156 | page_cache_release(page); |
130 | ** reiserfs_prepare_write on that page. This will force a | 157 | |
131 | ** reiserfs_get_block to unpack the tail for us. | 158 | out: |
132 | */ | 159 | up(&inode->i_sem); |
133 | index = inode->i_size >> PAGE_CACHE_SHIFT ; | 160 | reiserfs_write_unlock(inode->i_sb); |
134 | mapping = inode->i_mapping ; | 161 | return retval; |
135 | page = grab_cache_page(mapping, index) ; | ||
136 | retval = -ENOMEM; | ||
137 | if (!page) { | ||
138 | goto out ; | ||
139 | } | ||
140 | retval = mapping->a_ops->prepare_write(NULL, page, write_from, write_from) ; | ||
141 | if (retval) | ||
142 | goto out_unlock ; | ||
143 | |||
144 | /* conversion can change page contents, must flush */ | ||
145 | flush_dcache_page(page) ; | ||
146 | retval = mapping->a_ops->commit_write(NULL, page, write_from, write_from) ; | ||
147 | REISERFS_I(inode)->i_flags |= i_nopack_mask; | ||
148 | |||
149 | out_unlock: | ||
150 | unlock_page(page) ; | ||
151 | page_cache_release(page) ; | ||
152 | |||
153 | out: | ||
154 | up(&inode->i_sem) ; | ||
155 | reiserfs_write_unlock(inode->i_sb); | ||
156 | return retval; | ||
157 | } | 162 | } |