Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit dc522adb authored by Linus Torvalds's avatar Linus Torvalds
Browse files
* 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jack/linux-fs-2.6:
  jbd: Fix comment to match the code in journal_start()
  jbd/jbd2: remove obsolete summarise_journal_usage.
  jbd: Fix forever sleeping process in do_get_write_access()
  ext2: fix error msg when mounting fs with too-large blocksize
  jbd: fix fsync() tid wraparound bug
  ext3: Fix fs corruption when make_indexed_dir() fails
  ext3: Fix lock inversion in ext3_symlink()
parents df3256f9 c2b67735
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -898,7 +898,8 @@ static int ext2_fill_super(struct super_block *sb, void *data, int silent)
		brelse(bh);

		if (!sb_set_blocksize(sb, blocksize)) {
			ext2_msg(sb, KERN_ERR, "error: blocksize is too small");
			ext2_msg(sb, KERN_ERR,
				"error: bad blocksize %d", blocksize);
			goto failed_sbi;
		}

+67 −13
Original line number Diff line number Diff line
@@ -1416,10 +1416,19 @@ static int make_indexed_dir(handle_t *handle, struct dentry *dentry,
	frame->at = entries;
	frame->bh = bh;
	bh = bh2;
	/*
	 * Mark buffers dirty here so that if do_split() fails we write a
	 * consistent set of buffers to disk.
	 */
	ext3_journal_dirty_metadata(handle, frame->bh);
	ext3_journal_dirty_metadata(handle, bh);
	de = do_split(handle,dir, &bh, frame, &hinfo, &retval);
	if (!de) {
		ext3_mark_inode_dirty(handle, dir);
		dx_release(frames);
	if (!(de))
		return retval;
	}
	dx_release(frames);

	return add_dirent_to_buf(handle, dentry, inode, de, bh);
}
@@ -2189,6 +2198,7 @@ static int ext3_symlink (struct inode * dir,
	handle_t *handle;
	struct inode * inode;
	int l, err, retries = 0;
	int credits;

	l = strlen(symname)+1;
	if (l > dir->i_sb->s_blocksize)
@@ -2196,10 +2206,26 @@ static int ext3_symlink (struct inode * dir,

	dquot_initialize(dir);

	if (l > EXT3_N_BLOCKS * 4) {
		/*
		 * For non-fast symlinks, we just allocate inode and put it on
		 * orphan list in the first transaction => we need bitmap,
		 * group descriptor, sb, inode block, quota blocks.
		 */
		credits = 4 + EXT3_MAXQUOTAS_INIT_BLOCKS(dir->i_sb);
	} else {
		/*
		 * Fast symlink. We have to add entry to directory
		 * (EXT3_DATA_TRANS_BLOCKS + EXT3_INDEX_EXTRA_TRANS_BLOCKS),
		 * allocate new inode (bitmap, group descriptor, inode block,
		 * quota blocks, sb is already counted in previous macros).
		 */
		credits = EXT3_DATA_TRANS_BLOCKS(dir->i_sb) +
			  EXT3_INDEX_EXTRA_TRANS_BLOCKS + 3 +
			  EXT3_MAXQUOTAS_INIT_BLOCKS(dir->i_sb);
	}
retry:
	handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS(dir->i_sb) +
					EXT3_INDEX_EXTRA_TRANS_BLOCKS + 5 +
					EXT3_MAXQUOTAS_INIT_BLOCKS(dir->i_sb));
	handle = ext3_journal_start(dir, credits);
	if (IS_ERR(handle))
		return PTR_ERR(handle);

@@ -2211,21 +2237,45 @@ static int ext3_symlink (struct inode * dir,
	if (IS_ERR(inode))
		goto out_stop;

	if (l > sizeof (EXT3_I(inode)->i_data)) {
	if (l > EXT3_N_BLOCKS * 4) {
		inode->i_op = &ext3_symlink_inode_operations;
		ext3_set_aops(inode);
		/*
		 * page_symlink() calls into ext3_prepare/commit_write.
		 * We have a transaction open.  All is sweetness.  It also sets
		 * i_size in generic_commit_write().
		 * We cannot call page_symlink() with transaction started
		 * because it calls into ext3_write_begin() which acquires page
		 * lock which ranks below transaction start (and it can also
		 * wait for journal commit if we are running out of space). So
		 * we have to stop transaction now and restart it when symlink
		 * contents is written. 
		 *
		 * To keep fs consistent in case of crash, we have to put inode
		 * to orphan list in the mean time.
		 */
		drop_nlink(inode);
		err = ext3_orphan_add(handle, inode);
		ext3_journal_stop(handle);
		if (err)
			goto err_drop_inode;
		err = __page_symlink(inode, symname, l, 1);
		if (err)
			goto err_drop_inode;
		/*
		 * Now inode is being linked into dir (EXT3_DATA_TRANS_BLOCKS
		 * + EXT3_INDEX_EXTRA_TRANS_BLOCKS), inode is also modified
		 */
		handle = ext3_journal_start(dir,
				EXT3_DATA_TRANS_BLOCKS(dir->i_sb) +
				EXT3_INDEX_EXTRA_TRANS_BLOCKS + 1);
		if (IS_ERR(handle)) {
			err = PTR_ERR(handle);
			goto err_drop_inode;
		}
		inc_nlink(inode);
		err = ext3_orphan_del(handle, inode);
		if (err) {
			ext3_journal_stop(handle);
			drop_nlink(inode);
			unlock_new_inode(inode);
			ext3_mark_inode_dirty(handle, inode);
			iput (inode);
			goto out_stop;
			goto err_drop_inode;
		}
	} else {
		inode->i_op = &ext3_fast_symlink_inode_operations;
@@ -2239,6 +2289,10 @@ static int ext3_symlink (struct inode * dir,
	if (err == -ENOSPC && ext3_should_retry_alloc(dir->i_sb, &retries))
		goto retry;
	return err;
err_drop_inode:
	unlock_new_inode(inode);
	iput(inode);
	return err;
}

static int ext3_link (struct dentry * old_dentry,
+7 −8
Original line number Diff line number Diff line
@@ -302,12 +302,6 @@ void journal_commit_transaction(journal_t *journal)
	 * all outstanding updates to complete.
	 */

#ifdef COMMIT_STATS
	spin_lock(&journal->j_list_lock);
	summarise_journal_usage(journal);
	spin_unlock(&journal->j_list_lock);
#endif

	/* Do we need to erase the effects of a prior journal_flush? */
	if (journal->j_flags & JFS_FLUSHED) {
		jbd_debug(3, "super block updated\n");
@@ -722,8 +716,13 @@ void journal_commit_transaction(journal_t *journal)
                   required. */
		JBUFFER_TRACE(jh, "file as BJ_Forget");
		journal_file_buffer(jh, commit_transaction, BJ_Forget);
		/* Wake up any transactions which were waiting for this
		   IO to complete */
		/*
		 * Wake up any transactions which were waiting for this
		 * IO to complete. The barrier must be here so that changes
		 * by journal_file_buffer() take effect before wake_up_bit()
		 * does the waitqueue check.
		 */
		smp_mb();
		wake_up_bit(&bh->b_state, BH_Unshadow);
		JBUFFER_TRACE(jh, "brelse shadowed buffer");
		__brelse(bh);
+13 −3
Original line number Diff line number Diff line
@@ -437,9 +437,12 @@ int __log_space_left(journal_t *journal)
int __log_start_commit(journal_t *journal, tid_t target)
{
	/*
	 * Are we already doing a recent enough commit?
	 * The only transaction we can possibly wait upon is the
	 * currently running transaction (if it exists).  Otherwise,
	 * the target tid must be an old one.
	 */
	if (!tid_geq(journal->j_commit_request, target)) {
	if (journal->j_running_transaction &&
	    journal->j_running_transaction->t_tid == target) {
		/*
		 * We want a new commit: OK, mark the request and wakeup the
		 * commit thread.  We do _not_ do the commit ourselves.
@@ -451,7 +454,14 @@ int __log_start_commit(journal_t *journal, tid_t target)
			  journal->j_commit_sequence);
		wake_up(&journal->j_wait_commit);
		return 1;
	}
	} else if (!tid_geq(journal->j_commit_request, target))
		/* This should never happen, but if it does, preserve
		   the evidence before kjournald goes into a loop and
		   increments j_commit_sequence beyond all recognition. */
		WARN_ONCE(1, "jbd: bad log_start_commit: %u %u %u %u\n",
		    journal->j_commit_request, journal->j_commit_sequence,
		    target, journal->j_running_transaction ?
		    journal->j_running_transaction->t_tid : 0);
	return 0;
}

+2 −1
Original line number Diff line number Diff line
@@ -266,7 +266,8 @@ static handle_t *new_handle(int nblocks)
 * This function is visible to journal users (like ext3fs), so is not
 * called with the journal already locked.
 *
 * Return a pointer to a newly allocated handle, or NULL on failure
 * Return a pointer to a newly allocated handle, or an ERR_PTR() value
 * on failure.
 */
handle_t *journal_start(journal_t *journal, int nblocks)
{
Loading