Commit 87b4126f authored by Suzuki K P's avatar Suzuki K P Committed by Linus Torvalds

[PATCH] fix reiserfs bad path release panic

One of our test team hit a reiserfs_panic while running fsstress tests on
2.6.19-rc1.  The message looks like :

  REISERFS: panic(device Null superblock):
  reiserfs[5676]: assertion !(p->path_length != 1 ) failed at
  fs/reiserfs/stree.c:397:reiserfs_check_path: path not properly relsed.

The backtrace looked :

  kernel BUG in reiserfs_panic at fs/reiserfs/prints.c:361!

Upon debugging I found that the restart_transaction was not releasing
the path if the th->refcount was > 1.

int restart_transaction(struct reiserfs_transaction_handle *th,
                           			struct inode *inode, struct path *path)

         /* we cannot restart while nested */
         if (th->t_refcount > 1) { <<- Path is not released in this case!
                 return 0;

         pathrelse(path); <<- Path released here.

This could happen in such a situation :

In reiserfs/inode.c: reiserfs_get_block() ::

      if (repeat == NO_DISK_SPACE || repeat == QUOTA_EXCEEDED) {
          /* restart the transaction to give the journal a chance to free
           ** some blocks.  releases the path, so we have to go back to
           ** research if we succeed on the second try
          SB_JOURNAL(inode->i_sb)->j_next_async_flush = 1;

        -->>  retval = restart_transaction(th, inode, &path); <<--

  We are supposed to release the path, no matter we succeed or fail. But
if the th->refcount is > 1, the path is still valid. And,

          if (retval)
                   goto failure;
          repeat =
              _allocate_block(th, block, inode,
                             &allocated_block_nr, NULL, create);

If the above allocate_block fails with NO_DISK_SPACE or QUOTA_EXCEEDED,
we would have path which is not released.

         if (repeat != NO_DISK_SPACE && repeat != QUOTA_EXCEEDED) {
                   goto research;
         if (repeat == QUOTA_EXCEEDED)
                   retval = -EDQUOT;
                   retval = -ENOSPC;
         goto failure;

         reiserfs_check_path(&path); << Panics here !

Attached here is a patch which could fix the issue.

fix reiserfs/inode.c : restart_transaction() to release the path in all

The restart_transaction() doesn't release the path when the the journal
handle has a refcount > 1.  This would trigger a reiserfs_panic() if we
encounter an -ENOSPC / -EDQUOT in reiserfs_get_block().
Signed-off-by: default avatarSuzuki K P <>
Cc: "Vladimir V. Saveliev" <>
Cc: <>
Cc: Jeff Mahoney <>
Acked-by: default avatarJan Kara <>
Signed-off-by: default avatarAndrew Morton <>
Signed-off-by: default avatarLinus Torvalds <>
parent 4cf30348
......@@ -216,11 +216,12 @@ static int file_capable(struct inode *inode, long block)
/* we cannot restart while nested */
if (th->t_refcount > 1) {
return 0;
reiserfs_update_sd(th, inode);
err = journal_end(th, s, len);
if (!err) {
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment