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