aboutsummaryrefslogtreecommitdiffstats
path: root/fs/gfs2/dir.c
diff options
context:
space:
mode:
authorSteven Whitehouse <swhiteho@redhat.com>2006-01-30 08:31:50 -0500
committerSteven Whitehouse <swhiteho@redhat.com>2006-01-30 08:31:50 -0500
commite13940ba56157a663944f2a827be96b6b787e260 (patch)
tree0bdc3669ed3cd3498b2dd73ed23003976d588c02 /fs/gfs2/dir.c
parent9b124fbb8ddb3d0b17f5a807414d85cbaf527a56 (diff)
[GFS2] Make dir.c independant of jdata.c
Copy & rename various jdata functions into dir.c. The plan being that directory metadata format will not change although the journalled data format for "normal" files will change. Signed-off-by: Steven Whitehouse <swhiteho@redhat.com>
Diffstat (limited to 'fs/gfs2/dir.c')
-rw-r--r--fs/gfs2/dir.c264
1 files changed, 255 insertions, 9 deletions
diff --git a/fs/gfs2/dir.c b/fs/gfs2/dir.c
index 93d3704ac58c..ada283a0f5f3 100644
--- a/fs/gfs2/dir.c
+++ b/fs/gfs2/dir.c
@@ -65,11 +65,11 @@
65#include "dir.h" 65#include "dir.h"
66#include "glock.h" 66#include "glock.h"
67#include "inode.h" 67#include "inode.h"
68#include "jdata.h"
69#include "meta_io.h" 68#include "meta_io.h"
70#include "quota.h" 69#include "quota.h"
71#include "rgrp.h" 70#include "rgrp.h"
72#include "trans.h" 71#include "trans.h"
72#include "bmap.h"
73 73
74#define IS_LEAF 1 /* Hashed (leaf) directory */ 74#define IS_LEAF 1 /* Hashed (leaf) directory */
75#define IS_DINODE 2 /* Linear (stuffed dinode block) directory */ 75#define IS_DINODE 2 /* Linear (stuffed dinode block) directory */
@@ -86,6 +86,252 @@ typedef int (*leaf_call_t) (struct gfs2_inode *dip,
86 uint32_t index, uint32_t len, uint64_t leaf_no, 86 uint32_t index, uint32_t len, uint64_t leaf_no,
87 void *data); 87 void *data);
88 88
89static int gfs2_dir_get_buffer(struct gfs2_inode *ip, uint64_t block, int new,
90 struct buffer_head **bhp)
91{
92 struct buffer_head *bh;
93 int error = 0;
94
95 if (new) {
96 bh = gfs2_meta_new(ip->i_gl, block);
97 gfs2_trans_add_bh(ip->i_gl, bh, 1);
98 gfs2_metatype_set(bh, GFS2_METATYPE_JD, GFS2_FORMAT_JD);
99 gfs2_buffer_clear_tail(bh, sizeof(struct gfs2_meta_header));
100 } else {
101 error = gfs2_meta_read(ip->i_gl, block, DIO_START | DIO_WAIT, &bh);
102 if (error)
103 return error;
104 if (gfs2_metatype_check(ip->i_sbd, bh, GFS2_METATYPE_JD)) {
105 brelse(bh);
106 return -EIO;
107 }
108 }
109
110 *bhp = bh;
111 return 0;
112}
113
114
115
116static int gfs2_dir_write_stuffed(struct gfs2_inode *ip, const char *buf,
117 unsigned int offset, unsigned int size)
118
119{
120 struct buffer_head *dibh;
121 int error;
122
123 error = gfs2_meta_inode_buffer(ip, &dibh);
124 if (error)
125 return error;
126
127 gfs2_trans_add_bh(ip->i_gl, dibh, 1);
128 memcpy(dibh->b_data + offset + sizeof(struct gfs2_inode), buf, size);
129 if (ip->i_di.di_size < offset + size)
130 ip->i_di.di_size = offset + size;
131 ip->i_di.di_mtime = ip->i_di.di_ctime = get_seconds();
132 gfs2_dinode_out(&ip->i_di, dibh->b_data);
133
134 brelse(dibh);
135
136 return size;
137}
138
139
140
141/**
142 * gfs2_dir_write_data - Write directory information to the inode
143 * @ip: The GFS2 inode
144 * @buf: The buffer containing information to be written
145 * @offset: The file offset to start writing at
146 * @size: The amount of data to write
147 *
148 * Returns: The number of bytes correctly written or error code
149 */
150static int gfs2_dir_write_data(struct gfs2_inode *ip, const char *buf,
151 uint64_t offset, unsigned int size)
152{
153 struct gfs2_sbd *sdp = ip->i_sbd;
154 struct buffer_head *dibh;
155 uint64_t lblock, dblock;
156 uint32_t extlen = 0;
157 unsigned int o;
158 int copied = 0;
159 int error = 0;
160
161 if (!size)
162 return 0;
163
164 if (gfs2_is_stuffed(ip) &&
165 offset + size <= sdp->sd_sb.sb_bsize - sizeof(struct gfs2_dinode))
166 return gfs2_dir_write_stuffed(ip, buf, (unsigned int)offset, size);
167
168 if (gfs2_assert_warn(sdp, gfs2_is_jdata(ip)))
169 return -EINVAL;
170
171 if (gfs2_is_stuffed(ip)) {
172 error = gfs2_unstuff_dinode(ip, NULL, NULL);
173 if (error)
174 return error;
175 }
176
177 lblock = offset;
178 o = do_div(lblock, sdp->sd_jbsize) + sizeof(struct gfs2_meta_header);
179
180 while (copied < size) {
181 unsigned int amount;
182 struct buffer_head *bh;
183 int new;
184
185 amount = size - copied;
186 if (amount > sdp->sd_sb.sb_bsize - o)
187 amount = sdp->sd_sb.sb_bsize - o;
188
189 if (!extlen) {
190 new = 1;
191 error = gfs2_block_map(ip, lblock, &new, &dblock, &extlen);
192 if (error)
193 goto fail;
194 error = -EIO;
195 if (gfs2_assert_withdraw(sdp, dblock))
196 goto fail;
197 }
198
199 error = gfs2_dir_get_buffer(ip, dblock, (amount == sdp->sd_jbsize) ? 1 : new, &bh);
200 if (error)
201 goto fail;
202
203 gfs2_trans_add_bh(ip->i_gl, bh, 1);
204 memcpy(bh->b_data + o, buf, amount);
205 brelse(bh);
206 if (error)
207 goto fail;
208
209 copied += amount;
210 lblock++;
211 dblock++;
212 extlen--;
213
214 o = sizeof(struct gfs2_meta_header);
215 }
216
217out:
218 error = gfs2_meta_inode_buffer(ip, &dibh);
219 if (error)
220 return error;
221
222 if (ip->i_di.di_size < offset + copied)
223 ip->i_di.di_size = offset + copied;
224 ip->i_di.di_mtime = ip->i_di.di_ctime = get_seconds();
225
226 gfs2_trans_add_bh(ip->i_gl, dibh, 1);
227 gfs2_dinode_out(&ip->i_di, dibh->b_data);
228 brelse(dibh);
229
230 return copied;
231fail:
232 if (copied)
233 goto out;
234 return error;
235}
236
237static int gfs2_dir_read_stuffed(struct gfs2_inode *ip, char *buf,
238 unsigned int offset, unsigned int size)
239{
240 struct buffer_head *dibh;
241 int error;
242
243 error = gfs2_meta_inode_buffer(ip, &dibh);
244 if (!error) {
245 offset += sizeof(struct gfs2_dinode);
246 memcpy(buf, dibh->b_data + offset, size);
247 brelse(dibh);
248 }
249
250 return (error) ? error : size;
251}
252
253
254/**
255 * gfs2_dir_read_data - Read a data from a directory inode
256 * @ip: The GFS2 Inode
257 * @buf: The buffer to place result into
258 * @offset: File offset to begin jdata_readng from
259 * @size: Amount of data to transfer
260 *
261 * Returns: The amount of data actually copied or the error
262 */
263static int gfs2_dir_read_data(struct gfs2_inode *ip, char *buf,
264 uint64_t offset, unsigned int size)
265{
266 struct gfs2_sbd *sdp = ip->i_sbd;
267 uint64_t lblock, dblock;
268 uint32_t extlen = 0;
269 unsigned int o;
270 int copied = 0;
271 int error = 0;
272
273 if (offset >= ip->i_di.di_size)
274 return 0;
275
276 if ((offset + size) > ip->i_di.di_size)
277 size = ip->i_di.di_size - offset;
278
279 if (!size)
280 return 0;
281
282 if (gfs2_is_stuffed(ip))
283 return gfs2_dir_read_stuffed(ip, buf, (unsigned int)offset, size);
284
285 if (gfs2_assert_warn(sdp, gfs2_is_jdata(ip)))
286 return -EINVAL;
287
288 lblock = offset;
289 o = do_div(lblock, sdp->sd_jbsize) + sizeof(struct gfs2_meta_header);
290
291 while (copied < size) {
292 unsigned int amount;
293 struct buffer_head *bh;
294 int new;
295
296 amount = size - copied;
297 if (amount > sdp->sd_sb.sb_bsize - o)
298 amount = sdp->sd_sb.sb_bsize - o;
299
300 if (!extlen) {
301 new = 0;
302 error = gfs2_block_map(ip, lblock, &new, &dblock, &extlen);
303 if (error)
304 goto fail;
305 }
306
307 if (extlen > 1)
308 gfs2_meta_ra(ip->i_gl, dblock, extlen);
309
310 if (dblock) {
311 error = gfs2_dir_get_buffer(ip, dblock, new, &bh);
312 if (error)
313 goto fail;
314 dblock++;
315 extlen--;
316 } else
317 bh = NULL;
318
319 memcpy(buf, bh->b_data + o, amount);
320 brelse(bh);
321 if (error)
322 goto fail;
323
324 copied += amount;
325 lblock++;
326
327 o = sizeof(struct gfs2_meta_header);
328 }
329
330 return copied;
331fail:
332 return (copied) ? copied : error;
333}
334
89/** 335/**
90 * int gfs2_filecmp - Compare two filenames 336 * int gfs2_filecmp - Compare two filenames
91 * @file1: The first filename 337 * @file1: The first filename
@@ -428,7 +674,7 @@ static int get_leaf_nr(struct gfs2_inode *dip, uint32_t index,
428 uint64_t leaf_no; 674 uint64_t leaf_no;
429 int error; 675 int error;
430 676
431 error = gfs2_jdata_read_mem(dip, (char *)&leaf_no, 677 error = gfs2_dir_read_data(dip, (char *)&leaf_no,
432 index * sizeof(uint64_t), 678 index * sizeof(uint64_t),
433 sizeof(uint64_t)); 679 sizeof(uint64_t));
434 if (error != sizeof(uint64_t)) 680 if (error != sizeof(uint64_t))
@@ -683,7 +929,7 @@ static int dir_split_leaf(struct gfs2_inode *dip, uint32_t index,
683 929
684 lp = kcalloc(half_len, sizeof(uint64_t), GFP_KERNEL | __GFP_NOFAIL); 930 lp = kcalloc(half_len, sizeof(uint64_t), GFP_KERNEL | __GFP_NOFAIL);
685 931
686 error = gfs2_jdata_read_mem(dip, (char *)lp, start * sizeof(uint64_t), 932 error = gfs2_dir_read_data(dip, (char *)lp, start * sizeof(uint64_t),
687 half_len * sizeof(uint64_t)); 933 half_len * sizeof(uint64_t));
688 if (error != half_len * sizeof(uint64_t)) { 934 if (error != half_len * sizeof(uint64_t)) {
689 if (error >= 0) 935 if (error >= 0)
@@ -696,7 +942,7 @@ static int dir_split_leaf(struct gfs2_inode *dip, uint32_t index,
696 for (x = 0; x < half_len; x++) 942 for (x = 0; x < half_len; x++)
697 lp[x] = cpu_to_be64(bn); 943 lp[x] = cpu_to_be64(bn);
698 944
699 error = gfs2_jdata_write_mem(dip, (char *)lp, start * sizeof(uint64_t), 945 error = gfs2_dir_write_data(dip, (char *)lp, start * sizeof(uint64_t),
700 half_len * sizeof(uint64_t)); 946 half_len * sizeof(uint64_t));
701 if (error != half_len * sizeof(uint64_t)) { 947 if (error != half_len * sizeof(uint64_t)) {
702 if (error >= 0) 948 if (error >= 0)
@@ -816,7 +1062,7 @@ static int dir_double_exhash(struct gfs2_inode *dip)
816 buf = kcalloc(3, sdp->sd_hash_bsize, GFP_KERNEL | __GFP_NOFAIL); 1062 buf = kcalloc(3, sdp->sd_hash_bsize, GFP_KERNEL | __GFP_NOFAIL);
817 1063
818 for (block = dip->i_di.di_size >> sdp->sd_hash_bsize_shift; block--;) { 1064 for (block = dip->i_di.di_size >> sdp->sd_hash_bsize_shift; block--;) {
819 error = gfs2_jdata_read_mem(dip, (char *)buf, 1065 error = gfs2_dir_read_data(dip, (char *)buf,
820 block * sdp->sd_hash_bsize, 1066 block * sdp->sd_hash_bsize,
821 sdp->sd_hash_bsize); 1067 sdp->sd_hash_bsize);
822 if (error != sdp->sd_hash_bsize) { 1068 if (error != sdp->sd_hash_bsize) {
@@ -833,7 +1079,7 @@ static int dir_double_exhash(struct gfs2_inode *dip)
833 *to++ = *from; 1079 *to++ = *from;
834 } 1080 }
835 1081
836 error = gfs2_jdata_write_mem(dip, 1082 error = gfs2_dir_write_data(dip,
837 (char *)buf + sdp->sd_hash_bsize, 1083 (char *)buf + sdp->sd_hash_bsize,
838 block * sdp->sd_sb.sb_bsize, 1084 block * sdp->sd_sb.sb_bsize,
839 sdp->sd_sb.sb_bsize); 1085 sdp->sd_sb.sb_bsize);
@@ -1424,7 +1670,7 @@ static int dir_e_read(struct gfs2_inode *dip, uint64_t *offset, void *opaque,
1424 ht_offset = index - lp_offset; 1670 ht_offset = index - lp_offset;
1425 1671
1426 if (ht_offset_cur != ht_offset) { 1672 if (ht_offset_cur != ht_offset) {
1427 error = gfs2_jdata_read_mem(dip, (char *)lp, 1673 error = gfs2_dir_read_data(dip, (char *)lp,
1428 ht_offset * sizeof(uint64_t), 1674 ht_offset * sizeof(uint64_t),
1429 sdp->sd_hash_bsize); 1675 sdp->sd_hash_bsize);
1430 if (error != sdp->sd_hash_bsize) { 1676 if (error != sdp->sd_hash_bsize) {
@@ -1839,7 +2085,7 @@ static int foreach_leaf(struct gfs2_inode *dip, leaf_call_t lc, void *data)
1839 ht_offset = index - lp_offset; 2085 ht_offset = index - lp_offset;
1840 2086
1841 if (ht_offset_cur != ht_offset) { 2087 if (ht_offset_cur != ht_offset) {
1842 error = gfs2_jdata_read_mem(dip, (char *)lp, 2088 error = gfs2_dir_read_data(dip, (char *)lp,
1843 ht_offset * sizeof(uint64_t), 2089 ht_offset * sizeof(uint64_t),
1844 sdp->sd_hash_bsize); 2090 sdp->sd_hash_bsize);
1845 if (error != sdp->sd_hash_bsize) { 2091 if (error != sdp->sd_hash_bsize) {
@@ -1965,7 +2211,7 @@ static int leaf_dealloc(struct gfs2_inode *dip, uint32_t index, uint32_t len,
1965 dip->i_di.di_blocks--; 2211 dip->i_di.di_blocks--;
1966 } 2212 }
1967 2213
1968 error = gfs2_jdata_write_mem(dip, ht, index * sizeof(uint64_t), size); 2214 error = gfs2_dir_write_data(dip, ht, index * sizeof(uint64_t), size);
1969 if (error != size) { 2215 if (error != size) {
1970 if (error >= 0) 2216 if (error >= 0)
1971 error = -EIO; 2217 error = -EIO;