diff options
Diffstat (limited to 'fs/xfs')
45 files changed, 790 insertions, 1102 deletions
diff --git a/fs/xfs/linux-2.6/xfs_aops.c b/fs/xfs/linux-2.6/xfs_aops.c index 7ec89fc05b2b..d5e5559e31db 100644 --- a/fs/xfs/linux-2.6/xfs_aops.c +++ b/fs/xfs/linux-2.6/xfs_aops.c | |||
@@ -216,7 +216,6 @@ xfs_setfilesize( | |||
216 | if (ip->i_d.di_size < isize) { | 216 | if (ip->i_d.di_size < isize) { |
217 | ip->i_d.di_size = isize; | 217 | ip->i_d.di_size = isize; |
218 | ip->i_update_core = 1; | 218 | ip->i_update_core = 1; |
219 | ip->i_update_size = 1; | ||
220 | xfs_mark_inode_dirty_sync(ip); | 219 | xfs_mark_inode_dirty_sync(ip); |
221 | } | 220 | } |
222 | 221 | ||
@@ -1268,6 +1267,14 @@ xfs_vm_writepage( | |||
1268 | if (!page_has_buffers(page)) | 1267 | if (!page_has_buffers(page)) |
1269 | create_empty_buffers(page, 1 << inode->i_blkbits, 0); | 1268 | create_empty_buffers(page, 1 << inode->i_blkbits, 0); |
1270 | 1269 | ||
1270 | |||
1271 | /* | ||
1272 | * VM calculation for nr_to_write seems off. Bump it way | ||
1273 | * up, this gets simple streaming writes zippy again. | ||
1274 | * To be reviewed again after Jens' writeback changes. | ||
1275 | */ | ||
1276 | wbc->nr_to_write *= 4; | ||
1277 | |||
1271 | /* | 1278 | /* |
1272 | * Convert delayed allocate, unwritten or unmapped space | 1279 | * Convert delayed allocate, unwritten or unmapped space |
1273 | * to real space and flush out to disk. | 1280 | * to real space and flush out to disk. |
diff --git a/fs/xfs/linux-2.6/xfs_buf.c b/fs/xfs/linux-2.6/xfs_buf.c index 0c93c7ef3d18..965df1227d64 100644 --- a/fs/xfs/linux-2.6/xfs_buf.c +++ b/fs/xfs/linux-2.6/xfs_buf.c | |||
@@ -770,7 +770,7 @@ xfs_buf_associate_memory( | |||
770 | bp->b_pages = NULL; | 770 | bp->b_pages = NULL; |
771 | bp->b_addr = mem; | 771 | bp->b_addr = mem; |
772 | 772 | ||
773 | rval = _xfs_buf_get_pages(bp, page_count, 0); | 773 | rval = _xfs_buf_get_pages(bp, page_count, XBF_DONT_BLOCK); |
774 | if (rval) | 774 | if (rval) |
775 | return rval; | 775 | return rval; |
776 | 776 | ||
diff --git a/fs/xfs/linux-2.6/xfs_file.c b/fs/xfs/linux-2.6/xfs_file.c index 0542fd507649..988d8f87bc0f 100644 --- a/fs/xfs/linux-2.6/xfs_file.c +++ b/fs/xfs/linux-2.6/xfs_file.c | |||
@@ -172,12 +172,21 @@ xfs_file_release( | |||
172 | */ | 172 | */ |
173 | STATIC int | 173 | STATIC int |
174 | xfs_file_fsync( | 174 | xfs_file_fsync( |
175 | struct file *filp, | 175 | struct file *file, |
176 | struct dentry *dentry, | 176 | struct dentry *dentry, |
177 | int datasync) | 177 | int datasync) |
178 | { | 178 | { |
179 | xfs_iflags_clear(XFS_I(dentry->d_inode), XFS_ITRUNCATED); | 179 | struct inode *inode = dentry->d_inode; |
180 | return -xfs_fsync(XFS_I(dentry->d_inode)); | 180 | struct xfs_inode *ip = XFS_I(inode); |
181 | int error; | ||
182 | |||
183 | /* capture size updates in I/O completion before writing the inode. */ | ||
184 | error = filemap_fdatawait(inode->i_mapping); | ||
185 | if (error) | ||
186 | return error; | ||
187 | |||
188 | xfs_iflags_clear(ip, XFS_ITRUNCATED); | ||
189 | return -xfs_fsync(ip); | ||
181 | } | 190 | } |
182 | 191 | ||
183 | STATIC int | 192 | STATIC int |
diff --git a/fs/xfs/linux-2.6/xfs_ioctl32.c b/fs/xfs/linux-2.6/xfs_ioctl32.c index 0882d166239a..eafcc7c18706 100644 --- a/fs/xfs/linux-2.6/xfs_ioctl32.c +++ b/fs/xfs/linux-2.6/xfs_ioctl32.c | |||
@@ -619,7 +619,7 @@ xfs_file_compat_ioctl( | |||
619 | case XFS_IOC_GETVERSION_32: | 619 | case XFS_IOC_GETVERSION_32: |
620 | cmd = _NATIVE_IOC(cmd, long); | 620 | cmd = _NATIVE_IOC(cmd, long); |
621 | return xfs_file_ioctl(filp, cmd, p); | 621 | return xfs_file_ioctl(filp, cmd, p); |
622 | case XFS_IOC_SWAPEXT: { | 622 | case XFS_IOC_SWAPEXT_32: { |
623 | struct xfs_swapext sxp; | 623 | struct xfs_swapext sxp; |
624 | struct compat_xfs_swapext __user *sxu = arg; | 624 | struct compat_xfs_swapext __user *sxu = arg; |
625 | 625 | ||
diff --git a/fs/xfs/linux-2.6/xfs_iops.c b/fs/xfs/linux-2.6/xfs_iops.c index 58973bb46038..da0159d99f82 100644 --- a/fs/xfs/linux-2.6/xfs_iops.c +++ b/fs/xfs/linux-2.6/xfs_iops.c | |||
@@ -43,7 +43,6 @@ | |||
43 | #include "xfs_error.h" | 43 | #include "xfs_error.h" |
44 | #include "xfs_itable.h" | 44 | #include "xfs_itable.h" |
45 | #include "xfs_rw.h" | 45 | #include "xfs_rw.h" |
46 | #include "xfs_acl.h" | ||
47 | #include "xfs_attr.h" | 46 | #include "xfs_attr.h" |
48 | #include "xfs_buf_item.h" | 47 | #include "xfs_buf_item.h" |
49 | #include "xfs_utils.h" | 48 | #include "xfs_utils.h" |
@@ -485,14 +484,6 @@ xfs_vn_put_link( | |||
485 | } | 484 | } |
486 | 485 | ||
487 | STATIC int | 486 | STATIC int |
488 | xfs_vn_permission( | ||
489 | struct inode *inode, | ||
490 | int mask) | ||
491 | { | ||
492 | return generic_permission(inode, mask, xfs_check_acl); | ||
493 | } | ||
494 | |||
495 | STATIC int | ||
496 | xfs_vn_getattr( | 487 | xfs_vn_getattr( |
497 | struct vfsmount *mnt, | 488 | struct vfsmount *mnt, |
498 | struct dentry *dentry, | 489 | struct dentry *dentry, |
@@ -680,8 +671,8 @@ xfs_vn_fiemap( | |||
680 | else | 671 | else |
681 | bm.bmv_length = BTOBB(length); | 672 | bm.bmv_length = BTOBB(length); |
682 | 673 | ||
683 | /* our formatter will tell xfs_getbmap when to stop. */ | 674 | /* We add one because in getbmap world count includes the header */ |
684 | bm.bmv_count = MAXEXTNUM; | 675 | bm.bmv_count = fieinfo->fi_extents_max + 1; |
685 | bm.bmv_iflags = BMV_IF_PREALLOC; | 676 | bm.bmv_iflags = BMV_IF_PREALLOC; |
686 | if (fieinfo->fi_flags & FIEMAP_FLAG_XATTR) | 677 | if (fieinfo->fi_flags & FIEMAP_FLAG_XATTR) |
687 | bm.bmv_iflags |= BMV_IF_ATTRFORK; | 678 | bm.bmv_iflags |= BMV_IF_ATTRFORK; |
@@ -696,7 +687,7 @@ xfs_vn_fiemap( | |||
696 | } | 687 | } |
697 | 688 | ||
698 | static const struct inode_operations xfs_inode_operations = { | 689 | static const struct inode_operations xfs_inode_operations = { |
699 | .permission = xfs_vn_permission, | 690 | .check_acl = xfs_check_acl, |
700 | .truncate = xfs_vn_truncate, | 691 | .truncate = xfs_vn_truncate, |
701 | .getattr = xfs_vn_getattr, | 692 | .getattr = xfs_vn_getattr, |
702 | .setattr = xfs_vn_setattr, | 693 | .setattr = xfs_vn_setattr, |
@@ -724,7 +715,7 @@ static const struct inode_operations xfs_dir_inode_operations = { | |||
724 | .rmdir = xfs_vn_unlink, | 715 | .rmdir = xfs_vn_unlink, |
725 | .mknod = xfs_vn_mknod, | 716 | .mknod = xfs_vn_mknod, |
726 | .rename = xfs_vn_rename, | 717 | .rename = xfs_vn_rename, |
727 | .permission = xfs_vn_permission, | 718 | .check_acl = xfs_check_acl, |
728 | .getattr = xfs_vn_getattr, | 719 | .getattr = xfs_vn_getattr, |
729 | .setattr = xfs_vn_setattr, | 720 | .setattr = xfs_vn_setattr, |
730 | .setxattr = generic_setxattr, | 721 | .setxattr = generic_setxattr, |
@@ -749,7 +740,7 @@ static const struct inode_operations xfs_dir_ci_inode_operations = { | |||
749 | .rmdir = xfs_vn_unlink, | 740 | .rmdir = xfs_vn_unlink, |
750 | .mknod = xfs_vn_mknod, | 741 | .mknod = xfs_vn_mknod, |
751 | .rename = xfs_vn_rename, | 742 | .rename = xfs_vn_rename, |
752 | .permission = xfs_vn_permission, | 743 | .check_acl = xfs_check_acl, |
753 | .getattr = xfs_vn_getattr, | 744 | .getattr = xfs_vn_getattr, |
754 | .setattr = xfs_vn_setattr, | 745 | .setattr = xfs_vn_setattr, |
755 | .setxattr = generic_setxattr, | 746 | .setxattr = generic_setxattr, |
@@ -762,7 +753,7 @@ static const struct inode_operations xfs_symlink_inode_operations = { | |||
762 | .readlink = generic_readlink, | 753 | .readlink = generic_readlink, |
763 | .follow_link = xfs_vn_follow_link, | 754 | .follow_link = xfs_vn_follow_link, |
764 | .put_link = xfs_vn_put_link, | 755 | .put_link = xfs_vn_put_link, |
765 | .permission = xfs_vn_permission, | 756 | .check_acl = xfs_check_acl, |
766 | .getattr = xfs_vn_getattr, | 757 | .getattr = xfs_vn_getattr, |
767 | .setattr = xfs_vn_setattr, | 758 | .setattr = xfs_vn_setattr, |
768 | .setxattr = generic_setxattr, | 759 | .setxattr = generic_setxattr, |
diff --git a/fs/xfs/linux-2.6/xfs_lrw.c b/fs/xfs/linux-2.6/xfs_lrw.c index 7078974a6eee..49e4a6aea73c 100644 --- a/fs/xfs/linux-2.6/xfs_lrw.c +++ b/fs/xfs/linux-2.6/xfs_lrw.c | |||
@@ -812,18 +812,21 @@ write_retry: | |||
812 | 812 | ||
813 | /* Handle various SYNC-type writes */ | 813 | /* Handle various SYNC-type writes */ |
814 | if ((file->f_flags & O_SYNC) || IS_SYNC(inode)) { | 814 | if ((file->f_flags & O_SYNC) || IS_SYNC(inode)) { |
815 | loff_t end = pos + ret - 1; | ||
815 | int error2; | 816 | int error2; |
816 | 817 | ||
817 | xfs_iunlock(xip, iolock); | 818 | xfs_iunlock(xip, iolock); |
818 | if (need_i_mutex) | 819 | if (need_i_mutex) |
819 | mutex_unlock(&inode->i_mutex); | 820 | mutex_unlock(&inode->i_mutex); |
820 | error2 = sync_page_range(inode, mapping, pos, ret); | 821 | |
822 | error2 = filemap_write_and_wait_range(mapping, pos, end); | ||
821 | if (!error) | 823 | if (!error) |
822 | error = error2; | 824 | error = error2; |
823 | if (need_i_mutex) | 825 | if (need_i_mutex) |
824 | mutex_lock(&inode->i_mutex); | 826 | mutex_lock(&inode->i_mutex); |
825 | xfs_ilock(xip, iolock); | 827 | xfs_ilock(xip, iolock); |
826 | error2 = xfs_write_sync_logforce(mp, xip); | 828 | |
829 | error2 = xfs_fsync(xip); | ||
827 | if (!error) | 830 | if (!error) |
828 | error = error2; | 831 | error = error2; |
829 | } | 832 | } |
diff --git a/fs/xfs/linux-2.6/xfs_stats.c b/fs/xfs/linux-2.6/xfs_stats.c index c3526d445f6a..76fdc5861932 100644 --- a/fs/xfs/linux-2.6/xfs_stats.c +++ b/fs/xfs/linux-2.6/xfs_stats.c | |||
@@ -20,16 +20,9 @@ | |||
20 | 20 | ||
21 | DEFINE_PER_CPU(struct xfsstats, xfsstats); | 21 | DEFINE_PER_CPU(struct xfsstats, xfsstats); |
22 | 22 | ||
23 | STATIC int | 23 | static int xfs_stat_proc_show(struct seq_file *m, void *v) |
24 | xfs_read_xfsstats( | ||
25 | char *buffer, | ||
26 | char **start, | ||
27 | off_t offset, | ||
28 | int count, | ||
29 | int *eof, | ||
30 | void *data) | ||
31 | { | 24 | { |
32 | int c, i, j, len, val; | 25 | int c, i, j, val; |
33 | __uint64_t xs_xstrat_bytes = 0; | 26 | __uint64_t xs_xstrat_bytes = 0; |
34 | __uint64_t xs_write_bytes = 0; | 27 | __uint64_t xs_write_bytes = 0; |
35 | __uint64_t xs_read_bytes = 0; | 28 | __uint64_t xs_read_bytes = 0; |
@@ -60,18 +53,18 @@ xfs_read_xfsstats( | |||
60 | }; | 53 | }; |
61 | 54 | ||
62 | /* Loop over all stats groups */ | 55 | /* Loop over all stats groups */ |
63 | for (i=j=len = 0; i < ARRAY_SIZE(xstats); i++) { | 56 | for (i=j = 0; i < ARRAY_SIZE(xstats); i++) { |
64 | len += sprintf(buffer + len, "%s", xstats[i].desc); | 57 | seq_printf(m, "%s", xstats[i].desc); |
65 | /* inner loop does each group */ | 58 | /* inner loop does each group */ |
66 | while (j < xstats[i].endpoint) { | 59 | while (j < xstats[i].endpoint) { |
67 | val = 0; | 60 | val = 0; |
68 | /* sum over all cpus */ | 61 | /* sum over all cpus */ |
69 | for_each_possible_cpu(c) | 62 | for_each_possible_cpu(c) |
70 | val += *(((__u32*)&per_cpu(xfsstats, c) + j)); | 63 | val += *(((__u32*)&per_cpu(xfsstats, c) + j)); |
71 | len += sprintf(buffer + len, " %u", val); | 64 | seq_printf(m, " %u", val); |
72 | j++; | 65 | j++; |
73 | } | 66 | } |
74 | buffer[len++] = '\n'; | 67 | seq_putc(m, '\n'); |
75 | } | 68 | } |
76 | /* extra precision counters */ | 69 | /* extra precision counters */ |
77 | for_each_possible_cpu(i) { | 70 | for_each_possible_cpu(i) { |
@@ -80,36 +73,38 @@ xfs_read_xfsstats( | |||
80 | xs_read_bytes += per_cpu(xfsstats, i).xs_read_bytes; | 73 | xs_read_bytes += per_cpu(xfsstats, i).xs_read_bytes; |
81 | } | 74 | } |
82 | 75 | ||
83 | len += sprintf(buffer + len, "xpc %Lu %Lu %Lu\n", | 76 | seq_printf(m, "xpc %Lu %Lu %Lu\n", |
84 | xs_xstrat_bytes, xs_write_bytes, xs_read_bytes); | 77 | xs_xstrat_bytes, xs_write_bytes, xs_read_bytes); |
85 | len += sprintf(buffer + len, "debug %u\n", | 78 | seq_printf(m, "debug %u\n", |
86 | #if defined(DEBUG) | 79 | #if defined(DEBUG) |
87 | 1); | 80 | 1); |
88 | #else | 81 | #else |
89 | 0); | 82 | 0); |
90 | #endif | 83 | #endif |
84 | return 0; | ||
85 | } | ||
91 | 86 | ||
92 | if (offset >= len) { | 87 | static int xfs_stat_proc_open(struct inode *inode, struct file *file) |
93 | *start = buffer; | 88 | { |
94 | *eof = 1; | 89 | return single_open(file, xfs_stat_proc_show, NULL); |
95 | return 0; | ||
96 | } | ||
97 | *start = buffer + offset; | ||
98 | if ((len -= offset) > count) | ||
99 | return count; | ||
100 | *eof = 1; | ||
101 | |||
102 | return len; | ||
103 | } | 90 | } |
104 | 91 | ||
92 | static const struct file_operations xfs_stat_proc_fops = { | ||
93 | .owner = THIS_MODULE, | ||
94 | .open = xfs_stat_proc_open, | ||
95 | .read = seq_read, | ||
96 | .llseek = seq_lseek, | ||
97 | .release = single_release, | ||
98 | }; | ||
99 | |||
105 | int | 100 | int |
106 | xfs_init_procfs(void) | 101 | xfs_init_procfs(void) |
107 | { | 102 | { |
108 | if (!proc_mkdir("fs/xfs", NULL)) | 103 | if (!proc_mkdir("fs/xfs", NULL)) |
109 | goto out; | 104 | goto out; |
110 | 105 | ||
111 | if (!create_proc_read_entry("fs/xfs/stat", 0, NULL, | 106 | if (!proc_create("fs/xfs/stat", 0, NULL, |
112 | xfs_read_xfsstats, NULL)) | 107 | &xfs_stat_proc_fops)) |
113 | goto out_remove_entry; | 108 | goto out_remove_entry; |
114 | return 0; | 109 | return 0; |
115 | 110 | ||
diff --git a/fs/xfs/linux-2.6/xfs_super.c b/fs/xfs/linux-2.6/xfs_super.c index a220d36f789b..5d7c60ac77b4 100644 --- a/fs/xfs/linux-2.6/xfs_super.c +++ b/fs/xfs/linux-2.6/xfs_super.c | |||
@@ -579,15 +579,19 @@ xfs_showargs( | |||
579 | else if (mp->m_qflags & XFS_UQUOTA_ACCT) | 579 | else if (mp->m_qflags & XFS_UQUOTA_ACCT) |
580 | seq_puts(m, "," MNTOPT_UQUOTANOENF); | 580 | seq_puts(m, "," MNTOPT_UQUOTANOENF); |
581 | 581 | ||
582 | if (mp->m_qflags & (XFS_PQUOTA_ACCT|XFS_OQUOTA_ENFD)) | 582 | /* Either project or group quotas can be active, not both */ |
583 | seq_puts(m, "," MNTOPT_PRJQUOTA); | 583 | |
584 | else if (mp->m_qflags & XFS_PQUOTA_ACCT) | 584 | if (mp->m_qflags & XFS_PQUOTA_ACCT) { |
585 | seq_puts(m, "," MNTOPT_PQUOTANOENF); | 585 | if (mp->m_qflags & XFS_OQUOTA_ENFD) |
586 | 586 | seq_puts(m, "," MNTOPT_PRJQUOTA); | |
587 | if (mp->m_qflags & (XFS_GQUOTA_ACCT|XFS_OQUOTA_ENFD)) | 587 | else |
588 | seq_puts(m, "," MNTOPT_GRPQUOTA); | 588 | seq_puts(m, "," MNTOPT_PQUOTANOENF); |
589 | else if (mp->m_qflags & XFS_GQUOTA_ACCT) | 589 | } else if (mp->m_qflags & XFS_GQUOTA_ACCT) { |
590 | seq_puts(m, "," MNTOPT_GQUOTANOENF); | 590 | if (mp->m_qflags & XFS_OQUOTA_ENFD) |
591 | seq_puts(m, "," MNTOPT_GRPQUOTA); | ||
592 | else | ||
593 | seq_puts(m, "," MNTOPT_GQUOTANOENF); | ||
594 | } | ||
591 | 595 | ||
592 | if (!(mp->m_qflags & XFS_ALL_QUOTA_ACCT)) | 596 | if (!(mp->m_qflags & XFS_ALL_QUOTA_ACCT)) |
593 | seq_puts(m, "," MNTOPT_NOQUOTA); | 597 | seq_puts(m, "," MNTOPT_NOQUOTA); |
@@ -687,7 +691,7 @@ xfs_barrier_test( | |||
687 | return error; | 691 | return error; |
688 | } | 692 | } |
689 | 693 | ||
690 | void | 694 | STATIC void |
691 | xfs_mountfs_check_barriers(xfs_mount_t *mp) | 695 | xfs_mountfs_check_barriers(xfs_mount_t *mp) |
692 | { | 696 | { |
693 | int error; | 697 | int error; |
diff --git a/fs/xfs/linux-2.6/xfs_sync.c b/fs/xfs/linux-2.6/xfs_sync.c index b619d6b8ca43..320be6aea492 100644 --- a/fs/xfs/linux-2.6/xfs_sync.c +++ b/fs/xfs/linux-2.6/xfs_sync.c | |||
@@ -708,6 +708,16 @@ xfs_reclaim_inode( | |||
708 | return 0; | 708 | return 0; |
709 | } | 709 | } |
710 | 710 | ||
711 | void | ||
712 | __xfs_inode_set_reclaim_tag( | ||
713 | struct xfs_perag *pag, | ||
714 | struct xfs_inode *ip) | ||
715 | { | ||
716 | radix_tree_tag_set(&pag->pag_ici_root, | ||
717 | XFS_INO_TO_AGINO(ip->i_mount, ip->i_ino), | ||
718 | XFS_ICI_RECLAIM_TAG); | ||
719 | } | ||
720 | |||
711 | /* | 721 | /* |
712 | * We set the inode flag atomically with the radix tree tag. | 722 | * We set the inode flag atomically with the radix tree tag. |
713 | * Once we get tag lookups on the radix tree, this inode flag | 723 | * Once we get tag lookups on the radix tree, this inode flag |
@@ -722,8 +732,7 @@ xfs_inode_set_reclaim_tag( | |||
722 | 732 | ||
723 | read_lock(&pag->pag_ici_lock); | 733 | read_lock(&pag->pag_ici_lock); |
724 | spin_lock(&ip->i_flags_lock); | 734 | spin_lock(&ip->i_flags_lock); |
725 | radix_tree_tag_set(&pag->pag_ici_root, | 735 | __xfs_inode_set_reclaim_tag(pag, ip); |
726 | XFS_INO_TO_AGINO(mp, ip->i_ino), XFS_ICI_RECLAIM_TAG); | ||
727 | __xfs_iflags_set(ip, XFS_IRECLAIMABLE); | 736 | __xfs_iflags_set(ip, XFS_IRECLAIMABLE); |
728 | spin_unlock(&ip->i_flags_lock); | 737 | spin_unlock(&ip->i_flags_lock); |
729 | read_unlock(&pag->pag_ici_lock); | 738 | read_unlock(&pag->pag_ici_lock); |
@@ -740,21 +749,6 @@ __xfs_inode_clear_reclaim_tag( | |||
740 | XFS_INO_TO_AGINO(mp, ip->i_ino), XFS_ICI_RECLAIM_TAG); | 749 | XFS_INO_TO_AGINO(mp, ip->i_ino), XFS_ICI_RECLAIM_TAG); |
741 | } | 750 | } |
742 | 751 | ||
743 | void | ||
744 | xfs_inode_clear_reclaim_tag( | ||
745 | xfs_inode_t *ip) | ||
746 | { | ||
747 | xfs_mount_t *mp = ip->i_mount; | ||
748 | xfs_perag_t *pag = xfs_get_perag(mp, ip->i_ino); | ||
749 | |||
750 | read_lock(&pag->pag_ici_lock); | ||
751 | spin_lock(&ip->i_flags_lock); | ||
752 | __xfs_inode_clear_reclaim_tag(mp, pag, ip); | ||
753 | spin_unlock(&ip->i_flags_lock); | ||
754 | read_unlock(&pag->pag_ici_lock); | ||
755 | xfs_put_perag(mp, pag); | ||
756 | } | ||
757 | |||
758 | STATIC int | 752 | STATIC int |
759 | xfs_reclaim_inode_now( | 753 | xfs_reclaim_inode_now( |
760 | struct xfs_inode *ip, | 754 | struct xfs_inode *ip, |
diff --git a/fs/xfs/linux-2.6/xfs_sync.h b/fs/xfs/linux-2.6/xfs_sync.h index 2a10301c99c7..27920eb7a820 100644 --- a/fs/xfs/linux-2.6/xfs_sync.h +++ b/fs/xfs/linux-2.6/xfs_sync.h | |||
@@ -48,7 +48,7 @@ int xfs_reclaim_inode(struct xfs_inode *ip, int locked, int sync_mode); | |||
48 | int xfs_reclaim_inodes(struct xfs_mount *mp, int mode); | 48 | int xfs_reclaim_inodes(struct xfs_mount *mp, int mode); |
49 | 49 | ||
50 | void xfs_inode_set_reclaim_tag(struct xfs_inode *ip); | 50 | void xfs_inode_set_reclaim_tag(struct xfs_inode *ip); |
51 | void xfs_inode_clear_reclaim_tag(struct xfs_inode *ip); | 51 | void __xfs_inode_set_reclaim_tag(struct xfs_perag *pag, struct xfs_inode *ip); |
52 | void __xfs_inode_clear_reclaim_tag(struct xfs_mount *mp, struct xfs_perag *pag, | 52 | void __xfs_inode_clear_reclaim_tag(struct xfs_mount *mp, struct xfs_perag *pag, |
53 | struct xfs_inode *ip); | 53 | struct xfs_inode *ip); |
54 | 54 | ||
diff --git a/fs/xfs/quota/xfs_qm_stats.c b/fs/xfs/quota/xfs_qm_stats.c index 21b08c0396a1..83e7ea3e25fa 100644 --- a/fs/xfs/quota/xfs_qm_stats.c +++ b/fs/xfs/quota/xfs_qm_stats.c | |||
@@ -48,50 +48,34 @@ | |||
48 | 48 | ||
49 | struct xqmstats xqmstats; | 49 | struct xqmstats xqmstats; |
50 | 50 | ||
51 | STATIC int | 51 | static int xqm_proc_show(struct seq_file *m, void *v) |
52 | xfs_qm_read_xfsquota( | ||
53 | char *buffer, | ||
54 | char **start, | ||
55 | off_t offset, | ||
56 | int count, | ||
57 | int *eof, | ||
58 | void *data) | ||
59 | { | 52 | { |
60 | int len; | ||
61 | |||
62 | /* maximum; incore; ratio free to inuse; freelist */ | 53 | /* maximum; incore; ratio free to inuse; freelist */ |
63 | len = sprintf(buffer, "%d\t%d\t%d\t%u\n", | 54 | seq_printf(m, "%d\t%d\t%d\t%u\n", |
64 | ndquot, | 55 | ndquot, |
65 | xfs_Gqm? atomic_read(&xfs_Gqm->qm_totaldquots) : 0, | 56 | xfs_Gqm? atomic_read(&xfs_Gqm->qm_totaldquots) : 0, |
66 | xfs_Gqm? xfs_Gqm->qm_dqfree_ratio : 0, | 57 | xfs_Gqm? xfs_Gqm->qm_dqfree_ratio : 0, |
67 | xfs_Gqm? xfs_Gqm->qm_dqfreelist.qh_nelems : 0); | 58 | xfs_Gqm? xfs_Gqm->qm_dqfreelist.qh_nelems : 0); |
68 | 59 | return 0; | |
69 | if (offset >= len) { | ||
70 | *start = buffer; | ||
71 | *eof = 1; | ||
72 | return 0; | ||
73 | } | ||
74 | *start = buffer + offset; | ||
75 | if ((len -= offset) > count) | ||
76 | return count; | ||
77 | *eof = 1; | ||
78 | |||
79 | return len; | ||
80 | } | 60 | } |
81 | 61 | ||
82 | STATIC int | 62 | static int xqm_proc_open(struct inode *inode, struct file *file) |
83 | xfs_qm_read_stats( | ||
84 | char *buffer, | ||
85 | char **start, | ||
86 | off_t offset, | ||
87 | int count, | ||
88 | int *eof, | ||
89 | void *data) | ||
90 | { | 63 | { |
91 | int len; | 64 | return single_open(file, xqm_proc_show, NULL); |
65 | } | ||
66 | |||
67 | static const struct file_operations xqm_proc_fops = { | ||
68 | .owner = THIS_MODULE, | ||
69 | .open = xqm_proc_open, | ||
70 | .read = seq_read, | ||
71 | .llseek = seq_lseek, | ||
72 | .release = single_release, | ||
73 | }; | ||
92 | 74 | ||
75 | static int xqmstat_proc_show(struct seq_file *m, void *v) | ||
76 | { | ||
93 | /* quota performance statistics */ | 77 | /* quota performance statistics */ |
94 | len = sprintf(buffer, "qm %u %u %u %u %u %u %u %u\n", | 78 | seq_printf(m, "qm %u %u %u %u %u %u %u %u\n", |
95 | xqmstats.xs_qm_dqreclaims, | 79 | xqmstats.xs_qm_dqreclaims, |
96 | xqmstats.xs_qm_dqreclaim_misses, | 80 | xqmstats.xs_qm_dqreclaim_misses, |
97 | xqmstats.xs_qm_dquot_dups, | 81 | xqmstats.xs_qm_dquot_dups, |
@@ -100,25 +84,27 @@ xfs_qm_read_stats( | |||
100 | xqmstats.xs_qm_dqwants, | 84 | xqmstats.xs_qm_dqwants, |
101 | xqmstats.xs_qm_dqshake_reclaims, | 85 | xqmstats.xs_qm_dqshake_reclaims, |
102 | xqmstats.xs_qm_dqinact_reclaims); | 86 | xqmstats.xs_qm_dqinact_reclaims); |
87 | return 0; | ||
88 | } | ||
103 | 89 | ||
104 | if (offset >= len) { | 90 | static int xqmstat_proc_open(struct inode *inode, struct file *file) |
105 | *start = buffer; | 91 | { |
106 | *eof = 1; | 92 | return single_open(file, xqmstat_proc_show, NULL); |
107 | return 0; | ||
108 | } | ||
109 | *start = buffer + offset; | ||
110 | if ((len -= offset) > count) | ||
111 | return count; | ||
112 | *eof = 1; | ||
113 | |||
114 | return len; | ||
115 | } | 93 | } |
116 | 94 | ||
95 | static const struct file_operations xqmstat_proc_fops = { | ||
96 | .owner = THIS_MODULE, | ||
97 | .open = xqmstat_proc_open, | ||
98 | .read = seq_read, | ||
99 | .llseek = seq_lseek, | ||
100 | .release = single_release, | ||
101 | }; | ||
102 | |||
117 | void | 103 | void |
118 | xfs_qm_init_procfs(void) | 104 | xfs_qm_init_procfs(void) |
119 | { | 105 | { |
120 | create_proc_read_entry("fs/xfs/xqmstat", 0, NULL, xfs_qm_read_stats, NULL); | 106 | proc_create("fs/xfs/xqmstat", 0, NULL, &xqmstat_proc_fops); |
121 | create_proc_read_entry("fs/xfs/xqm", 0, NULL, xfs_qm_read_xfsquota, NULL); | 107 | proc_create("fs/xfs/xqm", 0, NULL, &xqm_proc_fops); |
122 | } | 108 | } |
123 | 109 | ||
124 | void | 110 | void |
diff --git a/fs/xfs/xfs_ag.h b/fs/xfs/xfs_ag.h index f24b50b68d03..a5d54bf4931b 100644 --- a/fs/xfs/xfs_ag.h +++ b/fs/xfs/xfs_ag.h | |||
@@ -198,6 +198,15 @@ typedef struct xfs_perag | |||
198 | xfs_agino_t pagi_count; /* number of allocated inodes */ | 198 | xfs_agino_t pagi_count; /* number of allocated inodes */ |
199 | int pagb_count; /* pagb slots in use */ | 199 | int pagb_count; /* pagb slots in use */ |
200 | xfs_perag_busy_t *pagb_list; /* unstable blocks */ | 200 | xfs_perag_busy_t *pagb_list; /* unstable blocks */ |
201 | |||
202 | /* | ||
203 | * Inode allocation search lookup optimisation. | ||
204 | * If the pagino matches, the search for new inodes | ||
205 | * doesn't need to search the near ones again straight away | ||
206 | */ | ||
207 | xfs_agino_t pagl_pagino; | ||
208 | xfs_agino_t pagl_leftrec; | ||
209 | xfs_agino_t pagl_rightrec; | ||
201 | #ifdef __KERNEL__ | 210 | #ifdef __KERNEL__ |
202 | spinlock_t pagb_lock; /* lock for pagb_list */ | 211 | spinlock_t pagb_lock; /* lock for pagb_list */ |
203 | 212 | ||
diff --git a/fs/xfs/xfs_attr.c b/fs/xfs/xfs_attr.c index db15feb906ff..4ece1906bd41 100644 --- a/fs/xfs/xfs_attr.c +++ b/fs/xfs/xfs_attr.c | |||
@@ -2010,7 +2010,9 @@ xfs_attr_rmtval_get(xfs_da_args_t *args) | |||
2010 | dblkno = XFS_FSB_TO_DADDR(mp, map[i].br_startblock); | 2010 | dblkno = XFS_FSB_TO_DADDR(mp, map[i].br_startblock); |
2011 | blkcnt = XFS_FSB_TO_BB(mp, map[i].br_blockcount); | 2011 | blkcnt = XFS_FSB_TO_BB(mp, map[i].br_blockcount); |
2012 | error = xfs_read_buf(mp, mp->m_ddev_targp, dblkno, | 2012 | error = xfs_read_buf(mp, mp->m_ddev_targp, dblkno, |
2013 | blkcnt, XFS_BUF_LOCK, &bp); | 2013 | blkcnt, |
2014 | XFS_BUF_LOCK | XBF_DONT_BLOCK, | ||
2015 | &bp); | ||
2014 | if (error) | 2016 | if (error) |
2015 | return(error); | 2017 | return(error); |
2016 | 2018 | ||
@@ -2141,8 +2143,8 @@ xfs_attr_rmtval_set(xfs_da_args_t *args) | |||
2141 | dblkno = XFS_FSB_TO_DADDR(mp, map.br_startblock), | 2143 | dblkno = XFS_FSB_TO_DADDR(mp, map.br_startblock), |
2142 | blkcnt = XFS_FSB_TO_BB(mp, map.br_blockcount); | 2144 | blkcnt = XFS_FSB_TO_BB(mp, map.br_blockcount); |
2143 | 2145 | ||
2144 | bp = xfs_buf_get_flags(mp->m_ddev_targp, dblkno, | 2146 | bp = xfs_buf_get_flags(mp->m_ddev_targp, dblkno, blkcnt, |
2145 | blkcnt, XFS_BUF_LOCK); | 2147 | XFS_BUF_LOCK | XBF_DONT_BLOCK); |
2146 | ASSERT(bp); | 2148 | ASSERT(bp); |
2147 | ASSERT(!XFS_BUF_GETERROR(bp)); | 2149 | ASSERT(!XFS_BUF_GETERROR(bp)); |
2148 | 2150 | ||
diff --git a/fs/xfs/xfs_bmap.c b/fs/xfs/xfs_bmap.c index 7928b9983c1d..8971fb09d387 100644 --- a/fs/xfs/xfs_bmap.c +++ b/fs/xfs/xfs_bmap.c | |||
@@ -3713,7 +3713,7 @@ done: | |||
3713 | * entry (null if none). Else, *lastxp will be set to the index | 3713 | * entry (null if none). Else, *lastxp will be set to the index |
3714 | * of the found entry; *gotp will contain the entry. | 3714 | * of the found entry; *gotp will contain the entry. |
3715 | */ | 3715 | */ |
3716 | xfs_bmbt_rec_host_t * /* pointer to found extent entry */ | 3716 | STATIC xfs_bmbt_rec_host_t * /* pointer to found extent entry */ |
3717 | xfs_bmap_search_multi_extents( | 3717 | xfs_bmap_search_multi_extents( |
3718 | xfs_ifork_t *ifp, /* inode fork pointer */ | 3718 | xfs_ifork_t *ifp, /* inode fork pointer */ |
3719 | xfs_fileoff_t bno, /* block number searched for */ | 3719 | xfs_fileoff_t bno, /* block number searched for */ |
@@ -6009,7 +6009,7 @@ xfs_getbmap( | |||
6009 | */ | 6009 | */ |
6010 | error = ENOMEM; | 6010 | error = ENOMEM; |
6011 | subnex = 16; | 6011 | subnex = 16; |
6012 | map = kmem_alloc(subnex * sizeof(*map), KM_MAYFAIL); | 6012 | map = kmem_alloc(subnex * sizeof(*map), KM_MAYFAIL | KM_NOFS); |
6013 | if (!map) | 6013 | if (!map) |
6014 | goto out_unlock_ilock; | 6014 | goto out_unlock_ilock; |
6015 | 6015 | ||
diff --git a/fs/xfs/xfs_bmap.h b/fs/xfs/xfs_bmap.h index 1b8ff9256bd0..56f62d2edc35 100644 --- a/fs/xfs/xfs_bmap.h +++ b/fs/xfs/xfs_bmap.h | |||
@@ -392,17 +392,6 @@ xfs_bmap_count_blocks( | |||
392 | int whichfork, | 392 | int whichfork, |
393 | int *count); | 393 | int *count); |
394 | 394 | ||
395 | /* | ||
396 | * Search the extent records for the entry containing block bno. | ||
397 | * If bno lies in a hole, point to the next entry. If bno lies | ||
398 | * past eof, *eofp will be set, and *prevp will contain the last | ||
399 | * entry (null if none). Else, *lastxp will be set to the index | ||
400 | * of the found entry; *gotp will contain the entry. | ||
401 | */ | ||
402 | xfs_bmbt_rec_host_t * | ||
403 | xfs_bmap_search_multi_extents(struct xfs_ifork *, xfs_fileoff_t, int *, | ||
404 | xfs_extnum_t *, xfs_bmbt_irec_t *, xfs_bmbt_irec_t *); | ||
405 | |||
406 | #endif /* __KERNEL__ */ | 395 | #endif /* __KERNEL__ */ |
407 | 396 | ||
408 | #endif /* __XFS_BMAP_H__ */ | 397 | #endif /* __XFS_BMAP_H__ */ |
diff --git a/fs/xfs/xfs_bmap_btree.c b/fs/xfs/xfs_bmap_btree.c index 5c1ade06578e..eb7b702d0690 100644 --- a/fs/xfs/xfs_bmap_btree.c +++ b/fs/xfs/xfs_bmap_btree.c | |||
@@ -202,16 +202,6 @@ xfs_bmbt_get_state( | |||
202 | ext_flag); | 202 | ext_flag); |
203 | } | 203 | } |
204 | 204 | ||
205 | /* Endian flipping versions of the bmbt extraction functions */ | ||
206 | void | ||
207 | xfs_bmbt_disk_get_all( | ||
208 | xfs_bmbt_rec_t *r, | ||
209 | xfs_bmbt_irec_t *s) | ||
210 | { | ||
211 | __xfs_bmbt_get_all(get_unaligned_be64(&r->l0), | ||
212 | get_unaligned_be64(&r->l1), s); | ||
213 | } | ||
214 | |||
215 | /* | 205 | /* |
216 | * Extract the blockcount field from an on disk bmap extent record. | 206 | * Extract the blockcount field from an on disk bmap extent record. |
217 | */ | 207 | */ |
@@ -816,6 +806,16 @@ xfs_bmbt_trace_key( | |||
816 | *l1 = 0; | 806 | *l1 = 0; |
817 | } | 807 | } |
818 | 808 | ||
809 | /* Endian flipping versions of the bmbt extraction functions */ | ||
810 | STATIC void | ||
811 | xfs_bmbt_disk_get_all( | ||
812 | xfs_bmbt_rec_t *r, | ||
813 | xfs_bmbt_irec_t *s) | ||
814 | { | ||
815 | __xfs_bmbt_get_all(get_unaligned_be64(&r->l0), | ||
816 | get_unaligned_be64(&r->l1), s); | ||
817 | } | ||
818 | |||
819 | STATIC void | 819 | STATIC void |
820 | xfs_bmbt_trace_record( | 820 | xfs_bmbt_trace_record( |
821 | struct xfs_btree_cur *cur, | 821 | struct xfs_btree_cur *cur, |
diff --git a/fs/xfs/xfs_bmap_btree.h b/fs/xfs/xfs_bmap_btree.h index 0e8df007615e..5549d495947f 100644 --- a/fs/xfs/xfs_bmap_btree.h +++ b/fs/xfs/xfs_bmap_btree.h | |||
@@ -220,7 +220,6 @@ extern xfs_fsblock_t xfs_bmbt_get_startblock(xfs_bmbt_rec_host_t *r); | |||
220 | extern xfs_fileoff_t xfs_bmbt_get_startoff(xfs_bmbt_rec_host_t *r); | 220 | extern xfs_fileoff_t xfs_bmbt_get_startoff(xfs_bmbt_rec_host_t *r); |
221 | extern xfs_exntst_t xfs_bmbt_get_state(xfs_bmbt_rec_host_t *r); | 221 | extern xfs_exntst_t xfs_bmbt_get_state(xfs_bmbt_rec_host_t *r); |
222 | 222 | ||
223 | extern void xfs_bmbt_disk_get_all(xfs_bmbt_rec_t *r, xfs_bmbt_irec_t *s); | ||
224 | extern xfs_filblks_t xfs_bmbt_disk_get_blockcount(xfs_bmbt_rec_t *r); | 223 | extern xfs_filblks_t xfs_bmbt_disk_get_blockcount(xfs_bmbt_rec_t *r); |
225 | extern xfs_fileoff_t xfs_bmbt_disk_get_startoff(xfs_bmbt_rec_t *r); | 224 | extern xfs_fileoff_t xfs_bmbt_disk_get_startoff(xfs_bmbt_rec_t *r); |
226 | 225 | ||
diff --git a/fs/xfs/xfs_btree.c b/fs/xfs/xfs_btree.c index e9df99574829..52b5f14d0c32 100644 --- a/fs/xfs/xfs_btree.c +++ b/fs/xfs/xfs_btree.c | |||
@@ -120,8 +120,8 @@ xfs_btree_check_sblock( | |||
120 | XFS_RANDOM_BTREE_CHECK_SBLOCK))) { | 120 | XFS_RANDOM_BTREE_CHECK_SBLOCK))) { |
121 | if (bp) | 121 | if (bp) |
122 | xfs_buftrace("SBTREE ERROR", bp); | 122 | xfs_buftrace("SBTREE ERROR", bp); |
123 | XFS_ERROR_REPORT("xfs_btree_check_sblock", XFS_ERRLEVEL_LOW, | 123 | XFS_CORRUPTION_ERROR("xfs_btree_check_sblock", |
124 | cur->bc_mp); | 124 | XFS_ERRLEVEL_LOW, cur->bc_mp, block); |
125 | return XFS_ERROR(EFSCORRUPTED); | 125 | return XFS_ERROR(EFSCORRUPTED); |
126 | } | 126 | } |
127 | return 0; | 127 | return 0; |
@@ -646,46 +646,6 @@ xfs_btree_read_bufl( | |||
646 | } | 646 | } |
647 | 647 | ||
648 | /* | 648 | /* |
649 | * Get a buffer for the block, return it read in. | ||
650 | * Short-form addressing. | ||
651 | */ | ||
652 | int /* error */ | ||
653 | xfs_btree_read_bufs( | ||
654 | xfs_mount_t *mp, /* file system mount point */ | ||
655 | xfs_trans_t *tp, /* transaction pointer */ | ||
656 | xfs_agnumber_t agno, /* allocation group number */ | ||
657 | xfs_agblock_t agbno, /* allocation group block number */ | ||
658 | uint lock, /* lock flags for read_buf */ | ||
659 | xfs_buf_t **bpp, /* buffer for agno/agbno */ | ||
660 | int refval) /* ref count value for buffer */ | ||
661 | { | ||
662 | xfs_buf_t *bp; /* return value */ | ||
663 | xfs_daddr_t d; /* real disk block address */ | ||
664 | int error; | ||
665 | |||
666 | ASSERT(agno != NULLAGNUMBER); | ||
667 | ASSERT(agbno != NULLAGBLOCK); | ||
668 | d = XFS_AGB_TO_DADDR(mp, agno, agbno); | ||
669 | if ((error = xfs_trans_read_buf(mp, tp, mp->m_ddev_targp, d, | ||
670 | mp->m_bsize, lock, &bp))) { | ||
671 | return error; | ||
672 | } | ||
673 | ASSERT(!bp || !XFS_BUF_GETERROR(bp)); | ||
674 | if (bp != NULL) { | ||
675 | switch (refval) { | ||
676 | case XFS_ALLOC_BTREE_REF: | ||
677 | XFS_BUF_SET_VTYPE_REF(bp, B_FS_MAP, refval); | ||
678 | break; | ||
679 | case XFS_INO_BTREE_REF: | ||
680 | XFS_BUF_SET_VTYPE_REF(bp, B_FS_INOMAP, refval); | ||
681 | break; | ||
682 | } | ||
683 | } | ||
684 | *bpp = bp; | ||
685 | return 0; | ||
686 | } | ||
687 | |||
688 | /* | ||
689 | * Read-ahead the block, don't wait for it, don't return a buffer. | 649 | * Read-ahead the block, don't wait for it, don't return a buffer. |
690 | * Long-form addressing. | 650 | * Long-form addressing. |
691 | */ | 651 | */ |
@@ -2951,7 +2911,7 @@ error0: | |||
2951 | * inode we have to copy the single block it was pointing to into the | 2911 | * inode we have to copy the single block it was pointing to into the |
2952 | * inode. | 2912 | * inode. |
2953 | */ | 2913 | */ |
2954 | int | 2914 | STATIC int |
2955 | xfs_btree_kill_iroot( | 2915 | xfs_btree_kill_iroot( |
2956 | struct xfs_btree_cur *cur) | 2916 | struct xfs_btree_cur *cur) |
2957 | { | 2917 | { |
diff --git a/fs/xfs/xfs_btree.h b/fs/xfs/xfs_btree.h index 4f852b735b96..7fa07062bdda 100644 --- a/fs/xfs/xfs_btree.h +++ b/fs/xfs/xfs_btree.h | |||
@@ -379,20 +379,6 @@ xfs_btree_read_bufl( | |||
379 | int refval);/* ref count value for buffer */ | 379 | int refval);/* ref count value for buffer */ |
380 | 380 | ||
381 | /* | 381 | /* |
382 | * Get a buffer for the block, return it read in. | ||
383 | * Short-form addressing. | ||
384 | */ | ||
385 | int /* error */ | ||
386 | xfs_btree_read_bufs( | ||
387 | struct xfs_mount *mp, /* file system mount point */ | ||
388 | struct xfs_trans *tp, /* transaction pointer */ | ||
389 | xfs_agnumber_t agno, /* allocation group number */ | ||
390 | xfs_agblock_t agbno, /* allocation group block number */ | ||
391 | uint lock, /* lock flags for read_buf */ | ||
392 | struct xfs_buf **bpp, /* buffer for agno/agbno */ | ||
393 | int refval);/* ref count value for buffer */ | ||
394 | |||
395 | /* | ||
396 | * Read-ahead the block, don't wait for it, don't return a buffer. | 382 | * Read-ahead the block, don't wait for it, don't return a buffer. |
397 | * Long-form addressing. | 383 | * Long-form addressing. |
398 | */ | 384 | */ |
@@ -432,7 +418,6 @@ int xfs_btree_decrement(struct xfs_btree_cur *, int, int *); | |||
432 | int xfs_btree_lookup(struct xfs_btree_cur *, xfs_lookup_t, int *); | 418 | int xfs_btree_lookup(struct xfs_btree_cur *, xfs_lookup_t, int *); |
433 | int xfs_btree_update(struct xfs_btree_cur *, union xfs_btree_rec *); | 419 | int xfs_btree_update(struct xfs_btree_cur *, union xfs_btree_rec *); |
434 | int xfs_btree_new_iroot(struct xfs_btree_cur *, int *, int *); | 420 | int xfs_btree_new_iroot(struct xfs_btree_cur *, int *, int *); |
435 | int xfs_btree_kill_iroot(struct xfs_btree_cur *); | ||
436 | int xfs_btree_insert(struct xfs_btree_cur *, int *); | 421 | int xfs_btree_insert(struct xfs_btree_cur *, int *); |
437 | int xfs_btree_delete(struct xfs_btree_cur *, int *); | 422 | int xfs_btree_delete(struct xfs_btree_cur *, int *); |
438 | int xfs_btree_get_rec(struct xfs_btree_cur *, union xfs_btree_rec **, int *); | 423 | int xfs_btree_get_rec(struct xfs_btree_cur *, union xfs_btree_rec **, int *); |
diff --git a/fs/xfs/xfs_da_btree.c b/fs/xfs/xfs_da_btree.c index 9ff6e57a5075..2847bbc1c534 100644 --- a/fs/xfs/xfs_da_btree.c +++ b/fs/xfs/xfs_da_btree.c | |||
@@ -2201,7 +2201,7 @@ kmem_zone_t *xfs_dabuf_zone; /* dabuf zone */ | |||
2201 | xfs_da_state_t * | 2201 | xfs_da_state_t * |
2202 | xfs_da_state_alloc(void) | 2202 | xfs_da_state_alloc(void) |
2203 | { | 2203 | { |
2204 | return kmem_zone_zalloc(xfs_da_state_zone, KM_SLEEP); | 2204 | return kmem_zone_zalloc(xfs_da_state_zone, KM_NOFS); |
2205 | } | 2205 | } |
2206 | 2206 | ||
2207 | /* | 2207 | /* |
@@ -2261,9 +2261,9 @@ xfs_da_buf_make(int nbuf, xfs_buf_t **bps, inst_t *ra) | |||
2261 | int off; | 2261 | int off; |
2262 | 2262 | ||
2263 | if (nbuf == 1) | 2263 | if (nbuf == 1) |
2264 | dabuf = kmem_zone_alloc(xfs_dabuf_zone, KM_SLEEP); | 2264 | dabuf = kmem_zone_alloc(xfs_dabuf_zone, KM_NOFS); |
2265 | else | 2265 | else |
2266 | dabuf = kmem_alloc(XFS_DA_BUF_SIZE(nbuf), KM_SLEEP); | 2266 | dabuf = kmem_alloc(XFS_DA_BUF_SIZE(nbuf), KM_NOFS); |
2267 | dabuf->dirty = 0; | 2267 | dabuf->dirty = 0; |
2268 | #ifdef XFS_DABUF_DEBUG | 2268 | #ifdef XFS_DABUF_DEBUG |
2269 | dabuf->ra = ra; | 2269 | dabuf->ra = ra; |
diff --git a/fs/xfs/xfs_dir2.c b/fs/xfs/xfs_dir2.c index c657bec6d951..bb1d58eb3982 100644 --- a/fs/xfs/xfs_dir2.c +++ b/fs/xfs/xfs_dir2.c | |||
@@ -256,7 +256,7 @@ xfs_dir_cilookup_result( | |||
256 | !(args->op_flags & XFS_DA_OP_CILOOKUP)) | 256 | !(args->op_flags & XFS_DA_OP_CILOOKUP)) |
257 | return EEXIST; | 257 | return EEXIST; |
258 | 258 | ||
259 | args->value = kmem_alloc(len, KM_MAYFAIL); | 259 | args->value = kmem_alloc(len, KM_NOFS | KM_MAYFAIL); |
260 | if (!args->value) | 260 | if (!args->value) |
261 | return ENOMEM; | 261 | return ENOMEM; |
262 | 262 | ||
diff --git a/fs/xfs/xfs_fsops.c b/fs/xfs/xfs_fsops.c index cbd451bb4848..2d0b3e1da9e6 100644 --- a/fs/xfs/xfs_fsops.c +++ b/fs/xfs/xfs_fsops.c | |||
@@ -167,17 +167,25 @@ xfs_growfs_data_private( | |||
167 | new = nb - mp->m_sb.sb_dblocks; | 167 | new = nb - mp->m_sb.sb_dblocks; |
168 | oagcount = mp->m_sb.sb_agcount; | 168 | oagcount = mp->m_sb.sb_agcount; |
169 | if (nagcount > oagcount) { | 169 | if (nagcount > oagcount) { |
170 | void *new_perag, *old_perag; | ||
171 | |||
170 | xfs_filestream_flush(mp); | 172 | xfs_filestream_flush(mp); |
173 | |||
174 | new_perag = kmem_zalloc(sizeof(xfs_perag_t) * nagcount, | ||
175 | KM_MAYFAIL); | ||
176 | if (!new_perag) | ||
177 | return XFS_ERROR(ENOMEM); | ||
178 | |||
171 | down_write(&mp->m_peraglock); | 179 | down_write(&mp->m_peraglock); |
172 | mp->m_perag = kmem_realloc(mp->m_perag, | 180 | memcpy(new_perag, mp->m_perag, sizeof(xfs_perag_t) * oagcount); |
173 | sizeof(xfs_perag_t) * nagcount, | 181 | old_perag = mp->m_perag; |
174 | sizeof(xfs_perag_t) * oagcount, | 182 | mp->m_perag = new_perag; |
175 | KM_SLEEP); | 183 | |
176 | memset(&mp->m_perag[oagcount], 0, | ||
177 | (nagcount - oagcount) * sizeof(xfs_perag_t)); | ||
178 | mp->m_flags |= XFS_MOUNT_32BITINODES; | 184 | mp->m_flags |= XFS_MOUNT_32BITINODES; |
179 | nagimax = xfs_initialize_perag(mp, nagcount); | 185 | nagimax = xfs_initialize_perag(mp, nagcount); |
180 | up_write(&mp->m_peraglock); | 186 | up_write(&mp->m_peraglock); |
187 | |||
188 | kmem_free(old_perag); | ||
181 | } | 189 | } |
182 | tp = xfs_trans_alloc(mp, XFS_TRANS_GROWFS); | 190 | tp = xfs_trans_alloc(mp, XFS_TRANS_GROWFS); |
183 | tp->t_flags |= XFS_TRANS_RESERVE; | 191 | tp->t_flags |= XFS_TRANS_RESERVE; |
diff --git a/fs/xfs/xfs_ialloc.c b/fs/xfs/xfs_ialloc.c index 3120a3a5e20f..ab64f3efb43b 100644 --- a/fs/xfs/xfs_ialloc.c +++ b/fs/xfs/xfs_ialloc.c | |||
@@ -57,75 +57,35 @@ xfs_ialloc_cluster_alignment( | |||
57 | } | 57 | } |
58 | 58 | ||
59 | /* | 59 | /* |
60 | * Lookup the record equal to ino in the btree given by cur. | 60 | * Lookup a record by ino in the btree given by cur. |
61 | */ | ||
62 | STATIC int /* error */ | ||
63 | xfs_inobt_lookup_eq( | ||
64 | struct xfs_btree_cur *cur, /* btree cursor */ | ||
65 | xfs_agino_t ino, /* starting inode of chunk */ | ||
66 | __int32_t fcnt, /* free inode count */ | ||
67 | xfs_inofree_t free, /* free inode mask */ | ||
68 | int *stat) /* success/failure */ | ||
69 | { | ||
70 | cur->bc_rec.i.ir_startino = ino; | ||
71 | cur->bc_rec.i.ir_freecount = fcnt; | ||
72 | cur->bc_rec.i.ir_free = free; | ||
73 | return xfs_btree_lookup(cur, XFS_LOOKUP_EQ, stat); | ||
74 | } | ||
75 | |||
76 | /* | ||
77 | * Lookup the first record greater than or equal to ino | ||
78 | * in the btree given by cur. | ||
79 | */ | 61 | */ |
80 | int /* error */ | 62 | int /* error */ |
81 | xfs_inobt_lookup_ge( | 63 | xfs_inobt_lookup( |
82 | struct xfs_btree_cur *cur, /* btree cursor */ | 64 | struct xfs_btree_cur *cur, /* btree cursor */ |
83 | xfs_agino_t ino, /* starting inode of chunk */ | 65 | xfs_agino_t ino, /* starting inode of chunk */ |
84 | __int32_t fcnt, /* free inode count */ | 66 | xfs_lookup_t dir, /* <=, >=, == */ |
85 | xfs_inofree_t free, /* free inode mask */ | ||
86 | int *stat) /* success/failure */ | 67 | int *stat) /* success/failure */ |
87 | { | 68 | { |
88 | cur->bc_rec.i.ir_startino = ino; | 69 | cur->bc_rec.i.ir_startino = ino; |
89 | cur->bc_rec.i.ir_freecount = fcnt; | 70 | cur->bc_rec.i.ir_freecount = 0; |
90 | cur->bc_rec.i.ir_free = free; | 71 | cur->bc_rec.i.ir_free = 0; |
91 | return xfs_btree_lookup(cur, XFS_LOOKUP_GE, stat); | 72 | return xfs_btree_lookup(cur, dir, stat); |
92 | } | 73 | } |
93 | 74 | ||
94 | /* | 75 | /* |
95 | * Lookup the first record less than or equal to ino | 76 | * Update the record referred to by cur to the value given. |
96 | * in the btree given by cur. | ||
97 | */ | ||
98 | int /* error */ | ||
99 | xfs_inobt_lookup_le( | ||
100 | struct xfs_btree_cur *cur, /* btree cursor */ | ||
101 | xfs_agino_t ino, /* starting inode of chunk */ | ||
102 | __int32_t fcnt, /* free inode count */ | ||
103 | xfs_inofree_t free, /* free inode mask */ | ||
104 | int *stat) /* success/failure */ | ||
105 | { | ||
106 | cur->bc_rec.i.ir_startino = ino; | ||
107 | cur->bc_rec.i.ir_freecount = fcnt; | ||
108 | cur->bc_rec.i.ir_free = free; | ||
109 | return xfs_btree_lookup(cur, XFS_LOOKUP_LE, stat); | ||
110 | } | ||
111 | |||
112 | /* | ||
113 | * Update the record referred to by cur to the value given | ||
114 | * by [ino, fcnt, free]. | ||
115 | * This either works (return 0) or gets an EFSCORRUPTED error. | 77 | * This either works (return 0) or gets an EFSCORRUPTED error. |
116 | */ | 78 | */ |
117 | STATIC int /* error */ | 79 | STATIC int /* error */ |
118 | xfs_inobt_update( | 80 | xfs_inobt_update( |
119 | struct xfs_btree_cur *cur, /* btree cursor */ | 81 | struct xfs_btree_cur *cur, /* btree cursor */ |
120 | xfs_agino_t ino, /* starting inode of chunk */ | 82 | xfs_inobt_rec_incore_t *irec) /* btree record */ |
121 | __int32_t fcnt, /* free inode count */ | ||
122 | xfs_inofree_t free) /* free inode mask */ | ||
123 | { | 83 | { |
124 | union xfs_btree_rec rec; | 84 | union xfs_btree_rec rec; |
125 | 85 | ||
126 | rec.inobt.ir_startino = cpu_to_be32(ino); | 86 | rec.inobt.ir_startino = cpu_to_be32(irec->ir_startino); |
127 | rec.inobt.ir_freecount = cpu_to_be32(fcnt); | 87 | rec.inobt.ir_freecount = cpu_to_be32(irec->ir_freecount); |
128 | rec.inobt.ir_free = cpu_to_be64(free); | 88 | rec.inobt.ir_free = cpu_to_be64(irec->ir_free); |
129 | return xfs_btree_update(cur, &rec); | 89 | return xfs_btree_update(cur, &rec); |
130 | } | 90 | } |
131 | 91 | ||
@@ -135,9 +95,7 @@ xfs_inobt_update( | |||
135 | int /* error */ | 95 | int /* error */ |
136 | xfs_inobt_get_rec( | 96 | xfs_inobt_get_rec( |
137 | struct xfs_btree_cur *cur, /* btree cursor */ | 97 | struct xfs_btree_cur *cur, /* btree cursor */ |
138 | xfs_agino_t *ino, /* output: starting inode of chunk */ | 98 | xfs_inobt_rec_incore_t *irec, /* btree record */ |
139 | __int32_t *fcnt, /* output: number of free inodes */ | ||
140 | xfs_inofree_t *free, /* output: free inode mask */ | ||
141 | int *stat) /* output: success/failure */ | 99 | int *stat) /* output: success/failure */ |
142 | { | 100 | { |
143 | union xfs_btree_rec *rec; | 101 | union xfs_btree_rec *rec; |
@@ -145,14 +103,136 @@ xfs_inobt_get_rec( | |||
145 | 103 | ||
146 | error = xfs_btree_get_rec(cur, &rec, stat); | 104 | error = xfs_btree_get_rec(cur, &rec, stat); |
147 | if (!error && *stat == 1) { | 105 | if (!error && *stat == 1) { |
148 | *ino = be32_to_cpu(rec->inobt.ir_startino); | 106 | irec->ir_startino = be32_to_cpu(rec->inobt.ir_startino); |
149 | *fcnt = be32_to_cpu(rec->inobt.ir_freecount); | 107 | irec->ir_freecount = be32_to_cpu(rec->inobt.ir_freecount); |
150 | *free = be64_to_cpu(rec->inobt.ir_free); | 108 | irec->ir_free = be64_to_cpu(rec->inobt.ir_free); |
151 | } | 109 | } |
152 | return error; | 110 | return error; |
153 | } | 111 | } |
154 | 112 | ||
155 | /* | 113 | /* |
114 | * Verify that the number of free inodes in the AGI is correct. | ||
115 | */ | ||
116 | #ifdef DEBUG | ||
117 | STATIC int | ||
118 | xfs_check_agi_freecount( | ||
119 | struct xfs_btree_cur *cur, | ||
120 | struct xfs_agi *agi) | ||
121 | { | ||
122 | if (cur->bc_nlevels == 1) { | ||
123 | xfs_inobt_rec_incore_t rec; | ||
124 | int freecount = 0; | ||
125 | int error; | ||
126 | int i; | ||
127 | |||
128 | error = xfs_inobt_lookup(cur, 0, XFS_LOOKUP_GE, &i); | ||
129 | if (error) | ||
130 | return error; | ||
131 | |||
132 | do { | ||
133 | error = xfs_inobt_get_rec(cur, &rec, &i); | ||
134 | if (error) | ||
135 | return error; | ||
136 | |||
137 | if (i) { | ||
138 | freecount += rec.ir_freecount; | ||
139 | error = xfs_btree_increment(cur, 0, &i); | ||
140 | if (error) | ||
141 | return error; | ||
142 | } | ||
143 | } while (i == 1); | ||
144 | |||
145 | if (!XFS_FORCED_SHUTDOWN(cur->bc_mp)) | ||
146 | ASSERT(freecount == be32_to_cpu(agi->agi_freecount)); | ||
147 | } | ||
148 | return 0; | ||
149 | } | ||
150 | #else | ||
151 | #define xfs_check_agi_freecount(cur, agi) 0 | ||
152 | #endif | ||
153 | |||
154 | /* | ||
155 | * Initialise a new set of inodes. | ||
156 | */ | ||
157 | STATIC void | ||
158 | xfs_ialloc_inode_init( | ||
159 | struct xfs_mount *mp, | ||
160 | struct xfs_trans *tp, | ||
161 | xfs_agnumber_t agno, | ||
162 | xfs_agblock_t agbno, | ||
163 | xfs_agblock_t length, | ||
164 | unsigned int gen) | ||
165 | { | ||
166 | struct xfs_buf *fbuf; | ||
167 | struct xfs_dinode *free; | ||
168 | int blks_per_cluster, nbufs, ninodes; | ||
169 | int version; | ||
170 | int i, j; | ||
171 | xfs_daddr_t d; | ||
172 | |||
173 | /* | ||
174 | * Loop over the new block(s), filling in the inodes. | ||
175 | * For small block sizes, manipulate the inodes in buffers | ||
176 | * which are multiples of the blocks size. | ||
177 | */ | ||
178 | if (mp->m_sb.sb_blocksize >= XFS_INODE_CLUSTER_SIZE(mp)) { | ||
179 | blks_per_cluster = 1; | ||
180 | nbufs = length; | ||
181 | ninodes = mp->m_sb.sb_inopblock; | ||
182 | } else { | ||
183 | blks_per_cluster = XFS_INODE_CLUSTER_SIZE(mp) / | ||
184 | mp->m_sb.sb_blocksize; | ||
185 | nbufs = length / blks_per_cluster; | ||
186 | ninodes = blks_per_cluster * mp->m_sb.sb_inopblock; | ||
187 | } | ||
188 | |||
189 | /* | ||
190 | * Figure out what version number to use in the inodes we create. | ||
191 | * If the superblock version has caught up to the one that supports | ||
192 | * the new inode format, then use the new inode version. Otherwise | ||
193 | * use the old version so that old kernels will continue to be | ||
194 | * able to use the file system. | ||
195 | */ | ||
196 | if (xfs_sb_version_hasnlink(&mp->m_sb)) | ||
197 | version = 2; | ||
198 | else | ||
199 | version = 1; | ||
200 | |||
201 | for (j = 0; j < nbufs; j++) { | ||
202 | /* | ||
203 | * Get the block. | ||
204 | */ | ||
205 | d = XFS_AGB_TO_DADDR(mp, agno, agbno + (j * blks_per_cluster)); | ||
206 | fbuf = xfs_trans_get_buf(tp, mp->m_ddev_targp, d, | ||
207 | mp->m_bsize * blks_per_cluster, | ||
208 | XFS_BUF_LOCK); | ||
209 | ASSERT(fbuf); | ||
210 | ASSERT(!XFS_BUF_GETERROR(fbuf)); | ||
211 | |||
212 | /* | ||
213 | * Initialize all inodes in this buffer and then log them. | ||
214 | * | ||
215 | * XXX: It would be much better if we had just one transaction | ||
216 | * to log a whole cluster of inodes instead of all the | ||
217 | * individual transactions causing a lot of log traffic. | ||
218 | */ | ||
219 | xfs_biozero(fbuf, 0, ninodes << mp->m_sb.sb_inodelog); | ||
220 | for (i = 0; i < ninodes; i++) { | ||
221 | int ioffset = i << mp->m_sb.sb_inodelog; | ||
222 | uint isize = sizeof(struct xfs_dinode); | ||
223 | |||
224 | free = xfs_make_iptr(mp, fbuf, i); | ||
225 | free->di_magic = cpu_to_be16(XFS_DINODE_MAGIC); | ||
226 | free->di_version = version; | ||
227 | free->di_gen = cpu_to_be32(gen); | ||
228 | free->di_next_unlinked = cpu_to_be32(NULLAGINO); | ||
229 | xfs_trans_log_buf(tp, fbuf, ioffset, ioffset + isize - 1); | ||
230 | } | ||
231 | xfs_trans_inode_alloc_buf(tp, fbuf); | ||
232 | } | ||
233 | } | ||
234 | |||
235 | /* | ||
156 | * Allocate new inodes in the allocation group specified by agbp. | 236 | * Allocate new inodes in the allocation group specified by agbp. |
157 | * Return 0 for success, else error code. | 237 | * Return 0 for success, else error code. |
158 | */ | 238 | */ |
@@ -164,24 +244,15 @@ xfs_ialloc_ag_alloc( | |||
164 | { | 244 | { |
165 | xfs_agi_t *agi; /* allocation group header */ | 245 | xfs_agi_t *agi; /* allocation group header */ |
166 | xfs_alloc_arg_t args; /* allocation argument structure */ | 246 | xfs_alloc_arg_t args; /* allocation argument structure */ |
167 | int blks_per_cluster; /* fs blocks per inode cluster */ | ||
168 | xfs_btree_cur_t *cur; /* inode btree cursor */ | 247 | xfs_btree_cur_t *cur; /* inode btree cursor */ |
169 | xfs_daddr_t d; /* disk addr of buffer */ | ||
170 | xfs_agnumber_t agno; | 248 | xfs_agnumber_t agno; |
171 | int error; | 249 | int error; |
172 | xfs_buf_t *fbuf; /* new free inodes' buffer */ | 250 | int i; |
173 | xfs_dinode_t *free; /* new free inode structure */ | ||
174 | int i; /* inode counter */ | ||
175 | int j; /* block counter */ | ||
176 | int nbufs; /* num bufs of new inodes */ | ||
177 | xfs_agino_t newino; /* new first inode's number */ | 251 | xfs_agino_t newino; /* new first inode's number */ |
178 | xfs_agino_t newlen; /* new number of inodes */ | 252 | xfs_agino_t newlen; /* new number of inodes */ |
179 | int ninodes; /* num inodes per buf */ | ||
180 | xfs_agino_t thisino; /* current inode number, for loop */ | 253 | xfs_agino_t thisino; /* current inode number, for loop */ |
181 | int version; /* inode version number to use */ | ||
182 | int isaligned = 0; /* inode allocation at stripe unit */ | 254 | int isaligned = 0; /* inode allocation at stripe unit */ |
183 | /* boundary */ | 255 | /* boundary */ |
184 | unsigned int gen; | ||
185 | 256 | ||
186 | args.tp = tp; | 257 | args.tp = tp; |
187 | args.mp = tp->t_mountp; | 258 | args.mp = tp->t_mountp; |
@@ -202,12 +273,12 @@ xfs_ialloc_ag_alloc( | |||
202 | */ | 273 | */ |
203 | agi = XFS_BUF_TO_AGI(agbp); | 274 | agi = XFS_BUF_TO_AGI(agbp); |
204 | newino = be32_to_cpu(agi->agi_newino); | 275 | newino = be32_to_cpu(agi->agi_newino); |
276 | agno = be32_to_cpu(agi->agi_seqno); | ||
205 | args.agbno = XFS_AGINO_TO_AGBNO(args.mp, newino) + | 277 | args.agbno = XFS_AGINO_TO_AGBNO(args.mp, newino) + |
206 | XFS_IALLOC_BLOCKS(args.mp); | 278 | XFS_IALLOC_BLOCKS(args.mp); |
207 | if (likely(newino != NULLAGINO && | 279 | if (likely(newino != NULLAGINO && |
208 | (args.agbno < be32_to_cpu(agi->agi_length)))) { | 280 | (args.agbno < be32_to_cpu(agi->agi_length)))) { |
209 | args.fsbno = XFS_AGB_TO_FSB(args.mp, | 281 | args.fsbno = XFS_AGB_TO_FSB(args.mp, agno, args.agbno); |
210 | be32_to_cpu(agi->agi_seqno), args.agbno); | ||
211 | args.type = XFS_ALLOCTYPE_THIS_BNO; | 282 | args.type = XFS_ALLOCTYPE_THIS_BNO; |
212 | args.mod = args.total = args.wasdel = args.isfl = | 283 | args.mod = args.total = args.wasdel = args.isfl = |
213 | args.userdata = args.minalignslop = 0; | 284 | args.userdata = args.minalignslop = 0; |
@@ -258,8 +329,7 @@ xfs_ialloc_ag_alloc( | |||
258 | * For now, just allocate blocks up front. | 329 | * For now, just allocate blocks up front. |
259 | */ | 330 | */ |
260 | args.agbno = be32_to_cpu(agi->agi_root); | 331 | args.agbno = be32_to_cpu(agi->agi_root); |
261 | args.fsbno = XFS_AGB_TO_FSB(args.mp, | 332 | args.fsbno = XFS_AGB_TO_FSB(args.mp, agno, args.agbno); |
262 | be32_to_cpu(agi->agi_seqno), args.agbno); | ||
263 | /* | 333 | /* |
264 | * Allocate a fixed-size extent of inodes. | 334 | * Allocate a fixed-size extent of inodes. |
265 | */ | 335 | */ |
@@ -282,8 +352,7 @@ xfs_ialloc_ag_alloc( | |||
282 | if (isaligned && args.fsbno == NULLFSBLOCK) { | 352 | if (isaligned && args.fsbno == NULLFSBLOCK) { |
283 | args.type = XFS_ALLOCTYPE_NEAR_BNO; | 353 | args.type = XFS_ALLOCTYPE_NEAR_BNO; |
284 | args.agbno = be32_to_cpu(agi->agi_root); | 354 | args.agbno = be32_to_cpu(agi->agi_root); |
285 | args.fsbno = XFS_AGB_TO_FSB(args.mp, | 355 | args.fsbno = XFS_AGB_TO_FSB(args.mp, agno, args.agbno); |
286 | be32_to_cpu(agi->agi_seqno), args.agbno); | ||
287 | args.alignment = xfs_ialloc_cluster_alignment(&args); | 356 | args.alignment = xfs_ialloc_cluster_alignment(&args); |
288 | if ((error = xfs_alloc_vextent(&args))) | 357 | if ((error = xfs_alloc_vextent(&args))) |
289 | return error; | 358 | return error; |
@@ -294,85 +363,30 @@ xfs_ialloc_ag_alloc( | |||
294 | return 0; | 363 | return 0; |
295 | } | 364 | } |
296 | ASSERT(args.len == args.minlen); | 365 | ASSERT(args.len == args.minlen); |
297 | /* | ||
298 | * Convert the results. | ||
299 | */ | ||
300 | newino = XFS_OFFBNO_TO_AGINO(args.mp, args.agbno, 0); | ||
301 | /* | ||
302 | * Loop over the new block(s), filling in the inodes. | ||
303 | * For small block sizes, manipulate the inodes in buffers | ||
304 | * which are multiples of the blocks size. | ||
305 | */ | ||
306 | if (args.mp->m_sb.sb_blocksize >= XFS_INODE_CLUSTER_SIZE(args.mp)) { | ||
307 | blks_per_cluster = 1; | ||
308 | nbufs = (int)args.len; | ||
309 | ninodes = args.mp->m_sb.sb_inopblock; | ||
310 | } else { | ||
311 | blks_per_cluster = XFS_INODE_CLUSTER_SIZE(args.mp) / | ||
312 | args.mp->m_sb.sb_blocksize; | ||
313 | nbufs = (int)args.len / blks_per_cluster; | ||
314 | ninodes = blks_per_cluster * args.mp->m_sb.sb_inopblock; | ||
315 | } | ||
316 | /* | ||
317 | * Figure out what version number to use in the inodes we create. | ||
318 | * If the superblock version has caught up to the one that supports | ||
319 | * the new inode format, then use the new inode version. Otherwise | ||
320 | * use the old version so that old kernels will continue to be | ||
321 | * able to use the file system. | ||
322 | */ | ||
323 | if (xfs_sb_version_hasnlink(&args.mp->m_sb)) | ||
324 | version = 2; | ||
325 | else | ||
326 | version = 1; | ||
327 | 366 | ||
328 | /* | 367 | /* |
368 | * Stamp and write the inode buffers. | ||
369 | * | ||
329 | * Seed the new inode cluster with a random generation number. This | 370 | * Seed the new inode cluster with a random generation number. This |
330 | * prevents short-term reuse of generation numbers if a chunk is | 371 | * prevents short-term reuse of generation numbers if a chunk is |
331 | * freed and then immediately reallocated. We use random numbers | 372 | * freed and then immediately reallocated. We use random numbers |
332 | * rather than a linear progression to prevent the next generation | 373 | * rather than a linear progression to prevent the next generation |
333 | * number from being easily guessable. | 374 | * number from being easily guessable. |
334 | */ | 375 | */ |
335 | gen = random32(); | 376 | xfs_ialloc_inode_init(args.mp, tp, agno, args.agbno, args.len, |
336 | for (j = 0; j < nbufs; j++) { | 377 | random32()); |
337 | /* | ||
338 | * Get the block. | ||
339 | */ | ||
340 | d = XFS_AGB_TO_DADDR(args.mp, be32_to_cpu(agi->agi_seqno), | ||
341 | args.agbno + (j * blks_per_cluster)); | ||
342 | fbuf = xfs_trans_get_buf(tp, args.mp->m_ddev_targp, d, | ||
343 | args.mp->m_bsize * blks_per_cluster, | ||
344 | XFS_BUF_LOCK); | ||
345 | ASSERT(fbuf); | ||
346 | ASSERT(!XFS_BUF_GETERROR(fbuf)); | ||
347 | 378 | ||
348 | /* | 379 | /* |
349 | * Initialize all inodes in this buffer and then log them. | 380 | * Convert the results. |
350 | * | 381 | */ |
351 | * XXX: It would be much better if we had just one transaction to | 382 | newino = XFS_OFFBNO_TO_AGINO(args.mp, args.agbno, 0); |
352 | * log a whole cluster of inodes instead of all the individual | ||
353 | * transactions causing a lot of log traffic. | ||
354 | */ | ||
355 | xfs_biozero(fbuf, 0, ninodes << args.mp->m_sb.sb_inodelog); | ||
356 | for (i = 0; i < ninodes; i++) { | ||
357 | int ioffset = i << args.mp->m_sb.sb_inodelog; | ||
358 | uint isize = sizeof(struct xfs_dinode); | ||
359 | |||
360 | free = xfs_make_iptr(args.mp, fbuf, i); | ||
361 | free->di_magic = cpu_to_be16(XFS_DINODE_MAGIC); | ||
362 | free->di_version = version; | ||
363 | free->di_gen = cpu_to_be32(gen); | ||
364 | free->di_next_unlinked = cpu_to_be32(NULLAGINO); | ||
365 | xfs_trans_log_buf(tp, fbuf, ioffset, ioffset + isize - 1); | ||
366 | } | ||
367 | xfs_trans_inode_alloc_buf(tp, fbuf); | ||
368 | } | ||
369 | be32_add_cpu(&agi->agi_count, newlen); | 383 | be32_add_cpu(&agi->agi_count, newlen); |
370 | be32_add_cpu(&agi->agi_freecount, newlen); | 384 | be32_add_cpu(&agi->agi_freecount, newlen); |
371 | agno = be32_to_cpu(agi->agi_seqno); | ||
372 | down_read(&args.mp->m_peraglock); | 385 | down_read(&args.mp->m_peraglock); |
373 | args.mp->m_perag[agno].pagi_freecount += newlen; | 386 | args.mp->m_perag[agno].pagi_freecount += newlen; |
374 | up_read(&args.mp->m_peraglock); | 387 | up_read(&args.mp->m_peraglock); |
375 | agi->agi_newino = cpu_to_be32(newino); | 388 | agi->agi_newino = cpu_to_be32(newino); |
389 | |||
376 | /* | 390 | /* |
377 | * Insert records describing the new inode chunk into the btree. | 391 | * Insert records describing the new inode chunk into the btree. |
378 | */ | 392 | */ |
@@ -380,13 +394,17 @@ xfs_ialloc_ag_alloc( | |||
380 | for (thisino = newino; | 394 | for (thisino = newino; |
381 | thisino < newino + newlen; | 395 | thisino < newino + newlen; |
382 | thisino += XFS_INODES_PER_CHUNK) { | 396 | thisino += XFS_INODES_PER_CHUNK) { |
383 | if ((error = xfs_inobt_lookup_eq(cur, thisino, | 397 | cur->bc_rec.i.ir_startino = thisino; |
384 | XFS_INODES_PER_CHUNK, XFS_INOBT_ALL_FREE, &i))) { | 398 | cur->bc_rec.i.ir_freecount = XFS_INODES_PER_CHUNK; |
399 | cur->bc_rec.i.ir_free = XFS_INOBT_ALL_FREE; | ||
400 | error = xfs_btree_lookup(cur, XFS_LOOKUP_EQ, &i); | ||
401 | if (error) { | ||
385 | xfs_btree_del_cursor(cur, XFS_BTREE_ERROR); | 402 | xfs_btree_del_cursor(cur, XFS_BTREE_ERROR); |
386 | return error; | 403 | return error; |
387 | } | 404 | } |
388 | ASSERT(i == 0); | 405 | ASSERT(i == 0); |
389 | if ((error = xfs_btree_insert(cur, &i))) { | 406 | error = xfs_btree_insert(cur, &i); |
407 | if (error) { | ||
390 | xfs_btree_del_cursor(cur, XFS_BTREE_ERROR); | 408 | xfs_btree_del_cursor(cur, XFS_BTREE_ERROR); |
391 | return error; | 409 | return error; |
392 | } | 410 | } |
@@ -539,6 +557,62 @@ nextag: | |||
539 | } | 557 | } |
540 | 558 | ||
541 | /* | 559 | /* |
560 | * Try to retrieve the next record to the left/right from the current one. | ||
561 | */ | ||
562 | STATIC int | ||
563 | xfs_ialloc_next_rec( | ||
564 | struct xfs_btree_cur *cur, | ||
565 | xfs_inobt_rec_incore_t *rec, | ||
566 | int *done, | ||
567 | int left) | ||
568 | { | ||
569 | int error; | ||
570 | int i; | ||
571 | |||
572 | if (left) | ||
573 | error = xfs_btree_decrement(cur, 0, &i); | ||
574 | else | ||
575 | error = xfs_btree_increment(cur, 0, &i); | ||
576 | |||
577 | if (error) | ||
578 | return error; | ||
579 | *done = !i; | ||
580 | if (i) { | ||
581 | error = xfs_inobt_get_rec(cur, rec, &i); | ||
582 | if (error) | ||
583 | return error; | ||
584 | XFS_WANT_CORRUPTED_RETURN(i == 1); | ||
585 | } | ||
586 | |||
587 | return 0; | ||
588 | } | ||
589 | |||
590 | STATIC int | ||
591 | xfs_ialloc_get_rec( | ||
592 | struct xfs_btree_cur *cur, | ||
593 | xfs_agino_t agino, | ||
594 | xfs_inobt_rec_incore_t *rec, | ||
595 | int *done, | ||
596 | int left) | ||
597 | { | ||
598 | int error; | ||
599 | int i; | ||
600 | |||
601 | error = xfs_inobt_lookup(cur, agino, XFS_LOOKUP_EQ, &i); | ||
602 | if (error) | ||
603 | return error; | ||
604 | *done = !i; | ||
605 | if (i) { | ||
606 | error = xfs_inobt_get_rec(cur, rec, &i); | ||
607 | if (error) | ||
608 | return error; | ||
609 | XFS_WANT_CORRUPTED_RETURN(i == 1); | ||
610 | } | ||
611 | |||
612 | return 0; | ||
613 | } | ||
614 | |||
615 | /* | ||
542 | * Visible inode allocation functions. | 616 | * Visible inode allocation functions. |
543 | */ | 617 | */ |
544 | 618 | ||
@@ -592,8 +666,8 @@ xfs_dialloc( | |||
592 | int j; /* result code */ | 666 | int j; /* result code */ |
593 | xfs_mount_t *mp; /* file system mount structure */ | 667 | xfs_mount_t *mp; /* file system mount structure */ |
594 | int offset; /* index of inode in chunk */ | 668 | int offset; /* index of inode in chunk */ |
595 | xfs_agino_t pagino; /* parent's a.g. relative inode # */ | 669 | xfs_agino_t pagino; /* parent's AG relative inode # */ |
596 | xfs_agnumber_t pagno; /* parent's allocation group number */ | 670 | xfs_agnumber_t pagno; /* parent's AG number */ |
597 | xfs_inobt_rec_incore_t rec; /* inode allocation record */ | 671 | xfs_inobt_rec_incore_t rec; /* inode allocation record */ |
598 | xfs_agnumber_t tagno; /* testing allocation group number */ | 672 | xfs_agnumber_t tagno; /* testing allocation group number */ |
599 | xfs_btree_cur_t *tcur; /* temp cursor */ | 673 | xfs_btree_cur_t *tcur; /* temp cursor */ |
@@ -716,6 +790,8 @@ nextag: | |||
716 | */ | 790 | */ |
717 | agno = tagno; | 791 | agno = tagno; |
718 | *IO_agbp = NULL; | 792 | *IO_agbp = NULL; |
793 | |||
794 | restart_pagno: | ||
719 | cur = xfs_inobt_init_cursor(mp, tp, agbp, be32_to_cpu(agi->agi_seqno)); | 795 | cur = xfs_inobt_init_cursor(mp, tp, agbp, be32_to_cpu(agi->agi_seqno)); |
720 | /* | 796 | /* |
721 | * If pagino is 0 (this is the root inode allocation) use newino. | 797 | * If pagino is 0 (this is the root inode allocation) use newino. |
@@ -723,220 +799,199 @@ nextag: | |||
723 | */ | 799 | */ |
724 | if (!pagino) | 800 | if (!pagino) |
725 | pagino = be32_to_cpu(agi->agi_newino); | 801 | pagino = be32_to_cpu(agi->agi_newino); |
726 | #ifdef DEBUG | ||
727 | if (cur->bc_nlevels == 1) { | ||
728 | int freecount = 0; | ||
729 | 802 | ||
730 | if ((error = xfs_inobt_lookup_ge(cur, 0, 0, 0, &i))) | 803 | error = xfs_check_agi_freecount(cur, agi); |
731 | goto error0; | 804 | if (error) |
732 | XFS_WANT_CORRUPTED_GOTO(i == 1, error0); | 805 | goto error0; |
733 | do { | ||
734 | if ((error = xfs_inobt_get_rec(cur, &rec.ir_startino, | ||
735 | &rec.ir_freecount, &rec.ir_free, &i))) | ||
736 | goto error0; | ||
737 | XFS_WANT_CORRUPTED_GOTO(i == 1, error0); | ||
738 | freecount += rec.ir_freecount; | ||
739 | if ((error = xfs_btree_increment(cur, 0, &i))) | ||
740 | goto error0; | ||
741 | } while (i == 1); | ||
742 | 806 | ||
743 | ASSERT(freecount == be32_to_cpu(agi->agi_freecount) || | ||
744 | XFS_FORCED_SHUTDOWN(mp)); | ||
745 | } | ||
746 | #endif | ||
747 | /* | 807 | /* |
748 | * If in the same a.g. as the parent, try to get near the parent. | 808 | * If in the same AG as the parent, try to get near the parent. |
749 | */ | 809 | */ |
750 | if (pagno == agno) { | 810 | if (pagno == agno) { |
751 | if ((error = xfs_inobt_lookup_le(cur, pagino, 0, 0, &i))) | 811 | xfs_perag_t *pag = &mp->m_perag[agno]; |
812 | int doneleft; /* done, to the left */ | ||
813 | int doneright; /* done, to the right */ | ||
814 | int searchdistance = 10; | ||
815 | |||
816 | error = xfs_inobt_lookup(cur, pagino, XFS_LOOKUP_LE, &i); | ||
817 | if (error) | ||
818 | goto error0; | ||
819 | XFS_WANT_CORRUPTED_GOTO(i == 1, error0); | ||
820 | |||
821 | error = xfs_inobt_get_rec(cur, &rec, &j); | ||
822 | if (error) | ||
752 | goto error0; | 823 | goto error0; |
753 | if (i != 0 && | 824 | XFS_WANT_CORRUPTED_GOTO(i == 1, error0); |
754 | (error = xfs_inobt_get_rec(cur, &rec.ir_startino, | 825 | |
755 | &rec.ir_freecount, &rec.ir_free, &j)) == 0 && | 826 | if (rec.ir_freecount > 0) { |
756 | j == 1 && | ||
757 | rec.ir_freecount > 0) { | ||
758 | /* | 827 | /* |
759 | * Found a free inode in the same chunk | 828 | * Found a free inode in the same chunk |
760 | * as parent, done. | 829 | * as the parent, done. |
761 | */ | 830 | */ |
831 | goto alloc_inode; | ||
762 | } | 832 | } |
833 | |||
834 | |||
835 | /* | ||
836 | * In the same AG as parent, but parent's chunk is full. | ||
837 | */ | ||
838 | |||
839 | /* duplicate the cursor, search left & right simultaneously */ | ||
840 | error = xfs_btree_dup_cursor(cur, &tcur); | ||
841 | if (error) | ||
842 | goto error0; | ||
843 | |||
763 | /* | 844 | /* |
764 | * In the same a.g. as parent, but parent's chunk is full. | 845 | * Skip to last blocks looked up if same parent inode. |
765 | */ | 846 | */ |
766 | else { | 847 | if (pagino != NULLAGINO && |
767 | int doneleft; /* done, to the left */ | 848 | pag->pagl_pagino == pagino && |
768 | int doneright; /* done, to the right */ | 849 | pag->pagl_leftrec != NULLAGINO && |
850 | pag->pagl_rightrec != NULLAGINO) { | ||
851 | error = xfs_ialloc_get_rec(tcur, pag->pagl_leftrec, | ||
852 | &trec, &doneleft, 1); | ||
853 | if (error) | ||
854 | goto error1; | ||
769 | 855 | ||
856 | error = xfs_ialloc_get_rec(cur, pag->pagl_rightrec, | ||
857 | &rec, &doneright, 0); | ||
770 | if (error) | 858 | if (error) |
771 | goto error0; | ||
772 | ASSERT(i == 1); | ||
773 | ASSERT(j == 1); | ||
774 | /* | ||
775 | * Duplicate the cursor, search left & right | ||
776 | * simultaneously. | ||
777 | */ | ||
778 | if ((error = xfs_btree_dup_cursor(cur, &tcur))) | ||
779 | goto error0; | ||
780 | /* | ||
781 | * Search left with tcur, back up 1 record. | ||
782 | */ | ||
783 | if ((error = xfs_btree_decrement(tcur, 0, &i))) | ||
784 | goto error1; | 859 | goto error1; |
785 | doneleft = !i; | 860 | } else { |
786 | if (!doneleft) { | 861 | /* search left with tcur, back up 1 record */ |
787 | if ((error = xfs_inobt_get_rec(tcur, | 862 | error = xfs_ialloc_next_rec(tcur, &trec, &doneleft, 1); |
788 | &trec.ir_startino, | 863 | if (error) |
789 | &trec.ir_freecount, | ||
790 | &trec.ir_free, &i))) | ||
791 | goto error1; | ||
792 | XFS_WANT_CORRUPTED_GOTO(i == 1, error1); | ||
793 | } | ||
794 | /* | ||
795 | * Search right with cur, go forward 1 record. | ||
796 | */ | ||
797 | if ((error = xfs_btree_increment(cur, 0, &i))) | ||
798 | goto error1; | 864 | goto error1; |
799 | doneright = !i; | ||
800 | if (!doneright) { | ||
801 | if ((error = xfs_inobt_get_rec(cur, | ||
802 | &rec.ir_startino, | ||
803 | &rec.ir_freecount, | ||
804 | &rec.ir_free, &i))) | ||
805 | goto error1; | ||
806 | XFS_WANT_CORRUPTED_GOTO(i == 1, error1); | ||
807 | } | ||
808 | /* | ||
809 | * Loop until we find the closest inode chunk | ||
810 | * with a free one. | ||
811 | */ | ||
812 | while (!doneleft || !doneright) { | ||
813 | int useleft; /* using left inode | ||
814 | chunk this time */ | ||
815 | 865 | ||
866 | /* search right with cur, go forward 1 record. */ | ||
867 | error = xfs_ialloc_next_rec(cur, &rec, &doneright, 0); | ||
868 | if (error) | ||
869 | goto error1; | ||
870 | } | ||
871 | |||
872 | /* | ||
873 | * Loop until we find an inode chunk with a free inode. | ||
874 | */ | ||
875 | while (!doneleft || !doneright) { | ||
876 | int useleft; /* using left inode chunk this time */ | ||
877 | |||
878 | if (!--searchdistance) { | ||
816 | /* | 879 | /* |
817 | * Figure out which block is closer, | 880 | * Not in range - save last search |
818 | * if both are valid. | 881 | * location and allocate a new inode |
819 | */ | ||
820 | if (!doneleft && !doneright) | ||
821 | useleft = | ||
822 | pagino - | ||
823 | (trec.ir_startino + | ||
824 | XFS_INODES_PER_CHUNK - 1) < | ||
825 | rec.ir_startino - pagino; | ||
826 | else | ||
827 | useleft = !doneleft; | ||
828 | /* | ||
829 | * If checking the left, does it have | ||
830 | * free inodes? | ||
831 | */ | ||
832 | if (useleft && trec.ir_freecount) { | ||
833 | /* | ||
834 | * Yes, set it up as the chunk to use. | ||
835 | */ | ||
836 | rec = trec; | ||
837 | xfs_btree_del_cursor(cur, | ||
838 | XFS_BTREE_NOERROR); | ||
839 | cur = tcur; | ||
840 | break; | ||
841 | } | ||
842 | /* | ||
843 | * If checking the right, does it have | ||
844 | * free inodes? | ||
845 | */ | ||
846 | if (!useleft && rec.ir_freecount) { | ||
847 | /* | ||
848 | * Yes, it's already set up. | ||
849 | */ | ||
850 | xfs_btree_del_cursor(tcur, | ||
851 | XFS_BTREE_NOERROR); | ||
852 | break; | ||
853 | } | ||
854 | /* | ||
855 | * If used the left, get another one | ||
856 | * further left. | ||
857 | */ | ||
858 | if (useleft) { | ||
859 | if ((error = xfs_btree_decrement(tcur, 0, | ||
860 | &i))) | ||
861 | goto error1; | ||
862 | doneleft = !i; | ||
863 | if (!doneleft) { | ||
864 | if ((error = xfs_inobt_get_rec( | ||
865 | tcur, | ||
866 | &trec.ir_startino, | ||
867 | &trec.ir_freecount, | ||
868 | &trec.ir_free, &i))) | ||
869 | goto error1; | ||
870 | XFS_WANT_CORRUPTED_GOTO(i == 1, | ||
871 | error1); | ||
872 | } | ||
873 | } | ||
874 | /* | ||
875 | * If used the right, get another one | ||
876 | * further right. | ||
877 | */ | 882 | */ |
878 | else { | 883 | pag->pagl_leftrec = trec.ir_startino; |
879 | if ((error = xfs_btree_increment(cur, 0, | 884 | pag->pagl_rightrec = rec.ir_startino; |
880 | &i))) | 885 | pag->pagl_pagino = pagino; |
881 | goto error1; | 886 | goto newino; |
882 | doneright = !i; | 887 | } |
883 | if (!doneright) { | 888 | |
884 | if ((error = xfs_inobt_get_rec( | 889 | /* figure out the closer block if both are valid. */ |
885 | cur, | 890 | if (!doneleft && !doneright) { |
886 | &rec.ir_startino, | 891 | useleft = pagino - |
887 | &rec.ir_freecount, | 892 | (trec.ir_startino + XFS_INODES_PER_CHUNK - 1) < |
888 | &rec.ir_free, &i))) | 893 | rec.ir_startino - pagino; |
889 | goto error1; | 894 | } else { |
890 | XFS_WANT_CORRUPTED_GOTO(i == 1, | 895 | useleft = !doneleft; |
891 | error1); | ||
892 | } | ||
893 | } | ||
894 | } | 896 | } |
895 | ASSERT(!doneleft || !doneright); | 897 | |
898 | /* free inodes to the left? */ | ||
899 | if (useleft && trec.ir_freecount) { | ||
900 | rec = trec; | ||
901 | xfs_btree_del_cursor(cur, XFS_BTREE_NOERROR); | ||
902 | cur = tcur; | ||
903 | |||
904 | pag->pagl_leftrec = trec.ir_startino; | ||
905 | pag->pagl_rightrec = rec.ir_startino; | ||
906 | pag->pagl_pagino = pagino; | ||
907 | goto alloc_inode; | ||
908 | } | ||
909 | |||
910 | /* free inodes to the right? */ | ||
911 | if (!useleft && rec.ir_freecount) { | ||
912 | xfs_btree_del_cursor(tcur, XFS_BTREE_NOERROR); | ||
913 | |||
914 | pag->pagl_leftrec = trec.ir_startino; | ||
915 | pag->pagl_rightrec = rec.ir_startino; | ||
916 | pag->pagl_pagino = pagino; | ||
917 | goto alloc_inode; | ||
918 | } | ||
919 | |||
920 | /* get next record to check */ | ||
921 | if (useleft) { | ||
922 | error = xfs_ialloc_next_rec(tcur, &trec, | ||
923 | &doneleft, 1); | ||
924 | } else { | ||
925 | error = xfs_ialloc_next_rec(cur, &rec, | ||
926 | &doneright, 0); | ||
927 | } | ||
928 | if (error) | ||
929 | goto error1; | ||
896 | } | 930 | } |
931 | |||
932 | /* | ||
933 | * We've reached the end of the btree. because | ||
934 | * we are only searching a small chunk of the | ||
935 | * btree each search, there is obviously free | ||
936 | * inodes closer to the parent inode than we | ||
937 | * are now. restart the search again. | ||
938 | */ | ||
939 | pag->pagl_pagino = NULLAGINO; | ||
940 | pag->pagl_leftrec = NULLAGINO; | ||
941 | pag->pagl_rightrec = NULLAGINO; | ||
942 | xfs_btree_del_cursor(tcur, XFS_BTREE_NOERROR); | ||
943 | xfs_btree_del_cursor(cur, XFS_BTREE_NOERROR); | ||
944 | goto restart_pagno; | ||
897 | } | 945 | } |
946 | |||
898 | /* | 947 | /* |
899 | * In a different a.g. from the parent. | 948 | * In a different AG from the parent. |
900 | * See if the most recently allocated block has any free. | 949 | * See if the most recently allocated block has any free. |
901 | */ | 950 | */ |
902 | else if (be32_to_cpu(agi->agi_newino) != NULLAGINO) { | 951 | newino: |
903 | if ((error = xfs_inobt_lookup_eq(cur, | 952 | if (be32_to_cpu(agi->agi_newino) != NULLAGINO) { |
904 | be32_to_cpu(agi->agi_newino), 0, 0, &i))) | 953 | error = xfs_inobt_lookup(cur, be32_to_cpu(agi->agi_newino), |
954 | XFS_LOOKUP_EQ, &i); | ||
955 | if (error) | ||
905 | goto error0; | 956 | goto error0; |
906 | if (i == 1 && | 957 | |
907 | (error = xfs_inobt_get_rec(cur, &rec.ir_startino, | 958 | if (i == 1) { |
908 | &rec.ir_freecount, &rec.ir_free, &j)) == 0 && | 959 | error = xfs_inobt_get_rec(cur, &rec, &j); |
909 | j == 1 && | ||
910 | rec.ir_freecount > 0) { | ||
911 | /* | ||
912 | * The last chunk allocated in the group still has | ||
913 | * a free inode. | ||
914 | */ | ||
915 | } | ||
916 | /* | ||
917 | * None left in the last group, search the whole a.g. | ||
918 | */ | ||
919 | else { | ||
920 | if (error) | 960 | if (error) |
921 | goto error0; | 961 | goto error0; |
922 | if ((error = xfs_inobt_lookup_ge(cur, 0, 0, 0, &i))) | 962 | |
923 | goto error0; | 963 | if (j == 1 && rec.ir_freecount > 0) { |
924 | ASSERT(i == 1); | 964 | /* |
925 | for (;;) { | 965 | * The last chunk allocated in the group |
926 | if ((error = xfs_inobt_get_rec(cur, | 966 | * still has a free inode. |
927 | &rec.ir_startino, | 967 | */ |
928 | &rec.ir_freecount, &rec.ir_free, | 968 | goto alloc_inode; |
929 | &i))) | ||
930 | goto error0; | ||
931 | XFS_WANT_CORRUPTED_GOTO(i == 1, error0); | ||
932 | if (rec.ir_freecount > 0) | ||
933 | break; | ||
934 | if ((error = xfs_btree_increment(cur, 0, &i))) | ||
935 | goto error0; | ||
936 | XFS_WANT_CORRUPTED_GOTO(i == 1, error0); | ||
937 | } | 969 | } |
938 | } | 970 | } |
939 | } | 971 | } |
972 | |||
973 | /* | ||
974 | * None left in the last group, search the whole AG | ||
975 | */ | ||
976 | error = xfs_inobt_lookup(cur, 0, XFS_LOOKUP_GE, &i); | ||
977 | if (error) | ||
978 | goto error0; | ||
979 | XFS_WANT_CORRUPTED_GOTO(i == 1, error0); | ||
980 | |||
981 | for (;;) { | ||
982 | error = xfs_inobt_get_rec(cur, &rec, &i); | ||
983 | if (error) | ||
984 | goto error0; | ||
985 | XFS_WANT_CORRUPTED_GOTO(i == 1, error0); | ||
986 | if (rec.ir_freecount > 0) | ||
987 | break; | ||
988 | error = xfs_btree_increment(cur, 0, &i); | ||
989 | if (error) | ||
990 | goto error0; | ||
991 | XFS_WANT_CORRUPTED_GOTO(i == 1, error0); | ||
992 | } | ||
993 | |||
994 | alloc_inode: | ||
940 | offset = xfs_ialloc_find_free(&rec.ir_free); | 995 | offset = xfs_ialloc_find_free(&rec.ir_free); |
941 | ASSERT(offset >= 0); | 996 | ASSERT(offset >= 0); |
942 | ASSERT(offset < XFS_INODES_PER_CHUNK); | 997 | ASSERT(offset < XFS_INODES_PER_CHUNK); |
@@ -945,33 +1000,19 @@ nextag: | |||
945 | ino = XFS_AGINO_TO_INO(mp, agno, rec.ir_startino + offset); | 1000 | ino = XFS_AGINO_TO_INO(mp, agno, rec.ir_startino + offset); |
946 | rec.ir_free &= ~XFS_INOBT_MASK(offset); | 1001 | rec.ir_free &= ~XFS_INOBT_MASK(offset); |
947 | rec.ir_freecount--; | 1002 | rec.ir_freecount--; |
948 | if ((error = xfs_inobt_update(cur, rec.ir_startino, rec.ir_freecount, | 1003 | error = xfs_inobt_update(cur, &rec); |
949 | rec.ir_free))) | 1004 | if (error) |
950 | goto error0; | 1005 | goto error0; |
951 | be32_add_cpu(&agi->agi_freecount, -1); | 1006 | be32_add_cpu(&agi->agi_freecount, -1); |
952 | xfs_ialloc_log_agi(tp, agbp, XFS_AGI_FREECOUNT); | 1007 | xfs_ialloc_log_agi(tp, agbp, XFS_AGI_FREECOUNT); |
953 | down_read(&mp->m_peraglock); | 1008 | down_read(&mp->m_peraglock); |
954 | mp->m_perag[tagno].pagi_freecount--; | 1009 | mp->m_perag[tagno].pagi_freecount--; |
955 | up_read(&mp->m_peraglock); | 1010 | up_read(&mp->m_peraglock); |
956 | #ifdef DEBUG | ||
957 | if (cur->bc_nlevels == 1) { | ||
958 | int freecount = 0; | ||
959 | 1011 | ||
960 | if ((error = xfs_inobt_lookup_ge(cur, 0, 0, 0, &i))) | 1012 | error = xfs_check_agi_freecount(cur, agi); |
961 | goto error0; | 1013 | if (error) |
962 | do { | 1014 | goto error0; |
963 | if ((error = xfs_inobt_get_rec(cur, &rec.ir_startino, | 1015 | |
964 | &rec.ir_freecount, &rec.ir_free, &i))) | ||
965 | goto error0; | ||
966 | XFS_WANT_CORRUPTED_GOTO(i == 1, error0); | ||
967 | freecount += rec.ir_freecount; | ||
968 | if ((error = xfs_btree_increment(cur, 0, &i))) | ||
969 | goto error0; | ||
970 | } while (i == 1); | ||
971 | ASSERT(freecount == be32_to_cpu(agi->agi_freecount) || | ||
972 | XFS_FORCED_SHUTDOWN(mp)); | ||
973 | } | ||
974 | #endif | ||
975 | xfs_btree_del_cursor(cur, XFS_BTREE_NOERROR); | 1016 | xfs_btree_del_cursor(cur, XFS_BTREE_NOERROR); |
976 | xfs_trans_mod_sb(tp, XFS_TRANS_SB_IFREE, -1); | 1017 | xfs_trans_mod_sb(tp, XFS_TRANS_SB_IFREE, -1); |
977 | *inop = ino; | 1018 | *inop = ino; |
@@ -1062,38 +1103,23 @@ xfs_difree( | |||
1062 | * Initialize the cursor. | 1103 | * Initialize the cursor. |
1063 | */ | 1104 | */ |
1064 | cur = xfs_inobt_init_cursor(mp, tp, agbp, agno); | 1105 | cur = xfs_inobt_init_cursor(mp, tp, agbp, agno); |
1065 | #ifdef DEBUG | ||
1066 | if (cur->bc_nlevels == 1) { | ||
1067 | int freecount = 0; | ||
1068 | 1106 | ||
1069 | if ((error = xfs_inobt_lookup_ge(cur, 0, 0, 0, &i))) | 1107 | error = xfs_check_agi_freecount(cur, agi); |
1070 | goto error0; | 1108 | if (error) |
1071 | do { | 1109 | goto error0; |
1072 | if ((error = xfs_inobt_get_rec(cur, &rec.ir_startino, | 1110 | |
1073 | &rec.ir_freecount, &rec.ir_free, &i))) | ||
1074 | goto error0; | ||
1075 | if (i) { | ||
1076 | freecount += rec.ir_freecount; | ||
1077 | if ((error = xfs_btree_increment(cur, 0, &i))) | ||
1078 | goto error0; | ||
1079 | } | ||
1080 | } while (i == 1); | ||
1081 | ASSERT(freecount == be32_to_cpu(agi->agi_freecount) || | ||
1082 | XFS_FORCED_SHUTDOWN(mp)); | ||
1083 | } | ||
1084 | #endif | ||
1085 | /* | 1111 | /* |
1086 | * Look for the entry describing this inode. | 1112 | * Look for the entry describing this inode. |
1087 | */ | 1113 | */ |
1088 | if ((error = xfs_inobt_lookup_le(cur, agino, 0, 0, &i))) { | 1114 | if ((error = xfs_inobt_lookup(cur, agino, XFS_LOOKUP_LE, &i))) { |
1089 | cmn_err(CE_WARN, | 1115 | cmn_err(CE_WARN, |
1090 | "xfs_difree: xfs_inobt_lookup_le returned() an error %d on %s. Returning error.", | 1116 | "xfs_difree: xfs_inobt_lookup returned() an error %d on %s. Returning error.", |
1091 | error, mp->m_fsname); | 1117 | error, mp->m_fsname); |
1092 | goto error0; | 1118 | goto error0; |
1093 | } | 1119 | } |
1094 | XFS_WANT_CORRUPTED_GOTO(i == 1, error0); | 1120 | XFS_WANT_CORRUPTED_GOTO(i == 1, error0); |
1095 | if ((error = xfs_inobt_get_rec(cur, &rec.ir_startino, &rec.ir_freecount, | 1121 | error = xfs_inobt_get_rec(cur, &rec, &i); |
1096 | &rec.ir_free, &i))) { | 1122 | if (error) { |
1097 | cmn_err(CE_WARN, | 1123 | cmn_err(CE_WARN, |
1098 | "xfs_difree: xfs_inobt_get_rec() returned an error %d on %s. Returning error.", | 1124 | "xfs_difree: xfs_inobt_get_rec() returned an error %d on %s. Returning error.", |
1099 | error, mp->m_fsname); | 1125 | error, mp->m_fsname); |
@@ -1148,12 +1174,14 @@ xfs_difree( | |||
1148 | } else { | 1174 | } else { |
1149 | *delete = 0; | 1175 | *delete = 0; |
1150 | 1176 | ||
1151 | if ((error = xfs_inobt_update(cur, rec.ir_startino, rec.ir_freecount, rec.ir_free))) { | 1177 | error = xfs_inobt_update(cur, &rec); |
1178 | if (error) { | ||
1152 | cmn_err(CE_WARN, | 1179 | cmn_err(CE_WARN, |
1153 | "xfs_difree: xfs_inobt_update() returned an error %d on %s. Returning error.", | 1180 | "xfs_difree: xfs_inobt_update returned an error %d on %s.", |
1154 | error, mp->m_fsname); | 1181 | error, mp->m_fsname); |
1155 | goto error0; | 1182 | goto error0; |
1156 | } | 1183 | } |
1184 | |||
1157 | /* | 1185 | /* |
1158 | * Change the inode free counts and log the ag/sb changes. | 1186 | * Change the inode free counts and log the ag/sb changes. |
1159 | */ | 1187 | */ |
@@ -1165,28 +1193,10 @@ xfs_difree( | |||
1165 | xfs_trans_mod_sb(tp, XFS_TRANS_SB_IFREE, 1); | 1193 | xfs_trans_mod_sb(tp, XFS_TRANS_SB_IFREE, 1); |
1166 | } | 1194 | } |
1167 | 1195 | ||
1168 | #ifdef DEBUG | 1196 | error = xfs_check_agi_freecount(cur, agi); |
1169 | if (cur->bc_nlevels == 1) { | 1197 | if (error) |
1170 | int freecount = 0; | 1198 | goto error0; |
1171 | 1199 | ||
1172 | if ((error = xfs_inobt_lookup_ge(cur, 0, 0, 0, &i))) | ||
1173 | goto error0; | ||
1174 | do { | ||
1175 | if ((error = xfs_inobt_get_rec(cur, | ||
1176 | &rec.ir_startino, | ||
1177 | &rec.ir_freecount, | ||
1178 | &rec.ir_free, &i))) | ||
1179 | goto error0; | ||
1180 | if (i) { | ||
1181 | freecount += rec.ir_freecount; | ||
1182 | if ((error = xfs_btree_increment(cur, 0, &i))) | ||
1183 | goto error0; | ||
1184 | } | ||
1185 | } while (i == 1); | ||
1186 | ASSERT(freecount == be32_to_cpu(agi->agi_freecount) || | ||
1187 | XFS_FORCED_SHUTDOWN(mp)); | ||
1188 | } | ||
1189 | #endif | ||
1190 | xfs_btree_del_cursor(cur, XFS_BTREE_NOERROR); | 1200 | xfs_btree_del_cursor(cur, XFS_BTREE_NOERROR); |
1191 | return 0; | 1201 | return 0; |
1192 | 1202 | ||
@@ -1297,9 +1307,7 @@ xfs_imap( | |||
1297 | chunk_agbno = agbno - offset_agbno; | 1307 | chunk_agbno = agbno - offset_agbno; |
1298 | } else { | 1308 | } else { |
1299 | xfs_btree_cur_t *cur; /* inode btree cursor */ | 1309 | xfs_btree_cur_t *cur; /* inode btree cursor */ |
1300 | xfs_agino_t chunk_agino; /* first agino in inode chunk */ | 1310 | xfs_inobt_rec_incore_t chunk_rec; |
1301 | __int32_t chunk_cnt; /* count of free inodes in chunk */ | ||
1302 | xfs_inofree_t chunk_free; /* mask of free inodes in chunk */ | ||
1303 | xfs_buf_t *agbp; /* agi buffer */ | 1311 | xfs_buf_t *agbp; /* agi buffer */ |
1304 | int i; /* temp state */ | 1312 | int i; /* temp state */ |
1305 | 1313 | ||
@@ -1315,15 +1323,14 @@ xfs_imap( | |||
1315 | } | 1323 | } |
1316 | 1324 | ||
1317 | cur = xfs_inobt_init_cursor(mp, tp, agbp, agno); | 1325 | cur = xfs_inobt_init_cursor(mp, tp, agbp, agno); |
1318 | error = xfs_inobt_lookup_le(cur, agino, 0, 0, &i); | 1326 | error = xfs_inobt_lookup(cur, agino, XFS_LOOKUP_LE, &i); |
1319 | if (error) { | 1327 | if (error) { |
1320 | xfs_fs_cmn_err(CE_ALERT, mp, "xfs_imap: " | 1328 | xfs_fs_cmn_err(CE_ALERT, mp, "xfs_imap: " |
1321 | "xfs_inobt_lookup_le() failed"); | 1329 | "xfs_inobt_lookup() failed"); |
1322 | goto error0; | 1330 | goto error0; |
1323 | } | 1331 | } |
1324 | 1332 | ||
1325 | error = xfs_inobt_get_rec(cur, &chunk_agino, &chunk_cnt, | 1333 | error = xfs_inobt_get_rec(cur, &chunk_rec, &i); |
1326 | &chunk_free, &i); | ||
1327 | if (error) { | 1334 | if (error) { |
1328 | xfs_fs_cmn_err(CE_ALERT, mp, "xfs_imap: " | 1335 | xfs_fs_cmn_err(CE_ALERT, mp, "xfs_imap: " |
1329 | "xfs_inobt_get_rec() failed"); | 1336 | "xfs_inobt_get_rec() failed"); |
@@ -1341,7 +1348,7 @@ xfs_imap( | |||
1341 | xfs_btree_del_cursor(cur, XFS_BTREE_NOERROR); | 1348 | xfs_btree_del_cursor(cur, XFS_BTREE_NOERROR); |
1342 | if (error) | 1349 | if (error) |
1343 | return error; | 1350 | return error; |
1344 | chunk_agbno = XFS_AGINO_TO_AGBNO(mp, chunk_agino); | 1351 | chunk_agbno = XFS_AGINO_TO_AGBNO(mp, chunk_rec.ir_startino); |
1345 | offset_agbno = agbno - chunk_agbno; | 1352 | offset_agbno = agbno - chunk_agbno; |
1346 | } | 1353 | } |
1347 | 1354 | ||
diff --git a/fs/xfs/xfs_ialloc.h b/fs/xfs/xfs_ialloc.h index aeee8278f92c..bb5385475e1f 100644 --- a/fs/xfs/xfs_ialloc.h +++ b/fs/xfs/xfs_ialloc.h | |||
@@ -150,23 +150,15 @@ xfs_ialloc_pagi_init( | |||
150 | xfs_agnumber_t agno); /* allocation group number */ | 150 | xfs_agnumber_t agno); /* allocation group number */ |
151 | 151 | ||
152 | /* | 152 | /* |
153 | * Lookup the first record greater than or equal to ino | 153 | * Lookup a record by ino in the btree given by cur. |
154 | * in the btree given by cur. | ||
155 | */ | 154 | */ |
156 | int xfs_inobt_lookup_ge(struct xfs_btree_cur *cur, xfs_agino_t ino, | 155 | int xfs_inobt_lookup(struct xfs_btree_cur *cur, xfs_agino_t ino, |
157 | __int32_t fcnt, xfs_inofree_t free, int *stat); | 156 | xfs_lookup_t dir, int *stat); |
158 | |||
159 | /* | ||
160 | * Lookup the first record less than or equal to ino | ||
161 | * in the btree given by cur. | ||
162 | */ | ||
163 | int xfs_inobt_lookup_le(struct xfs_btree_cur *cur, xfs_agino_t ino, | ||
164 | __int32_t fcnt, xfs_inofree_t free, int *stat); | ||
165 | 157 | ||
166 | /* | 158 | /* |
167 | * Get the data from the pointed-to record. | 159 | * Get the data from the pointed-to record. |
168 | */ | 160 | */ |
169 | extern int xfs_inobt_get_rec(struct xfs_btree_cur *cur, xfs_agino_t *ino, | 161 | extern int xfs_inobt_get_rec(struct xfs_btree_cur *cur, |
170 | __int32_t *fcnt, xfs_inofree_t *free, int *stat); | 162 | xfs_inobt_rec_incore_t *rec, int *stat); |
171 | 163 | ||
172 | #endif /* __XFS_IALLOC_H__ */ | 164 | #endif /* __XFS_IALLOC_H__ */ |
diff --git a/fs/xfs/xfs_iget.c b/fs/xfs/xfs_iget.c index 5fcec6f020a7..80e526489be5 100644 --- a/fs/xfs/xfs_iget.c +++ b/fs/xfs/xfs_iget.c | |||
@@ -64,6 +64,10 @@ xfs_inode_alloc( | |||
64 | ip = kmem_zone_alloc(xfs_inode_zone, KM_SLEEP); | 64 | ip = kmem_zone_alloc(xfs_inode_zone, KM_SLEEP); |
65 | if (!ip) | 65 | if (!ip) |
66 | return NULL; | 66 | return NULL; |
67 | if (inode_init_always(mp->m_super, VFS_I(ip))) { | ||
68 | kmem_zone_free(xfs_inode_zone, ip); | ||
69 | return NULL; | ||
70 | } | ||
67 | 71 | ||
68 | ASSERT(atomic_read(&ip->i_iocount) == 0); | 72 | ASSERT(atomic_read(&ip->i_iocount) == 0); |
69 | ASSERT(atomic_read(&ip->i_pincount) == 0); | 73 | ASSERT(atomic_read(&ip->i_pincount) == 0); |
@@ -78,7 +82,6 @@ xfs_inode_alloc( | |||
78 | memset(&ip->i_df, 0, sizeof(xfs_ifork_t)); | 82 | memset(&ip->i_df, 0, sizeof(xfs_ifork_t)); |
79 | ip->i_flags = 0; | 83 | ip->i_flags = 0; |
80 | ip->i_update_core = 0; | 84 | ip->i_update_core = 0; |
81 | ip->i_update_size = 0; | ||
82 | ip->i_delayed_blks = 0; | 85 | ip->i_delayed_blks = 0; |
83 | memset(&ip->i_d, 0, sizeof(xfs_icdinode_t)); | 86 | memset(&ip->i_d, 0, sizeof(xfs_icdinode_t)); |
84 | ip->i_size = 0; | 87 | ip->i_size = 0; |
@@ -105,17 +108,6 @@ xfs_inode_alloc( | |||
105 | #ifdef XFS_DIR2_TRACE | 108 | #ifdef XFS_DIR2_TRACE |
106 | ip->i_dir_trace = ktrace_alloc(XFS_DIR2_KTRACE_SIZE, KM_NOFS); | 109 | ip->i_dir_trace = ktrace_alloc(XFS_DIR2_KTRACE_SIZE, KM_NOFS); |
107 | #endif | 110 | #endif |
108 | /* | ||
109 | * Now initialise the VFS inode. We do this after the xfs_inode | ||
110 | * initialisation as internal failures will result in ->destroy_inode | ||
111 | * being called and that will pass down through the reclaim path and | ||
112 | * free the XFS inode. This path requires the XFS inode to already be | ||
113 | * initialised. Hence if this call fails, the xfs_inode has already | ||
114 | * been freed and we should not reference it at all in the error | ||
115 | * handling. | ||
116 | */ | ||
117 | if (!inode_init_always(mp->m_super, VFS_I(ip))) | ||
118 | return NULL; | ||
119 | 111 | ||
120 | /* prevent anyone from using this yet */ | 112 | /* prevent anyone from using this yet */ |
121 | VFS_I(ip)->i_state = I_NEW|I_LOCK; | 113 | VFS_I(ip)->i_state = I_NEW|I_LOCK; |
@@ -123,6 +115,71 @@ xfs_inode_alloc( | |||
123 | return ip; | 115 | return ip; |
124 | } | 116 | } |
125 | 117 | ||
118 | STATIC void | ||
119 | xfs_inode_free( | ||
120 | struct xfs_inode *ip) | ||
121 | { | ||
122 | switch (ip->i_d.di_mode & S_IFMT) { | ||
123 | case S_IFREG: | ||
124 | case S_IFDIR: | ||
125 | case S_IFLNK: | ||
126 | xfs_idestroy_fork(ip, XFS_DATA_FORK); | ||
127 | break; | ||
128 | } | ||
129 | |||
130 | if (ip->i_afp) | ||
131 | xfs_idestroy_fork(ip, XFS_ATTR_FORK); | ||
132 | |||
133 | #ifdef XFS_INODE_TRACE | ||
134 | ktrace_free(ip->i_trace); | ||
135 | #endif | ||
136 | #ifdef XFS_BMAP_TRACE | ||
137 | ktrace_free(ip->i_xtrace); | ||
138 | #endif | ||
139 | #ifdef XFS_BTREE_TRACE | ||
140 | ktrace_free(ip->i_btrace); | ||
141 | #endif | ||
142 | #ifdef XFS_RW_TRACE | ||
143 | ktrace_free(ip->i_rwtrace); | ||
144 | #endif | ||
145 | #ifdef XFS_ILOCK_TRACE | ||
146 | ktrace_free(ip->i_lock_trace); | ||
147 | #endif | ||
148 | #ifdef XFS_DIR2_TRACE | ||
149 | ktrace_free(ip->i_dir_trace); | ||
150 | #endif | ||
151 | |||
152 | if (ip->i_itemp) { | ||
153 | /* | ||
154 | * Only if we are shutting down the fs will we see an | ||
155 | * inode still in the AIL. If it is there, we should remove | ||
156 | * it to prevent a use-after-free from occurring. | ||
157 | */ | ||
158 | xfs_log_item_t *lip = &ip->i_itemp->ili_item; | ||
159 | struct xfs_ail *ailp = lip->li_ailp; | ||
160 | |||
161 | ASSERT(((lip->li_flags & XFS_LI_IN_AIL) == 0) || | ||
162 | XFS_FORCED_SHUTDOWN(ip->i_mount)); | ||
163 | if (lip->li_flags & XFS_LI_IN_AIL) { | ||
164 | spin_lock(&ailp->xa_lock); | ||
165 | if (lip->li_flags & XFS_LI_IN_AIL) | ||
166 | xfs_trans_ail_delete(ailp, lip); | ||
167 | else | ||
168 | spin_unlock(&ailp->xa_lock); | ||
169 | } | ||
170 | xfs_inode_item_destroy(ip); | ||
171 | ip->i_itemp = NULL; | ||
172 | } | ||
173 | |||
174 | /* asserts to verify all state is correct here */ | ||
175 | ASSERT(atomic_read(&ip->i_iocount) == 0); | ||
176 | ASSERT(atomic_read(&ip->i_pincount) == 0); | ||
177 | ASSERT(!spin_is_locked(&ip->i_flags_lock)); | ||
178 | ASSERT(completion_done(&ip->i_flush)); | ||
179 | |||
180 | kmem_zone_free(xfs_inode_zone, ip); | ||
181 | } | ||
182 | |||
126 | /* | 183 | /* |
127 | * Check the validity of the inode we just found it the cache | 184 | * Check the validity of the inode we just found it the cache |
128 | */ | 185 | */ |
@@ -133,80 +190,82 @@ xfs_iget_cache_hit( | |||
133 | int flags, | 190 | int flags, |
134 | int lock_flags) __releases(pag->pag_ici_lock) | 191 | int lock_flags) __releases(pag->pag_ici_lock) |
135 | { | 192 | { |
193 | struct inode *inode = VFS_I(ip); | ||
136 | struct xfs_mount *mp = ip->i_mount; | 194 | struct xfs_mount *mp = ip->i_mount; |
137 | int error = EAGAIN; | 195 | int error; |
196 | |||
197 | spin_lock(&ip->i_flags_lock); | ||
138 | 198 | ||
139 | /* | 199 | /* |
140 | * If INEW is set this inode is being set up | 200 | * If we are racing with another cache hit that is currently |
141 | * If IRECLAIM is set this inode is being torn down | 201 | * instantiating this inode or currently recycling it out of |
142 | * Pause and try again. | 202 | * reclaimabe state, wait for the initialisation to complete |
203 | * before continuing. | ||
204 | * | ||
205 | * XXX(hch): eventually we should do something equivalent to | ||
206 | * wait_on_inode to wait for these flags to be cleared | ||
207 | * instead of polling for it. | ||
143 | */ | 208 | */ |
144 | if (xfs_iflags_test(ip, (XFS_INEW|XFS_IRECLAIM))) { | 209 | if (ip->i_flags & (XFS_INEW|XFS_IRECLAIM)) { |
145 | XFS_STATS_INC(xs_ig_frecycle); | 210 | XFS_STATS_INC(xs_ig_frecycle); |
211 | error = EAGAIN; | ||
146 | goto out_error; | 212 | goto out_error; |
147 | } | 213 | } |
148 | 214 | ||
149 | /* If IRECLAIMABLE is set, we've torn down the vfs inode part */ | 215 | /* |
150 | if (xfs_iflags_test(ip, XFS_IRECLAIMABLE)) { | 216 | * If lookup is racing with unlink return an error immediately. |
151 | 217 | */ | |
152 | /* | 218 | if (ip->i_d.di_mode == 0 && !(flags & XFS_IGET_CREATE)) { |
153 | * If lookup is racing with unlink, then we should return an | 219 | error = ENOENT; |
154 | * error immediately so we don't remove it from the reclaim | 220 | goto out_error; |
155 | * list and potentially leak the inode. | 221 | } |
156 | */ | ||
157 | if ((ip->i_d.di_mode == 0) && !(flags & XFS_IGET_CREATE)) { | ||
158 | error = ENOENT; | ||
159 | goto out_error; | ||
160 | } | ||
161 | 222 | ||
223 | /* | ||
224 | * If IRECLAIMABLE is set, we've torn down the VFS inode already. | ||
225 | * Need to carefully get it back into useable state. | ||
226 | */ | ||
227 | if (ip->i_flags & XFS_IRECLAIMABLE) { | ||
162 | xfs_itrace_exit_tag(ip, "xfs_iget.alloc"); | 228 | xfs_itrace_exit_tag(ip, "xfs_iget.alloc"); |
163 | 229 | ||
164 | /* | 230 | /* |
165 | * We need to re-initialise the VFS inode as it has been | 231 | * We need to set XFS_INEW atomically with clearing the |
166 | * 'freed' by the VFS. Do this here so we can deal with | 232 | * reclaimable tag so that we do have an indicator of the |
167 | * errors cleanly, then tag it so it can be set up correctly | 233 | * inode still being initialized. |
168 | * later. | ||
169 | */ | 234 | */ |
170 | if (!inode_init_always(mp->m_super, VFS_I(ip))) { | 235 | ip->i_flags |= XFS_INEW; |
171 | error = ENOMEM; | 236 | ip->i_flags &= ~XFS_IRECLAIMABLE; |
172 | goto out_error; | 237 | __xfs_inode_clear_reclaim_tag(mp, pag, ip); |
173 | } | ||
174 | 238 | ||
175 | /* | 239 | spin_unlock(&ip->i_flags_lock); |
176 | * We must set the XFS_INEW flag before clearing the | 240 | read_unlock(&pag->pag_ici_lock); |
177 | * XFS_IRECLAIMABLE flag so that if a racing lookup does | ||
178 | * not find the XFS_IRECLAIMABLE above but has the igrab() | ||
179 | * below succeed we can safely check XFS_INEW to detect | ||
180 | * that this inode is still being initialised. | ||
181 | */ | ||
182 | xfs_iflags_set(ip, XFS_INEW); | ||
183 | xfs_iflags_clear(ip, XFS_IRECLAIMABLE); | ||
184 | 241 | ||
185 | /* clear the radix tree reclaim flag as well. */ | 242 | error = -inode_init_always(mp->m_super, inode); |
186 | __xfs_inode_clear_reclaim_tag(mp, pag, ip); | 243 | if (error) { |
187 | } else if (!igrab(VFS_I(ip))) { | 244 | /* |
245 | * Re-initializing the inode failed, and we are in deep | ||
246 | * trouble. Try to re-add it to the reclaim list. | ||
247 | */ | ||
248 | read_lock(&pag->pag_ici_lock); | ||
249 | spin_lock(&ip->i_flags_lock); | ||
250 | |||
251 | ip->i_flags &= ~XFS_INEW; | ||
252 | ip->i_flags |= XFS_IRECLAIMABLE; | ||
253 | __xfs_inode_set_reclaim_tag(pag, ip); | ||
254 | goto out_error; | ||
255 | } | ||
256 | inode->i_state = I_LOCK|I_NEW; | ||
257 | } else { | ||
188 | /* If the VFS inode is being torn down, pause and try again. */ | 258 | /* If the VFS inode is being torn down, pause and try again. */ |
189 | XFS_STATS_INC(xs_ig_frecycle); | 259 | if (!igrab(inode)) { |
190 | goto out_error; | 260 | error = EAGAIN; |
191 | } else if (xfs_iflags_test(ip, XFS_INEW)) { | 261 | goto out_error; |
192 | /* | 262 | } |
193 | * We are racing with another cache hit that is | ||
194 | * currently recycling this inode out of the XFS_IRECLAIMABLE | ||
195 | * state. Wait for the initialisation to complete before | ||
196 | * continuing. | ||
197 | */ | ||
198 | wait_on_inode(VFS_I(ip)); | ||
199 | } | ||
200 | 263 | ||
201 | if (ip->i_d.di_mode == 0 && !(flags & XFS_IGET_CREATE)) { | 264 | /* We've got a live one. */ |
202 | error = ENOENT; | 265 | spin_unlock(&ip->i_flags_lock); |
203 | iput(VFS_I(ip)); | 266 | read_unlock(&pag->pag_ici_lock); |
204 | goto out_error; | ||
205 | } | 267 | } |
206 | 268 | ||
207 | /* We've got a live one. */ | ||
208 | read_unlock(&pag->pag_ici_lock); | ||
209 | |||
210 | if (lock_flags != 0) | 269 | if (lock_flags != 0) |
211 | xfs_ilock(ip, lock_flags); | 270 | xfs_ilock(ip, lock_flags); |
212 | 271 | ||
@@ -216,6 +275,7 @@ xfs_iget_cache_hit( | |||
216 | return 0; | 275 | return 0; |
217 | 276 | ||
218 | out_error: | 277 | out_error: |
278 | spin_unlock(&ip->i_flags_lock); | ||
219 | read_unlock(&pag->pag_ici_lock); | 279 | read_unlock(&pag->pag_ici_lock); |
220 | return error; | 280 | return error; |
221 | } | 281 | } |
@@ -299,7 +359,8 @@ out_preload_end: | |||
299 | if (lock_flags) | 359 | if (lock_flags) |
300 | xfs_iunlock(ip, lock_flags); | 360 | xfs_iunlock(ip, lock_flags); |
301 | out_destroy: | 361 | out_destroy: |
302 | xfs_destroy_inode(ip); | 362 | __destroy_inode(VFS_I(ip)); |
363 | xfs_inode_free(ip); | ||
303 | return error; | 364 | return error; |
304 | } | 365 | } |
305 | 366 | ||
@@ -394,32 +455,6 @@ out_error_or_again: | |||
394 | return error; | 455 | return error; |
395 | } | 456 | } |
396 | 457 | ||
397 | |||
398 | /* | ||
399 | * Look for the inode corresponding to the given ino in the hash table. | ||
400 | * If it is there and its i_transp pointer matches tp, return it. | ||
401 | * Otherwise, return NULL. | ||
402 | */ | ||
403 | xfs_inode_t * | ||
404 | xfs_inode_incore(xfs_mount_t *mp, | ||
405 | xfs_ino_t ino, | ||
406 | xfs_trans_t *tp) | ||
407 | { | ||
408 | xfs_inode_t *ip; | ||
409 | xfs_perag_t *pag; | ||
410 | |||
411 | pag = xfs_get_perag(mp, ino); | ||
412 | read_lock(&pag->pag_ici_lock); | ||
413 | ip = radix_tree_lookup(&pag->pag_ici_root, XFS_INO_TO_AGINO(mp, ino)); | ||
414 | read_unlock(&pag->pag_ici_lock); | ||
415 | xfs_put_perag(mp, pag); | ||
416 | |||
417 | /* the returned inode must match the transaction */ | ||
418 | if (ip && (ip->i_transp != tp)) | ||
419 | return NULL; | ||
420 | return ip; | ||
421 | } | ||
422 | |||
423 | /* | 458 | /* |
424 | * Decrement reference count of an inode structure and unlock it. | 459 | * Decrement reference count of an inode structure and unlock it. |
425 | * | 460 | * |
@@ -504,62 +539,7 @@ xfs_ireclaim( | |||
504 | xfs_qm_dqdetach(ip); | 539 | xfs_qm_dqdetach(ip); |
505 | xfs_iunlock(ip, XFS_ILOCK_EXCL | XFS_IOLOCK_EXCL); | 540 | xfs_iunlock(ip, XFS_ILOCK_EXCL | XFS_IOLOCK_EXCL); |
506 | 541 | ||
507 | switch (ip->i_d.di_mode & S_IFMT) { | 542 | xfs_inode_free(ip); |
508 | case S_IFREG: | ||
509 | case S_IFDIR: | ||
510 | case S_IFLNK: | ||
511 | xfs_idestroy_fork(ip, XFS_DATA_FORK); | ||
512 | break; | ||
513 | } | ||
514 | |||
515 | if (ip->i_afp) | ||
516 | xfs_idestroy_fork(ip, XFS_ATTR_FORK); | ||
517 | |||
518 | #ifdef XFS_INODE_TRACE | ||
519 | ktrace_free(ip->i_trace); | ||
520 | #endif | ||
521 | #ifdef XFS_BMAP_TRACE | ||
522 | ktrace_free(ip->i_xtrace); | ||
523 | #endif | ||
524 | #ifdef XFS_BTREE_TRACE | ||
525 | ktrace_free(ip->i_btrace); | ||
526 | #endif | ||
527 | #ifdef XFS_RW_TRACE | ||
528 | ktrace_free(ip->i_rwtrace); | ||
529 | #endif | ||
530 | #ifdef XFS_ILOCK_TRACE | ||
531 | ktrace_free(ip->i_lock_trace); | ||
532 | #endif | ||
533 | #ifdef XFS_DIR2_TRACE | ||
534 | ktrace_free(ip->i_dir_trace); | ||
535 | #endif | ||
536 | if (ip->i_itemp) { | ||
537 | /* | ||
538 | * Only if we are shutting down the fs will we see an | ||
539 | * inode still in the AIL. If it is there, we should remove | ||
540 | * it to prevent a use-after-free from occurring. | ||
541 | */ | ||
542 | xfs_log_item_t *lip = &ip->i_itemp->ili_item; | ||
543 | struct xfs_ail *ailp = lip->li_ailp; | ||
544 | |||
545 | ASSERT(((lip->li_flags & XFS_LI_IN_AIL) == 0) || | ||
546 | XFS_FORCED_SHUTDOWN(ip->i_mount)); | ||
547 | if (lip->li_flags & XFS_LI_IN_AIL) { | ||
548 | spin_lock(&ailp->xa_lock); | ||
549 | if (lip->li_flags & XFS_LI_IN_AIL) | ||
550 | xfs_trans_ail_delete(ailp, lip); | ||
551 | else | ||
552 | spin_unlock(&ailp->xa_lock); | ||
553 | } | ||
554 | xfs_inode_item_destroy(ip); | ||
555 | ip->i_itemp = NULL; | ||
556 | } | ||
557 | /* asserts to verify all state is correct here */ | ||
558 | ASSERT(atomic_read(&ip->i_iocount) == 0); | ||
559 | ASSERT(atomic_read(&ip->i_pincount) == 0); | ||
560 | ASSERT(!spin_is_locked(&ip->i_flags_lock)); | ||
561 | ASSERT(completion_done(&ip->i_flush)); | ||
562 | kmem_zone_free(xfs_inode_zone, ip); | ||
563 | } | 543 | } |
564 | 544 | ||
565 | /* | 545 | /* |
diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c index 1f22d65fed0a..c1dc7ef5a1d8 100644 --- a/fs/xfs/xfs_inode.c +++ b/fs/xfs/xfs_inode.c | |||
@@ -343,6 +343,16 @@ xfs_iformat( | |||
343 | return XFS_ERROR(EFSCORRUPTED); | 343 | return XFS_ERROR(EFSCORRUPTED); |
344 | } | 344 | } |
345 | 345 | ||
346 | if (unlikely((ip->i_d.di_flags & XFS_DIFLAG_REALTIME) && | ||
347 | !ip->i_mount->m_rtdev_targp)) { | ||
348 | xfs_fs_repair_cmn_err(CE_WARN, ip->i_mount, | ||
349 | "corrupt dinode %Lu, has realtime flag set.", | ||
350 | ip->i_ino); | ||
351 | XFS_CORRUPTION_ERROR("xfs_iformat(realtime)", | ||
352 | XFS_ERRLEVEL_LOW, ip->i_mount, dip); | ||
353 | return XFS_ERROR(EFSCORRUPTED); | ||
354 | } | ||
355 | |||
346 | switch (ip->i_d.di_mode & S_IFMT) { | 356 | switch (ip->i_d.di_mode & S_IFMT) { |
347 | case S_IFIFO: | 357 | case S_IFIFO: |
348 | case S_IFCHR: | 358 | case S_IFCHR: |
@@ -641,7 +651,7 @@ xfs_iformat_btree( | |||
641 | return 0; | 651 | return 0; |
642 | } | 652 | } |
643 | 653 | ||
644 | void | 654 | STATIC void |
645 | xfs_dinode_from_disk( | 655 | xfs_dinode_from_disk( |
646 | xfs_icdinode_t *to, | 656 | xfs_icdinode_t *to, |
647 | xfs_dinode_t *from) | 657 | xfs_dinode_t *from) |
@@ -1237,7 +1247,7 @@ xfs_isize_check( | |||
1237 | * In that case the pages will still be in memory, but the inode size | 1247 | * In that case the pages will still be in memory, but the inode size |
1238 | * will never have been updated. | 1248 | * will never have been updated. |
1239 | */ | 1249 | */ |
1240 | xfs_fsize_t | 1250 | STATIC xfs_fsize_t |
1241 | xfs_file_last_byte( | 1251 | xfs_file_last_byte( |
1242 | xfs_inode_t *ip) | 1252 | xfs_inode_t *ip) |
1243 | { | 1253 | { |
@@ -3827,7 +3837,7 @@ xfs_iext_inline_to_direct( | |||
3827 | /* | 3837 | /* |
3828 | * Resize an extent indirection array to new_size bytes. | 3838 | * Resize an extent indirection array to new_size bytes. |
3829 | */ | 3839 | */ |
3830 | void | 3840 | STATIC void |
3831 | xfs_iext_realloc_indirect( | 3841 | xfs_iext_realloc_indirect( |
3832 | xfs_ifork_t *ifp, /* inode fork pointer */ | 3842 | xfs_ifork_t *ifp, /* inode fork pointer */ |
3833 | int new_size) /* new indirection array size */ | 3843 | int new_size) /* new indirection array size */ |
@@ -3852,7 +3862,7 @@ xfs_iext_realloc_indirect( | |||
3852 | /* | 3862 | /* |
3853 | * Switch from indirection array to linear (direct) extent allocations. | 3863 | * Switch from indirection array to linear (direct) extent allocations. |
3854 | */ | 3864 | */ |
3855 | void | 3865 | STATIC void |
3856 | xfs_iext_indirect_to_direct( | 3866 | xfs_iext_indirect_to_direct( |
3857 | xfs_ifork_t *ifp) /* inode fork pointer */ | 3867 | xfs_ifork_t *ifp) /* inode fork pointer */ |
3858 | { | 3868 | { |
diff --git a/fs/xfs/xfs_inode.h b/fs/xfs/xfs_inode.h index 1804f866a71d..0b38b9a869ec 100644 --- a/fs/xfs/xfs_inode.h +++ b/fs/xfs/xfs_inode.h | |||
@@ -261,7 +261,6 @@ typedef struct xfs_inode { | |||
261 | /* Miscellaneous state. */ | 261 | /* Miscellaneous state. */ |
262 | unsigned short i_flags; /* see defined flags below */ | 262 | unsigned short i_flags; /* see defined flags below */ |
263 | unsigned char i_update_core; /* timestamps/size is dirty */ | 263 | unsigned char i_update_core; /* timestamps/size is dirty */ |
264 | unsigned char i_update_size; /* di_size field is dirty */ | ||
265 | unsigned int i_delayed_blks; /* count of delay alloc blks */ | 264 | unsigned int i_delayed_blks; /* count of delay alloc blks */ |
266 | 265 | ||
267 | xfs_icdinode_t i_d; /* most of ondisk inode */ | 266 | xfs_icdinode_t i_d; /* most of ondisk inode */ |
@@ -310,23 +309,6 @@ static inline struct inode *VFS_I(struct xfs_inode *ip) | |||
310 | } | 309 | } |
311 | 310 | ||
312 | /* | 311 | /* |
313 | * Get rid of a partially initialized inode. | ||
314 | * | ||
315 | * We have to go through destroy_inode to make sure allocations | ||
316 | * from init_inode_always like the security data are undone. | ||
317 | * | ||
318 | * We mark the inode bad so that it takes the short cut in | ||
319 | * the reclaim path instead of going through the flush path | ||
320 | * which doesn't make sense for an inode that has never seen the | ||
321 | * light of day. | ||
322 | */ | ||
323 | static inline void xfs_destroy_inode(struct xfs_inode *ip) | ||
324 | { | ||
325 | make_bad_inode(VFS_I(ip)); | ||
326 | return destroy_inode(VFS_I(ip)); | ||
327 | } | ||
328 | |||
329 | /* | ||
330 | * i_flags helper functions | 312 | * i_flags helper functions |
331 | */ | 313 | */ |
332 | static inline void | 314 | static inline void |
@@ -485,8 +467,6 @@ static inline void xfs_ifunlock(xfs_inode_t *ip) | |||
485 | /* | 467 | /* |
486 | * xfs_iget.c prototypes. | 468 | * xfs_iget.c prototypes. |
487 | */ | 469 | */ |
488 | xfs_inode_t *xfs_inode_incore(struct xfs_mount *, xfs_ino_t, | ||
489 | struct xfs_trans *); | ||
490 | int xfs_iget(struct xfs_mount *, struct xfs_trans *, xfs_ino_t, | 470 | int xfs_iget(struct xfs_mount *, struct xfs_trans *, xfs_ino_t, |
491 | uint, uint, xfs_inode_t **, xfs_daddr_t); | 471 | uint, uint, xfs_inode_t **, xfs_daddr_t); |
492 | void xfs_iput(xfs_inode_t *, uint); | 472 | void xfs_iput(xfs_inode_t *, uint); |
@@ -521,7 +501,6 @@ void xfs_ipin(xfs_inode_t *); | |||
521 | void xfs_iunpin(xfs_inode_t *); | 501 | void xfs_iunpin(xfs_inode_t *); |
522 | int xfs_iflush(xfs_inode_t *, uint); | 502 | int xfs_iflush(xfs_inode_t *, uint); |
523 | void xfs_ichgtime(xfs_inode_t *, int); | 503 | void xfs_ichgtime(xfs_inode_t *, int); |
524 | xfs_fsize_t xfs_file_last_byte(xfs_inode_t *); | ||
525 | void xfs_lock_inodes(xfs_inode_t **, int, uint); | 504 | void xfs_lock_inodes(xfs_inode_t **, int, uint); |
526 | void xfs_lock_two_inodes(xfs_inode_t *, xfs_inode_t *, uint); | 505 | void xfs_lock_two_inodes(xfs_inode_t *, xfs_inode_t *, uint); |
527 | 506 | ||
@@ -589,8 +568,6 @@ int xfs_itobp(struct xfs_mount *, struct xfs_trans *, | |||
589 | struct xfs_buf **, uint); | 568 | struct xfs_buf **, uint); |
590 | int xfs_iread(struct xfs_mount *, struct xfs_trans *, | 569 | int xfs_iread(struct xfs_mount *, struct xfs_trans *, |
591 | struct xfs_inode *, xfs_daddr_t, uint); | 570 | struct xfs_inode *, xfs_daddr_t, uint); |
592 | void xfs_dinode_from_disk(struct xfs_icdinode *, | ||
593 | struct xfs_dinode *); | ||
594 | void xfs_dinode_to_disk(struct xfs_dinode *, | 571 | void xfs_dinode_to_disk(struct xfs_dinode *, |
595 | struct xfs_icdinode *); | 572 | struct xfs_icdinode *); |
596 | void xfs_idestroy_fork(struct xfs_inode *, int); | 573 | void xfs_idestroy_fork(struct xfs_inode *, int); |
@@ -609,8 +586,6 @@ void xfs_iext_remove_inline(xfs_ifork_t *, xfs_extnum_t, int); | |||
609 | void xfs_iext_remove_direct(xfs_ifork_t *, xfs_extnum_t, int); | 586 | void xfs_iext_remove_direct(xfs_ifork_t *, xfs_extnum_t, int); |
610 | void xfs_iext_remove_indirect(xfs_ifork_t *, xfs_extnum_t, int); | 587 | void xfs_iext_remove_indirect(xfs_ifork_t *, xfs_extnum_t, int); |
611 | void xfs_iext_realloc_direct(xfs_ifork_t *, int); | 588 | void xfs_iext_realloc_direct(xfs_ifork_t *, int); |
612 | void xfs_iext_realloc_indirect(xfs_ifork_t *, int); | ||
613 | void xfs_iext_indirect_to_direct(xfs_ifork_t *); | ||
614 | void xfs_iext_direct_to_inline(xfs_ifork_t *, xfs_extnum_t); | 589 | void xfs_iext_direct_to_inline(xfs_ifork_t *, xfs_extnum_t); |
615 | void xfs_iext_inline_to_direct(xfs_ifork_t *, int); | 590 | void xfs_iext_inline_to_direct(xfs_ifork_t *, int); |
616 | void xfs_iext_destroy(xfs_ifork_t *); | 591 | void xfs_iext_destroy(xfs_ifork_t *); |
diff --git a/fs/xfs/xfs_inode_item.c b/fs/xfs/xfs_inode_item.c index 977c4aec587e..47d5b663c37e 100644 --- a/fs/xfs/xfs_inode_item.c +++ b/fs/xfs/xfs_inode_item.c | |||
@@ -263,14 +263,6 @@ xfs_inode_item_format( | |||
263 | } | 263 | } |
264 | 264 | ||
265 | /* | 265 | /* |
266 | * We don't have to worry about re-ordering here because | ||
267 | * the update_size field is protected by the inode lock | ||
268 | * and we have that held in exclusive mode. | ||
269 | */ | ||
270 | if (ip->i_update_size) | ||
271 | ip->i_update_size = 0; | ||
272 | |||
273 | /* | ||
274 | * Make sure to get the latest atime from the Linux inode. | 266 | * Make sure to get the latest atime from the Linux inode. |
275 | */ | 267 | */ |
276 | xfs_synchronize_atime(ip); | 268 | xfs_synchronize_atime(ip); |
@@ -712,8 +704,6 @@ xfs_inode_item_unlock( | |||
712 | * Clear out the fields of the inode log item particular | 704 | * Clear out the fields of the inode log item particular |
713 | * to the current transaction. | 705 | * to the current transaction. |
714 | */ | 706 | */ |
715 | iip->ili_ilock_recur = 0; | ||
716 | iip->ili_iolock_recur = 0; | ||
717 | iip->ili_flags = 0; | 707 | iip->ili_flags = 0; |
718 | 708 | ||
719 | /* | 709 | /* |
diff --git a/fs/xfs/xfs_inode_item.h b/fs/xfs/xfs_inode_item.h index a52ac125f055..65bae4c9b8bf 100644 --- a/fs/xfs/xfs_inode_item.h +++ b/fs/xfs/xfs_inode_item.h | |||
@@ -137,8 +137,6 @@ typedef struct xfs_inode_log_item { | |||
137 | struct xfs_inode *ili_inode; /* inode ptr */ | 137 | struct xfs_inode *ili_inode; /* inode ptr */ |
138 | xfs_lsn_t ili_flush_lsn; /* lsn at last flush */ | 138 | xfs_lsn_t ili_flush_lsn; /* lsn at last flush */ |
139 | xfs_lsn_t ili_last_lsn; /* lsn at last transaction */ | 139 | xfs_lsn_t ili_last_lsn; /* lsn at last transaction */ |
140 | unsigned short ili_ilock_recur; /* lock recursion count */ | ||
141 | unsigned short ili_iolock_recur; /* lock recursion count */ | ||
142 | unsigned short ili_flags; /* misc flags */ | 140 | unsigned short ili_flags; /* misc flags */ |
143 | unsigned short ili_logged; /* flushed logged data */ | 141 | unsigned short ili_logged; /* flushed logged data */ |
144 | unsigned int ili_last_fields; /* fields when flushed */ | 142 | unsigned int ili_last_fields; /* fields when flushed */ |
diff --git a/fs/xfs/xfs_inum.h b/fs/xfs/xfs_inum.h index 7a28191cb0de..b8e4ee4e89a4 100644 --- a/fs/xfs/xfs_inum.h +++ b/fs/xfs/xfs_inum.h | |||
@@ -72,7 +72,6 @@ struct xfs_mount; | |||
72 | 72 | ||
73 | #if XFS_BIG_INUMS | 73 | #if XFS_BIG_INUMS |
74 | #define XFS_MAXINUMBER ((xfs_ino_t)((1ULL << 56) - 1ULL)) | 74 | #define XFS_MAXINUMBER ((xfs_ino_t)((1ULL << 56) - 1ULL)) |
75 | #define XFS_INO64_OFFSET ((xfs_ino_t)(1ULL << 32)) | ||
76 | #else | 75 | #else |
77 | #define XFS_MAXINUMBER ((xfs_ino_t)((1ULL << 32) - 1ULL)) | 76 | #define XFS_MAXINUMBER ((xfs_ino_t)((1ULL << 32) - 1ULL)) |
78 | #endif | 77 | #endif |
diff --git a/fs/xfs/xfs_itable.c b/fs/xfs/xfs_itable.c index aeb2d2221c7d..b68f9107e26c 100644 --- a/fs/xfs/xfs_itable.c +++ b/fs/xfs/xfs_itable.c | |||
@@ -39,7 +39,7 @@ | |||
39 | #include "xfs_error.h" | 39 | #include "xfs_error.h" |
40 | #include "xfs_btree.h" | 40 | #include "xfs_btree.h" |
41 | 41 | ||
42 | int | 42 | STATIC int |
43 | xfs_internal_inum( | 43 | xfs_internal_inum( |
44 | xfs_mount_t *mp, | 44 | xfs_mount_t *mp, |
45 | xfs_ino_t ino) | 45 | xfs_ino_t ino) |
@@ -353,9 +353,6 @@ xfs_bulkstat( | |||
353 | int end_of_ag; /* set if we've seen the ag end */ | 353 | int end_of_ag; /* set if we've seen the ag end */ |
354 | int error; /* error code */ | 354 | int error; /* error code */ |
355 | int fmterror;/* bulkstat formatter result */ | 355 | int fmterror;/* bulkstat formatter result */ |
356 | __int32_t gcnt; /* current btree rec's count */ | ||
357 | xfs_inofree_t gfree; /* current btree rec's free mask */ | ||
358 | xfs_agino_t gino; /* current btree rec's start inode */ | ||
359 | int i; /* loop index */ | 356 | int i; /* loop index */ |
360 | int icount; /* count of inodes good in irbuf */ | 357 | int icount; /* count of inodes good in irbuf */ |
361 | size_t irbsize; /* size of irec buffer in bytes */ | 358 | size_t irbsize; /* size of irec buffer in bytes */ |
@@ -442,40 +439,43 @@ xfs_bulkstat( | |||
442 | * we need to get the remainder of the chunk we're in. | 439 | * we need to get the remainder of the chunk we're in. |
443 | */ | 440 | */ |
444 | if (agino > 0) { | 441 | if (agino > 0) { |
442 | xfs_inobt_rec_incore_t r; | ||
443 | |||
445 | /* | 444 | /* |
446 | * Lookup the inode chunk that this inode lives in. | 445 | * Lookup the inode chunk that this inode lives in. |
447 | */ | 446 | */ |
448 | error = xfs_inobt_lookup_le(cur, agino, 0, 0, &tmp); | 447 | error = xfs_inobt_lookup(cur, agino, XFS_LOOKUP_LE, |
448 | &tmp); | ||
449 | if (!error && /* no I/O error */ | 449 | if (!error && /* no I/O error */ |
450 | tmp && /* lookup succeeded */ | 450 | tmp && /* lookup succeeded */ |
451 | /* got the record, should always work */ | 451 | /* got the record, should always work */ |
452 | !(error = xfs_inobt_get_rec(cur, &gino, &gcnt, | 452 | !(error = xfs_inobt_get_rec(cur, &r, &i)) && |
453 | &gfree, &i)) && | ||
454 | i == 1 && | 453 | i == 1 && |
455 | /* this is the right chunk */ | 454 | /* this is the right chunk */ |
456 | agino < gino + XFS_INODES_PER_CHUNK && | 455 | agino < r.ir_startino + XFS_INODES_PER_CHUNK && |
457 | /* lastino was not last in chunk */ | 456 | /* lastino was not last in chunk */ |
458 | (chunkidx = agino - gino + 1) < | 457 | (chunkidx = agino - r.ir_startino + 1) < |
459 | XFS_INODES_PER_CHUNK && | 458 | XFS_INODES_PER_CHUNK && |
460 | /* there are some left allocated */ | 459 | /* there are some left allocated */ |
461 | xfs_inobt_maskn(chunkidx, | 460 | xfs_inobt_maskn(chunkidx, |
462 | XFS_INODES_PER_CHUNK - chunkidx) & ~gfree) { | 461 | XFS_INODES_PER_CHUNK - chunkidx) & |
462 | ~r.ir_free) { | ||
463 | /* | 463 | /* |
464 | * Grab the chunk record. Mark all the | 464 | * Grab the chunk record. Mark all the |
465 | * uninteresting inodes (because they're | 465 | * uninteresting inodes (because they're |
466 | * before our start point) free. | 466 | * before our start point) free. |
467 | */ | 467 | */ |
468 | for (i = 0; i < chunkidx; i++) { | 468 | for (i = 0; i < chunkidx; i++) { |
469 | if (XFS_INOBT_MASK(i) & ~gfree) | 469 | if (XFS_INOBT_MASK(i) & ~r.ir_free) |
470 | gcnt++; | 470 | r.ir_freecount++; |
471 | } | 471 | } |
472 | gfree |= xfs_inobt_maskn(0, chunkidx); | 472 | r.ir_free |= xfs_inobt_maskn(0, chunkidx); |
473 | irbp->ir_startino = gino; | 473 | irbp->ir_startino = r.ir_startino; |
474 | irbp->ir_freecount = gcnt; | 474 | irbp->ir_freecount = r.ir_freecount; |
475 | irbp->ir_free = gfree; | 475 | irbp->ir_free = r.ir_free; |
476 | irbp++; | 476 | irbp++; |
477 | agino = gino + XFS_INODES_PER_CHUNK; | 477 | agino = r.ir_startino + XFS_INODES_PER_CHUNK; |
478 | icount = XFS_INODES_PER_CHUNK - gcnt; | 478 | icount = XFS_INODES_PER_CHUNK - r.ir_freecount; |
479 | } else { | 479 | } else { |
480 | /* | 480 | /* |
481 | * If any of those tests failed, bump the | 481 | * If any of those tests failed, bump the |
@@ -493,7 +493,7 @@ xfs_bulkstat( | |||
493 | /* | 493 | /* |
494 | * Start of ag. Lookup the first inode chunk. | 494 | * Start of ag. Lookup the first inode chunk. |
495 | */ | 495 | */ |
496 | error = xfs_inobt_lookup_ge(cur, 0, 0, 0, &tmp); | 496 | error = xfs_inobt_lookup(cur, 0, XFS_LOOKUP_GE, &tmp); |
497 | icount = 0; | 497 | icount = 0; |
498 | } | 498 | } |
499 | /* | 499 | /* |
@@ -501,6 +501,8 @@ xfs_bulkstat( | |||
501 | * until we run out of inodes or space in the buffer. | 501 | * until we run out of inodes or space in the buffer. |
502 | */ | 502 | */ |
503 | while (irbp < irbufend && icount < ubcount) { | 503 | while (irbp < irbufend && icount < ubcount) { |
504 | xfs_inobt_rec_incore_t r; | ||
505 | |||
504 | /* | 506 | /* |
505 | * Loop as long as we're unable to read the | 507 | * Loop as long as we're unable to read the |
506 | * inode btree. | 508 | * inode btree. |
@@ -510,51 +512,55 @@ xfs_bulkstat( | |||
510 | if (XFS_AGINO_TO_AGBNO(mp, agino) >= | 512 | if (XFS_AGINO_TO_AGBNO(mp, agino) >= |
511 | be32_to_cpu(agi->agi_length)) | 513 | be32_to_cpu(agi->agi_length)) |
512 | break; | 514 | break; |
513 | error = xfs_inobt_lookup_ge(cur, agino, 0, 0, | 515 | error = xfs_inobt_lookup(cur, agino, |
514 | &tmp); | 516 | XFS_LOOKUP_GE, &tmp); |
515 | cond_resched(); | 517 | cond_resched(); |
516 | } | 518 | } |
517 | /* | 519 | /* |
518 | * If ran off the end of the ag either with an error, | 520 | * If ran off the end of the ag either with an error, |
519 | * or the normal way, set end and stop collecting. | 521 | * or the normal way, set end and stop collecting. |
520 | */ | 522 | */ |
521 | if (error || | 523 | if (error) { |
522 | (error = xfs_inobt_get_rec(cur, &gino, &gcnt, | ||
523 | &gfree, &i)) || | ||
524 | i == 0) { | ||
525 | end_of_ag = 1; | 524 | end_of_ag = 1; |
526 | break; | 525 | break; |
527 | } | 526 | } |
527 | |||
528 | error = xfs_inobt_get_rec(cur, &r, &i); | ||
529 | if (error || i == 0) { | ||
530 | end_of_ag = 1; | ||
531 | break; | ||
532 | } | ||
533 | |||
528 | /* | 534 | /* |
529 | * If this chunk has any allocated inodes, save it. | 535 | * If this chunk has any allocated inodes, save it. |
530 | * Also start read-ahead now for this chunk. | 536 | * Also start read-ahead now for this chunk. |
531 | */ | 537 | */ |
532 | if (gcnt < XFS_INODES_PER_CHUNK) { | 538 | if (r.ir_freecount < XFS_INODES_PER_CHUNK) { |
533 | /* | 539 | /* |
534 | * Loop over all clusters in the next chunk. | 540 | * Loop over all clusters in the next chunk. |
535 | * Do a readahead if there are any allocated | 541 | * Do a readahead if there are any allocated |
536 | * inodes in that cluster. | 542 | * inodes in that cluster. |
537 | */ | 543 | */ |
538 | for (agbno = XFS_AGINO_TO_AGBNO(mp, gino), | 544 | agbno = XFS_AGINO_TO_AGBNO(mp, r.ir_startino); |
539 | chunkidx = 0; | 545 | for (chunkidx = 0; |
540 | chunkidx < XFS_INODES_PER_CHUNK; | 546 | chunkidx < XFS_INODES_PER_CHUNK; |
541 | chunkidx += nicluster, | 547 | chunkidx += nicluster, |
542 | agbno += nbcluster) { | 548 | agbno += nbcluster) { |
543 | if (xfs_inobt_maskn(chunkidx, | 549 | if (xfs_inobt_maskn(chunkidx, nicluster) |
544 | nicluster) & ~gfree) | 550 | & ~r.ir_free) |
545 | xfs_btree_reada_bufs(mp, agno, | 551 | xfs_btree_reada_bufs(mp, agno, |
546 | agbno, nbcluster); | 552 | agbno, nbcluster); |
547 | } | 553 | } |
548 | irbp->ir_startino = gino; | 554 | irbp->ir_startino = r.ir_startino; |
549 | irbp->ir_freecount = gcnt; | 555 | irbp->ir_freecount = r.ir_freecount; |
550 | irbp->ir_free = gfree; | 556 | irbp->ir_free = r.ir_free; |
551 | irbp++; | 557 | irbp++; |
552 | icount += XFS_INODES_PER_CHUNK - gcnt; | 558 | icount += XFS_INODES_PER_CHUNK - r.ir_freecount; |
553 | } | 559 | } |
554 | /* | 560 | /* |
555 | * Set agino to after this chunk and bump the cursor. | 561 | * Set agino to after this chunk and bump the cursor. |
556 | */ | 562 | */ |
557 | agino = gino + XFS_INODES_PER_CHUNK; | 563 | agino = r.ir_startino + XFS_INODES_PER_CHUNK; |
558 | error = xfs_btree_increment(cur, 0, &tmp); | 564 | error = xfs_btree_increment(cur, 0, &tmp); |
559 | cond_resched(); | 565 | cond_resched(); |
560 | } | 566 | } |
@@ -820,9 +826,7 @@ xfs_inumbers( | |||
820 | int bufidx; | 826 | int bufidx; |
821 | xfs_btree_cur_t *cur; | 827 | xfs_btree_cur_t *cur; |
822 | int error; | 828 | int error; |
823 | __int32_t gcnt; | 829 | xfs_inobt_rec_incore_t r; |
824 | xfs_inofree_t gfree; | ||
825 | xfs_agino_t gino; | ||
826 | int i; | 830 | int i; |
827 | xfs_ino_t ino; | 831 | xfs_ino_t ino; |
828 | int left; | 832 | int left; |
@@ -855,7 +859,8 @@ xfs_inumbers( | |||
855 | continue; | 859 | continue; |
856 | } | 860 | } |
857 | cur = xfs_inobt_init_cursor(mp, NULL, agbp, agno); | 861 | cur = xfs_inobt_init_cursor(mp, NULL, agbp, agno); |
858 | error = xfs_inobt_lookup_ge(cur, agino, 0, 0, &tmp); | 862 | error = xfs_inobt_lookup(cur, agino, XFS_LOOKUP_GE, |
863 | &tmp); | ||
859 | if (error) { | 864 | if (error) { |
860 | xfs_btree_del_cursor(cur, XFS_BTREE_ERROR); | 865 | xfs_btree_del_cursor(cur, XFS_BTREE_ERROR); |
861 | cur = NULL; | 866 | cur = NULL; |
@@ -870,9 +875,8 @@ xfs_inumbers( | |||
870 | continue; | 875 | continue; |
871 | } | 876 | } |
872 | } | 877 | } |
873 | if ((error = xfs_inobt_get_rec(cur, &gino, &gcnt, &gfree, | 878 | error = xfs_inobt_get_rec(cur, &r, &i); |
874 | &i)) || | 879 | if (error || i == 0) { |
875 | i == 0) { | ||
876 | xfs_buf_relse(agbp); | 880 | xfs_buf_relse(agbp); |
877 | agbp = NULL; | 881 | agbp = NULL; |
878 | xfs_btree_del_cursor(cur, XFS_BTREE_NOERROR); | 882 | xfs_btree_del_cursor(cur, XFS_BTREE_NOERROR); |
@@ -881,10 +885,12 @@ xfs_inumbers( | |||
881 | agino = 0; | 885 | agino = 0; |
882 | continue; | 886 | continue; |
883 | } | 887 | } |
884 | agino = gino + XFS_INODES_PER_CHUNK - 1; | 888 | agino = r.ir_startino + XFS_INODES_PER_CHUNK - 1; |
885 | buffer[bufidx].xi_startino = XFS_AGINO_TO_INO(mp, agno, gino); | 889 | buffer[bufidx].xi_startino = |
886 | buffer[bufidx].xi_alloccount = XFS_INODES_PER_CHUNK - gcnt; | 890 | XFS_AGINO_TO_INO(mp, agno, r.ir_startino); |
887 | buffer[bufidx].xi_allocmask = ~gfree; | 891 | buffer[bufidx].xi_alloccount = |
892 | XFS_INODES_PER_CHUNK - r.ir_freecount; | ||
893 | buffer[bufidx].xi_allocmask = ~r.ir_free; | ||
888 | bufidx++; | 894 | bufidx++; |
889 | left--; | 895 | left--; |
890 | if (bufidx == bcount) { | 896 | if (bufidx == bcount) { |
diff --git a/fs/xfs/xfs_itable.h b/fs/xfs/xfs_itable.h index 1fb04e7deb61..20792bf45946 100644 --- a/fs/xfs/xfs_itable.h +++ b/fs/xfs/xfs_itable.h | |||
@@ -99,11 +99,6 @@ xfs_bulkstat_one( | |||
99 | void *dibuff, | 99 | void *dibuff, |
100 | int *stat); | 100 | int *stat); |
101 | 101 | ||
102 | int | ||
103 | xfs_internal_inum( | ||
104 | xfs_mount_t *mp, | ||
105 | xfs_ino_t ino); | ||
106 | |||
107 | typedef int (*inumbers_fmt_pf)( | 102 | typedef int (*inumbers_fmt_pf)( |
108 | void __user *ubuffer, /* buffer to write to */ | 103 | void __user *ubuffer, /* buffer to write to */ |
109 | const xfs_inogrp_t *buffer, /* buffer to read from */ | 104 | const xfs_inogrp_t *buffer, /* buffer to read from */ |
diff --git a/fs/xfs/xfs_log.c b/fs/xfs/xfs_log.c index 3750f04ede0b..9dbdff3ea484 100644 --- a/fs/xfs/xfs_log.c +++ b/fs/xfs/xfs_log.c | |||
@@ -3180,7 +3180,7 @@ try_again: | |||
3180 | STATIC void | 3180 | STATIC void |
3181 | xlog_state_want_sync(xlog_t *log, xlog_in_core_t *iclog) | 3181 | xlog_state_want_sync(xlog_t *log, xlog_in_core_t *iclog) |
3182 | { | 3182 | { |
3183 | ASSERT(spin_is_locked(&log->l_icloglock)); | 3183 | assert_spin_locked(&log->l_icloglock); |
3184 | 3184 | ||
3185 | if (iclog->ic_state == XLOG_STATE_ACTIVE) { | 3185 | if (iclog->ic_state == XLOG_STATE_ACTIVE) { |
3186 | xlog_state_switch_iclogs(log, iclog, 0); | 3186 | xlog_state_switch_iclogs(log, iclog, 0); |
diff --git a/fs/xfs/xfs_log_priv.h b/fs/xfs/xfs_log_priv.h index bcad5f4c1fd1..679c7c4926a2 100644 --- a/fs/xfs/xfs_log_priv.h +++ b/fs/xfs/xfs_log_priv.h | |||
@@ -451,8 +451,6 @@ extern int xlog_find_tail(xlog_t *log, | |||
451 | extern int xlog_recover(xlog_t *log); | 451 | extern int xlog_recover(xlog_t *log); |
452 | extern int xlog_recover_finish(xlog_t *log); | 452 | extern int xlog_recover_finish(xlog_t *log); |
453 | extern void xlog_pack_data(xlog_t *log, xlog_in_core_t *iclog, int); | 453 | extern void xlog_pack_data(xlog_t *log, xlog_in_core_t *iclog, int); |
454 | extern void xlog_recover_process_iunlinks(xlog_t *log); | ||
455 | |||
456 | extern struct xfs_buf *xlog_get_bp(xlog_t *, int); | 454 | extern struct xfs_buf *xlog_get_bp(xlog_t *, int); |
457 | extern void xlog_put_bp(struct xfs_buf *); | 455 | extern void xlog_put_bp(struct xfs_buf *); |
458 | 456 | ||
diff --git a/fs/xfs/xfs_log_recover.c b/fs/xfs/xfs_log_recover.c index 47da2fb45377..1099395d7d6c 100644 --- a/fs/xfs/xfs_log_recover.c +++ b/fs/xfs/xfs_log_recover.c | |||
@@ -3263,7 +3263,7 @@ xlog_recover_process_one_iunlink( | |||
3263 | * freeing of the inode and its removal from the list must be | 3263 | * freeing of the inode and its removal from the list must be |
3264 | * atomic. | 3264 | * atomic. |
3265 | */ | 3265 | */ |
3266 | void | 3266 | STATIC void |
3267 | xlog_recover_process_iunlinks( | 3267 | xlog_recover_process_iunlinks( |
3268 | xlog_t *log) | 3268 | xlog_t *log) |
3269 | { | 3269 | { |
diff --git a/fs/xfs/xfs_mount.c b/fs/xfs/xfs_mount.c index 5c6f092659c1..8b6c9e807efb 100644 --- a/fs/xfs/xfs_mount.c +++ b/fs/xfs/xfs_mount.c | |||
@@ -1568,7 +1568,7 @@ xfs_mod_sb(xfs_trans_t *tp, __int64_t fields) | |||
1568 | * | 1568 | * |
1569 | * The m_sb_lock must be held when this routine is called. | 1569 | * The m_sb_lock must be held when this routine is called. |
1570 | */ | 1570 | */ |
1571 | int | 1571 | STATIC int |
1572 | xfs_mod_incore_sb_unlocked( | 1572 | xfs_mod_incore_sb_unlocked( |
1573 | xfs_mount_t *mp, | 1573 | xfs_mount_t *mp, |
1574 | xfs_sb_field_t field, | 1574 | xfs_sb_field_t field, |
diff --git a/fs/xfs/xfs_mount.h b/fs/xfs/xfs_mount.h index a5122382afde..a6c023bc0fb2 100644 --- a/fs/xfs/xfs_mount.h +++ b/fs/xfs/xfs_mount.h | |||
@@ -414,13 +414,10 @@ typedef struct xfs_mod_sb { | |||
414 | 414 | ||
415 | extern int xfs_log_sbcount(xfs_mount_t *, uint); | 415 | extern int xfs_log_sbcount(xfs_mount_t *, uint); |
416 | extern int xfs_mountfs(xfs_mount_t *mp); | 416 | extern int xfs_mountfs(xfs_mount_t *mp); |
417 | extern void xfs_mountfs_check_barriers(xfs_mount_t *mp); | ||
418 | 417 | ||
419 | extern void xfs_unmountfs(xfs_mount_t *); | 418 | extern void xfs_unmountfs(xfs_mount_t *); |
420 | extern int xfs_unmountfs_writesb(xfs_mount_t *); | 419 | extern int xfs_unmountfs_writesb(xfs_mount_t *); |
421 | extern int xfs_mod_incore_sb(xfs_mount_t *, xfs_sb_field_t, int64_t, int); | 420 | extern int xfs_mod_incore_sb(xfs_mount_t *, xfs_sb_field_t, int64_t, int); |
422 | extern int xfs_mod_incore_sb_unlocked(xfs_mount_t *, xfs_sb_field_t, | ||
423 | int64_t, int); | ||
424 | extern int xfs_mod_incore_sb_batch(xfs_mount_t *, xfs_mod_sb_t *, | 421 | extern int xfs_mod_incore_sb_batch(xfs_mount_t *, xfs_mod_sb_t *, |
425 | uint, int); | 422 | uint, int); |
426 | extern int xfs_mount_log_sb(xfs_mount_t *, __int64_t); | 423 | extern int xfs_mount_log_sb(xfs_mount_t *, __int64_t); |
diff --git a/fs/xfs/xfs_mru_cache.c b/fs/xfs/xfs_mru_cache.c index afee7eb24323..4b0613d99faa 100644 --- a/fs/xfs/xfs_mru_cache.c +++ b/fs/xfs/xfs_mru_cache.c | |||
@@ -564,35 +564,6 @@ xfs_mru_cache_lookup( | |||
564 | } | 564 | } |
565 | 565 | ||
566 | /* | 566 | /* |
567 | * To look up an element using its key, but leave its location in the internal | ||
568 | * lists alone, call xfs_mru_cache_peek(). If the element isn't found, this | ||
569 | * function returns NULL. | ||
570 | * | ||
571 | * See the comments above the declaration of the xfs_mru_cache_lookup() function | ||
572 | * for important locking information pertaining to this call. | ||
573 | */ | ||
574 | void * | ||
575 | xfs_mru_cache_peek( | ||
576 | xfs_mru_cache_t *mru, | ||
577 | unsigned long key) | ||
578 | { | ||
579 | xfs_mru_cache_elem_t *elem; | ||
580 | |||
581 | ASSERT(mru && mru->lists); | ||
582 | if (!mru || !mru->lists) | ||
583 | return NULL; | ||
584 | |||
585 | spin_lock(&mru->lock); | ||
586 | elem = radix_tree_lookup(&mru->store, key); | ||
587 | if (!elem) | ||
588 | spin_unlock(&mru->lock); | ||
589 | else | ||
590 | __release(mru_lock); /* help sparse not be stupid */ | ||
591 | |||
592 | return elem ? elem->value : NULL; | ||
593 | } | ||
594 | |||
595 | /* | ||
596 | * To release the internal data structure spinlock after having performed an | 567 | * To release the internal data structure spinlock after having performed an |
597 | * xfs_mru_cache_lookup() or an xfs_mru_cache_peek(), call xfs_mru_cache_done() | 568 | * xfs_mru_cache_lookup() or an xfs_mru_cache_peek(), call xfs_mru_cache_done() |
598 | * with the data store pointer. | 569 | * with the data store pointer. |
diff --git a/fs/xfs/xfs_mru_cache.h b/fs/xfs/xfs_mru_cache.h index dd58ea1bbebe..5d439f34b0c9 100644 --- a/fs/xfs/xfs_mru_cache.h +++ b/fs/xfs/xfs_mru_cache.h | |||
@@ -49,7 +49,6 @@ int xfs_mru_cache_insert(struct xfs_mru_cache *mru, unsigned long key, | |||
49 | void * xfs_mru_cache_remove(struct xfs_mru_cache *mru, unsigned long key); | 49 | void * xfs_mru_cache_remove(struct xfs_mru_cache *mru, unsigned long key); |
50 | void xfs_mru_cache_delete(struct xfs_mru_cache *mru, unsigned long key); | 50 | void xfs_mru_cache_delete(struct xfs_mru_cache *mru, unsigned long key); |
51 | void *xfs_mru_cache_lookup(struct xfs_mru_cache *mru, unsigned long key); | 51 | void *xfs_mru_cache_lookup(struct xfs_mru_cache *mru, unsigned long key); |
52 | void *xfs_mru_cache_peek(struct xfs_mru_cache *mru, unsigned long key); | ||
53 | void xfs_mru_cache_done(struct xfs_mru_cache *mru); | 52 | void xfs_mru_cache_done(struct xfs_mru_cache *mru); |
54 | 53 | ||
55 | #endif /* __XFS_MRU_CACHE_H__ */ | 54 | #endif /* __XFS_MRU_CACHE_H__ */ |
diff --git a/fs/xfs/xfs_rw.c b/fs/xfs/xfs_rw.c index fea68615ed23..3f816ad7ff19 100644 --- a/fs/xfs/xfs_rw.c +++ b/fs/xfs/xfs_rw.c | |||
@@ -88,90 +88,6 @@ xfs_write_clear_setuid( | |||
88 | } | 88 | } |
89 | 89 | ||
90 | /* | 90 | /* |
91 | * Handle logging requirements of various synchronous types of write. | ||
92 | */ | ||
93 | int | ||
94 | xfs_write_sync_logforce( | ||
95 | xfs_mount_t *mp, | ||
96 | xfs_inode_t *ip) | ||
97 | { | ||
98 | int error = 0; | ||
99 | |||
100 | /* | ||
101 | * If we're treating this as O_DSYNC and we have not updated the | ||
102 | * size, force the log. | ||
103 | */ | ||
104 | if (!(mp->m_flags & XFS_MOUNT_OSYNCISOSYNC) && | ||
105 | !(ip->i_update_size)) { | ||
106 | xfs_inode_log_item_t *iip = ip->i_itemp; | ||
107 | |||
108 | /* | ||
109 | * If an allocation transaction occurred | ||
110 | * without extending the size, then we have to force | ||
111 | * the log up the proper point to ensure that the | ||
112 | * allocation is permanent. We can't count on | ||
113 | * the fact that buffered writes lock out direct I/O | ||
114 | * writes - the direct I/O write could have extended | ||
115 | * the size nontransactionally, then finished before | ||
116 | * we started. xfs_write_file will think that the file | ||
117 | * didn't grow but the update isn't safe unless the | ||
118 | * size change is logged. | ||
119 | * | ||
120 | * Force the log if we've committed a transaction | ||
121 | * against the inode or if someone else has and | ||
122 | * the commit record hasn't gone to disk (e.g. | ||
123 | * the inode is pinned). This guarantees that | ||
124 | * all changes affecting the inode are permanent | ||
125 | * when we return. | ||
126 | */ | ||
127 | if (iip && iip->ili_last_lsn) { | ||
128 | error = _xfs_log_force(mp, iip->ili_last_lsn, | ||
129 | XFS_LOG_FORCE | XFS_LOG_SYNC, NULL); | ||
130 | } else if (xfs_ipincount(ip) > 0) { | ||
131 | error = _xfs_log_force(mp, (xfs_lsn_t)0, | ||
132 | XFS_LOG_FORCE | XFS_LOG_SYNC, NULL); | ||
133 | } | ||
134 | |||
135 | } else { | ||
136 | xfs_trans_t *tp; | ||
137 | |||
138 | /* | ||
139 | * O_SYNC or O_DSYNC _with_ a size update are handled | ||
140 | * the same way. | ||
141 | * | ||
142 | * If the write was synchronous then we need to make | ||
143 | * sure that the inode modification time is permanent. | ||
144 | * We'll have updated the timestamp above, so here | ||
145 | * we use a synchronous transaction to log the inode. | ||
146 | * It's not fast, but it's necessary. | ||
147 | * | ||
148 | * If this a dsync write and the size got changed | ||
149 | * non-transactionally, then we need to ensure that | ||
150 | * the size change gets logged in a synchronous | ||
151 | * transaction. | ||
152 | */ | ||
153 | tp = xfs_trans_alloc(mp, XFS_TRANS_WRITE_SYNC); | ||
154 | if ((error = xfs_trans_reserve(tp, 0, | ||
155 | XFS_SWRITE_LOG_RES(mp), | ||
156 | 0, 0, 0))) { | ||
157 | /* Transaction reserve failed */ | ||
158 | xfs_trans_cancel(tp, 0); | ||
159 | } else { | ||
160 | /* Transaction reserve successful */ | ||
161 | xfs_ilock(ip, XFS_ILOCK_EXCL); | ||
162 | xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL); | ||
163 | xfs_trans_ihold(tp, ip); | ||
164 | xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE); | ||
165 | xfs_trans_set_sync(tp); | ||
166 | error = xfs_trans_commit(tp, 0); | ||
167 | xfs_iunlock(ip, XFS_ILOCK_EXCL); | ||
168 | } | ||
169 | } | ||
170 | |||
171 | return error; | ||
172 | } | ||
173 | |||
174 | /* | ||
175 | * Force a shutdown of the filesystem instantly while keeping | 91 | * Force a shutdown of the filesystem instantly while keeping |
176 | * the filesystem consistent. We don't do an unmount here; just shutdown | 92 | * the filesystem consistent. We don't do an unmount here; just shutdown |
177 | * the shop, make sure that absolutely nothing persistent happens to | 93 | * the shop, make sure that absolutely nothing persistent happens to |
diff --git a/fs/xfs/xfs_rw.h b/fs/xfs/xfs_rw.h index f76c003ec55d..f5e4874c37d8 100644 --- a/fs/xfs/xfs_rw.h +++ b/fs/xfs/xfs_rw.h | |||
@@ -68,7 +68,6 @@ xfs_get_extsz_hint( | |||
68 | * Prototypes for functions in xfs_rw.c. | 68 | * Prototypes for functions in xfs_rw.c. |
69 | */ | 69 | */ |
70 | extern int xfs_write_clear_setuid(struct xfs_inode *ip); | 70 | extern int xfs_write_clear_setuid(struct xfs_inode *ip); |
71 | extern int xfs_write_sync_logforce(struct xfs_mount *mp, struct xfs_inode *ip); | ||
72 | extern int xfs_bwrite(struct xfs_mount *mp, struct xfs_buf *bp); | 71 | extern int xfs_bwrite(struct xfs_mount *mp, struct xfs_buf *bp); |
73 | extern int xfs_bioerror(struct xfs_buf *bp); | 72 | extern int xfs_bioerror(struct xfs_buf *bp); |
74 | extern int xfs_bioerror_relse(struct xfs_buf *bp); | 73 | extern int xfs_bioerror_relse(struct xfs_buf *bp); |
@@ -78,10 +77,4 @@ extern int xfs_read_buf(struct xfs_mount *mp, xfs_buftarg_t *btp, | |||
78 | extern void xfs_ioerror_alert(char *func, struct xfs_mount *mp, | 77 | extern void xfs_ioerror_alert(char *func, struct xfs_mount *mp, |
79 | xfs_buf_t *bp, xfs_daddr_t blkno); | 78 | xfs_buf_t *bp, xfs_daddr_t blkno); |
80 | 79 | ||
81 | /* | ||
82 | * Prototypes for functions in xfs_vnodeops.c. | ||
83 | */ | ||
84 | extern int xfs_free_eofblocks(struct xfs_mount *mp, struct xfs_inode *ip, | ||
85 | int flags); | ||
86 | |||
87 | #endif /* __XFS_RW_H__ */ | 80 | #endif /* __XFS_RW_H__ */ |
diff --git a/fs/xfs/xfs_trans.h b/fs/xfs/xfs_trans.h index 775249a54f6f..ed47fc77759c 100644 --- a/fs/xfs/xfs_trans.h +++ b/fs/xfs/xfs_trans.h | |||
@@ -68,7 +68,7 @@ typedef struct xfs_trans_header { | |||
68 | #define XFS_TRANS_GROWFS 14 | 68 | #define XFS_TRANS_GROWFS 14 |
69 | #define XFS_TRANS_STRAT_WRITE 15 | 69 | #define XFS_TRANS_STRAT_WRITE 15 |
70 | #define XFS_TRANS_DIOSTRAT 16 | 70 | #define XFS_TRANS_DIOSTRAT 16 |
71 | #define XFS_TRANS_WRITE_SYNC 17 | 71 | /* 17 was XFS_TRANS_WRITE_SYNC */ |
72 | #define XFS_TRANS_WRITEID 18 | 72 | #define XFS_TRANS_WRITEID 18 |
73 | #define XFS_TRANS_ADDAFORK 19 | 73 | #define XFS_TRANS_ADDAFORK 19 |
74 | #define XFS_TRANS_ATTRINVAL 20 | 74 | #define XFS_TRANS_ATTRINVAL 20 |
diff --git a/fs/xfs/xfs_trans_buf.c b/fs/xfs/xfs_trans_buf.c index 8ee2f8c8b0a6..218829e6a152 100644 --- a/fs/xfs/xfs_trans_buf.c +++ b/fs/xfs/xfs_trans_buf.c | |||
@@ -307,7 +307,7 @@ xfs_trans_read_buf( | |||
307 | return (flags & XFS_BUF_TRYLOCK) ? | 307 | return (flags & XFS_BUF_TRYLOCK) ? |
308 | EAGAIN : XFS_ERROR(ENOMEM); | 308 | EAGAIN : XFS_ERROR(ENOMEM); |
309 | 309 | ||
310 | if ((bp != NULL) && (XFS_BUF_GETERROR(bp) != 0)) { | 310 | if (XFS_BUF_GETERROR(bp) != 0) { |
311 | xfs_ioerror_alert("xfs_trans_read_buf", mp, | 311 | xfs_ioerror_alert("xfs_trans_read_buf", mp, |
312 | bp, blkno); | 312 | bp, blkno); |
313 | error = XFS_BUF_GETERROR(bp); | 313 | error = XFS_BUF_GETERROR(bp); |
@@ -315,7 +315,7 @@ xfs_trans_read_buf( | |||
315 | return error; | 315 | return error; |
316 | } | 316 | } |
317 | #ifdef DEBUG | 317 | #ifdef DEBUG |
318 | if (xfs_do_error && (bp != NULL)) { | 318 | if (xfs_do_error) { |
319 | if (xfs_error_target == target) { | 319 | if (xfs_error_target == target) { |
320 | if (((xfs_req_num++) % xfs_error_mod) == 0) { | 320 | if (((xfs_req_num++) % xfs_error_mod) == 0) { |
321 | xfs_buf_relse(bp); | 321 | xfs_buf_relse(bp); |
diff --git a/fs/xfs/xfs_trans_inode.c b/fs/xfs/xfs_trans_inode.c index 23d276af2e0c..785ff101da0a 100644 --- a/fs/xfs/xfs_trans_inode.c +++ b/fs/xfs/xfs_trans_inode.c | |||
@@ -49,30 +49,7 @@ xfs_trans_inode_broot_debug( | |||
49 | 49 | ||
50 | 50 | ||
51 | /* | 51 | /* |
52 | * Get and lock the inode for the caller if it is not already | 52 | * Get an inode and join it to the transaction. |
53 | * locked within the given transaction. If it is already locked | ||
54 | * within the transaction, just increment its lock recursion count | ||
55 | * and return a pointer to it. | ||
56 | * | ||
57 | * For an inode to be locked in a transaction, the inode lock, as | ||
58 | * opposed to the io lock, must be taken exclusively. This ensures | ||
59 | * that the inode can be involved in only 1 transaction at a time. | ||
60 | * Lock recursion is handled on the io lock, but only for lock modes | ||
61 | * of equal or lesser strength. That is, you can recur on the io lock | ||
62 | * held EXCL with a SHARED request but not vice versa. Also, if | ||
63 | * the inode is already a part of the transaction then you cannot | ||
64 | * go from not holding the io lock to having it EXCL or SHARED. | ||
65 | * | ||
66 | * Use the inode cache routine xfs_inode_incore() to find the inode | ||
67 | * if it is already owned by this transaction. | ||
68 | * | ||
69 | * If we don't already own the inode, use xfs_iget() to get it. | ||
70 | * Since the inode log item structure is embedded in the incore | ||
71 | * inode structure and is initialized when the inode is brought | ||
72 | * into memory, there is nothing to do with it here. | ||
73 | * | ||
74 | * If the given transaction pointer is NULL, just call xfs_iget(). | ||
75 | * This simplifies code which must handle both cases. | ||
76 | */ | 53 | */ |
77 | int | 54 | int |
78 | xfs_trans_iget( | 55 | xfs_trans_iget( |
@@ -84,62 +61,11 @@ xfs_trans_iget( | |||
84 | xfs_inode_t **ipp) | 61 | xfs_inode_t **ipp) |
85 | { | 62 | { |
86 | int error; | 63 | int error; |
87 | xfs_inode_t *ip; | ||
88 | |||
89 | /* | ||
90 | * If the transaction pointer is NULL, just call the normal | ||
91 | * xfs_iget(). | ||
92 | */ | ||
93 | if (tp == NULL) | ||
94 | return xfs_iget(mp, NULL, ino, flags, lock_flags, ipp, 0); | ||
95 | |||
96 | /* | ||
97 | * If we find the inode in core with this transaction | ||
98 | * pointer in its i_transp field, then we know we already | ||
99 | * have it locked. In this case we just increment the lock | ||
100 | * recursion count and return the inode to the caller. | ||
101 | * Assert that the inode is already locked in the mode requested | ||
102 | * by the caller. We cannot do lock promotions yet, so | ||
103 | * die if someone gets this wrong. | ||
104 | */ | ||
105 | if ((ip = xfs_inode_incore(tp->t_mountp, ino, tp)) != NULL) { | ||
106 | /* | ||
107 | * Make sure that the inode lock is held EXCL and | ||
108 | * that the io lock is never upgraded when the inode | ||
109 | * is already a part of the transaction. | ||
110 | */ | ||
111 | ASSERT(ip->i_itemp != NULL); | ||
112 | ASSERT(lock_flags & XFS_ILOCK_EXCL); | ||
113 | ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL)); | ||
114 | ASSERT((!(lock_flags & XFS_IOLOCK_EXCL)) || | ||
115 | xfs_isilocked(ip, XFS_IOLOCK_EXCL)); | ||
116 | ASSERT((!(lock_flags & XFS_IOLOCK_EXCL)) || | ||
117 | (ip->i_itemp->ili_flags & XFS_ILI_IOLOCKED_EXCL)); | ||
118 | ASSERT((!(lock_flags & XFS_IOLOCK_SHARED)) || | ||
119 | xfs_isilocked(ip, XFS_IOLOCK_EXCL|XFS_IOLOCK_SHARED)); | ||
120 | ASSERT((!(lock_flags & XFS_IOLOCK_SHARED)) || | ||
121 | (ip->i_itemp->ili_flags & XFS_ILI_IOLOCKED_ANY)); | ||
122 | |||
123 | if (lock_flags & (XFS_IOLOCK_SHARED | XFS_IOLOCK_EXCL)) { | ||
124 | ip->i_itemp->ili_iolock_recur++; | ||
125 | } | ||
126 | if (lock_flags & XFS_ILOCK_EXCL) { | ||
127 | ip->i_itemp->ili_ilock_recur++; | ||
128 | } | ||
129 | *ipp = ip; | ||
130 | return 0; | ||
131 | } | ||
132 | |||
133 | ASSERT(lock_flags & XFS_ILOCK_EXCL); | ||
134 | error = xfs_iget(tp->t_mountp, tp, ino, flags, lock_flags, &ip, 0); | ||
135 | if (error) { | ||
136 | return error; | ||
137 | } | ||
138 | ASSERT(ip != NULL); | ||
139 | 64 | ||
140 | xfs_trans_ijoin(tp, ip, lock_flags); | 65 | error = xfs_iget(mp, tp, ino, flags, lock_flags, ipp, 0); |
141 | *ipp = ip; | 66 | if (!error && tp) |
142 | return 0; | 67 | xfs_trans_ijoin(tp, *ipp, lock_flags); |
68 | return error; | ||
143 | } | 69 | } |
144 | 70 | ||
145 | /* | 71 | /* |
@@ -163,8 +89,6 @@ xfs_trans_ijoin( | |||
163 | xfs_inode_item_init(ip, ip->i_mount); | 89 | xfs_inode_item_init(ip, ip->i_mount); |
164 | iip = ip->i_itemp; | 90 | iip = ip->i_itemp; |
165 | ASSERT(iip->ili_flags == 0); | 91 | ASSERT(iip->ili_flags == 0); |
166 | ASSERT(iip->ili_ilock_recur == 0); | ||
167 | ASSERT(iip->ili_iolock_recur == 0); | ||
168 | 92 | ||
169 | /* | 93 | /* |
170 | * Get a log_item_desc to point at the new item. | 94 | * Get a log_item_desc to point at the new item. |
diff --git a/fs/xfs/xfs_vnodeops.c b/fs/xfs/xfs_vnodeops.c index c4eca5ed5dab..a434f287962d 100644 --- a/fs/xfs/xfs_vnodeops.c +++ b/fs/xfs/xfs_vnodeops.c | |||
@@ -538,7 +538,9 @@ xfs_readlink_bmap( | |||
538 | d = XFS_FSB_TO_DADDR(mp, mval[n].br_startblock); | 538 | d = XFS_FSB_TO_DADDR(mp, mval[n].br_startblock); |
539 | byte_cnt = XFS_FSB_TO_B(mp, mval[n].br_blockcount); | 539 | byte_cnt = XFS_FSB_TO_B(mp, mval[n].br_blockcount); |
540 | 540 | ||
541 | bp = xfs_buf_read(mp->m_ddev_targp, d, BTOBB(byte_cnt), 0); | 541 | bp = xfs_buf_read_flags(mp->m_ddev_targp, d, BTOBB(byte_cnt), |
542 | XBF_LOCK | XBF_MAPPED | | ||
543 | XBF_DONT_BLOCK); | ||
542 | error = XFS_BUF_GETERROR(bp); | 544 | error = XFS_BUF_GETERROR(bp); |
543 | if (error) { | 545 | if (error) { |
544 | xfs_ioerror_alert("xfs_readlink", | 546 | xfs_ioerror_alert("xfs_readlink", |
@@ -609,7 +611,7 @@ xfs_fsync( | |||
609 | xfs_inode_t *ip) | 611 | xfs_inode_t *ip) |
610 | { | 612 | { |
611 | xfs_trans_t *tp; | 613 | xfs_trans_t *tp; |
612 | int error; | 614 | int error = 0; |
613 | int log_flushed = 0, changed = 1; | 615 | int log_flushed = 0, changed = 1; |
614 | 616 | ||
615 | xfs_itrace_entry(ip); | 617 | xfs_itrace_entry(ip); |
@@ -617,14 +619,9 @@ xfs_fsync( | |||
617 | if (XFS_FORCED_SHUTDOWN(ip->i_mount)) | 619 | if (XFS_FORCED_SHUTDOWN(ip->i_mount)) |
618 | return XFS_ERROR(EIO); | 620 | return XFS_ERROR(EIO); |
619 | 621 | ||
620 | /* capture size updates in I/O completion before writing the inode. */ | ||
621 | error = xfs_wait_on_pages(ip, 0, -1); | ||
622 | if (error) | ||
623 | return XFS_ERROR(error); | ||
624 | |||
625 | /* | 622 | /* |
626 | * We always need to make sure that the required inode state is safe on | 623 | * We always need to make sure that the required inode state is safe on |
627 | * disk. The vnode might be clean but we still might need to force the | 624 | * disk. The inode might be clean but we still might need to force the |
628 | * log because of committed transactions that haven't hit the disk yet. | 625 | * log because of committed transactions that haven't hit the disk yet. |
629 | * Likewise, there could be unflushed non-transactional changes to the | 626 | * Likewise, there could be unflushed non-transactional changes to the |
630 | * inode core that have to go to disk and this requires us to issue | 627 | * inode core that have to go to disk and this requires us to issue |
@@ -636,7 +633,7 @@ xfs_fsync( | |||
636 | */ | 633 | */ |
637 | xfs_ilock(ip, XFS_ILOCK_SHARED); | 634 | xfs_ilock(ip, XFS_ILOCK_SHARED); |
638 | 635 | ||
639 | if (!(ip->i_update_size || ip->i_update_core)) { | 636 | if (!ip->i_update_core) { |
640 | /* | 637 | /* |
641 | * Timestamps/size haven't changed since last inode flush or | 638 | * Timestamps/size haven't changed since last inode flush or |
642 | * inode transaction commit. That means either nothing got | 639 | * inode transaction commit. That means either nothing got |
@@ -716,7 +713,7 @@ xfs_fsync( | |||
716 | * when the link count isn't zero and by xfs_dm_punch_hole() when | 713 | * when the link count isn't zero and by xfs_dm_punch_hole() when |
717 | * punching a hole to EOF. | 714 | * punching a hole to EOF. |
718 | */ | 715 | */ |
719 | int | 716 | STATIC int |
720 | xfs_free_eofblocks( | 717 | xfs_free_eofblocks( |
721 | xfs_mount_t *mp, | 718 | xfs_mount_t *mp, |
722 | xfs_inode_t *ip, | 719 | xfs_inode_t *ip, |
@@ -1474,8 +1471,8 @@ xfs_create( | |||
1474 | if (error == ENOSPC) { | 1471 | if (error == ENOSPC) { |
1475 | /* flush outstanding delalloc blocks and retry */ | 1472 | /* flush outstanding delalloc blocks and retry */ |
1476 | xfs_flush_inodes(dp); | 1473 | xfs_flush_inodes(dp); |
1477 | error = xfs_trans_reserve(tp, resblks, XFS_CREATE_LOG_RES(mp), 0, | 1474 | error = xfs_trans_reserve(tp, resblks, log_res, 0, |
1478 | XFS_TRANS_PERM_LOG_RES, XFS_CREATE_LOG_COUNT); | 1475 | XFS_TRANS_PERM_LOG_RES, log_count); |
1479 | } | 1476 | } |
1480 | if (error == ENOSPC) { | 1477 | if (error == ENOSPC) { |
1481 | /* No space at all so try a "no-allocation" reservation */ | 1478 | /* No space at all so try a "no-allocation" reservation */ |