aboutsummaryrefslogtreecommitdiffstats
path: root/fs/jbd2/transaction.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/jbd2/transaction.c')
-rw-r--r--fs/jbd2/transaction.c86
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 */
2203int 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);
2250done:
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 */
2262int 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 }
2281out:
2282 return ret;
2283}