diff options
author | Dave Chinner <dchinner@redhat.com> | 2013-08-12 06:49:47 -0400 |
---|---|---|
committer | Ben Myers <bpm@sgi.com> | 2013-08-12 17:55:17 -0400 |
commit | e546cb79ef7ebe53060369dae665fa449a544353 (patch) | |
tree | 06fc6552389e191a7a330057773c19a9428cad04 /fs/xfs/xfs_inode.c | |
parent | f6bba2017afb3bda8f2a27d6ba9d7023e8ff7f37 (diff) |
xfs: consolidate xfs_utils.c
There are a few small helper functions in xfs_util, all related to
xfs_inode modifications. Move them all to xfs_inode.c so all
xfs_inode operations are consiolidated in the one place.
Signed-off-by: Dave Chinner <dchinner@redhat.com>
Reviewed-by: Mark Tinguely <tinguely@sgi.com>
Signed-off-by: Ben Myers <bpm@sgi.com>
Diffstat (limited to 'fs/xfs/xfs_inode.c')
-rw-r--r-- | fs/xfs/xfs_inode.c | 279 |
1 files changed, 278 insertions, 1 deletions
diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c index 279ac3fdfde5..e83d3af3dfd4 100644 --- a/fs/xfs/xfs_inode.c +++ b/fs/xfs/xfs_inode.c | |||
@@ -46,7 +46,6 @@ | |||
46 | #include "xfs_bmap.h" | 46 | #include "xfs_bmap.h" |
47 | #include "xfs_bmap_util.h" | 47 | #include "xfs_bmap_util.h" |
48 | #include "xfs_error.h" | 48 | #include "xfs_error.h" |
49 | #include "xfs_utils.h" | ||
50 | #include "xfs_quota.h" | 49 | #include "xfs_quota.h" |
51 | #include "xfs_filestream.h" | 50 | #include "xfs_filestream.h" |
52 | #include "xfs_cksum.h" | 51 | #include "xfs_cksum.h" |
@@ -862,6 +861,284 @@ xfs_ialloc( | |||
862 | return 0; | 861 | return 0; |
863 | } | 862 | } |
864 | 863 | ||
864 | /* | ||
865 | * Allocates a new inode from disk and return a pointer to the | ||
866 | * incore copy. This routine will internally commit the current | ||
867 | * transaction and allocate a new one if the Space Manager needed | ||
868 | * to do an allocation to replenish the inode free-list. | ||
869 | * | ||
870 | * This routine is designed to be called from xfs_create and | ||
871 | * xfs_create_dir. | ||
872 | * | ||
873 | */ | ||
874 | int | ||
875 | xfs_dir_ialloc( | ||
876 | xfs_trans_t **tpp, /* input: current transaction; | ||
877 | output: may be a new transaction. */ | ||
878 | xfs_inode_t *dp, /* directory within whose allocate | ||
879 | the inode. */ | ||
880 | umode_t mode, | ||
881 | xfs_nlink_t nlink, | ||
882 | xfs_dev_t rdev, | ||
883 | prid_t prid, /* project id */ | ||
884 | int okalloc, /* ok to allocate new space */ | ||
885 | xfs_inode_t **ipp, /* pointer to inode; it will be | ||
886 | locked. */ | ||
887 | int *committed) | ||
888 | |||
889 | { | ||
890 | xfs_trans_t *tp; | ||
891 | xfs_trans_t *ntp; | ||
892 | xfs_inode_t *ip; | ||
893 | xfs_buf_t *ialloc_context = NULL; | ||
894 | int code; | ||
895 | uint log_res; | ||
896 | uint log_count; | ||
897 | void *dqinfo; | ||
898 | uint tflags; | ||
899 | |||
900 | tp = *tpp; | ||
901 | ASSERT(tp->t_flags & XFS_TRANS_PERM_LOG_RES); | ||
902 | |||
903 | /* | ||
904 | * xfs_ialloc will return a pointer to an incore inode if | ||
905 | * the Space Manager has an available inode on the free | ||
906 | * list. Otherwise, it will do an allocation and replenish | ||
907 | * the freelist. Since we can only do one allocation per | ||
908 | * transaction without deadlocks, we will need to commit the | ||
909 | * current transaction and start a new one. We will then | ||
910 | * need to call xfs_ialloc again to get the inode. | ||
911 | * | ||
912 | * If xfs_ialloc did an allocation to replenish the freelist, | ||
913 | * it returns the bp containing the head of the freelist as | ||
914 | * ialloc_context. We will hold a lock on it across the | ||
915 | * transaction commit so that no other process can steal | ||
916 | * the inode(s) that we've just allocated. | ||
917 | */ | ||
918 | code = xfs_ialloc(tp, dp, mode, nlink, rdev, prid, okalloc, | ||
919 | &ialloc_context, &ip); | ||
920 | |||
921 | /* | ||
922 | * Return an error if we were unable to allocate a new inode. | ||
923 | * This should only happen if we run out of space on disk or | ||
924 | * encounter a disk error. | ||
925 | */ | ||
926 | if (code) { | ||
927 | *ipp = NULL; | ||
928 | return code; | ||
929 | } | ||
930 | if (!ialloc_context && !ip) { | ||
931 | *ipp = NULL; | ||
932 | return XFS_ERROR(ENOSPC); | ||
933 | } | ||
934 | |||
935 | /* | ||
936 | * If the AGI buffer is non-NULL, then we were unable to get an | ||
937 | * inode in one operation. We need to commit the current | ||
938 | * transaction and call xfs_ialloc() again. It is guaranteed | ||
939 | * to succeed the second time. | ||
940 | */ | ||
941 | if (ialloc_context) { | ||
942 | /* | ||
943 | * Normally, xfs_trans_commit releases all the locks. | ||
944 | * We call bhold to hang on to the ialloc_context across | ||
945 | * the commit. Holding this buffer prevents any other | ||
946 | * processes from doing any allocations in this | ||
947 | * allocation group. | ||
948 | */ | ||
949 | xfs_trans_bhold(tp, ialloc_context); | ||
950 | /* | ||
951 | * Save the log reservation so we can use | ||
952 | * them in the next transaction. | ||
953 | */ | ||
954 | log_res = xfs_trans_get_log_res(tp); | ||
955 | log_count = xfs_trans_get_log_count(tp); | ||
956 | |||
957 | /* | ||
958 | * We want the quota changes to be associated with the next | ||
959 | * transaction, NOT this one. So, detach the dqinfo from this | ||
960 | * and attach it to the next transaction. | ||
961 | */ | ||
962 | dqinfo = NULL; | ||
963 | tflags = 0; | ||
964 | if (tp->t_dqinfo) { | ||
965 | dqinfo = (void *)tp->t_dqinfo; | ||
966 | tp->t_dqinfo = NULL; | ||
967 | tflags = tp->t_flags & XFS_TRANS_DQ_DIRTY; | ||
968 | tp->t_flags &= ~(XFS_TRANS_DQ_DIRTY); | ||
969 | } | ||
970 | |||
971 | ntp = xfs_trans_dup(tp); | ||
972 | code = xfs_trans_commit(tp, 0); | ||
973 | tp = ntp; | ||
974 | if (committed != NULL) { | ||
975 | *committed = 1; | ||
976 | } | ||
977 | /* | ||
978 | * If we get an error during the commit processing, | ||
979 | * release the buffer that is still held and return | ||
980 | * to the caller. | ||
981 | */ | ||
982 | if (code) { | ||
983 | xfs_buf_relse(ialloc_context); | ||
984 | if (dqinfo) { | ||
985 | tp->t_dqinfo = dqinfo; | ||
986 | xfs_trans_free_dqinfo(tp); | ||
987 | } | ||
988 | *tpp = ntp; | ||
989 | *ipp = NULL; | ||
990 | return code; | ||
991 | } | ||
992 | |||
993 | /* | ||
994 | * transaction commit worked ok so we can drop the extra ticket | ||
995 | * reference that we gained in xfs_trans_dup() | ||
996 | */ | ||
997 | xfs_log_ticket_put(tp->t_ticket); | ||
998 | code = xfs_trans_reserve(tp, 0, log_res, 0, | ||
999 | XFS_TRANS_PERM_LOG_RES, log_count); | ||
1000 | /* | ||
1001 | * Re-attach the quota info that we detached from prev trx. | ||
1002 | */ | ||
1003 | if (dqinfo) { | ||
1004 | tp->t_dqinfo = dqinfo; | ||
1005 | tp->t_flags |= tflags; | ||
1006 | } | ||
1007 | |||
1008 | if (code) { | ||
1009 | xfs_buf_relse(ialloc_context); | ||
1010 | *tpp = ntp; | ||
1011 | *ipp = NULL; | ||
1012 | return code; | ||
1013 | } | ||
1014 | xfs_trans_bjoin(tp, ialloc_context); | ||
1015 | |||
1016 | /* | ||
1017 | * Call ialloc again. Since we've locked out all | ||
1018 | * other allocations in this allocation group, | ||
1019 | * this call should always succeed. | ||
1020 | */ | ||
1021 | code = xfs_ialloc(tp, dp, mode, nlink, rdev, prid, | ||
1022 | okalloc, &ialloc_context, &ip); | ||
1023 | |||
1024 | /* | ||
1025 | * If we get an error at this point, return to the caller | ||
1026 | * so that the current transaction can be aborted. | ||
1027 | */ | ||
1028 | if (code) { | ||
1029 | *tpp = tp; | ||
1030 | *ipp = NULL; | ||
1031 | return code; | ||
1032 | } | ||
1033 | ASSERT(!ialloc_context && ip); | ||
1034 | |||
1035 | } else { | ||
1036 | if (committed != NULL) | ||
1037 | *committed = 0; | ||
1038 | } | ||
1039 | |||
1040 | *ipp = ip; | ||
1041 | *tpp = tp; | ||
1042 | |||
1043 | return 0; | ||
1044 | } | ||
1045 | |||
1046 | /* | ||
1047 | * Decrement the link count on an inode & log the change. | ||
1048 | * If this causes the link count to go to zero, initiate the | ||
1049 | * logging activity required to truncate a file. | ||
1050 | */ | ||
1051 | int /* error */ | ||
1052 | xfs_droplink( | ||
1053 | xfs_trans_t *tp, | ||
1054 | xfs_inode_t *ip) | ||
1055 | { | ||
1056 | int error; | ||
1057 | |||
1058 | xfs_trans_ichgtime(tp, ip, XFS_ICHGTIME_CHG); | ||
1059 | |||
1060 | ASSERT (ip->i_d.di_nlink > 0); | ||
1061 | ip->i_d.di_nlink--; | ||
1062 | drop_nlink(VFS_I(ip)); | ||
1063 | xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE); | ||
1064 | |||
1065 | error = 0; | ||
1066 | if (ip->i_d.di_nlink == 0) { | ||
1067 | /* | ||
1068 | * We're dropping the last link to this file. | ||
1069 | * Move the on-disk inode to the AGI unlinked list. | ||
1070 | * From xfs_inactive() we will pull the inode from | ||
1071 | * the list and free it. | ||
1072 | */ | ||
1073 | error = xfs_iunlink(tp, ip); | ||
1074 | } | ||
1075 | return error; | ||
1076 | } | ||
1077 | |||
1078 | /* | ||
1079 | * This gets called when the inode's version needs to be changed from 1 to 2. | ||
1080 | * Currently this happens when the nlink field overflows the old 16-bit value | ||
1081 | * or when chproj is called to change the project for the first time. | ||
1082 | * As a side effect the superblock version will also get rev'd | ||
1083 | * to contain the NLINK bit. | ||
1084 | */ | ||
1085 | void | ||
1086 | xfs_bump_ino_vers2( | ||
1087 | xfs_trans_t *tp, | ||
1088 | xfs_inode_t *ip) | ||
1089 | { | ||
1090 | xfs_mount_t *mp; | ||
1091 | |||
1092 | ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL)); | ||
1093 | ASSERT(ip->i_d.di_version == 1); | ||
1094 | |||
1095 | ip->i_d.di_version = 2; | ||
1096 | ip->i_d.di_onlink = 0; | ||
1097 | memset(&(ip->i_d.di_pad[0]), 0, sizeof(ip->i_d.di_pad)); | ||
1098 | mp = tp->t_mountp; | ||
1099 | if (!xfs_sb_version_hasnlink(&mp->m_sb)) { | ||
1100 | spin_lock(&mp->m_sb_lock); | ||
1101 | if (!xfs_sb_version_hasnlink(&mp->m_sb)) { | ||
1102 | xfs_sb_version_addnlink(&mp->m_sb); | ||
1103 | spin_unlock(&mp->m_sb_lock); | ||
1104 | xfs_mod_sb(tp, XFS_SB_VERSIONNUM); | ||
1105 | } else { | ||
1106 | spin_unlock(&mp->m_sb_lock); | ||
1107 | } | ||
1108 | } | ||
1109 | /* Caller must log the inode */ | ||
1110 | } | ||
1111 | |||
1112 | /* | ||
1113 | * Increment the link count on an inode & log the change. | ||
1114 | */ | ||
1115 | int | ||
1116 | xfs_bumplink( | ||
1117 | xfs_trans_t *tp, | ||
1118 | xfs_inode_t *ip) | ||
1119 | { | ||
1120 | xfs_trans_ichgtime(tp, ip, XFS_ICHGTIME_CHG); | ||
1121 | |||
1122 | ASSERT(ip->i_d.di_nlink > 0); | ||
1123 | ip->i_d.di_nlink++; | ||
1124 | inc_nlink(VFS_I(ip)); | ||
1125 | if ((ip->i_d.di_version == 1) && | ||
1126 | (ip->i_d.di_nlink > XFS_MAXLINK_1)) { | ||
1127 | /* | ||
1128 | * The inode has increased its number of links beyond | ||
1129 | * what can fit in an old format inode. It now needs | ||
1130 | * to be converted to a version 2 inode with a 32 bit | ||
1131 | * link count. If this is the first inode in the file | ||
1132 | * system to do this, then we need to bump the superblock | ||
1133 | * version number as well. | ||
1134 | */ | ||
1135 | xfs_bump_ino_vers2(tp, ip); | ||
1136 | } | ||
1137 | |||
1138 | xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE); | ||
1139 | return 0; | ||
1140 | } | ||
1141 | |||
865 | int | 1142 | int |
866 | xfs_create( | 1143 | xfs_create( |
867 | xfs_inode_t *dp, | 1144 | xfs_inode_t *dp, |