diff options
Diffstat (limited to 'fs/xfs/xfs_inode.c')
-rw-r--r-- | fs/xfs/xfs_inode.c | 292 |
1 files changed, 157 insertions, 135 deletions
diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c index dbd9cef852ec..cd522827f99e 100644 --- a/fs/xfs/xfs_inode.c +++ b/fs/xfs/xfs_inode.c | |||
@@ -41,6 +41,7 @@ | |||
41 | #include "xfs_buf_item.h" | 41 | #include "xfs_buf_item.h" |
42 | #include "xfs_inode_item.h" | 42 | #include "xfs_inode_item.h" |
43 | #include "xfs_btree.h" | 43 | #include "xfs_btree.h" |
44 | #include "xfs_btree_trace.h" | ||
44 | #include "xfs_alloc.h" | 45 | #include "xfs_alloc.h" |
45 | #include "xfs_ialloc.h" | 46 | #include "xfs_ialloc.h" |
46 | #include "xfs_bmap.h" | 47 | #include "xfs_bmap.h" |
@@ -221,25 +222,26 @@ xfs_imap_to_bp( | |||
221 | * Use xfs_imap() to determine the size and location of the | 222 | * Use xfs_imap() to determine the size and location of the |
222 | * buffer to read from disk. | 223 | * buffer to read from disk. |
223 | */ | 224 | */ |
224 | STATIC int | 225 | int |
225 | xfs_inotobp( | 226 | xfs_inotobp( |
226 | xfs_mount_t *mp, | 227 | xfs_mount_t *mp, |
227 | xfs_trans_t *tp, | 228 | xfs_trans_t *tp, |
228 | xfs_ino_t ino, | 229 | xfs_ino_t ino, |
229 | xfs_dinode_t **dipp, | 230 | xfs_dinode_t **dipp, |
230 | xfs_buf_t **bpp, | 231 | xfs_buf_t **bpp, |
231 | int *offset) | 232 | int *offset, |
233 | uint imap_flags) | ||
232 | { | 234 | { |
233 | xfs_imap_t imap; | 235 | xfs_imap_t imap; |
234 | xfs_buf_t *bp; | 236 | xfs_buf_t *bp; |
235 | int error; | 237 | int error; |
236 | 238 | ||
237 | imap.im_blkno = 0; | 239 | imap.im_blkno = 0; |
238 | error = xfs_imap(mp, tp, ino, &imap, XFS_IMAP_LOOKUP); | 240 | error = xfs_imap(mp, tp, ino, &imap, imap_flags | XFS_IMAP_LOOKUP); |
239 | if (error) | 241 | if (error) |
240 | return error; | 242 | return error; |
241 | 243 | ||
242 | error = xfs_imap_to_bp(mp, tp, &imap, &bp, XFS_BUF_LOCK, 0); | 244 | error = xfs_imap_to_bp(mp, tp, &imap, &bp, XFS_BUF_LOCK, imap_flags); |
243 | if (error) | 245 | if (error) |
244 | return error; | 246 | return error; |
245 | 247 | ||
@@ -621,7 +623,7 @@ xfs_iformat_btree( | |||
621 | ifp = XFS_IFORK_PTR(ip, whichfork); | 623 | ifp = XFS_IFORK_PTR(ip, whichfork); |
622 | dfp = (xfs_bmdr_block_t *)XFS_DFORK_PTR(dip, whichfork); | 624 | dfp = (xfs_bmdr_block_t *)XFS_DFORK_PTR(dip, whichfork); |
623 | size = XFS_BMAP_BROOT_SPACE(dfp); | 625 | size = XFS_BMAP_BROOT_SPACE(dfp); |
624 | nrecs = XFS_BMAP_BROOT_NUMRECS(dfp); | 626 | nrecs = be16_to_cpu(dfp->bb_numrecs); |
625 | 627 | ||
626 | /* | 628 | /* |
627 | * blow out if -- fork has less extents than can fit in | 629 | * blow out if -- fork has less extents than can fit in |
@@ -649,8 +651,9 @@ xfs_iformat_btree( | |||
649 | * Copy and convert from the on-disk structure | 651 | * Copy and convert from the on-disk structure |
650 | * to the in-memory structure. | 652 | * to the in-memory structure. |
651 | */ | 653 | */ |
652 | xfs_bmdr_to_bmbt(dfp, XFS_DFORK_SIZE(dip, ip->i_mount, whichfork), | 654 | xfs_bmdr_to_bmbt(ip->i_mount, dfp, |
653 | ifp->if_broot, size); | 655 | XFS_DFORK_SIZE(dip, ip->i_mount, whichfork), |
656 | ifp->if_broot, size); | ||
654 | ifp->if_flags &= ~XFS_IFEXTENTS; | 657 | ifp->if_flags &= ~XFS_IFEXTENTS; |
655 | ifp->if_flags |= XFS_IFBROOT; | 658 | ifp->if_flags |= XFS_IFBROOT; |
656 | 659 | ||
@@ -788,51 +791,56 @@ xfs_dic2xflags( | |||
788 | } | 791 | } |
789 | 792 | ||
790 | /* | 793 | /* |
791 | * Given a mount structure and an inode number, return a pointer | 794 | * Allocate and initialise an xfs_inode. |
792 | * to a newly allocated in-core inode corresponding to the given | ||
793 | * inode number. | ||
794 | * | ||
795 | * Initialize the inode's attributes and extent pointers if it | ||
796 | * already has them (it will not if the inode has no links). | ||
797 | */ | 795 | */ |
798 | int | 796 | STATIC struct xfs_inode * |
799 | xfs_iread( | 797 | xfs_inode_alloc( |
800 | xfs_mount_t *mp, | 798 | struct xfs_mount *mp, |
801 | xfs_trans_t *tp, | 799 | xfs_ino_t ino) |
802 | xfs_ino_t ino, | ||
803 | xfs_inode_t **ipp, | ||
804 | xfs_daddr_t bno, | ||
805 | uint imap_flags) | ||
806 | { | 800 | { |
807 | xfs_buf_t *bp; | 801 | struct xfs_inode *ip; |
808 | xfs_dinode_t *dip; | ||
809 | xfs_inode_t *ip; | ||
810 | int error; | ||
811 | 802 | ||
812 | ASSERT(xfs_inode_zone != NULL); | 803 | /* |
804 | * if this didn't occur in transactions, we could use | ||
805 | * KM_MAYFAIL and return NULL here on ENOMEM. Set the | ||
806 | * code up to do this anyway. | ||
807 | */ | ||
808 | ip = kmem_zone_alloc(xfs_inode_zone, KM_SLEEP); | ||
809 | if (!ip) | ||
810 | return NULL; | ||
813 | 811 | ||
814 | ip = kmem_zone_zalloc(xfs_inode_zone, KM_SLEEP); | 812 | ASSERT(atomic_read(&ip->i_iocount) == 0); |
815 | ip->i_ino = ino; | 813 | ASSERT(atomic_read(&ip->i_pincount) == 0); |
816 | ip->i_mount = mp; | 814 | ASSERT(!spin_is_locked(&ip->i_flags_lock)); |
817 | atomic_set(&ip->i_iocount, 0); | 815 | ASSERT(completion_done(&ip->i_flush)); |
818 | spin_lock_init(&ip->i_flags_lock); | ||
819 | 816 | ||
820 | /* | 817 | /* |
821 | * Get pointer's to the on-disk inode and the buffer containing it. | 818 | * initialise the VFS inode here to get failures |
822 | * If the inode number refers to a block outside the file system | 819 | * out of the way early. |
823 | * then xfs_itobp() will return NULL. In this case we should | ||
824 | * return NULL as well. Set i_blkno to 0 so that xfs_itobp() will | ||
825 | * know that this is a new incore inode. | ||
826 | */ | 820 | */ |
827 | error = xfs_itobp(mp, tp, ip, &dip, &bp, bno, imap_flags, XFS_BUF_LOCK); | 821 | if (!inode_init_always(mp->m_super, VFS_I(ip))) { |
828 | if (error) { | ||
829 | kmem_zone_free(xfs_inode_zone, ip); | 822 | kmem_zone_free(xfs_inode_zone, ip); |
830 | return error; | 823 | return NULL; |
831 | } | 824 | } |
832 | 825 | ||
826 | /* initialise the xfs inode */ | ||
827 | ip->i_ino = ino; | ||
828 | ip->i_mount = mp; | ||
829 | ip->i_blkno = 0; | ||
830 | ip->i_len = 0; | ||
831 | ip->i_boffset =0; | ||
832 | ip->i_afp = NULL; | ||
833 | memset(&ip->i_df, 0, sizeof(xfs_ifork_t)); | ||
834 | ip->i_flags = 0; | ||
835 | ip->i_update_core = 0; | ||
836 | ip->i_update_size = 0; | ||
837 | ip->i_delayed_blks = 0; | ||
838 | memset(&ip->i_d, 0, sizeof(xfs_icdinode_t)); | ||
839 | ip->i_size = 0; | ||
840 | ip->i_new_size = 0; | ||
841 | |||
833 | /* | 842 | /* |
834 | * Initialize inode's trace buffers. | 843 | * Initialize inode's trace buffers. |
835 | * Do this before xfs_iformat in case it adds entries. | ||
836 | */ | 844 | */ |
837 | #ifdef XFS_INODE_TRACE | 845 | #ifdef XFS_INODE_TRACE |
838 | ip->i_trace = ktrace_alloc(INODE_TRACE_SIZE, KM_NOFS); | 846 | ip->i_trace = ktrace_alloc(INODE_TRACE_SIZE, KM_NOFS); |
@@ -840,7 +848,7 @@ xfs_iread( | |||
840 | #ifdef XFS_BMAP_TRACE | 848 | #ifdef XFS_BMAP_TRACE |
841 | ip->i_xtrace = ktrace_alloc(XFS_BMAP_KTRACE_SIZE, KM_NOFS); | 849 | ip->i_xtrace = ktrace_alloc(XFS_BMAP_KTRACE_SIZE, KM_NOFS); |
842 | #endif | 850 | #endif |
843 | #ifdef XFS_BMBT_TRACE | 851 | #ifdef XFS_BTREE_TRACE |
844 | ip->i_btrace = ktrace_alloc(XFS_BMBT_KTRACE_SIZE, KM_NOFS); | 852 | ip->i_btrace = ktrace_alloc(XFS_BMBT_KTRACE_SIZE, KM_NOFS); |
845 | #endif | 853 | #endif |
846 | #ifdef XFS_RW_TRACE | 854 | #ifdef XFS_RW_TRACE |
@@ -853,13 +861,51 @@ xfs_iread( | |||
853 | ip->i_dir_trace = ktrace_alloc(XFS_DIR2_KTRACE_SIZE, KM_NOFS); | 861 | ip->i_dir_trace = ktrace_alloc(XFS_DIR2_KTRACE_SIZE, KM_NOFS); |
854 | #endif | 862 | #endif |
855 | 863 | ||
864 | return ip; | ||
865 | } | ||
866 | |||
867 | /* | ||
868 | * Given a mount structure and an inode number, return a pointer | ||
869 | * to a newly allocated in-core inode corresponding to the given | ||
870 | * inode number. | ||
871 | * | ||
872 | * Initialize the inode's attributes and extent pointers if it | ||
873 | * already has them (it will not if the inode has no links). | ||
874 | */ | ||
875 | int | ||
876 | xfs_iread( | ||
877 | xfs_mount_t *mp, | ||
878 | xfs_trans_t *tp, | ||
879 | xfs_ino_t ino, | ||
880 | xfs_inode_t **ipp, | ||
881 | xfs_daddr_t bno, | ||
882 | uint imap_flags) | ||
883 | { | ||
884 | xfs_buf_t *bp; | ||
885 | xfs_dinode_t *dip; | ||
886 | xfs_inode_t *ip; | ||
887 | int error; | ||
888 | |||
889 | ip = xfs_inode_alloc(mp, ino); | ||
890 | if (!ip) | ||
891 | return ENOMEM; | ||
892 | |||
893 | /* | ||
894 | * Get pointer's to the on-disk inode and the buffer containing it. | ||
895 | * If the inode number refers to a block outside the file system | ||
896 | * then xfs_itobp() will return NULL. In this case we should | ||
897 | * return NULL as well. Set i_blkno to 0 so that xfs_itobp() will | ||
898 | * know that this is a new incore inode. | ||
899 | */ | ||
900 | error = xfs_itobp(mp, tp, ip, &dip, &bp, bno, imap_flags, XFS_BUF_LOCK); | ||
901 | if (error) | ||
902 | goto out_destroy_inode; | ||
903 | |||
856 | /* | 904 | /* |
857 | * If we got something that isn't an inode it means someone | 905 | * If we got something that isn't an inode it means someone |
858 | * (nfs or dmi) has a stale handle. | 906 | * (nfs or dmi) has a stale handle. |
859 | */ | 907 | */ |
860 | if (be16_to_cpu(dip->di_core.di_magic) != XFS_DINODE_MAGIC) { | 908 | if (be16_to_cpu(dip->di_core.di_magic) != XFS_DINODE_MAGIC) { |
861 | kmem_zone_free(xfs_inode_zone, ip); | ||
862 | xfs_trans_brelse(tp, bp); | ||
863 | #ifdef DEBUG | 909 | #ifdef DEBUG |
864 | xfs_fs_cmn_err(CE_ALERT, mp, "xfs_iread: " | 910 | xfs_fs_cmn_err(CE_ALERT, mp, "xfs_iread: " |
865 | "dip->di_core.di_magic (0x%x) != " | 911 | "dip->di_core.di_magic (0x%x) != " |
@@ -867,7 +913,8 @@ xfs_iread( | |||
867 | be16_to_cpu(dip->di_core.di_magic), | 913 | be16_to_cpu(dip->di_core.di_magic), |
868 | XFS_DINODE_MAGIC); | 914 | XFS_DINODE_MAGIC); |
869 | #endif /* DEBUG */ | 915 | #endif /* DEBUG */ |
870 | return XFS_ERROR(EINVAL); | 916 | error = XFS_ERROR(EINVAL); |
917 | goto out_brelse; | ||
871 | } | 918 | } |
872 | 919 | ||
873 | /* | 920 | /* |
@@ -881,14 +928,12 @@ xfs_iread( | |||
881 | xfs_dinode_from_disk(&ip->i_d, &dip->di_core); | 928 | xfs_dinode_from_disk(&ip->i_d, &dip->di_core); |
882 | error = xfs_iformat(ip, dip); | 929 | error = xfs_iformat(ip, dip); |
883 | if (error) { | 930 | if (error) { |
884 | kmem_zone_free(xfs_inode_zone, ip); | ||
885 | xfs_trans_brelse(tp, bp); | ||
886 | #ifdef DEBUG | 931 | #ifdef DEBUG |
887 | xfs_fs_cmn_err(CE_ALERT, mp, "xfs_iread: " | 932 | xfs_fs_cmn_err(CE_ALERT, mp, "xfs_iread: " |
888 | "xfs_iformat() returned error %d", | 933 | "xfs_iformat() returned error %d", |
889 | error); | 934 | error); |
890 | #endif /* DEBUG */ | 935 | #endif /* DEBUG */ |
891 | return error; | 936 | goto out_brelse; |
892 | } | 937 | } |
893 | } else { | 938 | } else { |
894 | ip->i_d.di_magic = be16_to_cpu(dip->di_core.di_magic); | 939 | ip->i_d.di_magic = be16_to_cpu(dip->di_core.di_magic); |
@@ -911,8 +956,6 @@ xfs_iread( | |||
911 | XFS_IFORK_DSIZE(ip) / (uint)sizeof(xfs_bmbt_rec_t); | 956 | XFS_IFORK_DSIZE(ip) / (uint)sizeof(xfs_bmbt_rec_t); |
912 | } | 957 | } |
913 | 958 | ||
914 | INIT_LIST_HEAD(&ip->i_reclaim); | ||
915 | |||
916 | /* | 959 | /* |
917 | * The inode format changed when we moved the link count and | 960 | * The inode format changed when we moved the link count and |
918 | * made it 32 bits long. If this is an old format inode, | 961 | * made it 32 bits long. If this is an old format inode, |
@@ -956,6 +999,12 @@ xfs_iread( | |||
956 | xfs_trans_brelse(tp, bp); | 999 | xfs_trans_brelse(tp, bp); |
957 | *ipp = ip; | 1000 | *ipp = ip; |
958 | return 0; | 1001 | return 0; |
1002 | |||
1003 | out_brelse: | ||
1004 | xfs_trans_brelse(tp, bp); | ||
1005 | out_destroy_inode: | ||
1006 | xfs_destroy_inode(ip); | ||
1007 | return error; | ||
959 | } | 1008 | } |
960 | 1009 | ||
961 | /* | 1010 | /* |
@@ -1049,6 +1098,7 @@ xfs_ialloc( | |||
1049 | uint flags; | 1098 | uint flags; |
1050 | int error; | 1099 | int error; |
1051 | timespec_t tv; | 1100 | timespec_t tv; |
1101 | int filestreams = 0; | ||
1052 | 1102 | ||
1053 | /* | 1103 | /* |
1054 | * Call the space management code to pick | 1104 | * Call the space management code to pick |
@@ -1056,9 +1106,8 @@ xfs_ialloc( | |||
1056 | */ | 1106 | */ |
1057 | error = xfs_dialloc(tp, pip ? pip->i_ino : 0, mode, okalloc, | 1107 | error = xfs_dialloc(tp, pip ? pip->i_ino : 0, mode, okalloc, |
1058 | ialloc_context, call_again, &ino); | 1108 | ialloc_context, call_again, &ino); |
1059 | if (error != 0) { | 1109 | if (error) |
1060 | return error; | 1110 | return error; |
1061 | } | ||
1062 | if (*call_again || ino == NULLFSINO) { | 1111 | if (*call_again || ino == NULLFSINO) { |
1063 | *ipp = NULL; | 1112 | *ipp = NULL; |
1064 | return 0; | 1113 | return 0; |
@@ -1072,9 +1121,8 @@ xfs_ialloc( | |||
1072 | */ | 1121 | */ |
1073 | error = xfs_trans_iget(tp->t_mountp, tp, ino, | 1122 | error = xfs_trans_iget(tp->t_mountp, tp, ino, |
1074 | XFS_IGET_CREATE, XFS_ILOCK_EXCL, &ip); | 1123 | XFS_IGET_CREATE, XFS_ILOCK_EXCL, &ip); |
1075 | if (error != 0) { | 1124 | if (error) |
1076 | return error; | 1125 | return error; |
1077 | } | ||
1078 | ASSERT(ip != NULL); | 1126 | ASSERT(ip != NULL); |
1079 | 1127 | ||
1080 | ip->i_d.di_mode = (__uint16_t)mode; | 1128 | ip->i_d.di_mode = (__uint16_t)mode; |
@@ -1155,13 +1203,12 @@ xfs_ialloc( | |||
1155 | flags |= XFS_ILOG_DEV; | 1203 | flags |= XFS_ILOG_DEV; |
1156 | break; | 1204 | break; |
1157 | case S_IFREG: | 1205 | case S_IFREG: |
1158 | if (pip && xfs_inode_is_filestream(pip)) { | 1206 | /* |
1159 | error = xfs_filestream_associate(pip, ip); | 1207 | * we can't set up filestreams until after the VFS inode |
1160 | if (error < 0) | 1208 | * is set up properly. |
1161 | return -error; | 1209 | */ |
1162 | if (!error) | 1210 | if (pip && xfs_inode_is_filestream(pip)) |
1163 | xfs_iflags_set(ip, XFS_IFILESTREAM); | 1211 | filestreams = 1; |
1164 | } | ||
1165 | /* fall through */ | 1212 | /* fall through */ |
1166 | case S_IFDIR: | 1213 | case S_IFDIR: |
1167 | if (pip && (pip->i_d.di_flags & XFS_DIFLAG_ANY)) { | 1214 | if (pip && (pip->i_d.di_flags & XFS_DIFLAG_ANY)) { |
@@ -1227,6 +1274,15 @@ xfs_ialloc( | |||
1227 | /* now that we have an i_mode we can setup inode ops and unlock */ | 1274 | /* now that we have an i_mode we can setup inode ops and unlock */ |
1228 | xfs_setup_inode(ip); | 1275 | xfs_setup_inode(ip); |
1229 | 1276 | ||
1277 | /* now we have set up the vfs inode we can associate the filestream */ | ||
1278 | if (filestreams) { | ||
1279 | error = xfs_filestream_associate(pip, ip); | ||
1280 | if (error < 0) | ||
1281 | return -error; | ||
1282 | if (!error) | ||
1283 | xfs_iflags_set(ip, XFS_IFILESTREAM); | ||
1284 | } | ||
1285 | |||
1230 | *ipp = ip; | 1286 | *ipp = ip; |
1231 | return 0; | 1287 | return 0; |
1232 | } | 1288 | } |
@@ -1414,7 +1470,7 @@ xfs_itruncate_start( | |||
1414 | mp = ip->i_mount; | 1470 | mp = ip->i_mount; |
1415 | 1471 | ||
1416 | /* wait for the completion of any pending DIOs */ | 1472 | /* wait for the completion of any pending DIOs */ |
1417 | if (new_size < ip->i_size) | 1473 | if (new_size == 0 || new_size < ip->i_size) |
1418 | vn_iowait(ip); | 1474 | vn_iowait(ip); |
1419 | 1475 | ||
1420 | /* | 1476 | /* |
@@ -1992,7 +2048,7 @@ xfs_iunlink_remove( | |||
1992 | } | 2048 | } |
1993 | next_ino = XFS_AGINO_TO_INO(mp, agno, next_agino); | 2049 | next_ino = XFS_AGINO_TO_INO(mp, agno, next_agino); |
1994 | error = xfs_inotobp(mp, tp, next_ino, &last_dip, | 2050 | error = xfs_inotobp(mp, tp, next_ino, &last_dip, |
1995 | &last_ibp, &last_offset); | 2051 | &last_ibp, &last_offset, 0); |
1996 | if (error) { | 2052 | if (error) { |
1997 | cmn_err(CE_WARN, | 2053 | cmn_err(CE_WARN, |
1998 | "xfs_iunlink_remove: xfs_inotobp() returned an error %d on %s. Returning error.", | 2054 | "xfs_iunlink_remove: xfs_inotobp() returned an error %d on %s. Returning error.", |
@@ -2160,9 +2216,9 @@ xfs_ifree_cluster( | |||
2160 | iip = (xfs_inode_log_item_t *)lip; | 2216 | iip = (xfs_inode_log_item_t *)lip; |
2161 | ASSERT(iip->ili_logged == 1); | 2217 | ASSERT(iip->ili_logged == 1); |
2162 | lip->li_cb = (void(*)(xfs_buf_t*,xfs_log_item_t*)) xfs_istale_done; | 2218 | lip->li_cb = (void(*)(xfs_buf_t*,xfs_log_item_t*)) xfs_istale_done; |
2163 | spin_lock(&mp->m_ail_lock); | 2219 | xfs_trans_ail_copy_lsn(mp->m_ail, |
2164 | iip->ili_flush_lsn = iip->ili_item.li_lsn; | 2220 | &iip->ili_flush_lsn, |
2165 | spin_unlock(&mp->m_ail_lock); | 2221 | &iip->ili_item.li_lsn); |
2166 | xfs_iflags_set(iip->ili_inode, XFS_ISTALE); | 2222 | xfs_iflags_set(iip->ili_inode, XFS_ISTALE); |
2167 | pre_flushed++; | 2223 | pre_flushed++; |
2168 | } | 2224 | } |
@@ -2183,9 +2239,8 @@ xfs_ifree_cluster( | |||
2183 | iip->ili_last_fields = iip->ili_format.ilf_fields; | 2239 | iip->ili_last_fields = iip->ili_format.ilf_fields; |
2184 | iip->ili_format.ilf_fields = 0; | 2240 | iip->ili_format.ilf_fields = 0; |
2185 | iip->ili_logged = 1; | 2241 | iip->ili_logged = 1; |
2186 | spin_lock(&mp->m_ail_lock); | 2242 | xfs_trans_ail_copy_lsn(mp->m_ail, &iip->ili_flush_lsn, |
2187 | iip->ili_flush_lsn = iip->ili_item.li_lsn; | 2243 | &iip->ili_item.li_lsn); |
2188 | spin_unlock(&mp->m_ail_lock); | ||
2189 | 2244 | ||
2190 | xfs_buf_attach_iodone(bp, | 2245 | xfs_buf_attach_iodone(bp, |
2191 | (void(*)(xfs_buf_t*,xfs_log_item_t*)) | 2246 | (void(*)(xfs_buf_t*,xfs_log_item_t*)) |
@@ -2312,9 +2367,10 @@ xfs_iroot_realloc( | |||
2312 | int rec_diff, | 2367 | int rec_diff, |
2313 | int whichfork) | 2368 | int whichfork) |
2314 | { | 2369 | { |
2370 | struct xfs_mount *mp = ip->i_mount; | ||
2315 | int cur_max; | 2371 | int cur_max; |
2316 | xfs_ifork_t *ifp; | 2372 | xfs_ifork_t *ifp; |
2317 | xfs_bmbt_block_t *new_broot; | 2373 | struct xfs_btree_block *new_broot; |
2318 | int new_max; | 2374 | int new_max; |
2319 | size_t new_size; | 2375 | size_t new_size; |
2320 | char *np; | 2376 | char *np; |
@@ -2335,8 +2391,7 @@ xfs_iroot_realloc( | |||
2335 | */ | 2391 | */ |
2336 | if (ifp->if_broot_bytes == 0) { | 2392 | if (ifp->if_broot_bytes == 0) { |
2337 | new_size = (size_t)XFS_BMAP_BROOT_SPACE_CALC(rec_diff); | 2393 | new_size = (size_t)XFS_BMAP_BROOT_SPACE_CALC(rec_diff); |
2338 | ifp->if_broot = (xfs_bmbt_block_t*)kmem_alloc(new_size, | 2394 | ifp->if_broot = kmem_alloc(new_size, KM_SLEEP); |
2339 | KM_SLEEP); | ||
2340 | ifp->if_broot_bytes = (int)new_size; | 2395 | ifp->if_broot_bytes = (int)new_size; |
2341 | return; | 2396 | return; |
2342 | } | 2397 | } |
@@ -2347,18 +2402,16 @@ xfs_iroot_realloc( | |||
2347 | * location. The records don't change location because | 2402 | * location. The records don't change location because |
2348 | * they are kept butted up against the btree block header. | 2403 | * they are kept butted up against the btree block header. |
2349 | */ | 2404 | */ |
2350 | cur_max = XFS_BMAP_BROOT_MAXRECS(ifp->if_broot_bytes); | 2405 | cur_max = xfs_bmbt_maxrecs(mp, ifp->if_broot_bytes, 0); |
2351 | new_max = cur_max + rec_diff; | 2406 | new_max = cur_max + rec_diff; |
2352 | new_size = (size_t)XFS_BMAP_BROOT_SPACE_CALC(new_max); | 2407 | new_size = (size_t)XFS_BMAP_BROOT_SPACE_CALC(new_max); |
2353 | ifp->if_broot = (xfs_bmbt_block_t *) | 2408 | ifp->if_broot = kmem_realloc(ifp->if_broot, new_size, |
2354 | kmem_realloc(ifp->if_broot, | ||
2355 | new_size, | ||
2356 | (size_t)XFS_BMAP_BROOT_SPACE_CALC(cur_max), /* old size */ | 2409 | (size_t)XFS_BMAP_BROOT_SPACE_CALC(cur_max), /* old size */ |
2357 | KM_SLEEP); | 2410 | KM_SLEEP); |
2358 | op = (char *)XFS_BMAP_BROOT_PTR_ADDR(ifp->if_broot, 1, | 2411 | op = (char *)XFS_BMAP_BROOT_PTR_ADDR(mp, ifp->if_broot, 1, |
2359 | ifp->if_broot_bytes); | 2412 | ifp->if_broot_bytes); |
2360 | np = (char *)XFS_BMAP_BROOT_PTR_ADDR(ifp->if_broot, 1, | 2413 | np = (char *)XFS_BMAP_BROOT_PTR_ADDR(mp, ifp->if_broot, 1, |
2361 | (int)new_size); | 2414 | (int)new_size); |
2362 | ifp->if_broot_bytes = (int)new_size; | 2415 | ifp->if_broot_bytes = (int)new_size; |
2363 | ASSERT(ifp->if_broot_bytes <= | 2416 | ASSERT(ifp->if_broot_bytes <= |
2364 | XFS_IFORK_SIZE(ip, whichfork) + XFS_BROOT_SIZE_ADJ); | 2417 | XFS_IFORK_SIZE(ip, whichfork) + XFS_BROOT_SIZE_ADJ); |
@@ -2372,7 +2425,7 @@ xfs_iroot_realloc( | |||
2372 | * records, just get rid of the root and clear the status bit. | 2425 | * records, just get rid of the root and clear the status bit. |
2373 | */ | 2426 | */ |
2374 | ASSERT((ifp->if_broot != NULL) && (ifp->if_broot_bytes > 0)); | 2427 | ASSERT((ifp->if_broot != NULL) && (ifp->if_broot_bytes > 0)); |
2375 | cur_max = XFS_BMAP_BROOT_MAXRECS(ifp->if_broot_bytes); | 2428 | cur_max = xfs_bmbt_maxrecs(mp, ifp->if_broot_bytes, 0); |
2376 | new_max = cur_max + rec_diff; | 2429 | new_max = cur_max + rec_diff; |
2377 | ASSERT(new_max >= 0); | 2430 | ASSERT(new_max >= 0); |
2378 | if (new_max > 0) | 2431 | if (new_max > 0) |
@@ -2380,11 +2433,11 @@ xfs_iroot_realloc( | |||
2380 | else | 2433 | else |
2381 | new_size = 0; | 2434 | new_size = 0; |
2382 | if (new_size > 0) { | 2435 | if (new_size > 0) { |
2383 | new_broot = (xfs_bmbt_block_t *)kmem_alloc(new_size, KM_SLEEP); | 2436 | new_broot = kmem_alloc(new_size, KM_SLEEP); |
2384 | /* | 2437 | /* |
2385 | * First copy over the btree block header. | 2438 | * First copy over the btree block header. |
2386 | */ | 2439 | */ |
2387 | memcpy(new_broot, ifp->if_broot, sizeof(xfs_bmbt_block_t)); | 2440 | memcpy(new_broot, ifp->if_broot, XFS_BTREE_LBLOCK_LEN); |
2388 | } else { | 2441 | } else { |
2389 | new_broot = NULL; | 2442 | new_broot = NULL; |
2390 | ifp->if_flags &= ~XFS_IFBROOT; | 2443 | ifp->if_flags &= ~XFS_IFBROOT; |
@@ -2397,18 +2450,16 @@ xfs_iroot_realloc( | |||
2397 | /* | 2450 | /* |
2398 | * First copy the records. | 2451 | * First copy the records. |
2399 | */ | 2452 | */ |
2400 | op = (char *)XFS_BMAP_BROOT_REC_ADDR(ifp->if_broot, 1, | 2453 | op = (char *)XFS_BMBT_REC_ADDR(mp, ifp->if_broot, 1); |
2401 | ifp->if_broot_bytes); | 2454 | np = (char *)XFS_BMBT_REC_ADDR(mp, new_broot, 1); |
2402 | np = (char *)XFS_BMAP_BROOT_REC_ADDR(new_broot, 1, | ||
2403 | (int)new_size); | ||
2404 | memcpy(np, op, new_max * (uint)sizeof(xfs_bmbt_rec_t)); | 2455 | memcpy(np, op, new_max * (uint)sizeof(xfs_bmbt_rec_t)); |
2405 | 2456 | ||
2406 | /* | 2457 | /* |
2407 | * Then copy the pointers. | 2458 | * Then copy the pointers. |
2408 | */ | 2459 | */ |
2409 | op = (char *)XFS_BMAP_BROOT_PTR_ADDR(ifp->if_broot, 1, | 2460 | op = (char *)XFS_BMAP_BROOT_PTR_ADDR(mp, ifp->if_broot, 1, |
2410 | ifp->if_broot_bytes); | 2461 | ifp->if_broot_bytes); |
2411 | np = (char *)XFS_BMAP_BROOT_PTR_ADDR(new_broot, 1, | 2462 | np = (char *)XFS_BMAP_BROOT_PTR_ADDR(mp, new_broot, 1, |
2412 | (int)new_size); | 2463 | (int)new_size); |
2413 | memcpy(np, op, new_max * (uint)sizeof(xfs_dfsbno_t)); | 2464 | memcpy(np, op, new_max * (uint)sizeof(xfs_dfsbno_t)); |
2414 | } | 2465 | } |
@@ -2617,6 +2668,10 @@ xfs_idestroy_fork( | |||
2617 | * It must free the inode itself and any buffers allocated for | 2668 | * It must free the inode itself and any buffers allocated for |
2618 | * if_extents/if_data and if_broot. It must also free the lock | 2669 | * if_extents/if_data and if_broot. It must also free the lock |
2619 | * associated with the inode. | 2670 | * associated with the inode. |
2671 | * | ||
2672 | * Note: because we don't initialise everything on reallocation out | ||
2673 | * of the zone, we must ensure we nullify everything correctly before | ||
2674 | * freeing the structure. | ||
2620 | */ | 2675 | */ |
2621 | void | 2676 | void |
2622 | xfs_idestroy( | 2677 | xfs_idestroy( |
@@ -2631,8 +2686,6 @@ xfs_idestroy( | |||
2631 | } | 2686 | } |
2632 | if (ip->i_afp) | 2687 | if (ip->i_afp) |
2633 | xfs_idestroy_fork(ip, XFS_ATTR_FORK); | 2688 | xfs_idestroy_fork(ip, XFS_ATTR_FORK); |
2634 | mrfree(&ip->i_lock); | ||
2635 | mrfree(&ip->i_iolock); | ||
2636 | 2689 | ||
2637 | #ifdef XFS_INODE_TRACE | 2690 | #ifdef XFS_INODE_TRACE |
2638 | ktrace_free(ip->i_trace); | 2691 | ktrace_free(ip->i_trace); |
@@ -2640,7 +2693,7 @@ xfs_idestroy( | |||
2640 | #ifdef XFS_BMAP_TRACE | 2693 | #ifdef XFS_BMAP_TRACE |
2641 | ktrace_free(ip->i_xtrace); | 2694 | ktrace_free(ip->i_xtrace); |
2642 | #endif | 2695 | #endif |
2643 | #ifdef XFS_BMBT_TRACE | 2696 | #ifdef XFS_BTREE_TRACE |
2644 | ktrace_free(ip->i_btrace); | 2697 | ktrace_free(ip->i_btrace); |
2645 | #endif | 2698 | #endif |
2646 | #ifdef XFS_RW_TRACE | 2699 | #ifdef XFS_RW_TRACE |
@@ -2658,20 +2711,26 @@ xfs_idestroy( | |||
2658 | * inode still in the AIL. If it is there, we should remove | 2711 | * inode still in the AIL. If it is there, we should remove |
2659 | * it to prevent a use-after-free from occurring. | 2712 | * it to prevent a use-after-free from occurring. |
2660 | */ | 2713 | */ |
2661 | xfs_mount_t *mp = ip->i_mount; | ||
2662 | xfs_log_item_t *lip = &ip->i_itemp->ili_item; | 2714 | xfs_log_item_t *lip = &ip->i_itemp->ili_item; |
2715 | struct xfs_ail *ailp = lip->li_ailp; | ||
2663 | 2716 | ||
2664 | ASSERT(((lip->li_flags & XFS_LI_IN_AIL) == 0) || | 2717 | ASSERT(((lip->li_flags & XFS_LI_IN_AIL) == 0) || |
2665 | XFS_FORCED_SHUTDOWN(ip->i_mount)); | 2718 | XFS_FORCED_SHUTDOWN(ip->i_mount)); |
2666 | if (lip->li_flags & XFS_LI_IN_AIL) { | 2719 | if (lip->li_flags & XFS_LI_IN_AIL) { |
2667 | spin_lock(&mp->m_ail_lock); | 2720 | spin_lock(&ailp->xa_lock); |
2668 | if (lip->li_flags & XFS_LI_IN_AIL) | 2721 | if (lip->li_flags & XFS_LI_IN_AIL) |
2669 | xfs_trans_delete_ail(mp, lip); | 2722 | xfs_trans_ail_delete(ailp, lip); |
2670 | else | 2723 | else |
2671 | spin_unlock(&mp->m_ail_lock); | 2724 | spin_unlock(&ailp->xa_lock); |
2672 | } | 2725 | } |
2673 | xfs_inode_item_destroy(ip); | 2726 | xfs_inode_item_destroy(ip); |
2727 | ip->i_itemp = NULL; | ||
2674 | } | 2728 | } |
2729 | /* asserts to verify all state is correct here */ | ||
2730 | ASSERT(atomic_read(&ip->i_iocount) == 0); | ||
2731 | ASSERT(atomic_read(&ip->i_pincount) == 0); | ||
2732 | ASSERT(!spin_is_locked(&ip->i_flags_lock)); | ||
2733 | ASSERT(completion_done(&ip->i_flush)); | ||
2675 | kmem_zone_free(xfs_inode_zone, ip); | 2734 | kmem_zone_free(xfs_inode_zone, ip); |
2676 | } | 2735 | } |
2677 | 2736 | ||
@@ -2880,7 +2939,7 @@ xfs_iflush_fork( | |||
2880 | ASSERT(ifp->if_broot_bytes <= | 2939 | ASSERT(ifp->if_broot_bytes <= |
2881 | (XFS_IFORK_SIZE(ip, whichfork) + | 2940 | (XFS_IFORK_SIZE(ip, whichfork) + |
2882 | XFS_BROOT_SIZE_ADJ)); | 2941 | XFS_BROOT_SIZE_ADJ)); |
2883 | xfs_bmbt_to_bmdr(ifp->if_broot, ifp->if_broot_bytes, | 2942 | xfs_bmbt_to_bmdr(mp, ifp->if_broot, ifp->if_broot_bytes, |
2884 | (xfs_bmdr_block_t *)cp, | 2943 | (xfs_bmdr_block_t *)cp, |
2885 | XFS_DFORK_SIZE(dip, mp, whichfork)); | 2944 | XFS_DFORK_SIZE(dip, mp, whichfork)); |
2886 | } | 2945 | } |
@@ -3418,10 +3477,8 @@ xfs_iflush_int( | |||
3418 | iip->ili_format.ilf_fields = 0; | 3477 | iip->ili_format.ilf_fields = 0; |
3419 | iip->ili_logged = 1; | 3478 | iip->ili_logged = 1; |
3420 | 3479 | ||
3421 | ASSERT(sizeof(xfs_lsn_t) == 8); /* don't lock if it shrinks */ | 3480 | xfs_trans_ail_copy_lsn(mp->m_ail, &iip->ili_flush_lsn, |
3422 | spin_lock(&mp->m_ail_lock); | 3481 | &iip->ili_item.li_lsn); |
3423 | iip->ili_flush_lsn = iip->ili_item.li_lsn; | ||
3424 | spin_unlock(&mp->m_ail_lock); | ||
3425 | 3482 | ||
3426 | /* | 3483 | /* |
3427 | * Attach the function xfs_iflush_done to the inode's | 3484 | * Attach the function xfs_iflush_done to the inode's |
@@ -3459,41 +3516,6 @@ corrupt_out: | |||
3459 | } | 3516 | } |
3460 | 3517 | ||
3461 | 3518 | ||
3462 | /* | ||
3463 | * Flush all inactive inodes in mp. | ||
3464 | */ | ||
3465 | void | ||
3466 | xfs_iflush_all( | ||
3467 | xfs_mount_t *mp) | ||
3468 | { | ||
3469 | xfs_inode_t *ip; | ||
3470 | |||
3471 | again: | ||
3472 | XFS_MOUNT_ILOCK(mp); | ||
3473 | ip = mp->m_inodes; | ||
3474 | if (ip == NULL) | ||
3475 | goto out; | ||
3476 | |||
3477 | do { | ||
3478 | /* Make sure we skip markers inserted by sync */ | ||
3479 | if (ip->i_mount == NULL) { | ||
3480 | ip = ip->i_mnext; | ||
3481 | continue; | ||
3482 | } | ||
3483 | |||
3484 | if (!VFS_I(ip)) { | ||
3485 | XFS_MOUNT_IUNLOCK(mp); | ||
3486 | xfs_finish_reclaim(ip, 0, XFS_IFLUSH_ASYNC); | ||
3487 | goto again; | ||
3488 | } | ||
3489 | |||
3490 | ASSERT(vn_count(VFS_I(ip)) == 0); | ||
3491 | |||
3492 | ip = ip->i_mnext; | ||
3493 | } while (ip != mp->m_inodes); | ||
3494 | out: | ||
3495 | XFS_MOUNT_IUNLOCK(mp); | ||
3496 | } | ||
3497 | 3519 | ||
3498 | #ifdef XFS_ILOCK_TRACE | 3520 | #ifdef XFS_ILOCK_TRACE |
3499 | ktrace_t *xfs_ilock_trace_buf; | 3521 | ktrace_t *xfs_ilock_trace_buf; |