diff options
Diffstat (limited to 'fs/reiserfs/file.c')
-rw-r--r-- | fs/reiserfs/file.c | 100 |
1 files changed, 54 insertions, 46 deletions
diff --git a/fs/reiserfs/file.c b/fs/reiserfs/file.c index ed58d843d578..db9e80ba53a0 100644 --- a/fs/reiserfs/file.c +++ b/fs/reiserfs/file.c | |||
@@ -15,20 +15,20 @@ | |||
15 | #include <linux/quotaops.h> | 15 | #include <linux/quotaops.h> |
16 | 16 | ||
17 | /* | 17 | /* |
18 | ** We pack the tails of files on file close, not at the time they are written. | 18 | * We pack the tails of files on file close, not at the time they are written. |
19 | ** This implies an unnecessary copy of the tail and an unnecessary indirect item | 19 | * This implies an unnecessary copy of the tail and an unnecessary indirect item |
20 | ** insertion/balancing, for files that are written in one write. | 20 | * insertion/balancing, for files that are written in one write. |
21 | ** It avoids unnecessary tail packings (balances) for files that are written in | 21 | * It avoids unnecessary tail packings (balances) for files that are written in |
22 | ** multiple writes and are small enough to have tails. | 22 | * multiple writes and are small enough to have tails. |
23 | ** | 23 | * |
24 | ** file_release is called by the VFS layer when the file is closed. If | 24 | * file_release is called by the VFS layer when the file is closed. If |
25 | ** this is the last open file descriptor, and the file | 25 | * this is the last open file descriptor, and the file |
26 | ** small enough to have a tail, and the tail is currently in an | 26 | * small enough to have a tail, and the tail is currently in an |
27 | ** unformatted node, the tail is converted back into a direct item. | 27 | * unformatted node, the tail is converted back into a direct item. |
28 | ** | 28 | * |
29 | ** We use reiserfs_truncate_file to pack the tail, since it already has | 29 | * We use reiserfs_truncate_file to pack the tail, since it already has |
30 | ** all the conditions coded. | 30 | * all the conditions coded. |
31 | */ | 31 | */ |
32 | static int reiserfs_file_release(struct inode *inode, struct file *filp) | 32 | static int reiserfs_file_release(struct inode *inode, struct file *filp) |
33 | { | 33 | { |
34 | 34 | ||
@@ -41,10 +41,10 @@ static int reiserfs_file_release(struct inode *inode, struct file *filp) | |||
41 | if (atomic_add_unless(&REISERFS_I(inode)->openers, -1, 1)) | 41 | if (atomic_add_unless(&REISERFS_I(inode)->openers, -1, 1)) |
42 | return 0; | 42 | return 0; |
43 | 43 | ||
44 | mutex_lock(&(REISERFS_I(inode)->tailpack)); | 44 | mutex_lock(&REISERFS_I(inode)->tailpack); |
45 | 45 | ||
46 | if (!atomic_dec_and_test(&REISERFS_I(inode)->openers)) { | 46 | if (!atomic_dec_and_test(&REISERFS_I(inode)->openers)) { |
47 | mutex_unlock(&(REISERFS_I(inode)->tailpack)); | 47 | mutex_unlock(&REISERFS_I(inode)->tailpack); |
48 | return 0; | 48 | return 0; |
49 | } | 49 | } |
50 | 50 | ||
@@ -52,31 +52,35 @@ static int reiserfs_file_release(struct inode *inode, struct file *filp) | |||
52 | if ((!(REISERFS_I(inode)->i_flags & i_pack_on_close_mask) || | 52 | if ((!(REISERFS_I(inode)->i_flags & i_pack_on_close_mask) || |
53 | !tail_has_to_be_packed(inode)) && | 53 | !tail_has_to_be_packed(inode)) && |
54 | REISERFS_I(inode)->i_prealloc_count <= 0) { | 54 | REISERFS_I(inode)->i_prealloc_count <= 0) { |
55 | mutex_unlock(&(REISERFS_I(inode)->tailpack)); | 55 | mutex_unlock(&REISERFS_I(inode)->tailpack); |
56 | return 0; | 56 | return 0; |
57 | } | 57 | } |
58 | 58 | ||
59 | reiserfs_write_lock(inode->i_sb); | 59 | reiserfs_write_lock(inode->i_sb); |
60 | /* freeing preallocation only involves relogging blocks that | 60 | /* |
61 | * freeing preallocation only involves relogging blocks that | ||
61 | * are already in the current transaction. preallocation gets | 62 | * are already in the current transaction. preallocation gets |
62 | * freed at the end of each transaction, so it is impossible for | 63 | * freed at the end of each transaction, so it is impossible for |
63 | * us to log any additional blocks (including quota blocks) | 64 | * us to log any additional blocks (including quota blocks) |
64 | */ | 65 | */ |
65 | err = journal_begin(&th, inode->i_sb, 1); | 66 | err = journal_begin(&th, inode->i_sb, 1); |
66 | if (err) { | 67 | if (err) { |
67 | /* uh oh, we can't allow the inode to go away while there | 68 | /* |
69 | * uh oh, we can't allow the inode to go away while there | ||
68 | * is still preallocation blocks pending. Try to join the | 70 | * is still preallocation blocks pending. Try to join the |
69 | * aborted transaction | 71 | * aborted transaction |
70 | */ | 72 | */ |
71 | jbegin_failure = err; | 73 | jbegin_failure = err; |
72 | err = journal_join_abort(&th, inode->i_sb, 1); | 74 | err = journal_join_abort(&th, inode->i_sb); |
73 | 75 | ||
74 | if (err) { | 76 | if (err) { |
75 | /* hmpf, our choices here aren't good. We can pin the inode | 77 | /* |
76 | * which will disallow unmount from every happening, we can | 78 | * hmpf, our choices here aren't good. We can pin |
77 | * do nothing, which will corrupt random memory on unmount, | 79 | * the inode which will disallow unmount from ever |
78 | * or we can forcibly remove the file from the preallocation | 80 | * happening, we can do nothing, which will corrupt |
79 | * list, which will leak blocks on disk. Lets pin the inode | 81 | * random memory on unmount, or we can forcibly |
82 | * remove the file from the preallocation list, which | ||
83 | * will leak blocks on disk. Lets pin the inode | ||
80 | * and let the admin know what is going on. | 84 | * and let the admin know what is going on. |
81 | */ | 85 | */ |
82 | igrab(inode); | 86 | igrab(inode); |
@@ -92,7 +96,7 @@ static int reiserfs_file_release(struct inode *inode, struct file *filp) | |||
92 | #ifdef REISERFS_PREALLOCATE | 96 | #ifdef REISERFS_PREALLOCATE |
93 | reiserfs_discard_prealloc(&th, inode); | 97 | reiserfs_discard_prealloc(&th, inode); |
94 | #endif | 98 | #endif |
95 | err = journal_end(&th, inode->i_sb, 1); | 99 | err = journal_end(&th); |
96 | 100 | ||
97 | /* copy back the error code from journal_begin */ | 101 | /* copy back the error code from journal_begin */ |
98 | if (!err) | 102 | if (!err) |
@@ -102,35 +106,38 @@ static int reiserfs_file_release(struct inode *inode, struct file *filp) | |||
102 | (REISERFS_I(inode)->i_flags & i_pack_on_close_mask) && | 106 | (REISERFS_I(inode)->i_flags & i_pack_on_close_mask) && |
103 | tail_has_to_be_packed(inode)) { | 107 | tail_has_to_be_packed(inode)) { |
104 | 108 | ||
105 | /* if regular file is released by last holder and it has been | 109 | /* |
106 | appended (we append by unformatted node only) or its direct | 110 | * if regular file is released by last holder and it has been |
107 | item(s) had to be converted, then it may have to be | 111 | * appended (we append by unformatted node only) or its direct |
108 | indirect2direct converted */ | 112 | * item(s) had to be converted, then it may have to be |
113 | * indirect2direct converted | ||
114 | */ | ||
109 | err = reiserfs_truncate_file(inode, 0); | 115 | err = reiserfs_truncate_file(inode, 0); |
110 | } | 116 | } |
111 | out: | 117 | out: |
112 | reiserfs_write_unlock(inode->i_sb); | 118 | reiserfs_write_unlock(inode->i_sb); |
113 | mutex_unlock(&(REISERFS_I(inode)->tailpack)); | 119 | mutex_unlock(&REISERFS_I(inode)->tailpack); |
114 | return err; | 120 | return err; |
115 | } | 121 | } |
116 | 122 | ||
117 | static int reiserfs_file_open(struct inode *inode, struct file *file) | 123 | static int reiserfs_file_open(struct inode *inode, struct file *file) |
118 | { | 124 | { |
119 | int err = dquot_file_open(inode, file); | 125 | int err = dquot_file_open(inode, file); |
126 | |||
127 | /* somebody might be tailpacking on final close; wait for it */ | ||
120 | if (!atomic_inc_not_zero(&REISERFS_I(inode)->openers)) { | 128 | if (!atomic_inc_not_zero(&REISERFS_I(inode)->openers)) { |
121 | /* somebody might be tailpacking on final close; wait for it */ | 129 | mutex_lock(&REISERFS_I(inode)->tailpack); |
122 | mutex_lock(&(REISERFS_I(inode)->tailpack)); | ||
123 | atomic_inc(&REISERFS_I(inode)->openers); | 130 | atomic_inc(&REISERFS_I(inode)->openers); |
124 | mutex_unlock(&(REISERFS_I(inode)->tailpack)); | 131 | mutex_unlock(&REISERFS_I(inode)->tailpack); |
125 | } | 132 | } |
126 | return err; | 133 | return err; |
127 | } | 134 | } |
128 | 135 | ||
129 | void reiserfs_vfs_truncate_file(struct inode *inode) | 136 | void reiserfs_vfs_truncate_file(struct inode *inode) |
130 | { | 137 | { |
131 | mutex_lock(&(REISERFS_I(inode)->tailpack)); | 138 | mutex_lock(&REISERFS_I(inode)->tailpack); |
132 | reiserfs_truncate_file(inode, 1); | 139 | reiserfs_truncate_file(inode, 1); |
133 | mutex_unlock(&(REISERFS_I(inode)->tailpack)); | 140 | mutex_unlock(&REISERFS_I(inode)->tailpack); |
134 | } | 141 | } |
135 | 142 | ||
136 | /* Sync a reiserfs file. */ | 143 | /* Sync a reiserfs file. */ |
@@ -205,10 +212,11 @@ int reiserfs_commit_page(struct inode *inode, struct page *page, | |||
205 | set_buffer_uptodate(bh); | 212 | set_buffer_uptodate(bh); |
206 | if (logit) { | 213 | if (logit) { |
207 | reiserfs_prepare_for_journal(s, bh, 1); | 214 | reiserfs_prepare_for_journal(s, bh, 1); |
208 | journal_mark_dirty(&th, s, bh); | 215 | journal_mark_dirty(&th, bh); |
209 | } else if (!buffer_dirty(bh)) { | 216 | } else if (!buffer_dirty(bh)) { |
210 | mark_buffer_dirty(bh); | 217 | mark_buffer_dirty(bh); |
211 | /* do data=ordered on any page past the end | 218 | /* |
219 | * do data=ordered on any page past the end | ||
212 | * of file and any buffer marked BH_New. | 220 | * of file and any buffer marked BH_New. |
213 | */ | 221 | */ |
214 | if (reiserfs_data_ordered(inode->i_sb) && | 222 | if (reiserfs_data_ordered(inode->i_sb) && |
@@ -219,8 +227,8 @@ int reiserfs_commit_page(struct inode *inode, struct page *page, | |||
219 | } | 227 | } |
220 | } | 228 | } |
221 | if (logit) { | 229 | if (logit) { |
222 | ret = journal_end(&th, s, bh_per_page + 1); | 230 | ret = journal_end(&th); |
223 | drop_write_lock: | 231 | drop_write_lock: |
224 | reiserfs_write_unlock(s); | 232 | reiserfs_write_unlock(s); |
225 | } | 233 | } |
226 | /* | 234 | /* |
@@ -235,8 +243,8 @@ int reiserfs_commit_page(struct inode *inode, struct page *page, | |||
235 | } | 243 | } |
236 | 244 | ||
237 | const struct file_operations reiserfs_file_operations = { | 245 | const struct file_operations reiserfs_file_operations = { |
238 | .read = do_sync_read, | 246 | .read = new_sync_read, |
239 | .write = do_sync_write, | 247 | .write = new_sync_write, |
240 | .unlocked_ioctl = reiserfs_ioctl, | 248 | .unlocked_ioctl = reiserfs_ioctl, |
241 | #ifdef CONFIG_COMPAT | 249 | #ifdef CONFIG_COMPAT |
242 | .compat_ioctl = reiserfs_compat_ioctl, | 250 | .compat_ioctl = reiserfs_compat_ioctl, |
@@ -245,10 +253,10 @@ const struct file_operations reiserfs_file_operations = { | |||
245 | .open = reiserfs_file_open, | 253 | .open = reiserfs_file_open, |
246 | .release = reiserfs_file_release, | 254 | .release = reiserfs_file_release, |
247 | .fsync = reiserfs_sync_file, | 255 | .fsync = reiserfs_sync_file, |
248 | .aio_read = generic_file_aio_read, | 256 | .read_iter = generic_file_read_iter, |
249 | .aio_write = generic_file_aio_write, | 257 | .write_iter = generic_file_write_iter, |
250 | .splice_read = generic_file_splice_read, | 258 | .splice_read = generic_file_splice_read, |
251 | .splice_write = generic_file_splice_write, | 259 | .splice_write = iter_file_splice_write, |
252 | .llseek = generic_file_llseek, | 260 | .llseek = generic_file_llseek, |
253 | }; | 261 | }; |
254 | 262 | ||