This source file includes following definitions.
- trunc_direct
- trunc_indirect
- trunc_dindirect
- xiafs_truncate
1
2
3
4
5
6
7
8
9
10
11
12 #include <linux/errno.h>
13 #include <linux/sched.h>
14 #include <linux/xia_fs.h>
15 #include <linux/tty.h>
16 #include <linux/stat.h>
17 #include <linux/fcntl.h>
18
19 #include "xiafs_mac.h"
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36 #define DT_ZONE ((inode->i_size + XIAFS_ZSIZE(inode->i_sb) - 1) \
37 >> XIAFS_ZSIZE_BITS(inode->i_sb) )
38
39 static int trunc_direct(struct inode * inode)
40 {
41 u_long * lp;
42 struct buffer_head * bh;
43 int i, tmp;
44 int retry = 0;
45
46 repeat:
47 for (i = DT_ZONE ; i < 8 ; i++) {
48 if (i < DT_ZONE)
49 goto repeat;
50 lp=i + inode->u.xiafs_i.i_zone;
51 if (!(tmp = *lp))
52 continue;
53 bh = getblk(inode->i_dev, tmp, XIAFS_ZSIZE(inode->i_sb));
54 if (i < DT_ZONE) {
55 brelse(bh);
56 goto repeat;
57 }
58 if ((bh && bh->b_count != 1) || tmp != *lp)
59 retry = 1;
60 else {
61 *lp = 0;
62 inode->i_dirt = 1;
63 inode->i_blocks-=2 << XIAFS_ZSHIFT(inode->i_sb);
64 xiafs_free_zone(inode->i_sb, tmp);
65 }
66 brelse(bh);
67 }
68 return retry;
69 }
70
71 static int trunc_indirect(struct inode * inode, int addr_off, u_long * lp)
72 {
73
74 #define INDT_ZONE (DT_ZONE - addr_off)
75
76 struct buffer_head * bh, * ind_bh;
77 int i, tmp;
78 u_long * indp;
79 int retry = 0;
80
81 if ( !(tmp=*lp) )
82 return 0;
83 ind_bh = bread(inode->i_dev, tmp, XIAFS_ZSIZE(inode->i_sb));
84 if (tmp != *lp) {
85 brelse(ind_bh);
86 return 1;
87 }
88 if (!ind_bh) {
89 *lp = 0;
90 return 0;
91 }
92 repeat:
93 for (i = INDT_ZONE<0?0:INDT_ZONE; i < XIAFS_ADDRS_PER_Z(inode->i_sb); i++) {
94 if (i < INDT_ZONE)
95 goto repeat;
96 indp = i+(u_long *) ind_bh->b_data;
97 if (!(tmp=*indp))
98 continue;
99 bh = getblk(inode->i_dev, tmp, XIAFS_ZSIZE(inode->i_sb));
100 if (i < INDT_ZONE) {
101 brelse(bh);
102 goto repeat;
103 }
104 if ((bh && bh->b_count != 1) || tmp != *indp)
105 retry = 1;
106 else {
107 *indp = 0;
108 ind_bh->b_dirt = 1;
109 inode->i_blocks-= 2 << XIAFS_ZSHIFT(inode->i_sb);
110 xiafs_free_zone(inode->i_sb, tmp);
111 }
112 brelse(bh);
113 }
114 indp = (u_long *) ind_bh->b_data;
115 for (i = 0; i < XIAFS_ADDRS_PER_Z(inode->i_sb) && !(*indp++); i++) ;
116 if (i >= XIAFS_ADDRS_PER_Z(inode->i_sb)) {
117 if (ind_bh->b_count != 1)
118 retry = 1;
119 else {
120 tmp = *lp;
121 *lp = 0;
122 inode->i_blocks-= 2 << XIAFS_ZSHIFT(inode->i_sb);
123 xiafs_free_zone(inode->i_sb, tmp);
124 }
125 }
126 brelse(ind_bh);
127 return retry;
128 }
129
130 static int trunc_dindirect(struct inode * inode)
131 {
132
133 #define DINDT_ZONE \
134 ((DT_ZONE-XIAFS_ADDRS_PER_Z(inode->i_sb)-8)>>XIAFS_ADDRS_PER_Z_BITS(inode->i_sb))
135
136 int i, tmp;
137 struct buffer_head * dind_bh;
138 u_long * dindp, * lp;
139 int retry = 0;
140
141 lp = &(inode->u.xiafs_i.i_dind_zone);
142 if (!(tmp = *lp))
143 return 0;
144 dind_bh = bread(inode->i_dev, tmp, XIAFS_ZSIZE(inode->i_sb));
145 if (tmp != *lp) {
146 brelse(dind_bh);
147 return 1;
148 }
149 if (!dind_bh) {
150 *lp = 0;
151 return 0;
152 }
153 repeat:
154 for (i=DINDT_ZONE<0?0:DINDT_ZONE ; i < XIAFS_ADDRS_PER_Z(inode->i_sb) ; i ++) {
155 if (i < DINDT_ZONE)
156 goto repeat;
157 dindp = i+(u_long *) dind_bh->b_data;
158 retry |= trunc_indirect(inode,
159 8+((1+i)<<XIAFS_ADDRS_PER_Z_BITS(inode->i_sb)),
160 dindp);
161 dind_bh->b_dirt = 1;
162 }
163 dindp = (u_long *) dind_bh->b_data;
164 for (i = 0; i < XIAFS_ADDRS_PER_Z(inode->i_sb) && !(*dindp++); i++);
165 if (i >= XIAFS_ADDRS_PER_Z(inode->i_sb)) {
166 if (dind_bh->b_count != 1)
167 retry = 1;
168 else {
169 tmp = *lp;
170 *lp = 0;
171 inode->i_dirt = 1;
172 inode->i_blocks-=2 << XIAFS_ZSHIFT(inode->i_sb);
173 xiafs_free_zone(inode->i_sb, tmp);
174 }
175 }
176 brelse(dind_bh);
177 return retry;
178 }
179
180 void xiafs_truncate(struct inode * inode)
181 {
182 int retry;
183
184 if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) ||
185 S_ISLNK(inode->i_mode)))
186 return;
187 while (1) {
188 retry = trunc_direct(inode);
189 retry |= trunc_indirect(inode, 8, &(inode->u.xiafs_i.i_ind_zone));
190 retry |= trunc_dindirect(inode);
191 if (!retry)
192 break;
193 current->counter = 0;
194 schedule();
195 }
196 inode->i_ctime = inode->i_mtime = CURRENT_TIME;
197 inode->i_dirt = 1;
198 }