diff options
Diffstat (limited to 'fs/reiserfs')
-rw-r--r-- | fs/reiserfs/file.c | 50 | ||||
-rw-r--r-- | fs/reiserfs/inode.c | 134 | ||||
-rw-r--r-- | fs/reiserfs/super.c | 10 |
3 files changed, 111 insertions, 83 deletions
diff --git a/fs/reiserfs/file.c b/fs/reiserfs/file.c index b82cdd8a45dd..6846371498b6 100644 --- a/fs/reiserfs/file.c +++ b/fs/reiserfs/file.c | |||
@@ -38,20 +38,24 @@ static int reiserfs_file_release(struct inode *inode, struct file *filp) | |||
38 | 38 | ||
39 | BUG_ON(!S_ISREG(inode->i_mode)); | 39 | BUG_ON(!S_ISREG(inode->i_mode)); |
40 | 40 | ||
41 | if (atomic_add_unless(&REISERFS_I(inode)->openers, -1, 1)) | ||
42 | return 0; | ||
43 | |||
44 | mutex_lock(&(REISERFS_I(inode)->tailpack)); | ||
45 | |||
46 | if (!atomic_dec_and_test(&REISERFS_I(inode)->openers)) { | ||
47 | mutex_unlock(&(REISERFS_I(inode)->tailpack)); | ||
48 | return 0; | ||
49 | } | ||
50 | |||
41 | /* fast out for when nothing needs to be done */ | 51 | /* fast out for when nothing needs to be done */ |
42 | if ((atomic_read(&inode->i_count) > 1 || | 52 | if ((!(REISERFS_I(inode)->i_flags & i_pack_on_close_mask) || |
43 | !(REISERFS_I(inode)->i_flags & i_pack_on_close_mask) || | ||
44 | !tail_has_to_be_packed(inode)) && | 53 | !tail_has_to_be_packed(inode)) && |
45 | REISERFS_I(inode)->i_prealloc_count <= 0) { | 54 | REISERFS_I(inode)->i_prealloc_count <= 0) { |
55 | mutex_unlock(&(REISERFS_I(inode)->tailpack)); | ||
46 | return 0; | 56 | return 0; |
47 | } | 57 | } |
48 | 58 | ||
49 | mutex_lock(&inode->i_mutex); | ||
50 | |||
51 | mutex_lock(&(REISERFS_I(inode)->i_mmap)); | ||
52 | if (REISERFS_I(inode)->i_flags & i_ever_mapped) | ||
53 | REISERFS_I(inode)->i_flags &= ~i_pack_on_close_mask; | ||
54 | |||
55 | reiserfs_write_lock(inode->i_sb); | 59 | reiserfs_write_lock(inode->i_sb); |
56 | /* freeing preallocation only involves relogging blocks that | 60 | /* freeing preallocation only involves relogging blocks that |
57 | * are already in the current transaction. preallocation gets | 61 | * are already in the current transaction. preallocation gets |
@@ -94,9 +98,10 @@ static int reiserfs_file_release(struct inode *inode, struct file *filp) | |||
94 | if (!err) | 98 | if (!err) |
95 | err = jbegin_failure; | 99 | err = jbegin_failure; |
96 | 100 | ||
97 | if (!err && atomic_read(&inode->i_count) <= 1 && | 101 | if (!err && |
98 | (REISERFS_I(inode)->i_flags & i_pack_on_close_mask) && | 102 | (REISERFS_I(inode)->i_flags & i_pack_on_close_mask) && |
99 | tail_has_to_be_packed(inode)) { | 103 | tail_has_to_be_packed(inode)) { |
104 | |||
100 | /* if regular file is released by last holder and it has been | 105 | /* if regular file is released by last holder and it has been |
101 | appended (we append by unformatted node only) or its direct | 106 | appended (we append by unformatted node only) or its direct |
102 | item(s) had to be converted, then it may have to be | 107 | item(s) had to be converted, then it may have to be |
@@ -104,27 +109,28 @@ static int reiserfs_file_release(struct inode *inode, struct file *filp) | |||
104 | err = reiserfs_truncate_file(inode, 0); | 109 | err = reiserfs_truncate_file(inode, 0); |
105 | } | 110 | } |
106 | out: | 111 | out: |
107 | mutex_unlock(&(REISERFS_I(inode)->i_mmap)); | ||
108 | mutex_unlock(&inode->i_mutex); | ||
109 | reiserfs_write_unlock(inode->i_sb); | 112 | reiserfs_write_unlock(inode->i_sb); |
113 | mutex_unlock(&(REISERFS_I(inode)->tailpack)); | ||
110 | return err; | 114 | return err; |
111 | } | 115 | } |
112 | 116 | ||
113 | static int reiserfs_file_mmap(struct file *file, struct vm_area_struct *vma) | 117 | static int reiserfs_file_open(struct inode *inode, struct file *file) |
114 | { | 118 | { |
115 | struct inode *inode; | 119 | int err = dquot_file_open(inode, file); |
116 | 120 | if (!atomic_inc_not_zero(&REISERFS_I(inode)->openers)) { | |
117 | inode = file->f_path.dentry->d_inode; | 121 | /* somebody might be tailpacking on final close; wait for it */ |
118 | mutex_lock(&(REISERFS_I(inode)->i_mmap)); | 122 | mutex_lock(&(REISERFS_I(inode)->tailpack)); |
119 | REISERFS_I(inode)->i_flags |= i_ever_mapped; | 123 | atomic_inc(&REISERFS_I(inode)->openers); |
120 | mutex_unlock(&(REISERFS_I(inode)->i_mmap)); | 124 | mutex_unlock(&(REISERFS_I(inode)->tailpack)); |
121 | 125 | } | |
122 | return generic_file_mmap(file, vma); | 126 | return err; |
123 | } | 127 | } |
124 | 128 | ||
125 | static void reiserfs_vfs_truncate_file(struct inode *inode) | 129 | static void reiserfs_vfs_truncate_file(struct inode *inode) |
126 | { | 130 | { |
131 | mutex_lock(&(REISERFS_I(inode)->tailpack)); | ||
127 | reiserfs_truncate_file(inode, 1); | 132 | reiserfs_truncate_file(inode, 1); |
133 | mutex_unlock(&(REISERFS_I(inode)->tailpack)); | ||
128 | } | 134 | } |
129 | 135 | ||
130 | /* Sync a reiserfs file. */ | 136 | /* Sync a reiserfs file. */ |
@@ -288,8 +294,8 @@ const struct file_operations reiserfs_file_operations = { | |||
288 | #ifdef CONFIG_COMPAT | 294 | #ifdef CONFIG_COMPAT |
289 | .compat_ioctl = reiserfs_compat_ioctl, | 295 | .compat_ioctl = reiserfs_compat_ioctl, |
290 | #endif | 296 | #endif |
291 | .mmap = reiserfs_file_mmap, | 297 | .mmap = generic_file_mmap, |
292 | .open = dquot_file_open, | 298 | .open = reiserfs_file_open, |
293 | .release = reiserfs_file_release, | 299 | .release = reiserfs_file_release, |
294 | .fsync = reiserfs_sync_file, | 300 | .fsync = reiserfs_sync_file, |
295 | .aio_read = generic_file_aio_read, | 301 | .aio_read = generic_file_aio_read, |
diff --git a/fs/reiserfs/inode.c b/fs/reiserfs/inode.c index 29db72203bde..ae35413dcbe1 100644 --- a/fs/reiserfs/inode.c +++ b/fs/reiserfs/inode.c | |||
@@ -25,7 +25,7 @@ int reiserfs_commit_write(struct file *f, struct page *page, | |||
25 | int reiserfs_prepare_write(struct file *f, struct page *page, | 25 | int reiserfs_prepare_write(struct file *f, struct page *page, |
26 | unsigned from, unsigned to); | 26 | unsigned from, unsigned to); |
27 | 27 | ||
28 | void reiserfs_delete_inode(struct inode *inode) | 28 | void reiserfs_evict_inode(struct inode *inode) |
29 | { | 29 | { |
30 | /* We need blocks for transaction + (user+group) quota update (possibly delete) */ | 30 | /* We need blocks for transaction + (user+group) quota update (possibly delete) */ |
31 | int jbegin_count = | 31 | int jbegin_count = |
@@ -35,10 +35,12 @@ void reiserfs_delete_inode(struct inode *inode) | |||
35 | int depth; | 35 | int depth; |
36 | int err; | 36 | int err; |
37 | 37 | ||
38 | if (!is_bad_inode(inode)) | 38 | if (!inode->i_nlink && !is_bad_inode(inode)) |
39 | dquot_initialize(inode); | 39 | dquot_initialize(inode); |
40 | 40 | ||
41 | truncate_inode_pages(&inode->i_data, 0); | 41 | truncate_inode_pages(&inode->i_data, 0); |
42 | if (inode->i_nlink) | ||
43 | goto no_delete; | ||
42 | 44 | ||
43 | depth = reiserfs_write_lock_once(inode->i_sb); | 45 | depth = reiserfs_write_lock_once(inode->i_sb); |
44 | 46 | ||
@@ -77,9 +79,14 @@ void reiserfs_delete_inode(struct inode *inode) | |||
77 | ; | 79 | ; |
78 | } | 80 | } |
79 | out: | 81 | out: |
80 | clear_inode(inode); /* note this must go after the journal_end to prevent deadlock */ | 82 | end_writeback(inode); /* note this must go after the journal_end to prevent deadlock */ |
83 | dquot_drop(inode); | ||
81 | inode->i_blocks = 0; | 84 | inode->i_blocks = 0; |
82 | reiserfs_write_unlock_once(inode->i_sb, depth); | 85 | reiserfs_write_unlock_once(inode->i_sb, depth); |
86 | |||
87 | no_delete: | ||
88 | end_writeback(inode); | ||
89 | dquot_drop(inode); | ||
83 | } | 90 | } |
84 | 91 | ||
85 | static void _make_cpu_key(struct cpu_key *key, int version, __u32 dirid, | 92 | static void _make_cpu_key(struct cpu_key *key, int version, __u32 dirid, |
@@ -1138,7 +1145,6 @@ static void init_inode(struct inode *inode, struct treepath *path) | |||
1138 | REISERFS_I(inode)->i_prealloc_count = 0; | 1145 | REISERFS_I(inode)->i_prealloc_count = 0; |
1139 | REISERFS_I(inode)->i_trans_id = 0; | 1146 | REISERFS_I(inode)->i_trans_id = 0; |
1140 | REISERFS_I(inode)->i_jl = NULL; | 1147 | REISERFS_I(inode)->i_jl = NULL; |
1141 | mutex_init(&(REISERFS_I(inode)->i_mmap)); | ||
1142 | reiserfs_init_xattr_rwsem(inode); | 1148 | reiserfs_init_xattr_rwsem(inode); |
1143 | 1149 | ||
1144 | if (stat_data_v1(ih)) { | 1150 | if (stat_data_v1(ih)) { |
@@ -1841,7 +1847,6 @@ int reiserfs_new_inode(struct reiserfs_transaction_handle *th, | |||
1841 | REISERFS_I(inode)->i_attrs = | 1847 | REISERFS_I(inode)->i_attrs = |
1842 | REISERFS_I(dir)->i_attrs & REISERFS_INHERIT_MASK; | 1848 | REISERFS_I(dir)->i_attrs & REISERFS_INHERIT_MASK; |
1843 | sd_attrs_to_i_attrs(REISERFS_I(inode)->i_attrs, inode); | 1849 | sd_attrs_to_i_attrs(REISERFS_I(inode)->i_attrs, inode); |
1844 | mutex_init(&(REISERFS_I(inode)->i_mmap)); | ||
1845 | reiserfs_init_xattr_rwsem(inode); | 1850 | reiserfs_init_xattr_rwsem(inode); |
1846 | 1851 | ||
1847 | /* key to search for correct place for new stat data */ | 1852 | /* key to search for correct place for new stat data */ |
@@ -2587,8 +2592,7 @@ static int reiserfs_write_begin(struct file *file, | |||
2587 | old_ref = th->t_refcount; | 2592 | old_ref = th->t_refcount; |
2588 | th->t_refcount++; | 2593 | th->t_refcount++; |
2589 | } | 2594 | } |
2590 | ret = block_write_begin(file, mapping, pos, len, flags, pagep, fsdata, | 2595 | ret = __block_write_begin(page, pos, len, reiserfs_get_block); |
2591 | reiserfs_get_block); | ||
2592 | if (ret && reiserfs_transaction_running(inode->i_sb)) { | 2596 | if (ret && reiserfs_transaction_running(inode->i_sb)) { |
2593 | struct reiserfs_transaction_handle *th = current->journal_info; | 2597 | struct reiserfs_transaction_handle *th = current->journal_info; |
2594 | /* this gets a little ugly. If reiserfs_get_block returned an | 2598 | /* this gets a little ugly. If reiserfs_get_block returned an |
@@ -3059,10 +3063,25 @@ static ssize_t reiserfs_direct_IO(int rw, struct kiocb *iocb, | |||
3059 | { | 3063 | { |
3060 | struct file *file = iocb->ki_filp; | 3064 | struct file *file = iocb->ki_filp; |
3061 | struct inode *inode = file->f_mapping->host; | 3065 | struct inode *inode = file->f_mapping->host; |
3066 | ssize_t ret; | ||
3062 | 3067 | ||
3063 | return blockdev_direct_IO(rw, iocb, inode, inode->i_sb->s_bdev, iov, | 3068 | ret = blockdev_direct_IO(rw, iocb, inode, inode->i_sb->s_bdev, iov, |
3064 | offset, nr_segs, | 3069 | offset, nr_segs, |
3065 | reiserfs_get_blocks_direct_io, NULL); | 3070 | reiserfs_get_blocks_direct_io, NULL); |
3071 | |||
3072 | /* | ||
3073 | * In case of error extending write may have instantiated a few | ||
3074 | * blocks outside i_size. Trim these off again. | ||
3075 | */ | ||
3076 | if (unlikely((rw & WRITE) && ret < 0)) { | ||
3077 | loff_t isize = i_size_read(inode); | ||
3078 | loff_t end = offset + iov_length(iov, nr_segs); | ||
3079 | |||
3080 | if (end > isize) | ||
3081 | vmtruncate(inode, isize); | ||
3082 | } | ||
3083 | |||
3084 | return ret; | ||
3066 | } | 3085 | } |
3067 | 3086 | ||
3068 | int reiserfs_setattr(struct dentry *dentry, struct iattr *attr) | 3087 | int reiserfs_setattr(struct dentry *dentry, struct iattr *attr) |
@@ -3072,6 +3091,10 @@ int reiserfs_setattr(struct dentry *dentry, struct iattr *attr) | |||
3072 | int depth; | 3091 | int depth; |
3073 | int error; | 3092 | int error; |
3074 | 3093 | ||
3094 | error = inode_change_ok(inode, attr); | ||
3095 | if (error) | ||
3096 | return error; | ||
3097 | |||
3075 | /* must be turned off for recursive notify_change calls */ | 3098 | /* must be turned off for recursive notify_change calls */ |
3076 | ia_valid = attr->ia_valid &= ~(ATTR_KILL_SUID|ATTR_KILL_SGID); | 3099 | ia_valid = attr->ia_valid &= ~(ATTR_KILL_SUID|ATTR_KILL_SGID); |
3077 | 3100 | ||
@@ -3121,55 +3144,58 @@ int reiserfs_setattr(struct dentry *dentry, struct iattr *attr) | |||
3121 | goto out; | 3144 | goto out; |
3122 | } | 3145 | } |
3123 | 3146 | ||
3124 | error = inode_change_ok(inode, attr); | 3147 | if ((ia_valid & ATTR_UID && attr->ia_uid != inode->i_uid) || |
3125 | if (!error) { | 3148 | (ia_valid & ATTR_GID && attr->ia_gid != inode->i_gid)) { |
3126 | if ((ia_valid & ATTR_UID && attr->ia_uid != inode->i_uid) || | 3149 | struct reiserfs_transaction_handle th; |
3127 | (ia_valid & ATTR_GID && attr->ia_gid != inode->i_gid)) { | 3150 | int jbegin_count = |
3128 | error = reiserfs_chown_xattrs(inode, attr); | 3151 | 2 * |
3152 | (REISERFS_QUOTA_INIT_BLOCKS(inode->i_sb) + | ||
3153 | REISERFS_QUOTA_DEL_BLOCKS(inode->i_sb)) + | ||
3154 | 2; | ||
3129 | 3155 | ||
3130 | if (!error) { | 3156 | error = reiserfs_chown_xattrs(inode, attr); |
3131 | struct reiserfs_transaction_handle th; | 3157 | |
3132 | int jbegin_count = | 3158 | if (error) |
3133 | 2 * | 3159 | return error; |
3134 | (REISERFS_QUOTA_INIT_BLOCKS(inode->i_sb) + | 3160 | |
3135 | REISERFS_QUOTA_DEL_BLOCKS(inode->i_sb)) + | 3161 | /* (user+group)*(old+new) structure - we count quota info and , inode write (sb, inode) */ |
3136 | 2; | 3162 | error = journal_begin(&th, inode->i_sb, jbegin_count); |
3137 | 3163 | if (error) | |
3138 | /* (user+group)*(old+new) structure - we count quota info and , inode write (sb, inode) */ | 3164 | goto out; |
3139 | error = | 3165 | error = dquot_transfer(inode, attr); |
3140 | journal_begin(&th, inode->i_sb, | 3166 | if (error) { |
3141 | jbegin_count); | 3167 | journal_end(&th, inode->i_sb, jbegin_count); |
3142 | if (error) | 3168 | goto out; |
3143 | goto out; | ||
3144 | error = dquot_transfer(inode, attr); | ||
3145 | if (error) { | ||
3146 | journal_end(&th, inode->i_sb, | ||
3147 | jbegin_count); | ||
3148 | goto out; | ||
3149 | } | ||
3150 | /* Update corresponding info in inode so that everything is in | ||
3151 | * one transaction */ | ||
3152 | if (attr->ia_valid & ATTR_UID) | ||
3153 | inode->i_uid = attr->ia_uid; | ||
3154 | if (attr->ia_valid & ATTR_GID) | ||
3155 | inode->i_gid = attr->ia_gid; | ||
3156 | mark_inode_dirty(inode); | ||
3157 | error = | ||
3158 | journal_end(&th, inode->i_sb, jbegin_count); | ||
3159 | } | ||
3160 | } | ||
3161 | if (!error) { | ||
3162 | /* | ||
3163 | * Relax the lock here, as it might truncate the | ||
3164 | * inode pages and wait for inode pages locks. | ||
3165 | * To release such page lock, the owner needs the | ||
3166 | * reiserfs lock | ||
3167 | */ | ||
3168 | reiserfs_write_unlock_once(inode->i_sb, depth); | ||
3169 | error = inode_setattr(inode, attr); | ||
3170 | depth = reiserfs_write_lock_once(inode->i_sb); | ||
3171 | } | 3169 | } |
3170 | |||
3171 | /* Update corresponding info in inode so that everything is in | ||
3172 | * one transaction */ | ||
3173 | if (attr->ia_valid & ATTR_UID) | ||
3174 | inode->i_uid = attr->ia_uid; | ||
3175 | if (attr->ia_valid & ATTR_GID) | ||
3176 | inode->i_gid = attr->ia_gid; | ||
3177 | mark_inode_dirty(inode); | ||
3178 | error = journal_end(&th, inode->i_sb, jbegin_count); | ||
3179 | if (error) | ||
3180 | goto out; | ||
3181 | } | ||
3182 | |||
3183 | /* | ||
3184 | * Relax the lock here, as it might truncate the | ||
3185 | * inode pages and wait for inode pages locks. | ||
3186 | * To release such page lock, the owner needs the | ||
3187 | * reiserfs lock | ||
3188 | */ | ||
3189 | reiserfs_write_unlock_once(inode->i_sb, depth); | ||
3190 | if ((attr->ia_valid & ATTR_SIZE) && | ||
3191 | attr->ia_size != i_size_read(inode)) | ||
3192 | error = vmtruncate(inode, attr->ia_size); | ||
3193 | |||
3194 | if (!error) { | ||
3195 | setattr_copy(inode, attr); | ||
3196 | mark_inode_dirty(inode); | ||
3172 | } | 3197 | } |
3198 | depth = reiserfs_write_lock_once(inode->i_sb); | ||
3173 | 3199 | ||
3174 | if (!error && reiserfs_posixacl(inode->i_sb)) { | 3200 | if (!error && reiserfs_posixacl(inode->i_sb)) { |
3175 | if (attr->ia_valid & ATTR_MODE) | 3201 | if (attr->ia_valid & ATTR_MODE) |
diff --git a/fs/reiserfs/super.c b/fs/reiserfs/super.c index 9822fa15118b..e15ff612002d 100644 --- a/fs/reiserfs/super.c +++ b/fs/reiserfs/super.c | |||
@@ -525,6 +525,8 @@ static struct inode *reiserfs_alloc_inode(struct super_block *sb) | |||
525 | kmem_cache_alloc(reiserfs_inode_cachep, GFP_KERNEL); | 525 | kmem_cache_alloc(reiserfs_inode_cachep, GFP_KERNEL); |
526 | if (!ei) | 526 | if (!ei) |
527 | return NULL; | 527 | return NULL; |
528 | atomic_set(&ei->openers, 0); | ||
529 | mutex_init(&ei->tailpack); | ||
528 | return &ei->vfs_inode; | 530 | return &ei->vfs_inode; |
529 | } | 531 | } |
530 | 532 | ||
@@ -589,11 +591,6 @@ out: | |||
589 | reiserfs_write_unlock_once(inode->i_sb, lock_depth); | 591 | reiserfs_write_unlock_once(inode->i_sb, lock_depth); |
590 | } | 592 | } |
591 | 593 | ||
592 | static void reiserfs_clear_inode(struct inode *inode) | ||
593 | { | ||
594 | dquot_drop(inode); | ||
595 | } | ||
596 | |||
597 | #ifdef CONFIG_QUOTA | 594 | #ifdef CONFIG_QUOTA |
598 | static ssize_t reiserfs_quota_write(struct super_block *, int, const char *, | 595 | static ssize_t reiserfs_quota_write(struct super_block *, int, const char *, |
599 | size_t, loff_t); | 596 | size_t, loff_t); |
@@ -606,8 +603,7 @@ static const struct super_operations reiserfs_sops = { | |||
606 | .destroy_inode = reiserfs_destroy_inode, | 603 | .destroy_inode = reiserfs_destroy_inode, |
607 | .write_inode = reiserfs_write_inode, | 604 | .write_inode = reiserfs_write_inode, |
608 | .dirty_inode = reiserfs_dirty_inode, | 605 | .dirty_inode = reiserfs_dirty_inode, |
609 | .clear_inode = reiserfs_clear_inode, | 606 | .evict_inode = reiserfs_evict_inode, |
610 | .delete_inode = reiserfs_delete_inode, | ||
611 | .put_super = reiserfs_put_super, | 607 | .put_super = reiserfs_put_super, |
612 | .write_super = reiserfs_write_super, | 608 | .write_super = reiserfs_write_super, |
613 | .sync_fs = reiserfs_sync_fs, | 609 | .sync_fs = reiserfs_sync_fs, |