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

Commit 41f81e88 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge branch 'for-linus' of git://oss.sgi.com:8090/xfs/xfs-2.6

* 'for-linus' of git://oss.sgi.com:8090/xfs/xfs-2.6:
  [XFS] Fix xfs_ichgtime()s broken usage of I_SYNC
  [XFS] Make xfsbufd threads freezable
  [XFS] revert to double-buffering readdir
  [XFS] Fix broken inode cluster setup.
  [XFS] Clear XBF_READ_AHEAD flag on I/O completion.
  [XFS] Fixed a few bugs in xfs_buf_associate_memory()
  [XFS] 971064 Various fixups for xfs_bulkstat().
  [XFS] Fix dbflush panic in xfs_qm_sync.
parents dc3d532a cf10e82b
Loading
Loading
Loading
Loading
+16 −21
Original line number Diff line number Diff line
@@ -725,15 +725,15 @@ xfs_buf_associate_memory(
{
	int			rval;
	int			i = 0;
	size_t			ptr;
	size_t			end, end_cur;
	off_t			offset;
	unsigned long		pageaddr;
	unsigned long		offset;
	size_t			buflen;
	int			page_count;

	page_count = PAGE_CACHE_ALIGN(len) >> PAGE_CACHE_SHIFT;
	offset = (off_t) mem - ((off_t)mem & PAGE_CACHE_MASK);
	if (offset && (len > PAGE_CACHE_SIZE))
		page_count++;
	pageaddr = (unsigned long)mem & PAGE_CACHE_MASK;
	offset = (unsigned long)mem - pageaddr;
	buflen = PAGE_CACHE_ALIGN(len + offset);
	page_count = buflen >> PAGE_CACHE_SHIFT;

	/* Free any previous set of page pointers */
	if (bp->b_pages)
@@ -747,22 +747,15 @@ xfs_buf_associate_memory(
		return rval;

	bp->b_offset = offset;
	ptr = (size_t) mem & PAGE_CACHE_MASK;
	end = PAGE_CACHE_ALIGN((size_t) mem + len);
	end_cur = end;
	/* set up first page */
	bp->b_pages[0] = mem_to_page(mem);

	ptr += PAGE_CACHE_SIZE;
	bp->b_page_count = ++i;
	while (ptr < end) {
		bp->b_pages[i] = mem_to_page((void *)ptr);
		bp->b_page_count = ++i;
		ptr += PAGE_CACHE_SIZE;

	for (i = 0; i < bp->b_page_count; i++) {
		bp->b_pages[i] = mem_to_page((void *)pageaddr);
		pageaddr += PAGE_CACHE_SIZE;
	}
	bp->b_locked = 0;

	bp->b_count_desired = bp->b_buffer_length = len;
	bp->b_count_desired = len;
	bp->b_buffer_length = buflen;
	bp->b_flags |= XBF_MAPPED;

	return 0;
@@ -1032,7 +1025,7 @@ xfs_buf_ioend(
	xfs_buf_t		*bp,
	int			schedule)
{
	bp->b_flags &= ~(XBF_READ | XBF_WRITE);
	bp->b_flags &= ~(XBF_READ | XBF_WRITE | XBF_READ_AHEAD);
	if (bp->b_error == 0)
		bp->b_flags |= XBF_DONE;

@@ -1750,6 +1743,8 @@ xfsbufd(

	current->flags |= PF_MEMALLOC;

	set_freezable();

	do {
		if (unlikely(freezing(current))) {
			set_bit(XBT_FORCE_SLEEP, &target->bt_flags);
+124 −0
Original line number Diff line number Diff line
@@ -218,6 +218,15 @@ xfs_vm_fault(
}
#endif /* CONFIG_XFS_DMAPI */

/*
 * Unfortunately we can't just use the clean and simple readdir implementation
 * below, because nfs might call back into ->lookup from the filldir callback
 * and that will deadlock the low-level btree code.
 *
 * Hopefully we'll find a better workaround that allows to use the optimal
 * version at least for local readdirs for 2.6.25.
 */
#if 0
STATIC int
xfs_file_readdir(
	struct file	*filp,
@@ -249,6 +258,121 @@ xfs_file_readdir(
		return -error;
	return 0;
}
#else

struct hack_dirent {
	int		namlen;
	loff_t		offset;
	u64		ino;
	unsigned int	d_type;
	char		name[];
};

struct hack_callback {
	char		*dirent;
	size_t		len;
	size_t		used;
};

STATIC int
xfs_hack_filldir(
	void		*__buf,
	const char	*name,
	int		namlen,
	loff_t		offset,
	u64		ino,
	unsigned int	d_type)
{
	struct hack_callback *buf = __buf;
	struct hack_dirent *de = (struct hack_dirent *)(buf->dirent + buf->used);

	if (buf->used + sizeof(struct hack_dirent) + namlen > buf->len)
		return -EINVAL;

	de->namlen = namlen;
	de->offset = offset;
	de->ino = ino;
	de->d_type = d_type;
	memcpy(de->name, name, namlen);
	buf->used += sizeof(struct hack_dirent) + namlen;
	return 0;
}

STATIC int
xfs_file_readdir(
	struct file	*filp,
	void		*dirent,
	filldir_t	filldir)
{
	struct inode	*inode = filp->f_path.dentry->d_inode;
	xfs_inode_t	*ip = XFS_I(inode);
	struct hack_callback buf;
	struct hack_dirent *de;
	int		error;
	loff_t		size;
	int		eof = 0;
	xfs_off_t       start_offset, curr_offset, offset;

	/*
	 * Try fairly hard to get memory
	 */
	buf.len = PAGE_CACHE_SIZE;
	do {
		buf.dirent = kmalloc(buf.len, GFP_KERNEL);
		if (buf.dirent)
			break;
		buf.len >>= 1;
	} while (buf.len >= 1024);

	if (!buf.dirent)
		return -ENOMEM;

	curr_offset = filp->f_pos;
	if (curr_offset == 0x7fffffff)
		offset = 0xffffffff;
	else
		offset = filp->f_pos;

	while (!eof) {
		int reclen;
		start_offset = offset;

		buf.used = 0;
		error = -xfs_readdir(ip, &buf, buf.len, &offset,
				     xfs_hack_filldir);
		if (error || offset == start_offset) {
			size = 0;
			break;
		}

		size = buf.used;
		de = (struct hack_dirent *)buf.dirent;
		while (size > 0) {
			if (filldir(dirent, de->name, de->namlen,
					curr_offset & 0x7fffffff,
					de->ino, de->d_type)) {
				goto done;
			}

			reclen = sizeof(struct hack_dirent) + de->namlen;
			size -= reclen;
			curr_offset = de->offset /* & 0x7fffffff */;
			de = (struct hack_dirent *)((char *)de + reclen);
		}
	}

 done:
 	if (!error) {
		if (size == 0)
			filp->f_pos = offset & 0x7fffffff;
		else if (de)
			filp->f_pos = curr_offset;
	}

	kfree(buf.dirent);
	return error;
}
#endif

STATIC int
xfs_file_mmap(
+8 −12
Original line number Diff line number Diff line
@@ -1047,24 +1047,20 @@ xfs_ioc_bulkstat(
	if ((count = bulkreq.icount) <= 0)
		return -XFS_ERROR(EINVAL);

	if (bulkreq.ubuffer == NULL)
		return -XFS_ERROR(EINVAL);

	if (cmd == XFS_IOC_FSINUMBERS)
		error = xfs_inumbers(mp, &inlast, &count,
					bulkreq.ubuffer, xfs_inumbers_fmt);
	else if (cmd == XFS_IOC_FSBULKSTAT_SINGLE)
		error = xfs_bulkstat_single(mp, &inlast,
						bulkreq.ubuffer, &done);
	else {	/* XFS_IOC_FSBULKSTAT */
		if (count == 1 && inlast != 0) {
			inlast++;
			error = xfs_bulkstat_single(mp, &inlast,
					bulkreq.ubuffer, &done);
		} else {
	else	/* XFS_IOC_FSBULKSTAT */
		error = xfs_bulkstat(mp, &inlast, &count,
			(bulkstat_one_pf)xfs_bulkstat_one, NULL,
			sizeof(xfs_bstat_t), bulkreq.ubuffer,
			BULKSTAT_FG_QUICK, &done);
		}
	}

	if (error)
		return -error;
+3 −0
Original line number Diff line number Diff line
@@ -291,6 +291,9 @@ xfs_ioc_bulkstat_compat(
	if ((count = bulkreq.icount) <= 0)
		return -XFS_ERROR(EINVAL);

	if (bulkreq.ubuffer == NULL)
		return -XFS_ERROR(EINVAL);

	if (cmd == XFS_IOC_FSINUMBERS)
		error = xfs_inumbers(mp, &inlast, &count,
				bulkreq.ubuffer, xfs_inumbers_fmt_compat);
+2 −2
Original line number Diff line number Diff line
@@ -117,7 +117,7 @@ xfs_ichgtime(
	 */
	SYNCHRONIZE();
	ip->i_update_core = 1;
	if (!(inode->i_state & I_SYNC))
	if (!(inode->i_state & I_NEW))
		mark_inode_dirty_sync(inode);
}

@@ -169,7 +169,7 @@ xfs_ichgtime_fast(
	 */
	SYNCHRONIZE();
	ip->i_update_core = 1;
	if (!(inode->i_state & I_SYNC))
	if (!(inode->i_state & I_NEW))
		mark_inode_dirty_sync(inode);
}

Loading