aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ext3
diff options
context:
space:
mode:
Diffstat (limited to 'fs/ext3')
-rw-r--r--fs/ext3/acl.c94
-rw-r--r--fs/ext3/acl.h4
-rw-r--r--fs/ext3/file.c2
-rw-r--r--fs/ext3/fsync.c18
-rw-r--r--fs/ext3/inode.c8
-rw-r--r--fs/ext3/namei.c18
-rw-r--r--fs/ext3/super.c2
7 files changed, 61 insertions, 85 deletions
diff --git a/fs/ext3/acl.c b/fs/ext3/acl.c
index 9d021c0d472a..6c29bf0df04a 100644
--- a/fs/ext3/acl.c
+++ b/fs/ext3/acl.c
@@ -131,7 +131,7 @@ fail:
131 * 131 *
132 * inode->i_mutex: don't care 132 * inode->i_mutex: don't care
133 */ 133 */
134static struct posix_acl * 134struct posix_acl *
135ext3_get_acl(struct inode *inode, int type) 135ext3_get_acl(struct inode *inode, int type)
136{ 136{
137 int name_index; 137 int name_index;
@@ -239,29 +239,6 @@ ext3_set_acl(handle_t *handle, struct inode *inode, int type,
239 return error; 239 return error;
240} 240}
241 241
242int
243ext3_check_acl(struct inode *inode, int mask, unsigned int flags)
244{
245 struct posix_acl *acl;
246
247 if (flags & IPERM_FLAG_RCU) {
248 if (!negative_cached_acl(inode, ACL_TYPE_ACCESS))
249 return -ECHILD;
250 return -EAGAIN;
251 }
252
253 acl = ext3_get_acl(inode, ACL_TYPE_ACCESS);
254 if (IS_ERR(acl))
255 return PTR_ERR(acl);
256 if (acl) {
257 int error = posix_acl_permission(inode, acl, mask);
258 posix_acl_release(acl);
259 return error;
260 }
261
262 return -EAGAIN;
263}
264
265/* 242/*
266 * Initialize the ACLs of a new inode. Called from ext3_new_inode. 243 * Initialize the ACLs of a new inode. Called from ext3_new_inode.
267 * 244 *
@@ -284,8 +261,7 @@ ext3_init_acl(handle_t *handle, struct inode *inode, struct inode *dir)
284 inode->i_mode &= ~current_umask(); 261 inode->i_mode &= ~current_umask();
285 } 262 }
286 if (test_opt(inode->i_sb, POSIX_ACL) && acl) { 263 if (test_opt(inode->i_sb, POSIX_ACL) && acl) {
287 struct posix_acl *clone; 264 mode_t mode = inode->i_mode;
288 mode_t mode;
289 265
290 if (S_ISDIR(inode->i_mode)) { 266 if (S_ISDIR(inode->i_mode)) {
291 error = ext3_set_acl(handle, inode, 267 error = ext3_set_acl(handle, inode,
@@ -293,22 +269,15 @@ ext3_init_acl(handle_t *handle, struct inode *inode, struct inode *dir)
293 if (error) 269 if (error)
294 goto cleanup; 270 goto cleanup;
295 } 271 }
296 clone = posix_acl_clone(acl, GFP_NOFS); 272 error = posix_acl_create(&acl, GFP_NOFS, &mode);
297 error = -ENOMEM; 273 if (error < 0)
298 if (!clone) 274 return error;
299 goto cleanup; 275
300 276 inode->i_mode = mode;
301 mode = inode->i_mode; 277 if (error > 0) {
302 error = posix_acl_create_masq(clone, &mode); 278 /* This is an extended ACL */
303 if (error >= 0) { 279 error = ext3_set_acl(handle, inode, ACL_TYPE_ACCESS, acl);
304 inode->i_mode = mode;
305 if (error > 0) {
306 /* This is an extended ACL */
307 error = ext3_set_acl(handle, inode,
308 ACL_TYPE_ACCESS, clone);
309 }
310 } 280 }
311 posix_acl_release(clone);
312 } 281 }
313cleanup: 282cleanup:
314 posix_acl_release(acl); 283 posix_acl_release(acl);
@@ -332,7 +301,9 @@ cleanup:
332int 301int
333ext3_acl_chmod(struct inode *inode) 302ext3_acl_chmod(struct inode *inode)
334{ 303{
335 struct posix_acl *acl, *clone; 304 struct posix_acl *acl;
305 handle_t *handle;
306 int retries = 0;
336 int error; 307 int error;
337 308
338 if (S_ISLNK(inode->i_mode)) 309 if (S_ISLNK(inode->i_mode))
@@ -342,31 +313,24 @@ ext3_acl_chmod(struct inode *inode)
342 acl = ext3_get_acl(inode, ACL_TYPE_ACCESS); 313 acl = ext3_get_acl(inode, ACL_TYPE_ACCESS);
343 if (IS_ERR(acl) || !acl) 314 if (IS_ERR(acl) || !acl)
344 return PTR_ERR(acl); 315 return PTR_ERR(acl);
345 clone = posix_acl_clone(acl, GFP_KERNEL); 316 error = posix_acl_chmod(&acl, GFP_KERNEL, inode->i_mode);
346 posix_acl_release(acl); 317 if (error)
347 if (!clone) 318 return error;
348 return -ENOMEM; 319retry:
349 error = posix_acl_chmod_masq(clone, inode->i_mode); 320 handle = ext3_journal_start(inode,
350 if (!error) { 321 EXT3_DATA_TRANS_BLOCKS(inode->i_sb));
351 handle_t *handle; 322 if (IS_ERR(handle)) {
352 int retries = 0; 323 error = PTR_ERR(handle);
353 324 ext3_std_error(inode->i_sb, error);
354 retry: 325 goto out;
355 handle = ext3_journal_start(inode,
356 EXT3_DATA_TRANS_BLOCKS(inode->i_sb));
357 if (IS_ERR(handle)) {
358 error = PTR_ERR(handle);
359 ext3_std_error(inode->i_sb, error);
360 goto out;
361 }
362 error = ext3_set_acl(handle, inode, ACL_TYPE_ACCESS, clone);
363 ext3_journal_stop(handle);
364 if (error == -ENOSPC &&
365 ext3_should_retry_alloc(inode->i_sb, &retries))
366 goto retry;
367 } 326 }
327 error = ext3_set_acl(handle, inode, ACL_TYPE_ACCESS, acl);
328 ext3_journal_stop(handle);
329 if (error == -ENOSPC &&
330 ext3_should_retry_alloc(inode->i_sb, &retries))
331 goto retry;
368out: 332out:
369 posix_acl_release(clone); 333 posix_acl_release(acl);
370 return error; 334 return error;
371} 335}
372 336
diff --git a/fs/ext3/acl.h b/fs/ext3/acl.h
index 5faf8048e906..dbc921e458c5 100644
--- a/fs/ext3/acl.h
+++ b/fs/ext3/acl.h
@@ -54,13 +54,13 @@ static inline int ext3_acl_count(size_t size)
54#ifdef CONFIG_EXT3_FS_POSIX_ACL 54#ifdef CONFIG_EXT3_FS_POSIX_ACL
55 55
56/* acl.c */ 56/* acl.c */
57extern int ext3_check_acl (struct inode *, int, unsigned int); 57extern struct posix_acl *ext3_get_acl(struct inode *inode, int type);
58extern int ext3_acl_chmod (struct inode *); 58extern int ext3_acl_chmod (struct inode *);
59extern int ext3_init_acl (handle_t *, struct inode *, struct inode *); 59extern int ext3_init_acl (handle_t *, struct inode *, struct inode *);
60 60
61#else /* CONFIG_EXT3_FS_POSIX_ACL */ 61#else /* CONFIG_EXT3_FS_POSIX_ACL */
62#include <linux/sched.h> 62#include <linux/sched.h>
63#define ext3_check_acl NULL 63#define ext3_get_acl NULL
64 64
65static inline int 65static inline int
66ext3_acl_chmod(struct inode *inode) 66ext3_acl_chmod(struct inode *inode)
diff --git a/fs/ext3/file.c b/fs/ext3/file.c
index 86c8ab343f6f..724df69847dc 100644
--- a/fs/ext3/file.c
+++ b/fs/ext3/file.c
@@ -78,7 +78,7 @@ const struct inode_operations ext3_file_inode_operations = {
78 .listxattr = ext3_listxattr, 78 .listxattr = ext3_listxattr,
79 .removexattr = generic_removexattr, 79 .removexattr = generic_removexattr,
80#endif 80#endif
81 .check_acl = ext3_check_acl, 81 .get_acl = ext3_get_acl,
82 .fiemap = ext3_fiemap, 82 .fiemap = ext3_fiemap,
83}; 83};
84 84
diff --git a/fs/ext3/fsync.c b/fs/ext3/fsync.c
index 06a4394d2bc3..d494c554c6e6 100644
--- a/fs/ext3/fsync.c
+++ b/fs/ext3/fsync.c
@@ -44,7 +44,7 @@
44 * inode to disk. 44 * inode to disk.
45 */ 45 */
46 46
47int ext3_sync_file(struct file *file, int datasync) 47int ext3_sync_file(struct file *file, loff_t start, loff_t end, int datasync)
48{ 48{
49 struct inode *inode = file->f_mapping->host; 49 struct inode *inode = file->f_mapping->host;
50 struct ext3_inode_info *ei = EXT3_I(inode); 50 struct ext3_inode_info *ei = EXT3_I(inode);
@@ -52,13 +52,23 @@ int ext3_sync_file(struct file *file, int datasync)
52 int ret, needs_barrier = 0; 52 int ret, needs_barrier = 0;
53 tid_t commit_tid; 53 tid_t commit_tid;
54 54
55 J_ASSERT(ext3_journal_current_handle() == NULL);
56
57 trace_ext3_sync_file_enter(file, datasync); 55 trace_ext3_sync_file_enter(file, datasync);
58 56
59 if (inode->i_sb->s_flags & MS_RDONLY) 57 if (inode->i_sb->s_flags & MS_RDONLY)
60 return 0; 58 return 0;
61 59
60 ret = filemap_write_and_wait_range(inode->i_mapping, start, end);
61 if (ret)
62 goto out;
63
64 /*
65 * Taking the mutex here just to keep consistent with how fsync was
66 * called previously, however it looks like we don't need to take
67 * i_mutex at all.
68 */
69 mutex_lock(&inode->i_mutex);
70
71 J_ASSERT(ext3_journal_current_handle() == NULL);
62 72
63 /* 73 /*
64 * data=writeback,ordered: 74 * data=writeback,ordered:
@@ -75,6 +85,7 @@ int ext3_sync_file(struct file *file, int datasync)
75 * safe in-journal, which is all fsync() needs to ensure. 85 * safe in-journal, which is all fsync() needs to ensure.
76 */ 86 */
77 if (ext3_should_journal_data(inode)) { 87 if (ext3_should_journal_data(inode)) {
88 mutex_unlock(&inode->i_mutex);
78 ret = ext3_force_commit(inode->i_sb); 89 ret = ext3_force_commit(inode->i_sb);
79 goto out; 90 goto out;
80 } 91 }
@@ -98,6 +109,7 @@ int ext3_sync_file(struct file *file, int datasync)
98 if (needs_barrier) 109 if (needs_barrier)
99 blkdev_issue_flush(inode->i_sb->s_bdev, GFP_KERNEL, NULL); 110 blkdev_issue_flush(inode->i_sb->s_bdev, GFP_KERNEL, NULL);
100 111
112 mutex_unlock(&inode->i_mutex);
101out: 113out:
102 trace_ext3_sync_file_exit(inode, ret); 114 trace_ext3_sync_file_exit(inode, ret);
103 return ret; 115 return ret;
diff --git a/fs/ext3/inode.c b/fs/ext3/inode.c
index f57c87b0cb83..04da6acde85d 100644
--- a/fs/ext3/inode.c
+++ b/fs/ext3/inode.c
@@ -1876,9 +1876,8 @@ static ssize_t ext3_direct_IO(int rw, struct kiocb *iocb,
1876 } 1876 }
1877 1877
1878retry: 1878retry:
1879 ret = blockdev_direct_IO(rw, iocb, inode, inode->i_sb->s_bdev, iov, 1879 ret = blockdev_direct_IO(rw, iocb, inode, iov, offset, nr_segs,
1880 offset, nr_segs, 1880 ext3_get_block);
1881 ext3_get_block, NULL);
1882 /* 1881 /*
1883 * In case of error extending write may have instantiated a few 1882 * In case of error extending write may have instantiated a few
1884 * blocks outside i_size. Trim these off again. 1883 * blocks outside i_size. Trim these off again.
@@ -3276,6 +3275,9 @@ int ext3_setattr(struct dentry *dentry, struct iattr *attr)
3276 ext3_journal_stop(handle); 3275 ext3_journal_stop(handle);
3277 } 3276 }
3278 3277
3278 if (attr->ia_valid & ATTR_SIZE)
3279 inode_dio_wait(inode);
3280
3279 if (S_ISREG(inode->i_mode) && 3281 if (S_ISREG(inode->i_mode) &&
3280 attr->ia_valid & ATTR_SIZE && attr->ia_size < inode->i_size) { 3282 attr->ia_valid & ATTR_SIZE && attr->ia_size < inode->i_size) {
3281 handle_t *handle; 3283 handle_t *handle;
diff --git a/fs/ext3/namei.c b/fs/ext3/namei.c
index 0465368598bd..6e18a0b7750d 100644
--- a/fs/ext3/namei.c
+++ b/fs/ext3/namei.c
@@ -1039,15 +1039,11 @@ static struct dentry *ext3_lookup(struct inode * dir, struct dentry *dentry, str
1039 return ERR_PTR(-EIO); 1039 return ERR_PTR(-EIO);
1040 } 1040 }
1041 inode = ext3_iget(dir->i_sb, ino); 1041 inode = ext3_iget(dir->i_sb, ino);
1042 if (IS_ERR(inode)) { 1042 if (inode == ERR_PTR(-ESTALE)) {
1043 if (PTR_ERR(inode) == -ESTALE) { 1043 ext3_error(dir->i_sb, __func__,
1044 ext3_error(dir->i_sb, __func__, 1044 "deleted inode referenced: %lu",
1045 "deleted inode referenced: %lu", 1045 ino);
1046 ino); 1046 return ERR_PTR(-EIO);
1047 return ERR_PTR(-EIO);
1048 } else {
1049 return ERR_CAST(inode);
1050 }
1051 } 1047 }
1052 } 1048 }
1053 return d_splice_alias(inode, dentry); 1049 return d_splice_alias(inode, dentry);
@@ -2536,7 +2532,7 @@ const struct inode_operations ext3_dir_inode_operations = {
2536 .listxattr = ext3_listxattr, 2532 .listxattr = ext3_listxattr,
2537 .removexattr = generic_removexattr, 2533 .removexattr = generic_removexattr,
2538#endif 2534#endif
2539 .check_acl = ext3_check_acl, 2535 .get_acl = ext3_get_acl,
2540}; 2536};
2541 2537
2542const struct inode_operations ext3_special_inode_operations = { 2538const struct inode_operations ext3_special_inode_operations = {
@@ -2547,5 +2543,5 @@ const struct inode_operations ext3_special_inode_operations = {
2547 .listxattr = ext3_listxattr, 2543 .listxattr = ext3_listxattr,
2548 .removexattr = generic_removexattr, 2544 .removexattr = generic_removexattr,
2549#endif 2545#endif
2550 .check_acl = ext3_check_acl, 2546 .get_acl = ext3_get_acl,
2551}; 2547};
diff --git a/fs/ext3/super.c b/fs/ext3/super.c
index 662290fb6fff..7beb69ae0015 100644
--- a/fs/ext3/super.c
+++ b/fs/ext3/super.c
@@ -1730,6 +1730,8 @@ static int ext3_fill_super (struct super_block *sb, void *data, int silent)
1730 sbi->s_resuid = le16_to_cpu(es->s_def_resuid); 1730 sbi->s_resuid = le16_to_cpu(es->s_def_resuid);
1731 sbi->s_resgid = le16_to_cpu(es->s_def_resgid); 1731 sbi->s_resgid = le16_to_cpu(es->s_def_resgid);
1732 1732
1733 /* enable barriers by default */
1734 set_opt(sbi->s_mount_opt, BARRIER);
1733 set_opt(sbi->s_mount_opt, RESERVATION); 1735 set_opt(sbi->s_mount_opt, RESERVATION);
1734 1736
1735 if (!parse_options ((char *) data, sb, &journal_inum, &journal_devnum, 1737 if (!parse_options ((char *) data, sb, &journal_inum, &journal_devnum,