فهرست منبع

NTFS: Fix a bug in address space operations error recovery code paths where
if the runlist was not mapped at all and a mapping error occured we
would leave the runlist locked on exit to the function so that the
next access to the same file would try to take the lock and deadlock.

Signed-off-by: Anton Altaparmakov <aia21@cantab.net>

Anton Altaparmakov 20 سال پیش
والد
کامیت
9f993fe463
3فایلهای تغییر یافته به همراه17 افزوده شده و 5 حذف شده
  1. 4 0
      fs/ntfs/ChangeLog
  2. 12 4
      fs/ntfs/aops.c
  3. 1 1
      fs/ntfs/layout.h

+ 4 - 0
fs/ntfs/ChangeLog

@@ -121,6 +121,10 @@ ToDo/Notes:
 	- Stamp the transaction log ($UsnJrnl), aka user space journal, if it
 	- Stamp the transaction log ($UsnJrnl), aka user space journal, if it
 	  is active on the volume and we are mounting read-write or remounting
 	  is active on the volume and we are mounting read-write or remounting
 	  from read-only to read-write.
 	  from read-only to read-write.
+	- Fix a bug in address space operations error recovery code paths where
+	  if the runlist was not mapped at all and a mapping error occured we
+	  would leave the runlist locked on exit to the function so that the
+	  next access to the same file would try to take the lock and deadlock.
 
 
 2.1.22 - Many bug and race fixes and error handling improvements.
 2.1.22 - Many bug and race fixes and error handling improvements.
 
 

+ 12 - 4
fs/ntfs/aops.c

@@ -264,7 +264,8 @@ static int ntfs_read_block(struct page *page)
 					goto lock_retry_remap;
 					goto lock_retry_remap;
 				rl = NULL;
 				rl = NULL;
 				lcn = err;
 				lcn = err;
-			}
+			} else if (!rl)
+				up_read(&ni->runlist.lock);
 			/* Hard error, zero out region. */
 			/* Hard error, zero out region. */
 			bh->b_blocknr = -1;
 			bh->b_blocknr = -1;
 			SetPageError(page);
 			SetPageError(page);
@@ -690,7 +691,8 @@ static int ntfs_write_block(struct page *page, struct writeback_control *wbc)
 				goto lock_retry_remap;
 				goto lock_retry_remap;
 			rl = NULL;
 			rl = NULL;
 			lcn = err;
 			lcn = err;
-		}
+		} else if (!rl)
+			up_read(&ni->runlist.lock);
 		/* Failed to map the buffer, even after retrying. */
 		/* Failed to map the buffer, even after retrying. */
 		bh->b_blocknr = -1;
 		bh->b_blocknr = -1;
 		ntfs_error(vol->sb, "Failed to write to inode 0x%lx, "
 		ntfs_error(vol->sb, "Failed to write to inode 0x%lx, "
@@ -965,8 +967,11 @@ static int ntfs_write_mst_block(struct page *page,
 					if (err2 == -ENOMEM)
 					if (err2 == -ENOMEM)
 						page_is_dirty = TRUE;
 						page_is_dirty = TRUE;
 					lcn = err2;
 					lcn = err2;
-				} else
+				} else {
 					err2 = -EIO;
 					err2 = -EIO;
+					if (!rl)
+						up_read(&ni->runlist.lock);
+				}
 				/* Hard error.  Abort writing this record. */
 				/* Hard error.  Abort writing this record. */
 				if (!err || err == -ENOMEM)
 				if (!err || err == -ENOMEM)
 					err = err2;
 					err = err2;
@@ -1660,6 +1665,8 @@ static int ntfs_prepare_nonresident_write(struct page *page,
 							"not supported yet. "
 							"not supported yet. "
 							"Sorry.");
 							"Sorry.");
 					err = -EOPNOTSUPP;
 					err = -EOPNOTSUPP;
+					if (!rl)
+						up_read(&ni->runlist.lock);
 					goto err_out;
 					goto err_out;
 				} else if (!is_retry &&
 				} else if (!is_retry &&
 						lcn == LCN_RL_NOT_MAPPED) {
 						lcn == LCN_RL_NOT_MAPPED) {
@@ -1674,7 +1681,8 @@ static int ntfs_prepare_nonresident_write(struct page *page,
 						goto lock_retry_remap;
 						goto lock_retry_remap;
 					rl = NULL;
 					rl = NULL;
 					lcn = err;
 					lcn = err;
-				}
+				} else if (!rl)
+					up_read(&ni->runlist.lock);
 				/*
 				/*
 				 * Failed to map the buffer, even after
 				 * Failed to map the buffer, even after
 				 * retrying.
 				 * retrying.

+ 1 - 1
fs/ntfs/layout.h

@@ -936,7 +936,7 @@ typedef struct {
 		/* 56*/	le64 quota_charged;	/* Byte size of the charge to
 		/* 56*/	le64 quota_charged;	/* Byte size of the charge to
 				the quota for all streams of the file. Note: Is
 				the quota for all streams of the file. Note: Is
 				zero if quotas are disabled. */
 				zero if quotas are disabled. */
-		/* 64*/	USN usn;		/* Last update sequence number
+		/* 64*/	leUSN usn;		/* Last update sequence number
 				of the file.  This is a direct index into the
 				of the file.  This is a direct index into the
 				transaction log file ($UsnJrnl).  It is zero if
 				transaction log file ($UsnJrnl).  It is zero if
 				the usn journal is disabled or this file has
 				the usn journal is disabled or this file has