aboutsummaryrefslogtreecommitdiffstats
path: root/fs/xfs
diff options
context:
space:
mode:
authorTony Luck <tony.luck@intel.com>2005-06-15 17:06:48 -0400
committerTony Luck <tony.luck@intel.com>2005-06-15 17:06:48 -0400
commitf2cbb4f01936a3e4225692e03b084b78c56d386d (patch)
treef89f3d8baa250589a38a4dd2df56f84cddae3c76 /fs/xfs
parent325a479c4c110db278ef3361460a48c4093252cc (diff)
parent1016888fb69662936b32ab767c7419a3be9a69d3 (diff)
Auto merge with /home/aegl/GIT/linus
Diffstat (limited to 'fs/xfs')
-rw-r--r--fs/xfs/Makefile2
-rw-r--r--fs/xfs/linux-2.6/xfs_aops.c80
-rw-r--r--fs/xfs/linux-2.6/xfs_buf.c11
-rw-r--r--fs/xfs/linux-2.6/xfs_file.c50
-rw-r--r--fs/xfs/linux-2.6/xfs_ioctl32.c29
-rw-r--r--fs/xfs/linux-2.6/xfs_ioctl32.h6
-rw-r--r--fs/xfs/linux-2.6/xfs_lrw.c3
-rw-r--r--fs/xfs/linux-2.6/xfs_super.c3
-rw-r--r--fs/xfs/linux-2.6/xfs_vnode.c5
-rw-r--r--fs/xfs/linux-2.6/xfs_vnode.h10
-rw-r--r--fs/xfs/xfs_dfrag.c2
-rw-r--r--fs/xfs/xfs_iget.c51
-rw-r--r--fs/xfs/xfs_inode.c2
-rw-r--r--fs/xfs/xfs_inode.h6
-rw-r--r--fs/xfs/xfs_iomap.c30
-rw-r--r--fs/xfs/xfs_iomap.h25
-rw-r--r--fs/xfs/xfs_mount.c9
-rw-r--r--fs/xfs/xfs_mount.h19
-rw-r--r--fs/xfs/xfs_types.h1
-rw-r--r--fs/xfs/xfs_utils.c2
-rw-r--r--fs/xfs/xfs_utils.h2
-rw-r--r--fs/xfs/xfs_vfsops.c67
-rw-r--r--fs/xfs/xfs_vnodeops.c11
23 files changed, 294 insertions, 132 deletions
diff --git a/fs/xfs/Makefile b/fs/xfs/Makefile
index 554e4a18c152..d3ff78354638 100644
--- a/fs/xfs/Makefile
+++ b/fs/xfs/Makefile
@@ -49,7 +49,7 @@ ifeq ($(CONFIG_XFS_TRACE),y)
49 EXTRA_CFLAGS += -DXFS_LOG_TRACE 49 EXTRA_CFLAGS += -DXFS_LOG_TRACE
50 EXTRA_CFLAGS += -DXFS_RW_TRACE 50 EXTRA_CFLAGS += -DXFS_RW_TRACE
51 EXTRA_CFLAGS += -DPAGEBUF_TRACE 51 EXTRA_CFLAGS += -DPAGEBUF_TRACE
52 # EXTRA_CFLAGS += -DXFS_VNODE_TRACE 52 EXTRA_CFLAGS += -DXFS_VNODE_TRACE
53endif 53endif
54 54
55obj-$(CONFIG_XFS_FS) += xfs.o 55obj-$(CONFIG_XFS_FS) += xfs.o
diff --git a/fs/xfs/linux-2.6/xfs_aops.c b/fs/xfs/linux-2.6/xfs_aops.c
index 76a84758073a..93ce257cd149 100644
--- a/fs/xfs/linux-2.6/xfs_aops.c
+++ b/fs/xfs/linux-2.6/xfs_aops.c
@@ -558,7 +558,8 @@ xfs_submit_page(
558 int i; 558 int i;
559 559
560 BUG_ON(PageWriteback(page)); 560 BUG_ON(PageWriteback(page));
561 set_page_writeback(page); 561 if (bh_count)
562 set_page_writeback(page);
562 if (clear_dirty) 563 if (clear_dirty)
563 clear_page_dirty(page); 564 clear_page_dirty(page);
564 unlock_page(page); 565 unlock_page(page);
@@ -578,9 +579,6 @@ xfs_submit_page(
578 579
579 if (probed_page && clear_dirty) 580 if (probed_page && clear_dirty)
580 wbc->nr_to_write--; /* Wrote an "extra" page */ 581 wbc->nr_to_write--; /* Wrote an "extra" page */
581 } else {
582 end_page_writeback(page);
583 wbc->pages_skipped++; /* We didn't write this page */
584 } 582 }
585} 583}
586 584
@@ -602,21 +600,26 @@ xfs_convert_page(
602{ 600{
603 struct buffer_head *bh_arr[MAX_BUF_PER_PAGE], *bh, *head; 601 struct buffer_head *bh_arr[MAX_BUF_PER_PAGE], *bh, *head;
604 xfs_iomap_t *mp = iomapp, *tmp; 602 xfs_iomap_t *mp = iomapp, *tmp;
605 unsigned long end, offset; 603 unsigned long offset, end_offset;
606 pgoff_t end_index; 604 int index = 0;
607 int i = 0, index = 0;
608 int bbits = inode->i_blkbits; 605 int bbits = inode->i_blkbits;
606 int len, page_dirty;
609 607
610 end_index = i_size_read(inode) >> PAGE_CACHE_SHIFT; 608 end_offset = (i_size_read(inode) & (PAGE_CACHE_SIZE - 1));
611 if (page->index < end_index) { 609
612 end = PAGE_CACHE_SIZE; 610 /*
613 } else { 611 * page_dirty is initially a count of buffers on the page before
614 end = i_size_read(inode) & (PAGE_CACHE_SIZE-1); 612 * EOF and is decrememted as we move each into a cleanable state.
615 } 613 */
614 len = 1 << inode->i_blkbits;
615 end_offset = max(end_offset, PAGE_CACHE_SIZE);
616 end_offset = roundup(end_offset, len);
617 page_dirty = end_offset / len;
618
619 offset = 0;
616 bh = head = page_buffers(page); 620 bh = head = page_buffers(page);
617 do { 621 do {
618 offset = i << bbits; 622 if (offset >= end_offset)
619 if (offset >= end)
620 break; 623 break;
621 if (!(PageUptodate(page) || buffer_uptodate(bh))) 624 if (!(PageUptodate(page) || buffer_uptodate(bh)))
622 continue; 625 continue;
@@ -625,6 +628,7 @@ xfs_convert_page(
625 if (startio) { 628 if (startio) {
626 lock_buffer(bh); 629 lock_buffer(bh);
627 bh_arr[index++] = bh; 630 bh_arr[index++] = bh;
631 page_dirty--;
628 } 632 }
629 continue; 633 continue;
630 } 634 }
@@ -657,10 +661,11 @@ xfs_convert_page(
657 unlock_buffer(bh); 661 unlock_buffer(bh);
658 mark_buffer_dirty(bh); 662 mark_buffer_dirty(bh);
659 } 663 }
660 } while (i++, (bh = bh->b_this_page) != head); 664 page_dirty--;
665 } while (offset += len, (bh = bh->b_this_page) != head);
661 666
662 if (startio) { 667 if (startio && index) {
663 xfs_submit_page(page, wbc, bh_arr, index, 1, index == i); 668 xfs_submit_page(page, wbc, bh_arr, index, 1, !page_dirty);
664 } else { 669 } else {
665 unlock_page(page); 670 unlock_page(page);
666 } 671 }
@@ -725,8 +730,11 @@ xfs_page_state_convert(
725 __uint64_t end_offset; 730 __uint64_t end_offset;
726 pgoff_t end_index, last_index, tlast; 731 pgoff_t end_index, last_index, tlast;
727 int len, err, i, cnt = 0, uptodate = 1; 732 int len, err, i, cnt = 0, uptodate = 1;
728 int flags = startio ? 0 : BMAPI_TRYLOCK; 733 int flags;
729 int page_dirty, delalloc = 0; 734 int page_dirty;
735
736 /* wait for other IO threads? */
737 flags = (startio && wbc->sync_mode != WB_SYNC_NONE) ? 0 : BMAPI_TRYLOCK;
730 738
731 /* Is this page beyond the end of the file? */ 739 /* Is this page beyond the end of the file? */
732 offset = i_size_read(inode); 740 offset = i_size_read(inode);
@@ -740,19 +748,22 @@ xfs_page_state_convert(
740 } 748 }
741 } 749 }
742 750
743 offset = (loff_t)page->index << PAGE_CACHE_SHIFT;
744 end_offset = min_t(unsigned long long, 751 end_offset = min_t(unsigned long long,
745 offset + PAGE_CACHE_SIZE, i_size_read(inode)); 752 (loff_t)(page->index + 1) << PAGE_CACHE_SHIFT, offset);
746 753 offset = (loff_t)page->index << PAGE_CACHE_SHIFT;
747 bh = head = page_buffers(page);
748 iomp = NULL;
749 754
750 /* 755 /*
751 * page_dirty is initially a count of buffers on the page and 756 * page_dirty is initially a count of buffers on the page before
752 * is decrememted as we move each into a cleanable state. 757 * EOF and is decrememted as we move each into a cleanable state.
753 */ 758 */
754 len = bh->b_size; 759 len = 1 << inode->i_blkbits;
755 page_dirty = PAGE_CACHE_SIZE / len; 760 p_offset = max(p_offset, PAGE_CACHE_SIZE);
761 p_offset = roundup(p_offset, len);
762 page_dirty = p_offset / len;
763
764 iomp = NULL;
765 p_offset = 0;
766 bh = head = page_buffers(page);
756 767
757 do { 768 do {
758 if (offset >= end_offset) 769 if (offset >= end_offset)
@@ -804,7 +815,6 @@ xfs_page_state_convert(
804 */ 815 */
805 } else if (buffer_delay(bh)) { 816 } else if (buffer_delay(bh)) {
806 if (!iomp) { 817 if (!iomp) {
807 delalloc = 1;
808 err = xfs_map_blocks(inode, offset, len, &iomap, 818 err = xfs_map_blocks(inode, offset, len, &iomap,
809 BMAPI_ALLOCATE | flags); 819 BMAPI_ALLOCATE | flags);
810 if (err) { 820 if (err) {
@@ -875,14 +885,14 @@ xfs_page_state_convert(
875 if (uptodate && bh == head) 885 if (uptodate && bh == head)
876 SetPageUptodate(page); 886 SetPageUptodate(page);
877 887
878 if (startio) 888 if (startio) {
879 xfs_submit_page(page, wbc, bh_arr, cnt, 0, 1); 889 xfs_submit_page(page, wbc, bh_arr, cnt, 0, !page_dirty);
890 }
880 891
881 if (iomp) { 892 if (iomp) {
882 tlast = (iomp->iomap_offset + iomp->iomap_bsize - 1) >> 893 offset = (iomp->iomap_offset + iomp->iomap_bsize - 1) >>
883 PAGE_CACHE_SHIFT; 894 PAGE_CACHE_SHIFT;
884 if (delalloc && (tlast > last_index)) 895 tlast = min_t(pgoff_t, offset, last_index);
885 tlast = last_index;
886 xfs_cluster_write(inode, page->index + 1, iomp, wbc, 896 xfs_cluster_write(inode, page->index + 1, iomp, wbc,
887 startio, unmapped, tlast); 897 startio, unmapped, tlast);
888 } 898 }
diff --git a/fs/xfs/linux-2.6/xfs_buf.c b/fs/xfs/linux-2.6/xfs_buf.c
index 23e0eb67fc25..997963e53622 100644
--- a/fs/xfs/linux-2.6/xfs_buf.c
+++ b/fs/xfs/linux-2.6/xfs_buf.c
@@ -1746,13 +1746,15 @@ STATIC DECLARE_COMPLETION(pagebuf_daemon_done);
1746STATIC struct task_struct *pagebuf_daemon_task; 1746STATIC struct task_struct *pagebuf_daemon_task;
1747STATIC int pagebuf_daemon_active; 1747STATIC int pagebuf_daemon_active;
1748STATIC int force_flush; 1748STATIC int force_flush;
1749 1749STATIC int force_sleep;
1750 1750
1751STATIC int 1751STATIC int
1752pagebuf_daemon_wakeup( 1752pagebuf_daemon_wakeup(
1753 int priority, 1753 int priority,
1754 unsigned int mask) 1754 unsigned int mask)
1755{ 1755{
1756 if (force_sleep)
1757 return 0;
1756 force_flush = 1; 1758 force_flush = 1;
1757 barrier(); 1759 barrier();
1758 wake_up_process(pagebuf_daemon_task); 1760 wake_up_process(pagebuf_daemon_task);
@@ -1778,7 +1780,12 @@ pagebuf_daemon(
1778 1780
1779 INIT_LIST_HEAD(&tmp); 1781 INIT_LIST_HEAD(&tmp);
1780 do { 1782 do {
1781 try_to_freeze(PF_FREEZE); 1783 if (unlikely(current->flags & PF_FREEZE)) {
1784 force_sleep = 1;
1785 refrigerator(PF_FREEZE);
1786 } else {
1787 force_sleep = 0;
1788 }
1782 1789
1783 set_current_state(TASK_INTERRUPTIBLE); 1790 set_current_state(TASK_INTERRUPTIBLE);
1784 schedule_timeout((xfs_buf_timer_centisecs * HZ) / 100); 1791 schedule_timeout((xfs_buf_timer_centisecs * HZ) / 100);
diff --git a/fs/xfs/linux-2.6/xfs_file.c b/fs/xfs/linux-2.6/xfs_file.c
index 9f057a4a5b06..24fa3b101b93 100644
--- a/fs/xfs/linux-2.6/xfs_file.c
+++ b/fs/xfs/linux-2.6/xfs_file.c
@@ -515,10 +515,49 @@ open_exec_out:
515} 515}
516#endif /* HAVE_FOP_OPEN_EXEC */ 516#endif /* HAVE_FOP_OPEN_EXEC */
517 517
518/*
519 * Temporary workaround to the AIO direct IO write problem.
520 * This code can go and we can revert to do_sync_write once
521 * the writepage(s) rework is merged.
522 */
523STATIC ssize_t
524linvfs_write(
525 struct file *filp,
526 const char __user *buf,
527 size_t len,
528 loff_t *ppos)
529{
530 struct kiocb kiocb;
531 ssize_t ret;
532
533 init_sync_kiocb(&kiocb, filp);
534 kiocb.ki_pos = *ppos;
535 ret = __linvfs_write(&kiocb, buf, 0, len, kiocb.ki_pos);
536 *ppos = kiocb.ki_pos;
537 return ret;
538}
539STATIC ssize_t
540linvfs_write_invis(
541 struct file *filp,
542 const char __user *buf,
543 size_t len,
544 loff_t *ppos)
545{
546 struct kiocb kiocb;
547 ssize_t ret;
548
549 init_sync_kiocb(&kiocb, filp);
550 kiocb.ki_pos = *ppos;
551 ret = __linvfs_write(&kiocb, buf, IO_INVIS, len, kiocb.ki_pos);
552 *ppos = kiocb.ki_pos;
553 return ret;
554}
555
556
518struct file_operations linvfs_file_operations = { 557struct file_operations linvfs_file_operations = {
519 .llseek = generic_file_llseek, 558 .llseek = generic_file_llseek,
520 .read = do_sync_read, 559 .read = do_sync_read,
521 .write = do_sync_write, 560 .write = linvfs_write,
522 .readv = linvfs_readv, 561 .readv = linvfs_readv,
523 .writev = linvfs_writev, 562 .writev = linvfs_writev,
524 .aio_read = linvfs_aio_read, 563 .aio_read = linvfs_aio_read,
@@ -526,7 +565,7 @@ struct file_operations linvfs_file_operations = {
526 .sendfile = linvfs_sendfile, 565 .sendfile = linvfs_sendfile,
527 .unlocked_ioctl = linvfs_ioctl, 566 .unlocked_ioctl = linvfs_ioctl,
528#ifdef CONFIG_COMPAT 567#ifdef CONFIG_COMPAT
529 .compat_ioctl = xfs_compat_ioctl, 568 .compat_ioctl = linvfs_compat_ioctl,
530#endif 569#endif
531 .mmap = linvfs_file_mmap, 570 .mmap = linvfs_file_mmap,
532 .open = linvfs_open, 571 .open = linvfs_open,
@@ -540,7 +579,7 @@ struct file_operations linvfs_file_operations = {
540struct file_operations linvfs_invis_file_operations = { 579struct file_operations linvfs_invis_file_operations = {
541 .llseek = generic_file_llseek, 580 .llseek = generic_file_llseek,
542 .read = do_sync_read, 581 .read = do_sync_read,
543 .write = do_sync_write, 582 .write = linvfs_write_invis,
544 .readv = linvfs_readv_invis, 583 .readv = linvfs_readv_invis,
545 .writev = linvfs_writev_invis, 584 .writev = linvfs_writev_invis,
546 .aio_read = linvfs_aio_read_invis, 585 .aio_read = linvfs_aio_read_invis,
@@ -548,7 +587,7 @@ struct file_operations linvfs_invis_file_operations = {
548 .sendfile = linvfs_sendfile, 587 .sendfile = linvfs_sendfile,
549 .unlocked_ioctl = linvfs_ioctl_invis, 588 .unlocked_ioctl = linvfs_ioctl_invis,
550#ifdef CONFIG_COMPAT 589#ifdef CONFIG_COMPAT
551 .compat_ioctl = xfs_compat_invis_ioctl, 590 .compat_ioctl = linvfs_compat_invis_ioctl,
552#endif 591#endif
553 .mmap = linvfs_file_mmap, 592 .mmap = linvfs_file_mmap,
554 .open = linvfs_open, 593 .open = linvfs_open,
@@ -561,6 +600,9 @@ struct file_operations linvfs_dir_operations = {
561 .read = generic_read_dir, 600 .read = generic_read_dir,
562 .readdir = linvfs_readdir, 601 .readdir = linvfs_readdir,
563 .unlocked_ioctl = linvfs_ioctl, 602 .unlocked_ioctl = linvfs_ioctl,
603#ifdef CONFIG_COMPAT
604 .compat_ioctl = linvfs_compat_ioctl,
605#endif
564 .fsync = linvfs_fsync, 606 .fsync = linvfs_fsync,
565}; 607};
566 608
diff --git a/fs/xfs/linux-2.6/xfs_ioctl32.c b/fs/xfs/linux-2.6/xfs_ioctl32.c
index 7a12c83184f5..0f8f1384eb36 100644
--- a/fs/xfs/linux-2.6/xfs_ioctl32.c
+++ b/fs/xfs/linux-2.6/xfs_ioctl32.c
@@ -1,5 +1,5 @@
1/* 1/*
2 * Copyright (c) 2004 Silicon Graphics, Inc. All Rights Reserved. 2 * Copyright (c) 2004-2005 Silicon Graphics, Inc. All Rights Reserved.
3 * 3 *
4 * This program is free software; you can redistribute it and/or modify it 4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of version 2 of the GNU General Public License as 5 * under the terms of version 2 of the GNU General Public License as
@@ -58,8 +58,9 @@ typedef struct xfs_fsop_bulkreq32 {
58 __s32 ocount; /* output count pointer */ 58 __s32 ocount; /* output count pointer */
59} xfs_fsop_bulkreq32_t; 59} xfs_fsop_bulkreq32_t;
60 60
61static unsigned long 61STATIC unsigned long
62xfs_ioctl32_bulkstat(unsigned long arg) 62xfs_ioctl32_bulkstat(
63 unsigned long arg)
63{ 64{
64 xfs_fsop_bulkreq32_t __user *p32 = (void __user *)arg; 65 xfs_fsop_bulkreq32_t __user *p32 = (void __user *)arg;
65 xfs_fsop_bulkreq_t __user *p = compat_alloc_user_space(sizeof(*p)); 66 xfs_fsop_bulkreq_t __user *p = compat_alloc_user_space(sizeof(*p));
@@ -78,11 +79,11 @@ xfs_ioctl32_bulkstat(unsigned long arg)
78} 79}
79#endif 80#endif
80 81
81static long 82STATIC long
82__xfs_compat_ioctl(int mode, struct file *f, unsigned cmd, unsigned long arg) 83__linvfs_compat_ioctl(int mode, struct file *f, unsigned cmd, unsigned long arg)
83{ 84{
84 int error; 85 int error;
85 struct inode *inode = f->f_dentry->d_inode; 86 struct inode *inode = f->f_dentry->d_inode;
86 vnode_t *vp = LINVFS_GET_VP(inode); 87 vnode_t *vp = LINVFS_GET_VP(inode);
87 88
88 switch (cmd) { 89 switch (cmd) {
@@ -152,12 +153,20 @@ __xfs_compat_ioctl(int mode, struct file *f, unsigned cmd, unsigned long arg)
152 return error; 153 return error;
153} 154}
154 155
155long xfs_compat_ioctl(struct file *f, unsigned cmd, unsigned long arg) 156long
157linvfs_compat_ioctl(
158 struct file *f,
159 unsigned cmd,
160 unsigned long arg)
156{ 161{
157 return __xfs_compat_ioctl(0, f, cmd, arg); 162 return __linvfs_compat_ioctl(0, f, cmd, arg);
158} 163}
159 164
160long xfs_compat_invis_ioctl(struct file *f, unsigned cmd, unsigned long arg) 165long
166linvfs_compat_invis_ioctl(
167 struct file *f,
168 unsigned cmd,
169 unsigned long arg)
161{ 170{
162 return __xfs_compat_ioctl(IO_INVIS, f, cmd, arg); 171 return __linvfs_compat_ioctl(IO_INVIS, f, cmd, arg);
163} 172}
diff --git a/fs/xfs/linux-2.6/xfs_ioctl32.h b/fs/xfs/linux-2.6/xfs_ioctl32.h
index 779f69a48116..c874793a1dc9 100644
--- a/fs/xfs/linux-2.6/xfs_ioctl32.h
+++ b/fs/xfs/linux-2.6/xfs_ioctl32.h
@@ -1,5 +1,5 @@
1/* 1/*
2 * Copyright (c) 2004 Silicon Graphics, Inc. All Rights Reserved. 2 * Copyright (c) 2004-2005 Silicon Graphics, Inc. All Rights Reserved.
3 * 3 *
4 * This program is free software; you can redistribute it and/or modify it 4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of version 2 of the GNU General Public License as 5 * under the terms of version 2 of the GNU General Public License as
@@ -30,5 +30,5 @@
30 * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/ 30 * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
31 */ 31 */
32 32
33long xfs_compat_ioctl(struct file *f, unsigned cmd, unsigned long arg); 33long linvfs_compat_ioctl(struct file *f, unsigned cmd, unsigned long arg);
34long xfs_compat_invis_ioctl(struct file *f, unsigned cmd, unsigned long arg); 34long linvfs_compat_invis_ioctl(struct file *f, unsigned cmd, unsigned long arg);
diff --git a/fs/xfs/linux-2.6/xfs_lrw.c b/fs/xfs/linux-2.6/xfs_lrw.c
index ff145fd0d1a4..aa9daaea6c34 100644
--- a/fs/xfs/linux-2.6/xfs_lrw.c
+++ b/fs/xfs/linux-2.6/xfs_lrw.c
@@ -683,6 +683,9 @@ xfs_write(
683 (xip->i_d.di_flags & XFS_DIFLAG_REALTIME) ? 683 (xip->i_d.di_flags & XFS_DIFLAG_REALTIME) ?
684 mp->m_rtdev_targp : mp->m_ddev_targp; 684 mp->m_rtdev_targp : mp->m_ddev_targp;
685 685
686 if (ioflags & IO_ISAIO)
687 return XFS_ERROR(-ENOSYS);
688
686 if ((pos & target->pbr_smask) || (count & target->pbr_smask)) 689 if ((pos & target->pbr_smask) || (count & target->pbr_smask))
687 return XFS_ERROR(-EINVAL); 690 return XFS_ERROR(-EINVAL);
688 691
diff --git a/fs/xfs/linux-2.6/xfs_super.c b/fs/xfs/linux-2.6/xfs_super.c
index 53dc658cafa6..455e2b2fb964 100644
--- a/fs/xfs/linux-2.6/xfs_super.c
+++ b/fs/xfs/linux-2.6/xfs_super.c
@@ -1,5 +1,5 @@
1/* 1/*
2 * Copyright (c) 2000-2004 Silicon Graphics, Inc. All Rights Reserved. 2 * Copyright (c) 2000-2005 Silicon Graphics, Inc. All Rights Reserved.
3 * 3 *
4 * This program is free software; you can redistribute it and/or modify it 4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of version 2 of the GNU General Public License as 5 * under the terms of version 2 of the GNU General Public License as
@@ -66,7 +66,6 @@
66#include "xfs_buf_item.h" 66#include "xfs_buf_item.h"
67#include "xfs_utils.h" 67#include "xfs_utils.h"
68#include "xfs_version.h" 68#include "xfs_version.h"
69#include "xfs_ioctl32.h"
70 69
71#include <linux/namei.h> 70#include <linux/namei.h>
72#include <linux/init.h> 71#include <linux/init.h>
diff --git a/fs/xfs/linux-2.6/xfs_vnode.c b/fs/xfs/linux-2.6/xfs_vnode.c
index 849c61c74f3c..a832d165f24f 100644
--- a/fs/xfs/linux-2.6/xfs_vnode.c
+++ b/fs/xfs/linux-2.6/xfs_vnode.c
@@ -156,7 +156,6 @@ vn_initialize(
156 156
157#ifdef XFS_VNODE_TRACE 157#ifdef XFS_VNODE_TRACE
158 vp->v_trace = ktrace_alloc(VNODE_TRACE_SIZE, KM_SLEEP); 158 vp->v_trace = ktrace_alloc(VNODE_TRACE_SIZE, KM_SLEEP);
159 printk("Allocated VNODE_TRACE at 0x%p\n", vp->v_trace);
160#endif /* XFS_VNODE_TRACE */ 159#endif /* XFS_VNODE_TRACE */
161 160
162 vn_trace_exit(vp, "vn_initialize", (inst_t *)__return_address); 161 vn_trace_exit(vp, "vn_initialize", (inst_t *)__return_address);
@@ -424,13 +423,13 @@ vn_remove(
424 * Vnode tracing code. 423 * Vnode tracing code.
425 */ 424 */
426void 425void
427vn_trace_entry(vnode_t *vp, char *func, inst_t *ra) 426vn_trace_entry(vnode_t *vp, const char *func, inst_t *ra)
428{ 427{
429 KTRACE_ENTER(vp, VNODE_KTRACE_ENTRY, func, 0, ra); 428 KTRACE_ENTER(vp, VNODE_KTRACE_ENTRY, func, 0, ra);
430} 429}
431 430
432void 431void
433vn_trace_exit(vnode_t *vp, char *func, inst_t *ra) 432vn_trace_exit(vnode_t *vp, const char *func, inst_t *ra)
434{ 433{
435 KTRACE_ENTER(vp, VNODE_KTRACE_EXIT, func, 0, ra); 434 KTRACE_ENTER(vp, VNODE_KTRACE_EXIT, func, 0, ra);
436} 435}
diff --git a/fs/xfs/linux-2.6/xfs_vnode.h b/fs/xfs/linux-2.6/xfs_vnode.h
index da76c1f1e11c..00466c3194ac 100644
--- a/fs/xfs/linux-2.6/xfs_vnode.h
+++ b/fs/xfs/linux-2.6/xfs_vnode.h
@@ -86,10 +86,11 @@ typedef struct vnode {
86 vnumber_t v_number; /* in-core vnode number */ 86 vnumber_t v_number; /* in-core vnode number */
87 vn_bhv_head_t v_bh; /* behavior head */ 87 vn_bhv_head_t v_bh; /* behavior head */
88 spinlock_t v_lock; /* VN_LOCK/VN_UNLOCK */ 88 spinlock_t v_lock; /* VN_LOCK/VN_UNLOCK */
89 struct inode v_inode; /* Linux inode */
90#ifdef XFS_VNODE_TRACE 89#ifdef XFS_VNODE_TRACE
91 struct ktrace *v_trace; /* trace header structure */ 90 struct ktrace *v_trace; /* trace header structure */
92#endif 91#endif
92 struct inode v_inode; /* Linux inode */
93 /* inode MUST be last */
93} vnode_t; 94} vnode_t;
94 95
95#define v_fbhv v_bh.bh_first /* first behavior */ 96#define v_fbhv v_bh.bh_first /* first behavior */
@@ -409,7 +410,7 @@ typedef struct vattr {
409 int va_mask; /* bit-mask of attributes present */ 410 int va_mask; /* bit-mask of attributes present */
410 enum vtype va_type; /* vnode type (for create) */ 411 enum vtype va_type; /* vnode type (for create) */
411 mode_t va_mode; /* file access mode and type */ 412 mode_t va_mode; /* file access mode and type */
412 nlink_t va_nlink; /* number of references to file */ 413 xfs_nlink_t va_nlink; /* number of references to file */
413 uid_t va_uid; /* owner user id */ 414 uid_t va_uid; /* owner user id */
414 gid_t va_gid; /* owner group id */ 415 gid_t va_gid; /* owner group id */
415 xfs_ino_t va_nodeid; /* file id */ 416 xfs_ino_t va_nodeid; /* file id */
@@ -625,6 +626,7 @@ static inline int VN_BAD(struct vnode *vp)
625#define ATTR_DMI 0x08 /* invocation from a DMI function */ 626#define ATTR_DMI 0x08 /* invocation from a DMI function */
626#define ATTR_LAZY 0x80 /* set/get attributes lazily */ 627#define ATTR_LAZY 0x80 /* set/get attributes lazily */
627#define ATTR_NONBLOCK 0x100 /* return EAGAIN if operation would block */ 628#define ATTR_NONBLOCK 0x100 /* return EAGAIN if operation would block */
629#define ATTR_NOLOCK 0x200 /* Don't grab any conflicting locks */
628 630
629/* 631/*
630 * Flags to VOP_FSYNC and VOP_RECLAIM. 632 * Flags to VOP_FSYNC and VOP_RECLAIM.
@@ -646,8 +648,8 @@ static inline int VN_BAD(struct vnode *vp)
646#define VNODE_KTRACE_REF 4 648#define VNODE_KTRACE_REF 4
647#define VNODE_KTRACE_RELE 5 649#define VNODE_KTRACE_RELE 5
648 650
649extern void vn_trace_entry(struct vnode *, char *, inst_t *); 651extern void vn_trace_entry(struct vnode *, const char *, inst_t *);
650extern void vn_trace_exit(struct vnode *, char *, inst_t *); 652extern void vn_trace_exit(struct vnode *, const char *, inst_t *);
651extern void vn_trace_hold(struct vnode *, char *, int, inst_t *); 653extern void vn_trace_hold(struct vnode *, char *, int, inst_t *);
652extern void vn_trace_ref(struct vnode *, char *, int, inst_t *); 654extern void vn_trace_ref(struct vnode *, char *, int, inst_t *);
653extern void vn_trace_rele(struct vnode *, char *, int, inst_t *); 655extern void vn_trace_rele(struct vnode *, char *, int, inst_t *);
diff --git a/fs/xfs/xfs_dfrag.c b/fs/xfs/xfs_dfrag.c
index 08d551a17347..63abdc2ac7f4 100644
--- a/fs/xfs/xfs_dfrag.c
+++ b/fs/xfs/xfs_dfrag.c
@@ -182,7 +182,7 @@ xfs_swapext(
182 182
183 if (VN_CACHED(tvp) != 0) 183 if (VN_CACHED(tvp) != 0)
184 xfs_inval_cached_pages(XFS_ITOV(tip), &(tip->i_iocore), 184 xfs_inval_cached_pages(XFS_ITOV(tip), &(tip->i_iocore),
185 (loff_t)0, 0, 0); 185 (xfs_off_t)0, 0, 0);
186 186
187 /* Verify O_DIRECT for ftmp */ 187 /* Verify O_DIRECT for ftmp */
188 if (VN_CACHED(tvp) != 0) { 188 if (VN_CACHED(tvp) != 0) {
diff --git a/fs/xfs/xfs_iget.c b/fs/xfs/xfs_iget.c
index 3a0ba1dfd0e8..d3da00045f26 100644
--- a/fs/xfs/xfs_iget.c
+++ b/fs/xfs/xfs_iget.c
@@ -136,6 +136,40 @@ xfs_chash_free(xfs_mount_t *mp)
136} 136}
137 137
138/* 138/*
139 * Try to move an inode to the front of its hash list if possible
140 * (and if its not there already). Called right after obtaining
141 * the list version number and then dropping the read_lock on the
142 * hash list in question (which is done right after looking up the
143 * inode in question...).
144 */
145STATIC void
146xfs_ihash_promote(
147 xfs_ihash_t *ih,
148 xfs_inode_t *ip,
149 ulong version)
150{
151 xfs_inode_t *iq;
152
153 if ((ip->i_prevp != &ih->ih_next) && write_trylock(&ih->ih_lock)) {
154 if (likely(version == ih->ih_version)) {
155 /* remove from list */
156 if ((iq = ip->i_next)) {
157 iq->i_prevp = ip->i_prevp;
158 }
159 *ip->i_prevp = iq;
160
161 /* insert at list head */
162 iq = ih->ih_next;
163 iq->i_prevp = &ip->i_next;
164 ip->i_next = iq;
165 ip->i_prevp = &ih->ih_next;
166 ih->ih_next = ip;
167 }
168 write_unlock(&ih->ih_lock);
169 }
170}
171
172/*
139 * Look up an inode by number in the given file system. 173 * Look up an inode by number in the given file system.
140 * The inode is looked up in the hash table for the file system 174 * The inode is looked up in the hash table for the file system
141 * represented by the mount point parameter mp. Each bucket of 175 * represented by the mount point parameter mp. Each bucket of
@@ -229,7 +263,9 @@ again:
229 XFS_STATS_INC(xs_ig_found); 263 XFS_STATS_INC(xs_ig_found);
230 264
231 ip->i_flags &= ~XFS_IRECLAIMABLE; 265 ip->i_flags &= ~XFS_IRECLAIMABLE;
266 version = ih->ih_version;
232 read_unlock(&ih->ih_lock); 267 read_unlock(&ih->ih_lock);
268 xfs_ihash_promote(ih, ip, version);
233 269
234 XFS_MOUNT_ILOCK(mp); 270 XFS_MOUNT_ILOCK(mp);
235 list_del_init(&ip->i_reclaim); 271 list_del_init(&ip->i_reclaim);
@@ -259,8 +295,15 @@ again:
259 inode_vp, vp); 295 inode_vp, vp);
260 } 296 }
261 297
298 /*
299 * Inode cache hit: if ip is not at the front of
300 * its hash chain, move it there now.
301 * Do this with the lock held for update, but
302 * do statistics after releasing the lock.
303 */
304 version = ih->ih_version;
262 read_unlock(&ih->ih_lock); 305 read_unlock(&ih->ih_lock);
263 306 xfs_ihash_promote(ih, ip, version);
264 XFS_STATS_INC(xs_ig_found); 307 XFS_STATS_INC(xs_ig_found);
265 308
266finish_inode: 309finish_inode:
@@ -547,6 +590,7 @@ xfs_inode_incore(xfs_mount_t *mp,
547{ 590{
548 xfs_ihash_t *ih; 591 xfs_ihash_t *ih;
549 xfs_inode_t *ip; 592 xfs_inode_t *ip;
593 ulong version;
550 594
551 ih = XFS_IHASH(mp, ino); 595 ih = XFS_IHASH(mp, ino);
552 read_lock(&ih->ih_lock); 596 read_lock(&ih->ih_lock);
@@ -554,11 +598,15 @@ xfs_inode_incore(xfs_mount_t *mp,
554 if (ip->i_ino == ino) { 598 if (ip->i_ino == ino) {
555 /* 599 /*
556 * If we find it and tp matches, return it. 600 * If we find it and tp matches, return it.
601 * Also move it to the front of the hash list
602 * if we find it and it is not already there.
557 * Otherwise break from the loop and return 603 * Otherwise break from the loop and return
558 * NULL. 604 * NULL.
559 */ 605 */
560 if (ip->i_transp == tp) { 606 if (ip->i_transp == tp) {
607 version = ih->ih_version;
561 read_unlock(&ih->ih_lock); 608 read_unlock(&ih->ih_lock);
609 xfs_ihash_promote(ih, ip, version);
562 return (ip); 610 return (ip);
563 } 611 }
564 break; 612 break;
@@ -685,6 +733,7 @@ xfs_iextract(
685 iq->i_prevp = ip->i_prevp; 733 iq->i_prevp = ip->i_prevp;
686 } 734 }
687 *ip->i_prevp = iq; 735 *ip->i_prevp = iq;
736 ih->ih_version++;
688 write_unlock(&ih->ih_lock); 737 write_unlock(&ih->ih_lock);
689 738
690 /* 739 /*
diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c
index 43c632ab86ad..bc8c8c7f9039 100644
--- a/fs/xfs/xfs_inode.c
+++ b/fs/xfs/xfs_inode.c
@@ -1130,7 +1130,7 @@ xfs_ialloc(
1130 xfs_trans_t *tp, 1130 xfs_trans_t *tp,
1131 xfs_inode_t *pip, 1131 xfs_inode_t *pip,
1132 mode_t mode, 1132 mode_t mode,
1133 nlink_t nlink, 1133 xfs_nlink_t nlink,
1134 xfs_dev_t rdev, 1134 xfs_dev_t rdev,
1135 cred_t *cr, 1135 cred_t *cr,
1136 xfs_prid_t prid, 1136 xfs_prid_t prid,
diff --git a/fs/xfs/xfs_inode.h b/fs/xfs/xfs_inode.h
index a53b1ccf6070..37e1c316f3b6 100644
--- a/fs/xfs/xfs_inode.h
+++ b/fs/xfs/xfs_inode.h
@@ -495,9 +495,9 @@ int xfs_itobp(struct xfs_mount *, struct xfs_trans *,
495int xfs_iread(struct xfs_mount *, struct xfs_trans *, xfs_ino_t, 495int xfs_iread(struct xfs_mount *, struct xfs_trans *, xfs_ino_t,
496 xfs_inode_t **, xfs_daddr_t); 496 xfs_inode_t **, xfs_daddr_t);
497int xfs_iread_extents(struct xfs_trans *, xfs_inode_t *, int); 497int xfs_iread_extents(struct xfs_trans *, xfs_inode_t *, int);
498int xfs_ialloc(struct xfs_trans *, xfs_inode_t *, mode_t, nlink_t, 498int xfs_ialloc(struct xfs_trans *, xfs_inode_t *, mode_t,
499 xfs_dev_t, struct cred *, xfs_prid_t, int, 499 xfs_nlink_t, xfs_dev_t, struct cred *, xfs_prid_t,
500 struct xfs_buf **, boolean_t *, xfs_inode_t **); 500 int, struct xfs_buf **, boolean_t *, xfs_inode_t **);
501void xfs_xlate_dinode_core(xfs_caddr_t, struct xfs_dinode_core *, 501void xfs_xlate_dinode_core(xfs_caddr_t, struct xfs_dinode_core *,
502 int); 502 int);
503uint xfs_ip2xflags(struct xfs_inode *); 503uint xfs_ip2xflags(struct xfs_inode *);
diff --git a/fs/xfs/xfs_iomap.c b/fs/xfs/xfs_iomap.c
index 3826e8f0e28a..469e1a7939d4 100644
--- a/fs/xfs/xfs_iomap.c
+++ b/fs/xfs/xfs_iomap.c
@@ -278,7 +278,9 @@ phase2:
278 switch (flags & (BMAPI_WRITE|BMAPI_ALLOCATE|BMAPI_UNWRITTEN)) { 278 switch (flags & (BMAPI_WRITE|BMAPI_ALLOCATE|BMAPI_UNWRITTEN)) {
279 case BMAPI_WRITE: 279 case BMAPI_WRITE:
280 /* If we found an extent, return it */ 280 /* If we found an extent, return it */
281 if (nimaps && (imap.br_startblock != HOLESTARTBLOCK)) { 281 if (nimaps &&
282 (imap.br_startblock != HOLESTARTBLOCK) &&
283 (imap.br_startblock != DELAYSTARTBLOCK)) {
282 xfs_iomap_map_trace(XFS_IOMAP_WRITE_MAP, io, 284 xfs_iomap_map_trace(XFS_IOMAP_WRITE_MAP, io,
283 offset, count, iomapp, &imap, flags); 285 offset, count, iomapp, &imap, flags);
284 break; 286 break;
@@ -308,7 +310,8 @@ phase2:
308 break; 310 break;
309 } 311 }
310 312
311 error = XFS_IOMAP_WRITE_ALLOCATE(mp, io, &imap, &nimaps); 313 error = XFS_IOMAP_WRITE_ALLOCATE(mp, io, offset, count,
314 &imap, &nimaps);
312 break; 315 break;
313 case BMAPI_UNWRITTEN: 316 case BMAPI_UNWRITTEN:
314 lockmode = 0; 317 lockmode = 0;
@@ -365,7 +368,7 @@ xfs_flush_space(
365int 368int
366xfs_iomap_write_direct( 369xfs_iomap_write_direct(
367 xfs_inode_t *ip, 370 xfs_inode_t *ip,
368 loff_t offset, 371 xfs_off_t offset,
369 size_t count, 372 size_t count,
370 int flags, 373 int flags,
371 xfs_bmbt_irec_t *ret_imap, 374 xfs_bmbt_irec_t *ret_imap,
@@ -541,7 +544,7 @@ error_out:
541int 544int
542xfs_iomap_write_delay( 545xfs_iomap_write_delay(
543 xfs_inode_t *ip, 546 xfs_inode_t *ip,
544 loff_t offset, 547 xfs_off_t offset,
545 size_t count, 548 size_t count,
546 int ioflag, 549 int ioflag,
547 xfs_bmbt_irec_t *ret_imap, 550 xfs_bmbt_irec_t *ret_imap,
@@ -746,6 +749,8 @@ write_map:
746int 749int
747xfs_iomap_write_allocate( 750xfs_iomap_write_allocate(
748 xfs_inode_t *ip, 751 xfs_inode_t *ip,
752 xfs_off_t offset,
753 size_t count,
749 xfs_bmbt_irec_t *map, 754 xfs_bmbt_irec_t *map,
750 int *retmap) 755 int *retmap)
751{ 756{
@@ -770,9 +775,9 @@ xfs_iomap_write_allocate(
770 if ((error = XFS_QM_DQATTACH(mp, ip, 0))) 775 if ((error = XFS_QM_DQATTACH(mp, ip, 0)))
771 return XFS_ERROR(error); 776 return XFS_ERROR(error);
772 777
773 offset_fsb = map->br_startoff; 778 offset_fsb = XFS_B_TO_FSBT(mp, offset);
774 count_fsb = map->br_blockcount; 779 count_fsb = map->br_blockcount;
775 map_start_fsb = offset_fsb; 780 map_start_fsb = map->br_startoff;
776 781
777 XFS_STATS_ADD(xs_xstrat_bytes, XFS_FSB_TO_B(mp, count_fsb)); 782 XFS_STATS_ADD(xs_xstrat_bytes, XFS_FSB_TO_B(mp, count_fsb));
778 783
@@ -868,9 +873,9 @@ xfs_iomap_write_allocate(
868 imap[i].br_startoff, 873 imap[i].br_startoff,
869 imap[i].br_blockcount,imap[i].br_state); 874 imap[i].br_blockcount,imap[i].br_state);
870 } 875 }
871 if ((map->br_startoff >= imap[i].br_startoff) && 876 if ((offset_fsb >= imap[i].br_startoff) &&
872 (map->br_startoff < (imap[i].br_startoff + 877 (offset_fsb < (imap[i].br_startoff +
873 imap[i].br_blockcount))) { 878 imap[i].br_blockcount))) {
874 *map = imap[i]; 879 *map = imap[i];
875 *retmap = 1; 880 *retmap = 1;
876 XFS_STATS_INC(xs_xstrat_quick); 881 XFS_STATS_INC(xs_xstrat_quick);
@@ -883,9 +888,8 @@ xfs_iomap_write_allocate(
883 * file, just surrounding data, try again. 888 * file, just surrounding data, try again.
884 */ 889 */
885 nimaps--; 890 nimaps--;
886 offset_fsb = imap[nimaps].br_startoff + 891 map_start_fsb = imap[nimaps].br_startoff +
887 imap[nimaps].br_blockcount; 892 imap[nimaps].br_blockcount;
888 map_start_fsb = offset_fsb;
889 } 893 }
890 894
891trans_cancel: 895trans_cancel:
@@ -899,7 +903,7 @@ error0:
899int 903int
900xfs_iomap_write_unwritten( 904xfs_iomap_write_unwritten(
901 xfs_inode_t *ip, 905 xfs_inode_t *ip,
902 loff_t offset, 906 xfs_off_t offset,
903 size_t count) 907 size_t count)
904{ 908{
905 xfs_mount_t *mp = ip->i_mount; 909 xfs_mount_t *mp = ip->i_mount;
diff --git a/fs/xfs/xfs_iomap.h b/fs/xfs/xfs_iomap.h
index 31c91087cb33..4daaa5212102 100644
--- a/fs/xfs/xfs_iomap.h
+++ b/fs/xfs/xfs_iomap.h
@@ -1,5 +1,5 @@
1/* 1/*
2 * Copyright (c) 2003,2004 Silicon Graphics, Inc. All Rights Reserved. 2 * Copyright (c) 2003-2005 Silicon Graphics, Inc. All Rights Reserved.
3 * 3 *
4 * This program is free software; you can redistribute it and/or modify it 4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of version 2 of the GNU General Public License as 5 * under the terms of version 2 of the GNU General Public License as
@@ -29,9 +29,6 @@
29 * 29 *
30 * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/ 30 * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
31 */ 31 */
32
33
34
35#ifndef __XFS_IOMAP_H__ 32#ifndef __XFS_IOMAP_H__
36#define __XFS_IOMAP_H__ 33#define __XFS_IOMAP_H__
37 34
@@ -56,7 +53,7 @@ typedef enum {
56 BMAPI_UNWRITTEN = (1 << 3), /* unwritten extents to real extents */ 53 BMAPI_UNWRITTEN = (1 << 3), /* unwritten extents to real extents */
57 /* modifiers */ 54 /* modifiers */
58 BMAPI_IGNSTATE = (1 << 4), /* ignore unwritten state on read */ 55 BMAPI_IGNSTATE = (1 << 4), /* ignore unwritten state on read */
59 BMAPI_DIRECT = (1 << 5), /* direct instead of buffered write */ 56 BMAPI_DIRECT = (1 << 5), /* direct instead of buffered write */
60 BMAPI_MMAP = (1 << 6), /* allocate for mmap write */ 57 BMAPI_MMAP = (1 << 6), /* allocate for mmap write */
61 BMAPI_SYNC = (1 << 7), /* sync write to flush delalloc space */ 58 BMAPI_SYNC = (1 << 7), /* sync write to flush delalloc space */
62 BMAPI_TRYLOCK = (1 << 8), /* non-blocking request */ 59 BMAPI_TRYLOCK = (1 << 8), /* non-blocking request */
@@ -67,13 +64,13 @@ typedef enum {
67/* 64/*
68 * xfs_iomap_t: File system I/O map 65 * xfs_iomap_t: File system I/O map
69 * 66 *
70 * The iomap_bn field is expressed in 512-byte blocks, and is where the 67 * The iomap_bn field is expressed in 512-byte blocks, and is where the
71 * mapping starts on disk. 68 * mapping starts on disk.
72 * 69 *
73 * The iomap_offset, iomap_bsize and iomap_delta fields are in bytes. 70 * The iomap_offset, iomap_bsize and iomap_delta fields are in bytes.
74 * iomap_offset is the offset of the mapping in the file itself. 71 * iomap_offset is the offset of the mapping in the file itself.
75 * iomap_bsize is the size of the mapping, iomap_delta is the 72 * iomap_bsize is the size of the mapping, iomap_delta is the
76 * desired data's offset into the mapping, given the offset supplied 73 * desired data's offset into the mapping, given the offset supplied
77 * to the file I/O map routine. 74 * to the file I/O map routine.
78 * 75 *
79 * When a request is made to read beyond the logical end of the object, 76 * When a request is made to read beyond the logical end of the object,
@@ -84,8 +81,8 @@ typedef enum {
84typedef struct xfs_iomap { 81typedef struct xfs_iomap {
85 xfs_daddr_t iomap_bn; /* first 512b blk of mapping */ 82 xfs_daddr_t iomap_bn; /* first 512b blk of mapping */
86 xfs_buftarg_t *iomap_target; 83 xfs_buftarg_t *iomap_target;
87 loff_t iomap_offset; /* offset of mapping, bytes */ 84 xfs_off_t iomap_offset; /* offset of mapping, bytes */
88 loff_t iomap_bsize; /* size of mapping, bytes */ 85 xfs_off_t iomap_bsize; /* size of mapping, bytes */
89 size_t iomap_delta; /* offset into mapping, bytes */ 86 size_t iomap_delta; /* offset into mapping, bytes */
90 iomap_flags_t iomap_flags; 87 iomap_flags_t iomap_flags;
91} xfs_iomap_t; 88} xfs_iomap_t;
@@ -96,12 +93,12 @@ struct xfs_bmbt_irec;
96 93
97extern int xfs_iomap(struct xfs_iocore *, xfs_off_t, ssize_t, int, 94extern int xfs_iomap(struct xfs_iocore *, xfs_off_t, ssize_t, int,
98 struct xfs_iomap *, int *); 95 struct xfs_iomap *, int *);
99extern int xfs_iomap_write_direct(struct xfs_inode *, loff_t, size_t, 96extern int xfs_iomap_write_direct(struct xfs_inode *, xfs_off_t, size_t,
100 int, struct xfs_bmbt_irec *, int *, int); 97 int, struct xfs_bmbt_irec *, int *, int);
101extern int xfs_iomap_write_delay(struct xfs_inode *, loff_t, size_t, int, 98extern int xfs_iomap_write_delay(struct xfs_inode *, xfs_off_t, size_t, int,
102 struct xfs_bmbt_irec *, int *); 99 struct xfs_bmbt_irec *, int *);
103extern int xfs_iomap_write_allocate(struct xfs_inode *, 100extern int xfs_iomap_write_allocate(struct xfs_inode *, xfs_off_t, size_t,
104 struct xfs_bmbt_irec *, int *); 101 struct xfs_bmbt_irec *, int *);
105extern int xfs_iomap_write_unwritten(struct xfs_inode *, loff_t, size_t); 102extern int xfs_iomap_write_unwritten(struct xfs_inode *, xfs_off_t, size_t);
106 103
107#endif /* __XFS_IOMAP_H__*/ 104#endif /* __XFS_IOMAP_H__*/
diff --git a/fs/xfs/xfs_mount.c b/fs/xfs/xfs_mount.c
index b57423caef9b..2ec967d93e5a 100644
--- a/fs/xfs/xfs_mount.c
+++ b/fs/xfs/xfs_mount.c
@@ -301,6 +301,15 @@ xfs_mount_validate_sb(
301 } 301 }
302 302
303 /* 303 /*
304 * Version 1 directory format has never worked on Linux.
305 */
306 if (unlikely(!XFS_SB_VERSION_HASDIRV2(sbp))) {
307 cmn_err(CE_WARN,
308 "XFS: Attempted to mount file system using version 1 directory format");
309 return XFS_ERROR(ENOSYS);
310 }
311
312 /*
304 * Until this is fixed only page-sized or smaller data blocks work. 313 * Until this is fixed only page-sized or smaller data blocks work.
305 */ 314 */
306 if (unlikely(sbp->sb_blocksize > PAGE_SIZE)) { 315 if (unlikely(sbp->sb_blocksize > PAGE_SIZE)) {
diff --git a/fs/xfs/xfs_mount.h b/fs/xfs/xfs_mount.h
index 5fc6201dd8e2..30dd08fb9f57 100644
--- a/fs/xfs/xfs_mount.h
+++ b/fs/xfs/xfs_mount.h
@@ -210,15 +210,16 @@ typedef int (*xfs_bmapi_t)(struct xfs_trans *, void *,
210 struct xfs_bmap_free *); 210 struct xfs_bmap_free *);
211typedef int (*xfs_bmap_eof_t)(void *, xfs_fileoff_t, int, int *); 211typedef int (*xfs_bmap_eof_t)(void *, xfs_fileoff_t, int, int *);
212typedef int (*xfs_iomap_write_direct_t)( 212typedef int (*xfs_iomap_write_direct_t)(
213 void *, loff_t, size_t, int, 213 void *, xfs_off_t, size_t, int,
214 struct xfs_bmbt_irec *, int *, int); 214 struct xfs_bmbt_irec *, int *, int);
215typedef int (*xfs_iomap_write_delay_t)( 215typedef int (*xfs_iomap_write_delay_t)(
216 void *, loff_t, size_t, int, 216 void *, xfs_off_t, size_t, int,
217 struct xfs_bmbt_irec *, int *); 217 struct xfs_bmbt_irec *, int *);
218typedef int (*xfs_iomap_write_allocate_t)( 218typedef int (*xfs_iomap_write_allocate_t)(
219 void *, struct xfs_bmbt_irec *, int *); 219 void *, xfs_off_t, size_t,
220 struct xfs_bmbt_irec *, int *);
220typedef int (*xfs_iomap_write_unwritten_t)( 221typedef int (*xfs_iomap_write_unwritten_t)(
221 void *, loff_t, size_t); 222 void *, xfs_off_t, size_t);
222typedef uint (*xfs_lck_map_shared_t)(void *); 223typedef uint (*xfs_lck_map_shared_t)(void *);
223typedef void (*xfs_lock_t)(void *, uint); 224typedef void (*xfs_lock_t)(void *, uint);
224typedef void (*xfs_lock_demote_t)(void *, uint); 225typedef void (*xfs_lock_demote_t)(void *, uint);
@@ -258,9 +259,9 @@ typedef struct xfs_ioops {
258#define XFS_IOMAP_WRITE_DELAY(mp, io, offset, count, flags, mval, nmap) \ 259#define XFS_IOMAP_WRITE_DELAY(mp, io, offset, count, flags, mval, nmap) \
259 (*(mp)->m_io_ops.xfs_iomap_write_delay) \ 260 (*(mp)->m_io_ops.xfs_iomap_write_delay) \
260 ((io)->io_obj, offset, count, flags, mval, nmap) 261 ((io)->io_obj, offset, count, flags, mval, nmap)
261#define XFS_IOMAP_WRITE_ALLOCATE(mp, io, mval, nmap) \ 262#define XFS_IOMAP_WRITE_ALLOCATE(mp, io, offset, count, mval, nmap) \
262 (*(mp)->m_io_ops.xfs_iomap_write_allocate) \ 263 (*(mp)->m_io_ops.xfs_iomap_write_allocate) \
263 ((io)->io_obj, mval, nmap) 264 ((io)->io_obj, offset, count, mval, nmap)
264#define XFS_IOMAP_WRITE_UNWRITTEN(mp, io, offset, count) \ 265#define XFS_IOMAP_WRITE_UNWRITTEN(mp, io, offset, count) \
265 (*(mp)->m_io_ops.xfs_iomap_write_unwritten) \ 266 (*(mp)->m_io_ops.xfs_iomap_write_unwritten) \
266 ((io)->io_obj, offset, count) 267 ((io)->io_obj, offset, count)
@@ -428,10 +429,10 @@ typedef struct xfs_mount {
428#define XFS_WRITEIO_LOG_LARGE 16 429#define XFS_WRITEIO_LOG_LARGE 16
429 430
430/* 431/*
431 * Max and min values for UIO and mount-option defined I/O sizes; 432 * Max and min values for mount-option defined I/O
432 * min value can't be less than a page. Currently unused. 433 * preallocation sizes.
433 */ 434 */
434#define XFS_MAX_IO_LOG 16 /* 64K */ 435#define XFS_MAX_IO_LOG 30 /* 1G */
435#define XFS_MIN_IO_LOG PAGE_SHIFT 436#define XFS_MIN_IO_LOG PAGE_SHIFT
436 437
437/* 438/*
diff --git a/fs/xfs/xfs_types.h b/fs/xfs/xfs_types.h
index 04609d27ea51..e4bf711e48ff 100644
--- a/fs/xfs/xfs_types.h
+++ b/fs/xfs/xfs_types.h
@@ -63,6 +63,7 @@ typedef __u64 xfs_ino_t; /* <inode> type */
63typedef __s64 xfs_daddr_t; /* <disk address> type */ 63typedef __s64 xfs_daddr_t; /* <disk address> type */
64typedef char * xfs_caddr_t; /* <core address> type */ 64typedef char * xfs_caddr_t; /* <core address> type */
65typedef __u32 xfs_dev_t; 65typedef __u32 xfs_dev_t;
66typedef __u32 xfs_nlink_t;
66 67
67/* __psint_t is the same size as a pointer */ 68/* __psint_t is the same size as a pointer */
68#if (BITS_PER_LONG == 32) 69#if (BITS_PER_LONG == 32)
diff --git a/fs/xfs/xfs_utils.c b/fs/xfs/xfs_utils.c
index 816b945fa0ea..d1f8146a06ea 100644
--- a/fs/xfs/xfs_utils.c
+++ b/fs/xfs/xfs_utils.c
@@ -147,7 +147,7 @@ xfs_dir_ialloc(
147 xfs_inode_t *dp, /* directory within whose allocate 147 xfs_inode_t *dp, /* directory within whose allocate
148 the inode. */ 148 the inode. */
149 mode_t mode, 149 mode_t mode,
150 nlink_t nlink, 150 xfs_nlink_t nlink,
151 xfs_dev_t rdev, 151 xfs_dev_t rdev,
152 cred_t *credp, 152 cred_t *credp,
153 prid_t prid, /* project id */ 153 prid_t prid, /* project id */
diff --git a/fs/xfs/xfs_utils.h b/fs/xfs/xfs_utils.h
index e1ed6a588000..01d98b4b7af7 100644
--- a/fs/xfs/xfs_utils.h
+++ b/fs/xfs/xfs_utils.h
@@ -42,7 +42,7 @@ extern int xfs_get_dir_entry (vname_t *, xfs_inode_t **);
42extern int xfs_dir_lookup_int (bhv_desc_t *, uint, vname_t *, xfs_ino_t *, 42extern int xfs_dir_lookup_int (bhv_desc_t *, uint, vname_t *, xfs_ino_t *,
43 xfs_inode_t **); 43 xfs_inode_t **);
44extern int xfs_truncate_file (xfs_mount_t *, xfs_inode_t *); 44extern int xfs_truncate_file (xfs_mount_t *, xfs_inode_t *);
45extern int xfs_dir_ialloc (xfs_trans_t **, xfs_inode_t *, mode_t, nlink_t, 45extern int xfs_dir_ialloc (xfs_trans_t **, xfs_inode_t *, mode_t, xfs_nlink_t,
46 xfs_dev_t, cred_t *, prid_t, int, 46 xfs_dev_t, cred_t *, prid_t, int,
47 xfs_inode_t **, int *); 47 xfs_inode_t **, int *);
48extern int xfs_droplink (xfs_trans_t *, xfs_inode_t *); 48extern int xfs_droplink (xfs_trans_t *, xfs_inode_t *);
diff --git a/fs/xfs/xfs_vfsops.c b/fs/xfs/xfs_vfsops.c
index 00aae9c6a904..b53736650100 100644
--- a/fs/xfs/xfs_vfsops.c
+++ b/fs/xfs/xfs_vfsops.c
@@ -1649,6 +1649,7 @@ xfs_vget(
1649#define MNTOPT_SWIDTH "swidth" /* data volume stripe width */ 1649#define MNTOPT_SWIDTH "swidth" /* data volume stripe width */
1650#define MNTOPT_NOUUID "nouuid" /* ignore filesystem UUID */ 1650#define MNTOPT_NOUUID "nouuid" /* ignore filesystem UUID */
1651#define MNTOPT_MTPT "mtpt" /* filesystem mount point */ 1651#define MNTOPT_MTPT "mtpt" /* filesystem mount point */
1652#define MNTOPT_ALLOCSIZE "allocsize" /* preferred allocation size */
1652#define MNTOPT_IHASHSIZE "ihashsize" /* size of inode hash table */ 1653#define MNTOPT_IHASHSIZE "ihashsize" /* size of inode hash table */
1653#define MNTOPT_NORECOVERY "norecovery" /* don't run XFS recovery */ 1654#define MNTOPT_NORECOVERY "norecovery" /* don't run XFS recovery */
1654#define MNTOPT_NOLOGFLUSH "nologflush" /* don't hard flush on log writes */ 1655#define MNTOPT_NOLOGFLUSH "nologflush" /* don't hard flush on log writes */
@@ -1657,6 +1658,28 @@ xfs_vget(
1657#define MNTOPT_IKEEP "ikeep" /* do not free empty inode clusters */ 1658#define MNTOPT_IKEEP "ikeep" /* do not free empty inode clusters */
1658#define MNTOPT_NOIKEEP "noikeep" /* free empty inode clusters */ 1659#define MNTOPT_NOIKEEP "noikeep" /* free empty inode clusters */
1659 1660
1661STATIC unsigned long
1662suffix_strtoul(const char *cp, char **endp, unsigned int base)
1663{
1664 int last, shift_left_factor = 0;
1665 char *value = (char *)cp;
1666
1667 last = strlen(value) - 1;
1668 if (value[last] == 'K' || value[last] == 'k') {
1669 shift_left_factor = 10;
1670 value[last] = '\0';
1671 }
1672 if (value[last] == 'M' || value[last] == 'm') {
1673 shift_left_factor = 20;
1674 value[last] = '\0';
1675 }
1676 if (value[last] == 'G' || value[last] == 'g') {
1677 shift_left_factor = 30;
1678 value[last] = '\0';
1679 }
1680
1681 return simple_strtoul(cp, endp, base) << shift_left_factor;
1682}
1660 1683
1661int 1684int
1662xfs_parseargs( 1685xfs_parseargs(
@@ -1688,60 +1711,60 @@ xfs_parseargs(
1688 if (!strcmp(this_char, MNTOPT_LOGBUFS)) { 1711 if (!strcmp(this_char, MNTOPT_LOGBUFS)) {
1689 if (!value || !*value) { 1712 if (!value || !*value) {
1690 printk("XFS: %s option requires an argument\n", 1713 printk("XFS: %s option requires an argument\n",
1691 MNTOPT_LOGBUFS); 1714 this_char);
1692 return EINVAL; 1715 return EINVAL;
1693 } 1716 }
1694 args->logbufs = simple_strtoul(value, &eov, 10); 1717 args->logbufs = simple_strtoul(value, &eov, 10);
1695 } else if (!strcmp(this_char, MNTOPT_LOGBSIZE)) { 1718 } else if (!strcmp(this_char, MNTOPT_LOGBSIZE)) {
1696 int last, in_kilobytes = 0;
1697
1698 if (!value || !*value) { 1719 if (!value || !*value) {
1699 printk("XFS: %s option requires an argument\n", 1720 printk("XFS: %s option requires an argument\n",
1700 MNTOPT_LOGBSIZE); 1721 this_char);
1701 return EINVAL; 1722 return EINVAL;
1702 } 1723 }
1703 last = strlen(value) - 1; 1724 args->logbufsize = suffix_strtoul(value, &eov, 10);
1704 if (value[last] == 'K' || value[last] == 'k') {
1705 in_kilobytes = 1;
1706 value[last] = '\0';
1707 }
1708 args->logbufsize = simple_strtoul(value, &eov, 10);
1709 if (in_kilobytes)
1710 args->logbufsize <<= 10;
1711 } else if (!strcmp(this_char, MNTOPT_LOGDEV)) { 1725 } else if (!strcmp(this_char, MNTOPT_LOGDEV)) {
1712 if (!value || !*value) { 1726 if (!value || !*value) {
1713 printk("XFS: %s option requires an argument\n", 1727 printk("XFS: %s option requires an argument\n",
1714 MNTOPT_LOGDEV); 1728 this_char);
1715 return EINVAL; 1729 return EINVAL;
1716 } 1730 }
1717 strncpy(args->logname, value, MAXNAMELEN); 1731 strncpy(args->logname, value, MAXNAMELEN);
1718 } else if (!strcmp(this_char, MNTOPT_MTPT)) { 1732 } else if (!strcmp(this_char, MNTOPT_MTPT)) {
1719 if (!value || !*value) { 1733 if (!value || !*value) {
1720 printk("XFS: %s option requires an argument\n", 1734 printk("XFS: %s option requires an argument\n",
1721 MNTOPT_MTPT); 1735 this_char);
1722 return EINVAL; 1736 return EINVAL;
1723 } 1737 }
1724 strncpy(args->mtpt, value, MAXNAMELEN); 1738 strncpy(args->mtpt, value, MAXNAMELEN);
1725 } else if (!strcmp(this_char, MNTOPT_RTDEV)) { 1739 } else if (!strcmp(this_char, MNTOPT_RTDEV)) {
1726 if (!value || !*value) { 1740 if (!value || !*value) {
1727 printk("XFS: %s option requires an argument\n", 1741 printk("XFS: %s option requires an argument\n",
1728 MNTOPT_RTDEV); 1742 this_char);
1729 return EINVAL; 1743 return EINVAL;
1730 } 1744 }
1731 strncpy(args->rtname, value, MAXNAMELEN); 1745 strncpy(args->rtname, value, MAXNAMELEN);
1732 } else if (!strcmp(this_char, MNTOPT_BIOSIZE)) { 1746 } else if (!strcmp(this_char, MNTOPT_BIOSIZE)) {
1733 if (!value || !*value) { 1747 if (!value || !*value) {
1734 printk("XFS: %s option requires an argument\n", 1748 printk("XFS: %s option requires an argument\n",
1735 MNTOPT_BIOSIZE); 1749 this_char);
1736 return EINVAL; 1750 return EINVAL;
1737 } 1751 }
1738 iosize = simple_strtoul(value, &eov, 10); 1752 iosize = simple_strtoul(value, &eov, 10);
1739 args->flags |= XFSMNT_IOSIZE; 1753 args->flags |= XFSMNT_IOSIZE;
1740 args->iosizelog = (uint8_t) iosize; 1754 args->iosizelog = (uint8_t) iosize;
1755 } else if (!strcmp(this_char, MNTOPT_ALLOCSIZE)) {
1756 if (!value || !*value) {
1757 printk("XFS: %s option requires an argument\n",
1758 this_char);
1759 return EINVAL;
1760 }
1761 iosize = suffix_strtoul(value, &eov, 10);
1762 args->flags |= XFSMNT_IOSIZE;
1763 args->iosizelog = ffs(iosize) - 1;
1741 } else if (!strcmp(this_char, MNTOPT_IHASHSIZE)) { 1764 } else if (!strcmp(this_char, MNTOPT_IHASHSIZE)) {
1742 if (!value || !*value) { 1765 if (!value || !*value) {
1743 printk("XFS: %s option requires an argument\n", 1766 printk("XFS: %s option requires an argument\n",
1744 this_char); 1767 this_char);
1745 return EINVAL; 1768 return EINVAL;
1746 } 1769 }
1747 args->flags |= XFSMNT_IHASHSIZE; 1770 args->flags |= XFSMNT_IHASHSIZE;
@@ -1756,7 +1779,7 @@ xfs_parseargs(
1756 args->flags |= XFSMNT_INO64; 1779 args->flags |= XFSMNT_INO64;
1757#if !XFS_BIG_INUMS 1780#if !XFS_BIG_INUMS
1758 printk("XFS: %s option not allowed on this system\n", 1781 printk("XFS: %s option not allowed on this system\n",
1759 MNTOPT_INO64); 1782 this_char);
1760 return EINVAL; 1783 return EINVAL;
1761#endif 1784#endif
1762 } else if (!strcmp(this_char, MNTOPT_NOALIGN)) { 1785 } else if (!strcmp(this_char, MNTOPT_NOALIGN)) {
@@ -1766,14 +1789,14 @@ xfs_parseargs(
1766 } else if (!strcmp(this_char, MNTOPT_SUNIT)) { 1789 } else if (!strcmp(this_char, MNTOPT_SUNIT)) {
1767 if (!value || !*value) { 1790 if (!value || !*value) {
1768 printk("XFS: %s option requires an argument\n", 1791 printk("XFS: %s option requires an argument\n",
1769 MNTOPT_SUNIT); 1792 this_char);
1770 return EINVAL; 1793 return EINVAL;
1771 } 1794 }
1772 dsunit = simple_strtoul(value, &eov, 10); 1795 dsunit = simple_strtoul(value, &eov, 10);
1773 } else if (!strcmp(this_char, MNTOPT_SWIDTH)) { 1796 } else if (!strcmp(this_char, MNTOPT_SWIDTH)) {
1774 if (!value || !*value) { 1797 if (!value || !*value) {
1775 printk("XFS: %s option requires an argument\n", 1798 printk("XFS: %s option requires an argument\n",
1776 MNTOPT_SWIDTH); 1799 this_char);
1777 return EINVAL; 1800 return EINVAL;
1778 } 1801 }
1779 dswidth = simple_strtoul(value, &eov, 10); 1802 dswidth = simple_strtoul(value, &eov, 10);
@@ -1781,7 +1804,7 @@ xfs_parseargs(
1781 args->flags &= ~XFSMNT_32BITINODES; 1804 args->flags &= ~XFSMNT_32BITINODES;
1782#if !XFS_BIG_INUMS 1805#if !XFS_BIG_INUMS
1783 printk("XFS: %s option not allowed on this system\n", 1806 printk("XFS: %s option not allowed on this system\n",
1784 MNTOPT_64BITINODE); 1807 this_char);
1785 return EINVAL; 1808 return EINVAL;
1786#endif 1809#endif
1787 } else if (!strcmp(this_char, MNTOPT_NOUUID)) { 1810 } else if (!strcmp(this_char, MNTOPT_NOUUID)) {
@@ -1877,7 +1900,7 @@ xfs_showargs(
1877 seq_printf(m, "," MNTOPT_IHASHSIZE "=%d", mp->m_ihsize); 1900 seq_printf(m, "," MNTOPT_IHASHSIZE "=%d", mp->m_ihsize);
1878 1901
1879 if (mp->m_flags & XFS_MOUNT_DFLT_IOSIZE) 1902 if (mp->m_flags & XFS_MOUNT_DFLT_IOSIZE)
1880 seq_printf(m, "," MNTOPT_BIOSIZE "=%d", mp->m_writeio_log); 1903 seq_printf(m, "," MNTOPT_ALLOCSIZE "=%d", 1<<mp->m_writeio_log);
1881 1904
1882 if (mp->m_logbufs > 0) 1905 if (mp->m_logbufs > 0)
1883 seq_printf(m, "," MNTOPT_LOGBUFS "=%d", mp->m_logbufs); 1906 seq_printf(m, "," MNTOPT_LOGBUFS "=%d", mp->m_logbufs);
diff --git a/fs/xfs/xfs_vnodeops.c b/fs/xfs/xfs_vnodeops.c
index 70092963ca9e..25a526629b12 100644
--- a/fs/xfs/xfs_vnodeops.c
+++ b/fs/xfs/xfs_vnodeops.c
@@ -305,7 +305,7 @@ xfs_setattr(
305 int mandlock_before, mandlock_after; 305 int mandlock_before, mandlock_after;
306 struct xfs_dquot *udqp, *gdqp, *olddquot1, *olddquot2; 306 struct xfs_dquot *udqp, *gdqp, *olddquot1, *olddquot2;
307 int file_owner; 307 int file_owner;
308 int need_iolock = (flags & ATTR_DMI) == 0; 308 int need_iolock = 1;
309 309
310 vp = BHV_TO_VNODE(bdp); 310 vp = BHV_TO_VNODE(bdp);
311 vn_trace_entry(vp, __FUNCTION__, (inst_t *)__return_address); 311 vn_trace_entry(vp, __FUNCTION__, (inst_t *)__return_address);
@@ -384,6 +384,9 @@ xfs_setattr(
384 */ 384 */
385 tp = NULL; 385 tp = NULL;
386 lock_flags = XFS_ILOCK_EXCL; 386 lock_flags = XFS_ILOCK_EXCL;
387 ASSERT(flags & ATTR_NOLOCK ? flags & ATTR_DMI : 1);
388 if (flags & ATTR_NOLOCK)
389 need_iolock = 0;
387 if (!(mask & XFS_AT_SIZE)) { 390 if (!(mask & XFS_AT_SIZE)) {
388 if ((mask != (XFS_AT_CTIME|XFS_AT_ATIME|XFS_AT_MTIME)) || 391 if ((mask != (XFS_AT_CTIME|XFS_AT_ATIME|XFS_AT_MTIME)) ||
389 (mp->m_flags & XFS_MOUNT_WSYNC)) { 392 (mp->m_flags & XFS_MOUNT_WSYNC)) {
@@ -4320,7 +4323,7 @@ xfs_free_file_space(
4320 int rt; 4323 int rt;
4321 xfs_fileoff_t startoffset_fsb; 4324 xfs_fileoff_t startoffset_fsb;
4322 xfs_trans_t *tp; 4325 xfs_trans_t *tp;
4323 int need_iolock = (attr_flags & ATTR_DMI) == 0; 4326 int need_iolock = 1;
4324 4327
4325 vn_trace_entry(XFS_ITOV(ip), __FUNCTION__, (inst_t *)__return_address); 4328 vn_trace_entry(XFS_ITOV(ip), __FUNCTION__, (inst_t *)__return_address);
4326 mp = ip->i_mount; 4329 mp = ip->i_mount;
@@ -4348,8 +4351,12 @@ xfs_free_file_space(
4348 return(error); 4351 return(error);
4349 } 4352 }
4350 4353
4354 ASSERT(attr_flags & ATTR_NOLOCK ? attr_flags & ATTR_DMI : 1);
4355 if (attr_flags & ATTR_NOLOCK)
4356 need_iolock = 0;
4351 if (need_iolock) 4357 if (need_iolock)
4352 xfs_ilock(ip, XFS_IOLOCK_EXCL); 4358 xfs_ilock(ip, XFS_IOLOCK_EXCL);
4359
4353 rounding = MAX((__uint8_t)(1 << mp->m_sb.sb_blocklog), 4360 rounding = MAX((__uint8_t)(1 << mp->m_sb.sb_blocklog),
4354 (__uint8_t)NBPP); 4361 (__uint8_t)NBPP);
4355 ilen = len + (offset & (rounding - 1)); 4362 ilen = len + (offset & (rounding - 1));