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