Skip to content

Commit

Permalink
Merge branch 'for-linus' of git://oss.sgi.com:8090/xfs/xfs-2.6
Browse files Browse the repository at this point in the history
* '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.
  • Loading branch information
Linus Torvalds committed Dec 10, 2007
2 parents dc3d532 + cf10e82 commit 41f81e8
Show file tree
Hide file tree
Showing 8 changed files with 186 additions and 50 deletions.
37 changes: 16 additions & 21 deletions fs/xfs/linux-2.6/xfs_buf.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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;
Expand Down Expand Up @@ -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;

Expand Down Expand Up @@ -1750,6 +1743,8 @@ xfsbufd(

current->flags |= PF_MEMALLOC;

set_freezable();

do {
if (unlikely(freezing(current))) {
set_bit(XBT_FORCE_SLEEP, &target->bt_flags);
Expand Down
124 changes: 124 additions & 0 deletions fs/xfs/linux-2.6/xfs_file.c
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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(
Expand Down
20 changes: 8 additions & 12 deletions fs/xfs/linux-2.6/xfs_ioctl.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
error = xfs_bulkstat(mp, &inlast, &count,
(bulkstat_one_pf)xfs_bulkstat_one, NULL,
sizeof(xfs_bstat_t), bulkreq.ubuffer,
BULKSTAT_FG_QUICK, &done);
}
}
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;
Expand Down
3 changes: 3 additions & 0 deletions fs/xfs/linux-2.6/xfs_ioctl32.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
4 changes: 2 additions & 2 deletions fs/xfs/linux-2.6/xfs_iops.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}

Expand Down Expand Up @@ -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);
}

Expand Down
3 changes: 3 additions & 0 deletions fs/xfs/quota/xfs_qm.c
Original file line number Diff line number Diff line change
Expand Up @@ -1008,6 +1008,9 @@ xfs_qm_sync(
boolean_t nowait;
int error;

if (! XFS_IS_QUOTA_ON(mp))
return 0;

restarts = 0;
/*
* We won't block unless we are asked to.
Expand Down
2 changes: 1 addition & 1 deletion fs/xfs/xfs_iget.c
Original file line number Diff line number Diff line change
Expand Up @@ -267,7 +267,7 @@ xfs_iget_core(
icl = NULL;
if (radix_tree_gang_lookup(&pag->pag_ici_root, (void**)&iq,
first_index, 1)) {
if ((iq->i_ino & mask) == first_index)
if ((XFS_INO_TO_AGINO(mp, iq->i_ino) & mask) == first_index)
icl = iq->i_cluster;
}

Expand Down
Loading

0 comments on commit 41f81e8

Please sign in to comment.