aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ext2
diff options
context:
space:
mode:
Diffstat (limited to 'fs/ext2')
-rw-r--r--fs/ext2/acl.c65
-rw-r--r--fs/ext2/acl.h3
-rw-r--r--fs/ext2/ext2.h3
-rw-r--r--fs/ext2/file.c6
-rw-r--r--fs/ext2/inode.c6
-rw-r--r--fs/ext2/namei.c18
-rw-r--r--fs/ext2/xattr.c10
7 files changed, 35 insertions, 76 deletions
diff --git a/fs/ext2/acl.c b/fs/ext2/acl.c
index abea5a17c76..35d6a3cfd9f 100644
--- a/fs/ext2/acl.c
+++ b/fs/ext2/acl.c
@@ -128,7 +128,7 @@ fail:
128/* 128/*
129 * inode->i_mutex: don't care 129 * inode->i_mutex: don't care
130 */ 130 */
131static struct posix_acl * 131struct posix_acl *
132ext2_get_acl(struct inode *inode, int type) 132ext2_get_acl(struct inode *inode, int type)
133{ 133{
134 int name_index; 134 int name_index;
@@ -194,12 +194,10 @@ ext2_set_acl(struct inode *inode, int type, struct posix_acl *acl)
194 case ACL_TYPE_ACCESS: 194 case ACL_TYPE_ACCESS:
195 name_index = EXT2_XATTR_INDEX_POSIX_ACL_ACCESS; 195 name_index = EXT2_XATTR_INDEX_POSIX_ACL_ACCESS;
196 if (acl) { 196 if (acl) {
197 mode_t mode = inode->i_mode; 197 error = posix_acl_equiv_mode(acl, &inode->i_mode);
198 error = posix_acl_equiv_mode(acl, &mode);
199 if (error < 0) 198 if (error < 0)
200 return error; 199 return error;
201 else { 200 else {
202 inode->i_mode = mode;
203 inode->i_ctime = CURRENT_TIME_SEC; 201 inode->i_ctime = CURRENT_TIME_SEC;
204 mark_inode_dirty(inode); 202 mark_inode_dirty(inode);
205 if (error == 0) 203 if (error == 0)
@@ -231,29 +229,6 @@ ext2_set_acl(struct inode *inode, int type, struct posix_acl *acl)
231 return error; 229 return error;
232} 230}
233 231
234int
235ext2_check_acl(struct inode *inode, int mask, unsigned int flags)
236{
237 struct posix_acl *acl;
238
239 if (flags & IPERM_FLAG_RCU) {
240 if (!negative_cached_acl(inode, ACL_TYPE_ACCESS))
241 return -ECHILD;
242 return -EAGAIN;
243 }
244
245 acl = ext2_get_acl(inode, ACL_TYPE_ACCESS);
246 if (IS_ERR(acl))
247 return PTR_ERR(acl);
248 if (acl) {
249 int error = posix_acl_permission(inode, acl, mask);
250 posix_acl_release(acl);
251 return error;
252 }
253
254 return -EAGAIN;
255}
256
257/* 232/*
258 * Initialize the ACLs of a new inode. Called from ext2_new_inode. 233 * Initialize the ACLs of a new inode. Called from ext2_new_inode.
259 * 234 *
@@ -276,29 +251,18 @@ ext2_init_acl(struct inode *inode, struct inode *dir)
276 inode->i_mode &= ~current_umask(); 251 inode->i_mode &= ~current_umask();
277 } 252 }
278 if (test_opt(inode->i_sb, POSIX_ACL) && acl) { 253 if (test_opt(inode->i_sb, POSIX_ACL) && acl) {
279 struct posix_acl *clone;
280 mode_t mode;
281
282 if (S_ISDIR(inode->i_mode)) { 254 if (S_ISDIR(inode->i_mode)) {
283 error = ext2_set_acl(inode, ACL_TYPE_DEFAULT, acl); 255 error = ext2_set_acl(inode, ACL_TYPE_DEFAULT, acl);
284 if (error) 256 if (error)
285 goto cleanup; 257 goto cleanup;
286 } 258 }
287 clone = posix_acl_clone(acl, GFP_KERNEL); 259 error = posix_acl_create(&acl, GFP_KERNEL, &inode->i_mode);
288 error = -ENOMEM; 260 if (error < 0)
289 if (!clone) 261 return error;
290 goto cleanup; 262 if (error > 0) {
291 mode = inode->i_mode; 263 /* This is an extended ACL */
292 error = posix_acl_create_masq(clone, &mode); 264 error = ext2_set_acl(inode, ACL_TYPE_ACCESS, acl);
293 if (error >= 0) {
294 inode->i_mode = mode;
295 if (error > 0) {
296 /* This is an extended ACL */
297 error = ext2_set_acl(inode,
298 ACL_TYPE_ACCESS, clone);
299 }
300 } 265 }
301 posix_acl_release(clone);
302 } 266 }
303cleanup: 267cleanup:
304 posix_acl_release(acl); 268 posix_acl_release(acl);
@@ -322,7 +286,7 @@ cleanup:
322int 286int
323ext2_acl_chmod(struct inode *inode) 287ext2_acl_chmod(struct inode *inode)
324{ 288{
325 struct posix_acl *acl, *clone; 289 struct posix_acl *acl;
326 int error; 290 int error;
327 291
328 if (!test_opt(inode->i_sb, POSIX_ACL)) 292 if (!test_opt(inode->i_sb, POSIX_ACL))
@@ -332,14 +296,11 @@ ext2_acl_chmod(struct inode *inode)
332 acl = ext2_get_acl(inode, ACL_TYPE_ACCESS); 296 acl = ext2_get_acl(inode, ACL_TYPE_ACCESS);
333 if (IS_ERR(acl) || !acl) 297 if (IS_ERR(acl) || !acl)
334 return PTR_ERR(acl); 298 return PTR_ERR(acl);
335 clone = posix_acl_clone(acl, GFP_KERNEL); 299 error = posix_acl_chmod(&acl, GFP_KERNEL, inode->i_mode);
300 if (error)
301 return error;
302 error = ext2_set_acl(inode, ACL_TYPE_ACCESS, acl);
336 posix_acl_release(acl); 303 posix_acl_release(acl);
337 if (!clone)
338 return -ENOMEM;
339 error = posix_acl_chmod_masq(clone, inode->i_mode);
340 if (!error)
341 error = ext2_set_acl(inode, ACL_TYPE_ACCESS, clone);
342 posix_acl_release(clone);
343 return error; 304 return error;
344} 305}
345 306
diff --git a/fs/ext2/acl.h b/fs/ext2/acl.h
index c939b7b1209..503bfb0ed79 100644
--- a/fs/ext2/acl.h
+++ b/fs/ext2/acl.h
@@ -54,13 +54,12 @@ static inline int ext2_acl_count(size_t size)
54#ifdef CONFIG_EXT2_FS_POSIX_ACL 54#ifdef CONFIG_EXT2_FS_POSIX_ACL
55 55
56/* acl.c */ 56/* acl.c */
57extern int ext2_check_acl (struct inode *, int, unsigned int); 57extern struct posix_acl *ext2_get_acl(struct inode *inode, int type);
58extern int ext2_acl_chmod (struct inode *); 58extern int ext2_acl_chmod (struct inode *);
59extern int ext2_init_acl (struct inode *, struct inode *); 59extern int ext2_init_acl (struct inode *, struct inode *);
60 60
61#else 61#else
62#include <linux/sched.h> 62#include <linux/sched.h>
63#define ext2_check_acl NULL
64#define ext2_get_acl NULL 63#define ext2_get_acl NULL
65#define ext2_set_acl NULL 64#define ext2_set_acl NULL
66 65
diff --git a/fs/ext2/ext2.h b/fs/ext2/ext2.h
index 645be9e7ee4..af9fc89b1b2 100644
--- a/fs/ext2/ext2.h
+++ b/fs/ext2/ext2.h
@@ -150,7 +150,8 @@ extern void ext2_write_super (struct super_block *);
150extern const struct file_operations ext2_dir_operations; 150extern const struct file_operations ext2_dir_operations;
151 151
152/* file.c */ 152/* file.c */
153extern int ext2_fsync(struct file *file, int datasync); 153extern int ext2_fsync(struct file *file, loff_t start, loff_t end,
154 int datasync);
154extern const struct inode_operations ext2_file_inode_operations; 155extern const struct inode_operations ext2_file_inode_operations;
155extern const struct file_operations ext2_file_operations; 156extern const struct file_operations ext2_file_operations;
156extern const struct file_operations ext2_xip_file_operations; 157extern const struct file_operations ext2_xip_file_operations;
diff --git a/fs/ext2/file.c b/fs/ext2/file.c
index 49eec9456c5..a5b3a5db312 100644
--- a/fs/ext2/file.c
+++ b/fs/ext2/file.c
@@ -40,13 +40,13 @@ static int ext2_release_file (struct inode * inode, struct file * filp)
40 return 0; 40 return 0;
41} 41}
42 42
43int ext2_fsync(struct file *file, int datasync) 43int ext2_fsync(struct file *file, loff_t start, loff_t end, int datasync)
44{ 44{
45 int ret; 45 int ret;
46 struct super_block *sb = file->f_mapping->host->i_sb; 46 struct super_block *sb = file->f_mapping->host->i_sb;
47 struct address_space *mapping = sb->s_bdev->bd_inode->i_mapping; 47 struct address_space *mapping = sb->s_bdev->bd_inode->i_mapping;
48 48
49 ret = generic_file_fsync(file, datasync); 49 ret = generic_file_fsync(file, start, end, datasync);
50 if (ret == -EIO || test_and_clear_bit(AS_EIO, &mapping->flags)) { 50 if (ret == -EIO || test_and_clear_bit(AS_EIO, &mapping->flags)) {
51 /* We don't really know where the IO error happened... */ 51 /* We don't really know where the IO error happened... */
52 ext2_error(sb, __func__, 52 ext2_error(sb, __func__,
@@ -102,6 +102,6 @@ const struct inode_operations ext2_file_inode_operations = {
102 .removexattr = generic_removexattr, 102 .removexattr = generic_removexattr,
103#endif 103#endif
104 .setattr = ext2_setattr, 104 .setattr = ext2_setattr,
105 .check_acl = ext2_check_acl, 105 .get_acl = ext2_get_acl,
106 .fiemap = ext2_fiemap, 106 .fiemap = ext2_fiemap,
107}; 107};
diff --git a/fs/ext2/inode.c b/fs/ext2/inode.c
index 788e09a07f7..a8a58f63f07 100644
--- a/fs/ext2/inode.c
+++ b/fs/ext2/inode.c
@@ -843,8 +843,8 @@ ext2_direct_IO(int rw, struct kiocb *iocb, const struct iovec *iov,
843 struct inode *inode = mapping->host; 843 struct inode *inode = mapping->host;
844 ssize_t ret; 844 ssize_t ret;
845 845
846 ret = blockdev_direct_IO(rw, iocb, inode, inode->i_sb->s_bdev, 846 ret = blockdev_direct_IO(rw, iocb, inode, iov, offset, nr_segs,
847 iov, offset, nr_segs, ext2_get_block, NULL); 847 ext2_get_block);
848 if (ret < 0 && (rw & WRITE)) 848 if (ret < 0 && (rw & WRITE))
849 ext2_write_failed(mapping, offset + iov_length(iov, nr_segs)); 849 ext2_write_failed(mapping, offset + iov_length(iov, nr_segs));
850 return ret; 850 return ret;
@@ -1184,6 +1184,8 @@ static int ext2_setsize(struct inode *inode, loff_t newsize)
1184 if (IS_APPEND(inode) || IS_IMMUTABLE(inode)) 1184 if (IS_APPEND(inode) || IS_IMMUTABLE(inode))
1185 return -EPERM; 1185 return -EPERM;
1186 1186
1187 inode_dio_wait(inode);
1188
1187 if (mapping_is_xip(inode->i_mapping)) 1189 if (mapping_is_xip(inode->i_mapping))
1188 error = xip_truncate_page(inode->i_mapping, newsize); 1190 error = xip_truncate_page(inode->i_mapping, newsize);
1189 else if (test_opt(inode->i_sb, NOBH)) 1191 else if (test_opt(inode->i_sb, NOBH))
diff --git a/fs/ext2/namei.c b/fs/ext2/namei.c
index ed5c5d496ee..761fde807fc 100644
--- a/fs/ext2/namei.c
+++ b/fs/ext2/namei.c
@@ -67,15 +67,11 @@ static struct dentry *ext2_lookup(struct inode * dir, struct dentry *dentry, str
67 inode = NULL; 67 inode = NULL;
68 if (ino) { 68 if (ino) {
69 inode = ext2_iget(dir->i_sb, ino); 69 inode = ext2_iget(dir->i_sb, ino);
70 if (IS_ERR(inode)) { 70 if (inode == ERR_PTR(-ESTALE)) {
71 if (PTR_ERR(inode) == -ESTALE) { 71 ext2_error(dir->i_sb, __func__,
72 ext2_error(dir->i_sb, __func__, 72 "deleted inode referenced: %lu",
73 "deleted inode referenced: %lu", 73 (unsigned long) ino);
74 (unsigned long) ino); 74 return ERR_PTR(-EIO);
75 return ERR_PTR(-EIO);
76 } else {
77 return ERR_CAST(inode);
78 }
79 } 75 }
80 } 76 }
81 return d_splice_alias(inode, dentry); 77 return d_splice_alias(inode, dentry);
@@ -412,7 +408,7 @@ const struct inode_operations ext2_dir_inode_operations = {
412 .removexattr = generic_removexattr, 408 .removexattr = generic_removexattr,
413#endif 409#endif
414 .setattr = ext2_setattr, 410 .setattr = ext2_setattr,
415 .check_acl = ext2_check_acl, 411 .get_acl = ext2_get_acl,
416}; 412};
417 413
418const struct inode_operations ext2_special_inode_operations = { 414const struct inode_operations ext2_special_inode_operations = {
@@ -423,5 +419,5 @@ const struct inode_operations ext2_special_inode_operations = {
423 .removexattr = generic_removexattr, 419 .removexattr = generic_removexattr,
424#endif 420#endif
425 .setattr = ext2_setattr, 421 .setattr = ext2_setattr,
426 .check_acl = ext2_check_acl, 422 .get_acl = ext2_get_acl,
427}; 423};
diff --git a/fs/ext2/xattr.c b/fs/ext2/xattr.c
index 529970617a2..d27b71f1d18 100644
--- a/fs/ext2/xattr.c
+++ b/fs/ext2/xattr.c
@@ -161,6 +161,10 @@ ext2_xattr_get(struct inode *inode, int name_index, const char *name,
161 161
162 if (name == NULL) 162 if (name == NULL)
163 return -EINVAL; 163 return -EINVAL;
164 name_len = strlen(name);
165 if (name_len > 255)
166 return -ERANGE;
167
164 down_read(&EXT2_I(inode)->xattr_sem); 168 down_read(&EXT2_I(inode)->xattr_sem);
165 error = -ENODATA; 169 error = -ENODATA;
166 if (!EXT2_I(inode)->i_file_acl) 170 if (!EXT2_I(inode)->i_file_acl)
@@ -181,12 +185,8 @@ bad_block: ext2_error(inode->i_sb, "ext2_xattr_get",
181 error = -EIO; 185 error = -EIO;
182 goto cleanup; 186 goto cleanup;
183 } 187 }
184 /* find named attribute */
185 name_len = strlen(name);
186 188
187 error = -ERANGE; 189 /* find named attribute */
188 if (name_len > 255)
189 goto cleanup;
190 entry = FIRST_ENTRY(bh); 190 entry = FIRST_ENTRY(bh);
191 while (!IS_LAST_ENTRY(entry)) { 191 while (!IS_LAST_ENTRY(entry)) {
192 struct ext2_xattr_entry *next = 192 struct ext2_xattr_entry *next =