Browse Source

Merge branch 'xfs-misc-fixes-for-3.19-1' into for-next

Dave Chinner 10 years ago
parent
commit
4bd47c1bf4
7 changed files with 52 additions and 48 deletions
  1. 2 12
      fs/xfs/xfs_buf.c
  2. 6 9
      fs/xfs/xfs_inode.c
  3. 1 1
      fs/xfs/xfs_log.c
  4. 21 8
      fs/xfs/xfs_mount.c
  5. 2 1
      fs/xfs/xfs_mount.h
  6. 10 16
      fs/xfs/xfs_qm_syscalls.c
  7. 10 1
      fs/xfs/xfs_super.c

+ 2 - 12
fs/xfs/xfs_buf.c

@@ -44,8 +44,6 @@
 
 
 static kmem_zone_t *xfs_buf_zone;
 static kmem_zone_t *xfs_buf_zone;
 
 
-static struct workqueue_struct *xfslogd_workqueue;
-
 #ifdef XFS_BUF_LOCK_TRACKING
 #ifdef XFS_BUF_LOCK_TRACKING
 # define XB_SET_OWNER(bp)	((bp)->b_last_holder = current->pid)
 # define XB_SET_OWNER(bp)	((bp)->b_last_holder = current->pid)
 # define XB_CLEAR_OWNER(bp)	((bp)->b_last_holder = -1)
 # define XB_CLEAR_OWNER(bp)	((bp)->b_last_holder = -1)
@@ -463,7 +461,7 @@ _xfs_buf_find(
 	 * have to check that the buffer falls within the filesystem bounds.
 	 * have to check that the buffer falls within the filesystem bounds.
 	 */
 	 */
 	eofs = XFS_FSB_TO_BB(btp->bt_mount, btp->bt_mount->m_sb.sb_dblocks);
 	eofs = XFS_FSB_TO_BB(btp->bt_mount, btp->bt_mount->m_sb.sb_dblocks);
-	if (blkno >= eofs) {
+	if (blkno < 0 || blkno >= eofs) {
 		/*
 		/*
 		 * XXX (dgc): we should really be returning -EFSCORRUPTED here,
 		 * XXX (dgc): we should really be returning -EFSCORRUPTED here,
 		 * but none of the higher level infrastructure supports
 		 * but none of the higher level infrastructure supports
@@ -1053,7 +1051,7 @@ xfs_buf_ioend_async(
 	struct xfs_buf	*bp)
 	struct xfs_buf	*bp)
 {
 {
 	INIT_WORK(&bp->b_iodone_work, xfs_buf_ioend_work);
 	INIT_WORK(&bp->b_iodone_work, xfs_buf_ioend_work);
-	queue_work(xfslogd_workqueue, &bp->b_iodone_work);
+	queue_work(bp->b_target->bt_mount->m_buf_workqueue, &bp->b_iodone_work);
 }
 }
 
 
 void
 void
@@ -1882,15 +1880,8 @@ xfs_buf_init(void)
 	if (!xfs_buf_zone)
 	if (!xfs_buf_zone)
 		goto out;
 		goto out;
 
 
-	xfslogd_workqueue = alloc_workqueue("xfslogd",
-				WQ_MEM_RECLAIM | WQ_HIGHPRI | WQ_FREEZABLE, 1);
-	if (!xfslogd_workqueue)
-		goto out_free_buf_zone;
-
 	return 0;
 	return 0;
 
 
- out_free_buf_zone:
-	kmem_zone_destroy(xfs_buf_zone);
  out:
  out:
 	return -ENOMEM;
 	return -ENOMEM;
 }
 }
@@ -1898,6 +1889,5 @@ xfs_buf_init(void)
 void
 void
 xfs_buf_terminate(void)
 xfs_buf_terminate(void)
 {
 {
-	destroy_workqueue(xfslogd_workqueue);
 	kmem_zone_destroy(xfs_buf_zone);
 	kmem_zone_destroy(xfs_buf_zone);
 }
 }

+ 6 - 9
fs/xfs/xfs_inode.c

@@ -1082,7 +1082,7 @@ xfs_create(
 	struct xfs_dquot	*udqp = NULL;
 	struct xfs_dquot	*udqp = NULL;
 	struct xfs_dquot	*gdqp = NULL;
 	struct xfs_dquot	*gdqp = NULL;
 	struct xfs_dquot	*pdqp = NULL;
 	struct xfs_dquot	*pdqp = NULL;
-	struct xfs_trans_res	tres;
+	struct xfs_trans_res	*tres;
 	uint			resblks;
 	uint			resblks;
 
 
 	trace_xfs_create(dp, name);
 	trace_xfs_create(dp, name);
@@ -1105,13 +1105,11 @@ xfs_create(
 	if (is_dir) {
 	if (is_dir) {
 		rdev = 0;
 		rdev = 0;
 		resblks = XFS_MKDIR_SPACE_RES(mp, name->len);
 		resblks = XFS_MKDIR_SPACE_RES(mp, name->len);
-		tres.tr_logres = M_RES(mp)->tr_mkdir.tr_logres;
-		tres.tr_logcount = XFS_MKDIR_LOG_COUNT;
+		tres = &M_RES(mp)->tr_mkdir;
 		tp = xfs_trans_alloc(mp, XFS_TRANS_MKDIR);
 		tp = xfs_trans_alloc(mp, XFS_TRANS_MKDIR);
 	} else {
 	} else {
 		resblks = XFS_CREATE_SPACE_RES(mp, name->len);
 		resblks = XFS_CREATE_SPACE_RES(mp, name->len);
-		tres.tr_logres = M_RES(mp)->tr_create.tr_logres;
-		tres.tr_logcount = XFS_CREATE_LOG_COUNT;
+		tres = &M_RES(mp)->tr_create;
 		tp = xfs_trans_alloc(mp, XFS_TRANS_CREATE);
 		tp = xfs_trans_alloc(mp, XFS_TRANS_CREATE);
 	}
 	}
 
 
@@ -1123,17 +1121,16 @@ xfs_create(
 	 * the case we'll drop the one we have and get a more
 	 * the case we'll drop the one we have and get a more
 	 * appropriate transaction later.
 	 * appropriate transaction later.
 	 */
 	 */
-	tres.tr_logflags = XFS_TRANS_PERM_LOG_RES;
-	error = xfs_trans_reserve(tp, &tres, resblks, 0);
+	error = xfs_trans_reserve(tp, tres, resblks, 0);
 	if (error == -ENOSPC) {
 	if (error == -ENOSPC) {
 		/* flush outstanding delalloc blocks and retry */
 		/* flush outstanding delalloc blocks and retry */
 		xfs_flush_inodes(mp);
 		xfs_flush_inodes(mp);
-		error = xfs_trans_reserve(tp, &tres, resblks, 0);
+		error = xfs_trans_reserve(tp, tres, resblks, 0);
 	}
 	}
 	if (error == -ENOSPC) {
 	if (error == -ENOSPC) {
 		/* No space at all so try a "no-allocation" reservation */
 		/* No space at all so try a "no-allocation" reservation */
 		resblks = 0;
 		resblks = 0;
-		error = xfs_trans_reserve(tp, &tres, 0, 0);
+		error = xfs_trans_reserve(tp, tres, 0, 0);
 	}
 	}
 	if (error) {
 	if (error) {
 		cancel_flags = 0;
 		cancel_flags = 0;

+ 1 - 1
fs/xfs/xfs_log.c

@@ -1031,7 +1031,7 @@ xfs_log_need_covered(xfs_mount_t *mp)
 	struct xlog	*log = mp->m_log;
 	struct xlog	*log = mp->m_log;
 	int		needed = 0;
 	int		needed = 0;
 
 
-	if (!xfs_fs_writable(mp))
+	if (!xfs_fs_writable(mp, SB_FREEZE_WRITE))
 		return 0;
 		return 0;
 
 
 	if (!xlog_cil_empty(log))
 	if (!xlog_cil_empty(log))

+ 21 - 8
fs/xfs/xfs_mount.c

@@ -1074,11 +1074,23 @@ xfs_unmountfs(
 	xfs_sysfs_del(&mp->m_kobj);
 	xfs_sysfs_del(&mp->m_kobj);
 }
 }
 
 
-int
-xfs_fs_writable(xfs_mount_t *mp)
+/*
+ * Determine whether modifications can proceed. The caller specifies the minimum
+ * freeze level for which modifications should not be allowed. This allows
+ * certain operations to proceed while the freeze sequence is in progress, if
+ * necessary.
+ */
+bool
+xfs_fs_writable(
+	struct xfs_mount	*mp,
+	int			level)
 {
 {
-	return !(mp->m_super->s_writers.frozen || XFS_FORCED_SHUTDOWN(mp) ||
-		(mp->m_flags & XFS_MOUNT_RDONLY));
+	ASSERT(level > SB_UNFROZEN);
+	if ((mp->m_super->s_writers.frozen >= level) ||
+	    XFS_FORCED_SHUTDOWN(mp) || (mp->m_flags & XFS_MOUNT_RDONLY))
+		return false;
+
+	return true;
 }
 }
 
 
 /*
 /*
@@ -1086,9 +1098,9 @@ xfs_fs_writable(xfs_mount_t *mp)
  *
  *
  * Sync the superblock counters to disk.
  * Sync the superblock counters to disk.
  *
  *
- * Note this code can be called during the process of freezing, so
- * we may need to use the transaction allocator which does not
- * block when the transaction subsystem is in its frozen state.
+ * Note this code can be called during the process of freezing, so we use the
+ * transaction allocator that does not block when the transaction subsystem is
+ * in its frozen state.
  */
  */
 int
 int
 xfs_log_sbcount(xfs_mount_t *mp)
 xfs_log_sbcount(xfs_mount_t *mp)
@@ -1096,7 +1108,8 @@ xfs_log_sbcount(xfs_mount_t *mp)
 	xfs_trans_t	*tp;
 	xfs_trans_t	*tp;
 	int		error;
 	int		error;
 
 
-	if (!xfs_fs_writable(mp))
+	/* allow this to proceed during the freeze sequence... */
+	if (!xfs_fs_writable(mp, SB_FREEZE_COMPLETE))
 		return 0;
 		return 0;
 
 
 	xfs_icsb_sync_counters(mp, 0);
 	xfs_icsb_sync_counters(mp, 0);

+ 2 - 1
fs/xfs/xfs_mount.h

@@ -168,6 +168,7 @@ typedef struct xfs_mount {
 						/* low free space thresholds */
 						/* low free space thresholds */
 	struct xfs_kobj		m_kobj;
 	struct xfs_kobj		m_kobj;
 
 
+	struct workqueue_struct *m_buf_workqueue;
 	struct workqueue_struct	*m_data_workqueue;
 	struct workqueue_struct	*m_data_workqueue;
 	struct workqueue_struct	*m_unwritten_workqueue;
 	struct workqueue_struct	*m_unwritten_workqueue;
 	struct workqueue_struct	*m_cil_workqueue;
 	struct workqueue_struct	*m_cil_workqueue;
@@ -384,7 +385,7 @@ extern int	xfs_mount_log_sb(xfs_mount_t *, __int64_t);
 extern struct xfs_buf *xfs_getsb(xfs_mount_t *, int);
 extern struct xfs_buf *xfs_getsb(xfs_mount_t *, int);
 extern int	xfs_readsb(xfs_mount_t *, int);
 extern int	xfs_readsb(xfs_mount_t *, int);
 extern void	xfs_freesb(xfs_mount_t *);
 extern void	xfs_freesb(xfs_mount_t *);
-extern int	xfs_fs_writable(xfs_mount_t *);
+extern bool	xfs_fs_writable(struct xfs_mount *mp, int level);
 extern int	xfs_sb_validate_fsb_count(struct xfs_sb *, __uint64_t);
 extern int	xfs_sb_validate_fsb_count(struct xfs_sb *, __uint64_t);
 
 
 extern int	xfs_dev_is_read_only(struct xfs_mount *, char *);
 extern int	xfs_dev_is_read_only(struct xfs_mount *, char *);

+ 10 - 16
fs/xfs/xfs_qm_syscalls.c

@@ -784,19 +784,21 @@ xfs_qm_log_quotaoff(
 {
 {
 	xfs_trans_t	       *tp;
 	xfs_trans_t	       *tp;
 	int			error;
 	int			error;
-	xfs_qoff_logitem_t     *qoffi=NULL;
-	uint			oldsbqflag=0;
+	xfs_qoff_logitem_t     *qoffi;
+
+	*qoffstartp = NULL;
 
 
 	tp = xfs_trans_alloc(mp, XFS_TRANS_QM_QUOTAOFF);
 	tp = xfs_trans_alloc(mp, XFS_TRANS_QM_QUOTAOFF);
 	error = xfs_trans_reserve(tp, &M_RES(mp)->tr_qm_quotaoff, 0, 0);
 	error = xfs_trans_reserve(tp, &M_RES(mp)->tr_qm_quotaoff, 0, 0);
-	if (error)
-		goto error0;
+	if (error) {
+		xfs_trans_cancel(tp, 0);
+		goto out;
+	}
 
 
 	qoffi = xfs_trans_get_qoff_item(tp, NULL, flags & XFS_ALL_QUOTA_ACCT);
 	qoffi = xfs_trans_get_qoff_item(tp, NULL, flags & XFS_ALL_QUOTA_ACCT);
 	xfs_trans_log_quotaoff_item(tp, qoffi);
 	xfs_trans_log_quotaoff_item(tp, qoffi);
 
 
 	spin_lock(&mp->m_sb_lock);
 	spin_lock(&mp->m_sb_lock);
-	oldsbqflag = mp->m_sb.sb_qflags;
 	mp->m_sb.sb_qflags = (mp->m_qflags & ~(flags)) & XFS_MOUNT_QUOTA_ALL;
 	mp->m_sb.sb_qflags = (mp->m_qflags & ~(flags)) & XFS_MOUNT_QUOTA_ALL;
 	spin_unlock(&mp->m_sb_lock);
 	spin_unlock(&mp->m_sb_lock);
 
 
@@ -809,19 +811,11 @@ xfs_qm_log_quotaoff(
 	 */
 	 */
 	xfs_trans_set_sync(tp);
 	xfs_trans_set_sync(tp);
 	error = xfs_trans_commit(tp, 0);
 	error = xfs_trans_commit(tp, 0);
+	if (error)
+		goto out;
 
 
-error0:
-	if (error) {
-		xfs_trans_cancel(tp, 0);
-		/*
-		 * No one else is modifying sb_qflags, so this is OK.
-		 * We still hold the quotaofflock.
-		 */
-		spin_lock(&mp->m_sb_lock);
-		mp->m_sb.sb_qflags = oldsbqflag;
-		spin_unlock(&mp->m_sb_lock);
-	}
 	*qoffstartp = qoffi;
 	*qoffstartp = qoffi;
+out:
 	return error;
 	return error;
 }
 }
 
 

+ 10 - 1
fs/xfs/xfs_super.c

@@ -842,10 +842,16 @@ STATIC int
 xfs_init_mount_workqueues(
 xfs_init_mount_workqueues(
 	struct xfs_mount	*mp)
 	struct xfs_mount	*mp)
 {
 {
+	mp->m_buf_workqueue = alloc_workqueue("xfs-buf/%s",
+			WQ_MEM_RECLAIM|WQ_HIGHPRI|WQ_FREEZABLE, 1,
+			mp->m_fsname);
+	if (!mp->m_buf_workqueue)
+		goto out;
+
 	mp->m_data_workqueue = alloc_workqueue("xfs-data/%s",
 	mp->m_data_workqueue = alloc_workqueue("xfs-data/%s",
 			WQ_MEM_RECLAIM|WQ_FREEZABLE, 0, mp->m_fsname);
 			WQ_MEM_RECLAIM|WQ_FREEZABLE, 0, mp->m_fsname);
 	if (!mp->m_data_workqueue)
 	if (!mp->m_data_workqueue)
-		goto out;
+		goto out_destroy_buf;
 
 
 	mp->m_unwritten_workqueue = alloc_workqueue("xfs-conv/%s",
 	mp->m_unwritten_workqueue = alloc_workqueue("xfs-conv/%s",
 			WQ_MEM_RECLAIM|WQ_FREEZABLE, 0, mp->m_fsname);
 			WQ_MEM_RECLAIM|WQ_FREEZABLE, 0, mp->m_fsname);
@@ -884,6 +890,8 @@ out_destroy_unwritten:
 	destroy_workqueue(mp->m_unwritten_workqueue);
 	destroy_workqueue(mp->m_unwritten_workqueue);
 out_destroy_data_iodone_queue:
 out_destroy_data_iodone_queue:
 	destroy_workqueue(mp->m_data_workqueue);
 	destroy_workqueue(mp->m_data_workqueue);
+out_destroy_buf:
+	destroy_workqueue(mp->m_buf_workqueue);
 out:
 out:
 	return -ENOMEM;
 	return -ENOMEM;
 }
 }
@@ -898,6 +906,7 @@ xfs_destroy_mount_workqueues(
 	destroy_workqueue(mp->m_cil_workqueue);
 	destroy_workqueue(mp->m_cil_workqueue);
 	destroy_workqueue(mp->m_data_workqueue);
 	destroy_workqueue(mp->m_data_workqueue);
 	destroy_workqueue(mp->m_unwritten_workqueue);
 	destroy_workqueue(mp->m_unwritten_workqueue);
+	destroy_workqueue(mp->m_buf_workqueue);
 }
 }
 
 
 /*
 /*