diff options
Diffstat (limited to 'fs/jbd2/transaction.c')
-rw-r--r-- | fs/jbd2/transaction.c | 86 |
1 files changed, 86 insertions, 0 deletions
diff --git a/fs/jbd2/transaction.c b/fs/jbd2/transaction.c index ba620c4493d2..98b596d23705 100644 --- a/fs/jbd2/transaction.c +++ b/fs/jbd2/transaction.c | |||
@@ -51,6 +51,7 @@ jbd2_get_transaction(journal_t *journal, transaction_t *transaction) | |||
51 | transaction->t_tid = journal->j_transaction_sequence++; | 51 | transaction->t_tid = journal->j_transaction_sequence++; |
52 | transaction->t_expires = jiffies + journal->j_commit_interval; | 52 | transaction->t_expires = jiffies + journal->j_commit_interval; |
53 | spin_lock_init(&transaction->t_handle_lock); | 53 | spin_lock_init(&transaction->t_handle_lock); |
54 | INIT_LIST_HEAD(&transaction->t_inode_list); | ||
54 | 55 | ||
55 | /* Set up the commit timer for the new transaction. */ | 56 | /* Set up the commit timer for the new transaction. */ |
56 | journal->j_commit_timer.expires = round_jiffies(transaction->t_expires); | 57 | journal->j_commit_timer.expires = round_jiffies(transaction->t_expires); |
@@ -2195,3 +2196,88 @@ void jbd2_journal_refile_buffer(journal_t *journal, struct journal_head *jh) | |||
2195 | spin_unlock(&journal->j_list_lock); | 2196 | spin_unlock(&journal->j_list_lock); |
2196 | __brelse(bh); | 2197 | __brelse(bh); |
2197 | } | 2198 | } |
2199 | |||
2200 | /* | ||
2201 | * File inode in the inode list of the handle's transaction | ||
2202 | */ | ||
2203 | int jbd2_journal_file_inode(handle_t *handle, struct jbd2_inode *jinode) | ||
2204 | { | ||
2205 | transaction_t *transaction = handle->h_transaction; | ||
2206 | journal_t *journal = transaction->t_journal; | ||
2207 | |||
2208 | if (is_handle_aborted(handle)) | ||
2209 | return -EIO; | ||
2210 | |||
2211 | jbd_debug(4, "Adding inode %lu, tid:%d\n", jinode->i_vfs_inode->i_ino, | ||
2212 | transaction->t_tid); | ||
2213 | |||
2214 | /* | ||
2215 | * First check whether inode isn't already on the transaction's | ||
2216 | * lists without taking the lock. Note that this check is safe | ||
2217 | * without the lock as we cannot race with somebody removing inode | ||
2218 | * from the transaction. The reason is that we remove inode from the | ||
2219 | * transaction only in journal_release_jbd_inode() and when we commit | ||
2220 | * the transaction. We are guarded from the first case by holding | ||
2221 | * a reference to the inode. We are safe against the second case | ||
2222 | * because if jinode->i_transaction == transaction, commit code | ||
2223 | * cannot touch the transaction because we hold reference to it, | ||
2224 | * and if jinode->i_next_transaction == transaction, commit code | ||
2225 | * will only file the inode where we want it. | ||
2226 | */ | ||
2227 | if (jinode->i_transaction == transaction || | ||
2228 | jinode->i_next_transaction == transaction) | ||
2229 | return 0; | ||
2230 | |||
2231 | spin_lock(&journal->j_list_lock); | ||
2232 | |||
2233 | if (jinode->i_transaction == transaction || | ||
2234 | jinode->i_next_transaction == transaction) | ||
2235 | goto done; | ||
2236 | |||
2237 | /* On some different transaction's list - should be | ||
2238 | * the committing one */ | ||
2239 | if (jinode->i_transaction) { | ||
2240 | J_ASSERT(jinode->i_next_transaction == NULL); | ||
2241 | J_ASSERT(jinode->i_transaction == | ||
2242 | journal->j_committing_transaction); | ||
2243 | jinode->i_next_transaction = transaction; | ||
2244 | goto done; | ||
2245 | } | ||
2246 | /* Not on any transaction list... */ | ||
2247 | J_ASSERT(!jinode->i_next_transaction); | ||
2248 | jinode->i_transaction = transaction; | ||
2249 | list_add(&jinode->i_list, &transaction->t_inode_list); | ||
2250 | done: | ||
2251 | spin_unlock(&journal->j_list_lock); | ||
2252 | |||
2253 | return 0; | ||
2254 | } | ||
2255 | |||
2256 | /* | ||
2257 | * This function must be called when inode is journaled in ordered mode | ||
2258 | * before truncation happens. It starts writeout of truncated part in | ||
2259 | * case it is in the committing transaction so that we stand to ordered | ||
2260 | * mode consistency guarantees. | ||
2261 | */ | ||
2262 | int jbd2_journal_begin_ordered_truncate(struct jbd2_inode *inode, | ||
2263 | loff_t new_size) | ||
2264 | { | ||
2265 | journal_t *journal; | ||
2266 | transaction_t *commit_trans; | ||
2267 | int ret = 0; | ||
2268 | |||
2269 | if (!inode->i_transaction && !inode->i_next_transaction) | ||
2270 | goto out; | ||
2271 | journal = inode->i_transaction->t_journal; | ||
2272 | spin_lock(&journal->j_state_lock); | ||
2273 | commit_trans = journal->j_committing_transaction; | ||
2274 | spin_unlock(&journal->j_state_lock); | ||
2275 | if (inode->i_transaction == commit_trans) { | ||
2276 | ret = filemap_fdatawrite_range(inode->i_vfs_inode->i_mapping, | ||
2277 | new_size, LLONG_MAX); | ||
2278 | if (ret) | ||
2279 | jbd2_journal_abort(journal, ret); | ||
2280 | } | ||
2281 | out: | ||
2282 | return ret; | ||
2283 | } | ||