aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDave Chinner <dchinner@redhat.com>2013-08-12 06:49:47 -0400
committerBen Myers <bpm@sgi.com>2013-08-12 17:55:17 -0400
commite546cb79ef7ebe53060369dae665fa449a544353 (patch)
tree06fc6552389e191a7a330057773c19a9428cad04
parentf6bba2017afb3bda8f2a27d6ba9d7023e8ff7f37 (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>
-rw-r--r--fs/xfs/Makefile1
-rw-r--r--fs/xfs/xfs_error.c1
-rw-r--r--fs/xfs/xfs_filestream.c1
-rw-r--r--fs/xfs/xfs_inode.c279
-rw-r--r--fs/xfs/xfs_inode.h7
-rw-r--r--fs/xfs/xfs_inode_fork.c1
-rw-r--r--fs/xfs/xfs_ioctl.c1
-rw-r--r--fs/xfs/xfs_iomap.c1
-rw-r--r--fs/xfs/xfs_iops.c1
-rw-r--r--fs/xfs/xfs_log_recover.c1
-rw-r--r--fs/xfs/xfs_mount.c1
-rw-r--r--fs/xfs/xfs_qm.c1
-rw-r--r--fs/xfs/xfs_qm_syscalls.c1
-rw-r--r--fs/xfs/xfs_rtalloc.c1
-rw-r--r--fs/xfs/xfs_super.c1
-rw-r--r--fs/xfs/xfs_symlink.c1
-rw-r--r--fs/xfs/xfs_utils.c316
-rw-r--r--fs/xfs/xfs_utils.h27
18 files changed, 285 insertions, 358 deletions
diff --git a/fs/xfs/Makefile b/fs/xfs/Makefile
index e5a0758fd20c..201c61df3c45 100644
--- a/fs/xfs/Makefile
+++ b/fs/xfs/Makefile
@@ -53,7 +53,6 @@ xfs-y += xfs_aops.o \
53 xfs_super.o \ 53 xfs_super.o \
54 xfs_symlink.o \ 54 xfs_symlink.o \
55 xfs_trans.o \ 55 xfs_trans.o \
56 xfs_utils.o \
57 xfs_xattr.o \ 56 xfs_xattr.o \
58 kmem.o \ 57 kmem.o \
59 uuid.o 58 uuid.o
diff --git a/fs/xfs/xfs_error.c b/fs/xfs/xfs_error.c
index 35d3f5b041dd..1123d93ff795 100644
--- a/fs/xfs/xfs_error.c
+++ b/fs/xfs/xfs_error.c
@@ -26,7 +26,6 @@
26#include "xfs_bmap_btree.h" 26#include "xfs_bmap_btree.h"
27#include "xfs_dinode.h" 27#include "xfs_dinode.h"
28#include "xfs_inode.h" 28#include "xfs_inode.h"
29#include "xfs_utils.h"
30#include "xfs_error.h" 29#include "xfs_error.h"
31 30
32#ifdef DEBUG 31#ifdef DEBUG
diff --git a/fs/xfs/xfs_filestream.c b/fs/xfs/xfs_filestream.c
index d0e8890dac86..ce78e654d37b 100644
--- a/fs/xfs/xfs_filestream.c
+++ b/fs/xfs/xfs_filestream.c
@@ -28,7 +28,6 @@
28#include "xfs_bmap.h" 28#include "xfs_bmap.h"
29#include "xfs_bmap_util.h" 29#include "xfs_bmap_util.h"
30#include "xfs_alloc.h" 30#include "xfs_alloc.h"
31#include "xfs_utils.h"
32#include "xfs_mru_cache.h" 31#include "xfs_mru_cache.h"
33#include "xfs_filestream.h" 32#include "xfs_filestream.h"
34#include "xfs_trace.h" 33#include "xfs_trace.h"
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 */
874int
875xfs_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 */
1051int /* error */
1052xfs_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 */
1085void
1086xfs_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 */
1115int
1116xfs_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
865int 1142int
866xfs_create( 1143xfs_create(
867 xfs_inode_t *dp, 1144 xfs_inode_t *dp,
diff --git a/fs/xfs/xfs_inode.h b/fs/xfs/xfs_inode.h
index 2a6347038cd8..4a91358c1470 100644
--- a/fs/xfs/xfs_inode.h
+++ b/fs/xfs/xfs_inode.h
@@ -360,6 +360,13 @@ void xfs_lock_two_inodes(xfs_inode_t *, xfs_inode_t *, uint);
360 360
361xfs_extlen_t xfs_get_extsz_hint(struct xfs_inode *ip); 361xfs_extlen_t xfs_get_extsz_hint(struct xfs_inode *ip);
362 362
363int xfs_dir_ialloc(struct xfs_trans **, struct xfs_inode *, umode_t,
364 xfs_nlink_t, xfs_dev_t, prid_t, int,
365 struct xfs_inode **, int *);
366int xfs_droplink(struct xfs_trans *, struct xfs_inode *);
367int xfs_bumplink(struct xfs_trans *, struct xfs_inode *);
368void xfs_bump_ino_vers2(struct xfs_trans *, struct xfs_inode *);
369
363/* from xfs_file.c */ 370/* from xfs_file.c */
364int xfs_zero_eof(struct xfs_inode *, xfs_off_t, xfs_fsize_t); 371int xfs_zero_eof(struct xfs_inode *, xfs_off_t, xfs_fsize_t);
365int xfs_iozero(struct xfs_inode *, loff_t, size_t); 372int xfs_iozero(struct xfs_inode *, loff_t, size_t);
diff --git a/fs/xfs/xfs_inode_fork.c b/fs/xfs/xfs_inode_fork.c
index 3f9ff99d6007..123971b31fbe 100644
--- a/fs/xfs/xfs_inode_fork.c
+++ b/fs/xfs/xfs_inode_fork.c
@@ -40,7 +40,6 @@
40#include "xfs_ialloc.h" 40#include "xfs_ialloc.h"
41#include "xfs_bmap.h" 41#include "xfs_bmap.h"
42#include "xfs_error.h" 42#include "xfs_error.h"
43#include "xfs_utils.h"
44#include "xfs_quota.h" 43#include "xfs_quota.h"
45#include "xfs_filestream.h" 44#include "xfs_filestream.h"
46#include "xfs_cksum.h" 45#include "xfs_cksum.h"
diff --git a/fs/xfs/xfs_ioctl.c b/fs/xfs/xfs_ioctl.c
index ce636bf0d550..557c7b8b2425 100644
--- a/fs/xfs/xfs_ioctl.c
+++ b/fs/xfs/xfs_ioctl.c
@@ -35,7 +35,6 @@
35#include "xfs_bmap.h" 35#include "xfs_bmap.h"
36#include "xfs_bmap_util.h" 36#include "xfs_bmap_util.h"
37#include "xfs_buf_item.h" 37#include "xfs_buf_item.h"
38#include "xfs_utils.h"
39#include "xfs_dfrag.h" 38#include "xfs_dfrag.h"
40#include "xfs_fsops.h" 39#include "xfs_fsops.h"
41#include "xfs_discard.h" 40#include "xfs_discard.h"
diff --git a/fs/xfs/xfs_iomap.c b/fs/xfs/xfs_iomap.c
index b04a60f66411..cf8f74407660 100644
--- a/fs/xfs/xfs_iomap.c
+++ b/fs/xfs/xfs_iomap.c
@@ -40,7 +40,6 @@
40#include "xfs_attr.h" 40#include "xfs_attr.h"
41#include "xfs_buf_item.h" 41#include "xfs_buf_item.h"
42#include "xfs_trans_space.h" 42#include "xfs_trans_space.h"
43#include "xfs_utils.h"
44#include "xfs_iomap.h" 43#include "xfs_iomap.h"
45#include "xfs_trace.h" 44#include "xfs_trace.h"
46#include "xfs_icache.h" 45#include "xfs_icache.h"
diff --git a/fs/xfs/xfs_iops.c b/fs/xfs/xfs_iops.c
index e0cefd417bf8..24be68d82f11 100644
--- a/fs/xfs/xfs_iops.c
+++ b/fs/xfs/xfs_iops.c
@@ -36,7 +36,6 @@
36#include "xfs_itable.h" 36#include "xfs_itable.h"
37#include "xfs_attr.h" 37#include "xfs_attr.h"
38#include "xfs_buf_item.h" 38#include "xfs_buf_item.h"
39#include "xfs_utils.h"
40#include "xfs_inode_item.h" 39#include "xfs_inode_item.h"
41#include "xfs_trace.h" 40#include "xfs_trace.h"
42#include "xfs_icache.h" 41#include "xfs_icache.h"
diff --git a/fs/xfs/xfs_log_recover.c b/fs/xfs/xfs_log_recover.c
index 62ddae32b991..81c04eb90521 100644
--- a/fs/xfs/xfs_log_recover.c
+++ b/fs/xfs/xfs_log_recover.c
@@ -41,7 +41,6 @@
41#include "xfs_extfree_item.h" 41#include "xfs_extfree_item.h"
42#include "xfs_trans_priv.h" 42#include "xfs_trans_priv.h"
43#include "xfs_quota.h" 43#include "xfs_quota.h"
44#include "xfs_utils.h"
45#include "xfs_cksum.h" 44#include "xfs_cksum.h"
46#include "xfs_trace.h" 45#include "xfs_trace.h"
47#include "xfs_icache.h" 46#include "xfs_icache.h"
diff --git a/fs/xfs/xfs_mount.c b/fs/xfs/xfs_mount.c
index 3b6fe4ffd724..7a9986db47e2 100644
--- a/fs/xfs/xfs_mount.c
+++ b/fs/xfs/xfs_mount.c
@@ -42,7 +42,6 @@
42#include "xfs_error.h" 42#include "xfs_error.h"
43#include "xfs_quota.h" 43#include "xfs_quota.h"
44#include "xfs_fsops.h" 44#include "xfs_fsops.h"
45#include "xfs_utils.h"
46#include "xfs_trace.h" 45#include "xfs_trace.h"
47#include "xfs_icache.h" 46#include "xfs_icache.h"
48#include "xfs_cksum.h" 47#include "xfs_cksum.h"
diff --git a/fs/xfs/xfs_qm.c b/fs/xfs/xfs_qm.c
index 92c36ac4bb23..35a6f568e9c9 100644
--- a/fs/xfs/xfs_qm.c
+++ b/fs/xfs/xfs_qm.c
@@ -38,7 +38,6 @@
38#include "xfs_attr.h" 38#include "xfs_attr.h"
39#include "xfs_buf_item.h" 39#include "xfs_buf_item.h"
40#include "xfs_trans_space.h" 40#include "xfs_trans_space.h"
41#include "xfs_utils.h"
42#include "xfs_qm.h" 41#include "xfs_qm.h"
43#include "xfs_trace.h" 42#include "xfs_trace.h"
44#include "xfs_icache.h" 43#include "xfs_icache.h"
diff --git a/fs/xfs/xfs_qm_syscalls.c b/fs/xfs/xfs_qm_syscalls.c
index 18519392c486..6fdccc324f7e 100644
--- a/fs/xfs/xfs_qm_syscalls.c
+++ b/fs/xfs/xfs_qm_syscalls.c
@@ -38,7 +38,6 @@
38#include "xfs_error.h" 38#include "xfs_error.h"
39#include "xfs_attr.h" 39#include "xfs_attr.h"
40#include "xfs_buf_item.h" 40#include "xfs_buf_item.h"
41#include "xfs_utils.h"
42#include "xfs_qm.h" 41#include "xfs_qm.h"
43#include "xfs_trace.h" 42#include "xfs_trace.h"
44#include "xfs_icache.h" 43#include "xfs_icache.h"
diff --git a/fs/xfs/xfs_rtalloc.c b/fs/xfs/xfs_rtalloc.c
index 7a445e68c35b..48228067b0d2 100644
--- a/fs/xfs/xfs_rtalloc.c
+++ b/fs/xfs/xfs_rtalloc.c
@@ -35,7 +35,6 @@
35#include "xfs_error.h" 35#include "xfs_error.h"
36#include "xfs_inode_item.h" 36#include "xfs_inode_item.h"
37#include "xfs_trans_space.h" 37#include "xfs_trans_space.h"
38#include "xfs_utils.h"
39#include "xfs_trace.h" 38#include "xfs_trace.h"
40#include "xfs_buf.h" 39#include "xfs_buf.h"
41#include "xfs_icache.h" 40#include "xfs_icache.h"
diff --git a/fs/xfs/xfs_super.c b/fs/xfs/xfs_super.c
index 978a2845f9af..979a77d4b87d 100644
--- a/fs/xfs/xfs_super.c
+++ b/fs/xfs/xfs_super.c
@@ -40,7 +40,6 @@
40#include "xfs_fsops.h" 40#include "xfs_fsops.h"
41#include "xfs_attr.h" 41#include "xfs_attr.h"
42#include "xfs_buf_item.h" 42#include "xfs_buf_item.h"
43#include "xfs_utils.h"
44#include "xfs_log_priv.h" 43#include "xfs_log_priv.h"
45#include "xfs_trans_priv.h" 44#include "xfs_trans_priv.h"
46#include "xfs_filestream.h" 45#include "xfs_filestream.h"
diff --git a/fs/xfs/xfs_symlink.c b/fs/xfs/xfs_symlink.c
index 1ce2756dfb71..e6facbf7043e 100644
--- a/fs/xfs/xfs_symlink.c
+++ b/fs/xfs/xfs_symlink.c
@@ -38,7 +38,6 @@
38#include "xfs_bmap_util.h" 38#include "xfs_bmap_util.h"
39#include "xfs_error.h" 39#include "xfs_error.h"
40#include "xfs_quota.h" 40#include "xfs_quota.h"
41#include "xfs_utils.h"
42#include "xfs_trans_space.h" 41#include "xfs_trans_space.h"
43#include "xfs_trace.h" 42#include "xfs_trace.h"
44#include "xfs_symlink.h" 43#include "xfs_symlink.h"
diff --git a/fs/xfs/xfs_utils.c b/fs/xfs/xfs_utils.c
deleted file mode 100644
index fde7d2231ee8..000000000000
--- a/fs/xfs/xfs_utils.c
+++ /dev/null
@@ -1,316 +0,0 @@
1/*
2 * Copyright (c) 2000-2002,2005 Silicon Graphics, Inc.
3 * All Rights Reserved.
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License as
7 * published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it would be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write the Free Software Foundation,
16 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
17 */
18#include "xfs.h"
19#include "xfs_fs.h"
20#include "xfs_format.h"
21#include "xfs_log.h"
22#include "xfs_trans.h"
23#include "xfs_sb.h"
24#include "xfs_ag.h"
25#include "xfs_mount.h"
26#include "xfs_da_btree.h"
27#include "xfs_dir2_format.h"
28#include "xfs_dir2.h"
29#include "xfs_bmap_btree.h"
30#include "xfs_dinode.h"
31#include "xfs_inode.h"
32#include "xfs_inode_item.h"
33#include "xfs_bmap.h"
34#include "xfs_error.h"
35#include "xfs_quota.h"
36#include "xfs_itable.h"
37#include "xfs_utils.h"
38
39
40/*
41 * Allocates a new inode from disk and return a pointer to the
42 * incore copy. This routine will internally commit the current
43 * transaction and allocate a new one if the Space Manager needed
44 * to do an allocation to replenish the inode free-list.
45 *
46 * This routine is designed to be called from xfs_create and
47 * xfs_create_dir.
48 *
49 */
50int
51xfs_dir_ialloc(
52 xfs_trans_t **tpp, /* input: current transaction;
53 output: may be a new transaction. */
54 xfs_inode_t *dp, /* directory within whose allocate
55 the inode. */
56 umode_t mode,
57 xfs_nlink_t nlink,
58 xfs_dev_t rdev,
59 prid_t prid, /* project id */
60 int okalloc, /* ok to allocate new space */
61 xfs_inode_t **ipp, /* pointer to inode; it will be
62 locked. */
63 int *committed)
64
65{
66 xfs_trans_t *tp;
67 xfs_trans_t *ntp;
68 xfs_inode_t *ip;
69 xfs_buf_t *ialloc_context = NULL;
70 int code;
71 uint log_res;
72 uint log_count;
73 void *dqinfo;
74 uint tflags;
75
76 tp = *tpp;
77 ASSERT(tp->t_flags & XFS_TRANS_PERM_LOG_RES);
78
79 /*
80 * xfs_ialloc will return a pointer to an incore inode if
81 * the Space Manager has an available inode on the free
82 * list. Otherwise, it will do an allocation and replenish
83 * the freelist. Since we can only do one allocation per
84 * transaction without deadlocks, we will need to commit the
85 * current transaction and start a new one. We will then
86 * need to call xfs_ialloc again to get the inode.
87 *
88 * If xfs_ialloc did an allocation to replenish the freelist,
89 * it returns the bp containing the head of the freelist as
90 * ialloc_context. We will hold a lock on it across the
91 * transaction commit so that no other process can steal
92 * the inode(s) that we've just allocated.
93 */
94 code = xfs_ialloc(tp, dp, mode, nlink, rdev, prid, okalloc,
95 &ialloc_context, &ip);
96
97 /*
98 * Return an error if we were unable to allocate a new inode.
99 * This should only happen if we run out of space on disk or
100 * encounter a disk error.
101 */
102 if (code) {
103 *ipp = NULL;
104 return code;
105 }
106 if (!ialloc_context && !ip) {
107 *ipp = NULL;
108 return XFS_ERROR(ENOSPC);
109 }
110
111 /*
112 * If the AGI buffer is non-NULL, then we were unable to get an
113 * inode in one operation. We need to commit the current
114 * transaction and call xfs_ialloc() again. It is guaranteed
115 * to succeed the second time.
116 */
117 if (ialloc_context) {
118 /*
119 * Normally, xfs_trans_commit releases all the locks.
120 * We call bhold to hang on to the ialloc_context across
121 * the commit. Holding this buffer prevents any other
122 * processes from doing any allocations in this
123 * allocation group.
124 */
125 xfs_trans_bhold(tp, ialloc_context);
126 /*
127 * Save the log reservation so we can use
128 * them in the next transaction.
129 */
130 log_res = xfs_trans_get_log_res(tp);
131 log_count = xfs_trans_get_log_count(tp);
132
133 /*
134 * We want the quota changes to be associated with the next
135 * transaction, NOT this one. So, detach the dqinfo from this
136 * and attach it to the next transaction.
137 */
138 dqinfo = NULL;
139 tflags = 0;
140 if (tp->t_dqinfo) {
141 dqinfo = (void *)tp->t_dqinfo;
142 tp->t_dqinfo = NULL;
143 tflags = tp->t_flags & XFS_TRANS_DQ_DIRTY;
144 tp->t_flags &= ~(XFS_TRANS_DQ_DIRTY);
145 }
146
147 ntp = xfs_trans_dup(tp);
148 code = xfs_trans_commit(tp, 0);
149 tp = ntp;
150 if (committed != NULL) {
151 *committed = 1;
152 }
153 /*
154 * If we get an error during the commit processing,
155 * release the buffer that is still held and return
156 * to the caller.
157 */
158 if (code) {
159 xfs_buf_relse(ialloc_context);
160 if (dqinfo) {
161 tp->t_dqinfo = dqinfo;
162 xfs_trans_free_dqinfo(tp);
163 }
164 *tpp = ntp;
165 *ipp = NULL;
166 return code;
167 }
168
169 /*
170 * transaction commit worked ok so we can drop the extra ticket
171 * reference that we gained in xfs_trans_dup()
172 */
173 xfs_log_ticket_put(tp->t_ticket);
174 code = xfs_trans_reserve(tp, 0, log_res, 0,
175 XFS_TRANS_PERM_LOG_RES, log_count);
176 /*
177 * Re-attach the quota info that we detached from prev trx.
178 */
179 if (dqinfo) {
180 tp->t_dqinfo = dqinfo;
181 tp->t_flags |= tflags;
182 }
183
184 if (code) {
185 xfs_buf_relse(ialloc_context);
186 *tpp = ntp;
187 *ipp = NULL;
188 return code;
189 }
190 xfs_trans_bjoin(tp, ialloc_context);
191
192 /*
193 * Call ialloc again. Since we've locked out all
194 * other allocations in this allocation group,
195 * this call should always succeed.
196 */
197 code = xfs_ialloc(tp, dp, mode, nlink, rdev, prid,
198 okalloc, &ialloc_context, &ip);
199
200 /*
201 * If we get an error at this point, return to the caller
202 * so that the current transaction can be aborted.
203 */
204 if (code) {
205 *tpp = tp;
206 *ipp = NULL;
207 return code;
208 }
209 ASSERT(!ialloc_context && ip);
210
211 } else {
212 if (committed != NULL)
213 *committed = 0;
214 }
215
216 *ipp = ip;
217 *tpp = tp;
218
219 return 0;
220}
221
222/*
223 * Decrement the link count on an inode & log the change.
224 * If this causes the link count to go to zero, initiate the
225 * logging activity required to truncate a file.
226 */
227int /* error */
228xfs_droplink(
229 xfs_trans_t *tp,
230 xfs_inode_t *ip)
231{
232 int error;
233
234 xfs_trans_ichgtime(tp, ip, XFS_ICHGTIME_CHG);
235
236 ASSERT (ip->i_d.di_nlink > 0);
237 ip->i_d.di_nlink--;
238 drop_nlink(VFS_I(ip));
239 xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
240
241 error = 0;
242 if (ip->i_d.di_nlink == 0) {
243 /*
244 * We're dropping the last link to this file.
245 * Move the on-disk inode to the AGI unlinked list.
246 * From xfs_inactive() we will pull the inode from
247 * the list and free it.
248 */
249 error = xfs_iunlink(tp, ip);
250 }
251 return error;
252}
253
254/*
255 * This gets called when the inode's version needs to be changed from 1 to 2.
256 * Currently this happens when the nlink field overflows the old 16-bit value
257 * or when chproj is called to change the project for the first time.
258 * As a side effect the superblock version will also get rev'd
259 * to contain the NLINK bit.
260 */
261void
262xfs_bump_ino_vers2(
263 xfs_trans_t *tp,
264 xfs_inode_t *ip)
265{
266 xfs_mount_t *mp;
267
268 ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL));
269 ASSERT(ip->i_d.di_version == 1);
270
271 ip->i_d.di_version = 2;
272 ip->i_d.di_onlink = 0;
273 memset(&(ip->i_d.di_pad[0]), 0, sizeof(ip->i_d.di_pad));
274 mp = tp->t_mountp;
275 if (!xfs_sb_version_hasnlink(&mp->m_sb)) {
276 spin_lock(&mp->m_sb_lock);
277 if (!xfs_sb_version_hasnlink(&mp->m_sb)) {
278 xfs_sb_version_addnlink(&mp->m_sb);
279 spin_unlock(&mp->m_sb_lock);
280 xfs_mod_sb(tp, XFS_SB_VERSIONNUM);
281 } else {
282 spin_unlock(&mp->m_sb_lock);
283 }
284 }
285 /* Caller must log the inode */
286}
287
288/*
289 * Increment the link count on an inode & log the change.
290 */
291int
292xfs_bumplink(
293 xfs_trans_t *tp,
294 xfs_inode_t *ip)
295{
296 xfs_trans_ichgtime(tp, ip, XFS_ICHGTIME_CHG);
297
298 ASSERT(ip->i_d.di_nlink > 0);
299 ip->i_d.di_nlink++;
300 inc_nlink(VFS_I(ip));
301 if ((ip->i_d.di_version == 1) &&
302 (ip->i_d.di_nlink > XFS_MAXLINK_1)) {
303 /*
304 * The inode has increased its number of links beyond
305 * what can fit in an old format inode. It now needs
306 * to be converted to a version 2 inode with a 32 bit
307 * link count. If this is the first inode in the file
308 * system to do this, then we need to bump the superblock
309 * version number as well.
310 */
311 xfs_bump_ino_vers2(tp, ip);
312 }
313
314 xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
315 return 0;
316}
diff --git a/fs/xfs/xfs_utils.h b/fs/xfs/xfs_utils.h
deleted file mode 100644
index 5eeab4690cfe..000000000000
--- a/fs/xfs/xfs_utils.h
+++ /dev/null
@@ -1,27 +0,0 @@
1/*
2 * Copyright (c) 2000-2002,2005 Silicon Graphics, Inc.
3 * All Rights Reserved.
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License as
7 * published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it would be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write the Free Software Foundation,
16 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
17 */
18#ifndef __XFS_UTILS_H__
19#define __XFS_UTILS_H__
20
21extern int xfs_dir_ialloc(xfs_trans_t **, xfs_inode_t *, umode_t, xfs_nlink_t,
22 xfs_dev_t, prid_t, int, xfs_inode_t **, int *);
23extern int xfs_droplink(xfs_trans_t *, xfs_inode_t *);
24extern int xfs_bumplink(xfs_trans_t *, xfs_inode_t *);
25extern void xfs_bump_ino_vers2(xfs_trans_t *, xfs_inode_t *);
26
27#endif /* __XFS_UTILS_H__ */