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

Commit af84b99f authored by Linus Torvalds's avatar Linus Torvalds
Browse files
* git://oss.sgi.com:8090/xfs/xfs-2.6:
  [XFS] Fix a bad pointer dereference in the quota statvfs handling.
  [XFS] Fix xfs_splice_write() so appended data gets to disk.
  [XFS] Fix ABBA deadlock between i_mutex and iolock. Avoid calling
  [XFS] Prevent free space oversubscription and xfssyncd looping.
parents 05ff0e29 0edc7d0f
Loading
Loading
Loading
Loading
+13 −5
Original line number Original line Diff line number Diff line
@@ -1390,11 +1390,19 @@ xfs_vm_direct_IO(


	iocb->private = xfs_alloc_ioend(inode, IOMAP_UNWRITTEN);
	iocb->private = xfs_alloc_ioend(inode, IOMAP_UNWRITTEN);


	if (rw == WRITE) {
		ret = blockdev_direct_IO_own_locking(rw, iocb, inode,
		ret = blockdev_direct_IO_own_locking(rw, iocb, inode,
			iomap.iomap_target->bt_bdev,
			iomap.iomap_target->bt_bdev,
			iov, offset, nr_segs,
			iov, offset, nr_segs,
			xfs_get_blocks_direct,
			xfs_get_blocks_direct,
			xfs_end_io_direct);
			xfs_end_io_direct);
	} else {
		ret = blockdev_direct_IO_no_locking(rw, iocb, inode,
			iomap.iomap_target->bt_bdev,
			iov, offset, nr_segs,
			xfs_get_blocks_direct,
			xfs_end_io_direct);
	}


	if (unlikely(ret <= 0 && iocb->private))
	if (unlikely(ret <= 0 && iocb->private))
		xfs_destroy_ioend(iocb->private);
		xfs_destroy_ioend(iocb->private);
+22 −5
Original line number Original line Diff line number Diff line
@@ -264,7 +264,9 @@ xfs_read(
					dmflags, &locktype);
					dmflags, &locktype);
		if (ret) {
		if (ret) {
			xfs_iunlock(ip, XFS_IOLOCK_SHARED);
			xfs_iunlock(ip, XFS_IOLOCK_SHARED);
			goto unlock_mutex;
			if (unlikely(ioflags & IO_ISDIRECT))
				mutex_unlock(&inode->i_mutex);
			return ret;
		}
		}
	}
	}


@@ -272,6 +274,9 @@ xfs_read(
		bhv_vop_flushinval_pages(vp, ctooff(offtoct(*offset)),
		bhv_vop_flushinval_pages(vp, ctooff(offtoct(*offset)),
						-1, FI_REMAPF_LOCKED);
						-1, FI_REMAPF_LOCKED);


	if (unlikely(ioflags & IO_ISDIRECT))
		mutex_unlock(&inode->i_mutex);

	xfs_rw_enter_trace(XFS_READ_ENTER, &ip->i_iocore,
	xfs_rw_enter_trace(XFS_READ_ENTER, &ip->i_iocore,
				(void *)iovp, segs, *offset, ioflags);
				(void *)iovp, segs, *offset, ioflags);
	ret = __generic_file_aio_read(iocb, iovp, segs, offset);
	ret = __generic_file_aio_read(iocb, iovp, segs, offset);
@@ -281,10 +286,6 @@ xfs_read(
		XFS_STATS_ADD(xs_read_bytes, ret);
		XFS_STATS_ADD(xs_read_bytes, ret);


	xfs_iunlock(ip, XFS_IOLOCK_SHARED);
	xfs_iunlock(ip, XFS_IOLOCK_SHARED);

unlock_mutex:
	if (unlikely(ioflags & IO_ISDIRECT))
		mutex_unlock(&inode->i_mutex);
	return ret;
	return ret;
}
}


@@ -390,6 +391,8 @@ xfs_splice_write(
	xfs_inode_t		*ip = XFS_BHVTOI(bdp);
	xfs_inode_t		*ip = XFS_BHVTOI(bdp);
	xfs_mount_t		*mp = ip->i_mount;
	xfs_mount_t		*mp = ip->i_mount;
	ssize_t			ret;
	ssize_t			ret;
	struct inode		*inode = outfilp->f_mapping->host;
	xfs_fsize_t		isize;


	XFS_STATS_INC(xs_write_calls);
	XFS_STATS_INC(xs_write_calls);
	if (XFS_FORCED_SHUTDOWN(ip->i_mount))
	if (XFS_FORCED_SHUTDOWN(ip->i_mount))
@@ -416,6 +419,20 @@ xfs_splice_write(
	if (ret > 0)
	if (ret > 0)
		XFS_STATS_ADD(xs_write_bytes, ret);
		XFS_STATS_ADD(xs_write_bytes, ret);


	isize = i_size_read(inode);
	if (unlikely(ret < 0 && ret != -EFAULT && *ppos > isize))
		*ppos = isize;

	if (*ppos > ip->i_d.di_size) {
		xfs_ilock(ip, XFS_ILOCK_EXCL);
		if (*ppos > ip->i_d.di_size) {
			ip->i_d.di_size = *ppos;
			i_size_write(inode, *ppos);
			ip->i_update_core = 1;
			ip->i_update_size = 1;
		}
		xfs_iunlock(ip, XFS_ILOCK_EXCL);
	}
	xfs_iunlock(ip, XFS_IOLOCK_EXCL);
	xfs_iunlock(ip, XFS_IOLOCK_EXCL);
	return ret;
	return ret;
}
}
+1 −1
Original line number Original line Diff line number Diff line
@@ -203,7 +203,7 @@ xfs_qm_statvfs(
	if (error || !vnode)
	if (error || !vnode)
		return error;
		return error;


	mp = XFS_BHVTOM(bhv);
	mp = xfs_vfstom(bhvtovfs(bhv));
	ip = xfs_vtoi(vnode);
	ip = xfs_vtoi(vnode);


	if (!(ip->i_d.di_flags & XFS_DIFLAG_PROJINHERIT))
	if (!(ip->i_d.di_flags & XFS_DIFLAG_PROJINHERIT))
+20 −0
Original line number Original line Diff line number Diff line
@@ -43,6 +43,26 @@ typedef enum xfs_alloctype
#define	XFS_ALLOC_FLAG_TRYLOCK	0x00000001  /* use trylock for buffer locking */
#define	XFS_ALLOC_FLAG_TRYLOCK	0x00000001  /* use trylock for buffer locking */
#define	XFS_ALLOC_FLAG_FREEING	0x00000002  /* indicate caller is freeing extents*/
#define	XFS_ALLOC_FLAG_FREEING	0x00000002  /* indicate caller is freeing extents*/


/*
 * In order to avoid ENOSPC-related deadlock caused by
 * out-of-order locking of AGF buffer (PV 947395), we place
 * constraints on the relationship among actual allocations for
 * data blocks, freelist blocks, and potential file data bmap
 * btree blocks. However, these restrictions may result in no
 * actual space allocated for a delayed extent, for example, a data
 * block in a certain AG is allocated but there is no additional
 * block for the additional bmap btree block due to a split of the
 * bmap btree of the file. The result of this may lead to an
 * infinite loop in xfssyncd when the file gets flushed to disk and
 * all delayed extents need to be actually allocated. To get around
 * this, we explicitly set aside a few blocks which will not be
 * reserved in delayed allocation. Considering the minimum number of
 * needed freelist blocks is 4 fsbs _per AG_, a potential split of file's bmap
 * btree requires 1 fsb, so we set the number of set-aside blocks
 * to 4 + 4*agcount.
 */
#define XFS_ALLOC_SET_ASIDE(mp)  (4 + ((mp)->m_sb.sb_agcount * 4))

/*
/*
 * Argument structure for xfs_alloc routines.
 * Argument structure for xfs_alloc routines.
 * This is turned into a structure to avoid having 20 arguments passed
 * This is turned into a structure to avoid having 20 arguments passed
+10 −6
Original line number Original line Diff line number Diff line
@@ -462,7 +462,7 @@ xfs_fs_counts(


	xfs_icsb_sync_counters_lazy(mp);
	xfs_icsb_sync_counters_lazy(mp);
	s = XFS_SB_LOCK(mp);
	s = XFS_SB_LOCK(mp);
	cnt->freedata = mp->m_sb.sb_fdblocks;
	cnt->freedata = mp->m_sb.sb_fdblocks - XFS_ALLOC_SET_ASIDE(mp);
	cnt->freertx = mp->m_sb.sb_frextents;
	cnt->freertx = mp->m_sb.sb_frextents;
	cnt->freeino = mp->m_sb.sb_ifree;
	cnt->freeino = mp->m_sb.sb_ifree;
	cnt->allocino = mp->m_sb.sb_icount;
	cnt->allocino = mp->m_sb.sb_icount;
@@ -519,15 +519,19 @@ xfs_reserve_blocks(
		}
		}
		mp->m_resblks = request;
		mp->m_resblks = request;
	} else {
	} else {
		__int64_t	free;

		free =  mp->m_sb.sb_fdblocks - XFS_ALLOC_SET_ASIDE(mp);
		delta = request - mp->m_resblks;
		delta = request - mp->m_resblks;
		lcounter = mp->m_sb.sb_fdblocks - delta;
		lcounter = free - delta;
		if (lcounter < 0) {
		if (lcounter < 0) {
			/* We can't satisfy the request, just get what we can */
			/* We can't satisfy the request, just get what we can */
			mp->m_resblks += mp->m_sb.sb_fdblocks;
			mp->m_resblks += free;
			mp->m_resblks_avail += mp->m_sb.sb_fdblocks;
			mp->m_resblks_avail += free;
			mp->m_sb.sb_fdblocks = 0;
			mp->m_sb.sb_fdblocks = XFS_ALLOC_SET_ASIDE(mp);
		} else {
		} else {
			mp->m_sb.sb_fdblocks = lcounter;
			mp->m_sb.sb_fdblocks =
				lcounter + XFS_ALLOC_SET_ASIDE(mp);
			mp->m_resblks = request;
			mp->m_resblks = request;
			mp->m_resblks_avail += delta;
			mp->m_resblks_avail += delta;
		}
		}
Loading