Line data Source code
1 : #include "clusterautoconfig.h"
2 :
3 : #include <stdio.h>
4 : #include <stdlib.h>
5 : #include <string.h>
6 : #include <stdint.h>
7 : #include <inttypes.h>
8 : #include <sys/types.h>
9 : #include <sys/stat.h>
10 : #include <fcntl.h>
11 : #include <unistd.h>
12 : #include <errno.h>
13 :
14 : #include "libgfs2.h"
15 : #include "rgrp.h"
16 :
17 23387564 : static __inline__ __be64 *metapointer(char *buf,
18 : unsigned int height,
19 : struct lgfs2_metapath *mp)
20 : {
21 23387564 : unsigned int head_size = (height > 0) ?
22 : sizeof(struct gfs2_meta_header) : sizeof(struct gfs2_dinode);
23 :
24 23387564 : return ((__be64 *)(buf + head_size)) + mp->mp_list[height];
25 : }
26 :
27 : /* Detect directory is a stuffed inode */
28 6420966 : static int inode_is_stuffed(const struct lgfs2_inode *ip)
29 : {
30 6420966 : return !ip->i_height;
31 : }
32 :
33 15191 : struct lgfs2_inode *lgfs2_inode_get(struct lgfs2_sbd *sdp, struct lgfs2_buffer_head *bh)
34 : {
35 : struct lgfs2_inode *ip;
36 :
37 15191 : ip = calloc(1, sizeof(struct lgfs2_inode));
38 15191 : if (ip == NULL) {
39 0 : return NULL;
40 : }
41 15191 : lgfs2_dinode_in(ip, bh->b_data);
42 15191 : ip->i_bh = bh;
43 15191 : ip->i_sbd = sdp;
44 15191 : return ip;
45 : }
46 :
47 14131 : struct lgfs2_inode *lgfs2_inode_read(struct lgfs2_sbd *sdp, uint64_t di_addr)
48 : {
49 : struct lgfs2_inode *ip;
50 14131 : struct lgfs2_buffer_head *bh = lgfs2_bread(sdp, di_addr);
51 14131 : if (bh == NULL) {
52 0 : return NULL;
53 : }
54 14131 : ip = lgfs2_inode_get(sdp, bh);
55 14131 : if (ip == NULL) {
56 0 : lgfs2_brelse(bh);
57 0 : return NULL;
58 : }
59 14131 : ip->bh_owned = 1; /* We did the lgfs2_bread so we own the bh */
60 14131 : return ip;
61 : }
62 :
63 2304 : struct lgfs2_inode *lgfs2_is_system_inode(struct lgfs2_sbd *sdp, uint64_t block)
64 : {
65 : int j;
66 :
67 2304 : if (sdp->md.inum && block == sdp->md.inum->i_num.in_addr)
68 112 : return sdp->md.inum;
69 2192 : if (sdp->md.statfs && block == sdp->md.statfs->i_num.in_addr)
70 112 : return sdp->md.statfs;
71 2080 : if (sdp->md.jiinode && block == sdp->md.jiinode->i_num.in_addr)
72 168 : return sdp->md.jiinode;
73 1912 : if (sdp->md.riinode && block == sdp->md.riinode->i_num.in_addr)
74 112 : return sdp->md.riinode;
75 1800 : if (sdp->md.qinode && block == sdp->md.qinode->i_num.in_addr)
76 112 : return sdp->md.qinode;
77 1688 : if (sdp->md.pinode && block == sdp->md.pinode->i_num.in_addr)
78 168 : return sdp->md.pinode;
79 1520 : if (sdp->md.rooti && block == sdp->md.rooti->i_num.in_addr)
80 168 : return sdp->md.rooti;
81 1352 : if (sdp->master_dir && block == sdp->master_dir->i_num.in_addr)
82 280 : return sdp->master_dir;
83 2435 : for (j = 0; j < sdp->md.journals; j++)
84 1488 : if (sdp->md.journal && sdp->md.journal[j] &&
85 1484 : block == sdp->md.journal[j]->i_num.in_addr)
86 125 : return sdp->md.journal[j];
87 947 : return NULL;
88 : }
89 :
90 6226 : void lgfs2_inode_put(struct lgfs2_inode **ip_in)
91 : {
92 6226 : struct lgfs2_inode *ip = *ip_in;
93 6226 : uint64_t block = ip->i_num.in_addr;
94 6226 : struct lgfs2_sbd *sdp = ip->i_sbd;
95 :
96 6226 : if (ip->i_bh != NULL) {
97 6226 : if (ip->i_bh->b_modified) {
98 794 : lgfs2_dinode_out(ip, ip->i_bh->b_data);
99 794 : if (!ip->bh_owned && lgfs2_is_system_inode(sdp, block))
100 0 : fprintf(stderr, "Warning: Changes made to inode were discarded.\n");
101 : }
102 6226 : if (ip->bh_owned)
103 6030 : lgfs2_brelse(ip->i_bh);
104 6226 : ip->i_bh = NULL;
105 : }
106 6226 : free(ip);
107 6226 : *ip_in = NULL; /* make sure the memory isn't accessed again */
108 6226 : }
109 :
110 : /**
111 : * Free an inode, discarding modifications.
112 : * @ipp: A pointer to the inode.
113 : */
114 0 : void lgfs2_inode_free(struct lgfs2_inode **ipp)
115 : {
116 0 : struct lgfs2_inode *ip = *ipp;
117 :
118 0 : free(ip->i_bh);
119 0 : free(ip);
120 0 : *ipp = NULL;
121 0 : }
122 :
123 70774 : static uint64_t find_free_block(struct lgfs2_rgrp_tree *rgd)
124 : {
125 : unsigned bm;
126 70774 : uint64_t blkno = 0;
127 :
128 70774 : if (rgd == NULL || rgd->rt_free == 0) {
129 0 : errno = ENOSPC;
130 0 : return 0;
131 : }
132 :
133 116687 : for (bm = 0; bm < rgd->rt_length; bm++) {
134 116687 : unsigned long blk = 0;
135 116687 : struct lgfs2_bitmap *bits = &rgd->rt_bits[bm];
136 :
137 116687 : blk = lgfs2_bitfit((uint8_t *)bits->bi_data + bits->bi_offset,
138 : bits->bi_len, blk, GFS2_BLKST_FREE);
139 116687 : if (blk != LGFS2_BFITNOENT) {
140 70774 : blkno = blk + (bits->bi_start * GFS2_NBBY) + rgd->rt_data0;
141 70774 : break;
142 : }
143 : }
144 70774 : return blkno;
145 : }
146 :
147 70774 : static int blk_alloc_in_rg(struct lgfs2_sbd *sdp, unsigned state, struct lgfs2_rgrp_tree *rgd, uint64_t blkno, int dinode)
148 : {
149 70774 : if (blkno == 0)
150 0 : return -1;
151 :
152 70774 : if (lgfs2_set_bitmap(rgd, blkno, state))
153 0 : return -1;
154 :
155 70774 : if (state == GFS2_BLKST_DINODE) {
156 793 : if (dinode)
157 793 : rgd->rt_dinodes++;
158 : }
159 :
160 70774 : rgd->rt_free--;
161 70774 : lgfs2_rgrp_out(rgd, rgd->rt_bits[0].bi_data);
162 70774 : rgd->rt_bits[0].bi_modified = 1;
163 70774 : sdp->blks_alloced++;
164 70774 : return 0;
165 : }
166 :
167 : /**
168 : * Allocate a block in a bitmap. In order to plan ahead we look for a
169 : * resource group with blksreq free blocks but only allocate the one block.
170 : * Returns 0 on success with the allocated block number in *blkno or non-zero otherwise.
171 : */
172 70775 : static int block_alloc(struct lgfs2_sbd *sdp, const uint64_t blksreq, int state, uint64_t *blkno, int dinode)
173 : {
174 : int ret;
175 70775 : int release = 0;
176 70775 : struct lgfs2_rgrp_tree *rgt = NULL;
177 70775 : struct osi_node *n = NULL;
178 70775 : uint64_t bn = 0;
179 :
180 168652 : for (n = osi_first(&sdp->rgtree); n; n = osi_next(n)) {
181 168651 : rgt = (struct lgfs2_rgrp_tree *)n;
182 168651 : if (rgt->rt_free >= blksreq)
183 70774 : break;
184 : }
185 70775 : if (n == NULL)
186 1 : return -1;
187 :
188 70774 : if (rgt->rt_bits[0].bi_data == NULL) {
189 37938 : if (lgfs2_rgrp_read(sdp, rgt))
190 0 : return -1;
191 37938 : release = 1;
192 : }
193 :
194 70774 : bn = find_free_block(rgt);
195 70774 : ret = blk_alloc_in_rg(sdp, state, rgt, bn, dinode);
196 70774 : if (release)
197 37938 : lgfs2_rgrp_relse(sdp, rgt);
198 70774 : *blkno = bn;
199 70774 : return ret;
200 : }
201 :
202 794 : int lgfs2_dinode_alloc(struct lgfs2_sbd *sdp, const uint64_t blksreq, uint64_t *blkno)
203 : {
204 794 : int ret = block_alloc(sdp, blksreq, GFS2_BLKST_DINODE, blkno, 1);
205 794 : if (ret == 0)
206 793 : sdp->dinodes_alloced++;
207 794 : return ret;
208 : }
209 :
210 69981 : int lgfs2_meta_alloc(struct lgfs2_inode *ip, uint64_t *blkno)
211 : {
212 69981 : int ret = block_alloc(ip->i_sbd, 1, GFS2_BLKST_USED, blkno, 0);
213 69981 : if (ret == 0) {
214 69981 : ip->i_goal_meta = *blkno;
215 69981 : lgfs2_bmodified(ip->i_bh);
216 : }
217 69981 : return ret;
218 : }
219 :
220 160 : static __inline__ void buffer_clear_tail(struct lgfs2_sbd *sdp,
221 : struct lgfs2_buffer_head *bh, int head)
222 : {
223 160 : memset(bh->b_data + head, 0, sdp->sd_bsize - head);
224 160 : lgfs2_bmodified(bh);
225 160 : }
226 :
227 : static __inline__ void
228 67 : buffer_copy_tail(struct lgfs2_sbd *sdp,
229 : struct lgfs2_buffer_head *to_bh, int to_head,
230 : struct lgfs2_buffer_head *from_bh, int from_head)
231 : {
232 67 : memcpy(to_bh->b_data + to_head, from_bh->b_data + from_head,
233 67 : sdp->sd_bsize - from_head);
234 67 : memset(to_bh->b_data + sdp->sd_bsize + to_head - from_head, 0,
235 67 : from_head - to_head);
236 67 : lgfs2_bmodified(to_bh);
237 67 : }
238 :
239 60 : int lgfs2_unstuff_dinode(struct lgfs2_inode *ip)
240 : {
241 60 : struct lgfs2_sbd *sdp = ip->i_sbd;
242 : struct lgfs2_buffer_head *bh;
243 60 : uint64_t block = 0;
244 60 : int isdir = S_ISDIR(ip->i_mode);
245 :
246 60 : if (ip->i_size) {
247 60 : if (lgfs2_meta_alloc(ip, &block))
248 0 : return -1;
249 60 : if (isdir) {
250 0 : struct gfs2_meta_header mh = {
251 0 : .mh_magic = cpu_to_be32(GFS2_MAGIC),
252 0 : .mh_type = cpu_to_be32(GFS2_METATYPE_JD),
253 0 : .mh_format = cpu_to_be32(GFS2_FORMAT_JD)
254 : };
255 :
256 0 : bh = lgfs2_bget(sdp, block);
257 0 : memcpy(bh->b_data, &mh, sizeof(mh));
258 0 : buffer_copy_tail(sdp, bh,
259 : sizeof(struct gfs2_meta_header),
260 : ip->i_bh, sizeof(struct gfs2_dinode));
261 :
262 0 : lgfs2_bmodified(bh);
263 0 : lgfs2_brelse(bh);
264 : } else {
265 60 : bh = lgfs2_bget(sdp, block);
266 :
267 60 : buffer_copy_tail(sdp, bh, 0,
268 : ip->i_bh, sizeof(struct gfs2_dinode));
269 60 : lgfs2_brelse(bh);
270 : }
271 : }
272 :
273 60 : buffer_clear_tail(sdp, ip->i_bh, sizeof(struct gfs2_dinode));
274 :
275 60 : if (ip->i_size) {
276 60 : *(__be64 *)(ip->i_bh->b_data + sizeof(struct gfs2_dinode)) = cpu_to_be64(block);
277 : /* no need: lgfs2_bmodified(ip->i_bh); buffer_clear_tail does it */
278 60 : ip->i_blocks++;
279 : }
280 :
281 60 : ip->i_height = 1;
282 60 : return 0;
283 : }
284 :
285 : /**
286 : * Calculate the total number of blocks required by a file containing 'bytes' bytes of data.
287 : */
288 147 : uint64_t lgfs2_space_for_data(const struct lgfs2_sbd *sdp, const unsigned bsize, const uint64_t bytes)
289 : {
290 147 : uint64_t blks = (bytes + bsize - 1) / bsize;
291 147 : uint64_t ptrs = blks;
292 :
293 147 : if (bytes <= bsize - sizeof(struct gfs2_dinode))
294 0 : return 1;
295 :
296 313 : while (ptrs > sdp->sd_diptrs) {
297 166 : ptrs = (ptrs + sdp->sd_inptrs - 1) / sdp->sd_inptrs;
298 166 : blks += ptrs;
299 : }
300 147 : return blks + 1;
301 : }
302 :
303 : /**
304 : * Allocate an extent for a file in a resource group's bitmaps.
305 : * rg: The resource group in which to allocate the extent
306 : * di_size: The size of the file in bytes
307 : * ip: A pointer to the inode structure, whose fields will be set appropriately.
308 : * If ip->i_num.no_addr is not 0, the extent search will be skipped and
309 : * the file allocated from that address.
310 : * flags: GFS2_DIF_* flags
311 : * mode: File mode flags, see creat(2)
312 : * Returns 0 on success with the contents of ip set accordingly, or non-zero
313 : * with errno set on error. If errno is ENOSPC then rg does not contain a
314 : * large enough free extent for the given di_size.
315 : */
316 77 : int lgfs2_file_alloc(lgfs2_rgrp_t rg, uint64_t di_size, struct lgfs2_inode *ip, uint32_t flags, unsigned mode)
317 : {
318 : unsigned extlen;
319 77 : struct lgfs2_sbd *sdp = rg->rt_rgrps->rgs_sdp;
320 77 : struct lgfs2_rbm rbm = { .rgd = rg, .offset = 0, .bii = 0 };
321 77 : uint32_t blocks = lgfs2_space_for_data(sdp, sdp->sd_bsize, di_size);
322 :
323 77 : if (ip->i_num.in_addr != 0) {
324 77 : if (lgfs2_rbm_from_block(&rbm, ip->i_num.in_addr) != 0)
325 0 : return 1;
326 0 : } else if (lgfs2_rbm_find(&rbm, GFS2_BLKST_FREE, &blocks) != 0) {
327 0 : return 1;
328 : }
329 :
330 77 : extlen = lgfs2_alloc_extent(&rbm, GFS2_BLKST_DINODE, blocks);
331 77 : if (extlen < blocks) {
332 0 : errno = EINVAL;
333 0 : return 1;
334 : }
335 :
336 77 : ip->i_sbd = sdp;
337 :
338 77 : ip->i_magic = GFS2_MAGIC;
339 77 : ip->i_mh_type = GFS2_METATYPE_DI;
340 77 : ip->i_format = GFS2_FORMAT_DI;
341 77 : ip->i_size = di_size;
342 77 : ip->i_num.in_addr = lgfs2_rbm_to_block(&rbm);
343 77 : ip->i_num.in_formal_ino = sdp->md.next_inum++;
344 77 : ip->i_mode = mode;
345 77 : ip->i_nlink = 1;
346 77 : ip->i_blocks = blocks;
347 77 : ip->i_atime = ip->i_mtime = ip->i_ctime = sdp->sd_time;
348 77 : ip->i_goal_data = ip->i_num.in_addr + ip->i_blocks - 1;
349 77 : ip->i_goal_meta = ip->i_goal_data - ((di_size + sdp->sd_bsize - 1) / sdp->sd_bsize);
350 77 : ip->i_height = lgfs2_calc_tree_height(ip, di_size);
351 77 : ip->i_flags = flags;
352 :
353 77 : rg->rt_free -= blocks;
354 77 : rg->rt_dinodes += 1;
355 :
356 77 : sdp->dinodes_alloced++;
357 77 : sdp->blks_alloced += blocks;
358 :
359 77 : return 0;
360 : }
361 :
362 4262163 : unsigned int lgfs2_calc_tree_height(struct lgfs2_inode *ip, uint64_t size)
363 : {
364 4262163 : struct lgfs2_sbd *sdp = ip->i_sbd;
365 : uint64_t *arr;
366 : unsigned int max, height;
367 :
368 4262163 : if (ip->i_size > size)
369 3999399 : size = ip->i_size;
370 :
371 4262163 : if (S_ISDIR(ip->i_mode)) {
372 0 : arr = sdp->sd_jheightsize;
373 0 : max = sdp->sd_max_jheight;
374 : } else {
375 4262163 : arr = sdp->sd_heightsize;
376 4262163 : max = sdp->sd_max_height;
377 : }
378 :
379 11125405 : for (height = 0; height < max; height++)
380 11125405 : if (arr[height] >= size)
381 4262163 : break;
382 :
383 4262163 : return height;
384 : }
385 :
386 78 : int lgfs2_build_height(struct lgfs2_inode *ip, int height)
387 : {
388 78 : struct lgfs2_sbd *sdp = ip->i_sbd;
389 : struct lgfs2_buffer_head *bh;
390 78 : uint64_t block = 0, *bp;
391 : unsigned int x;
392 : int new_block;
393 :
394 169 : while (ip->i_height < height) {
395 91 : new_block = 0;
396 91 : bp = (uint64_t *)(ip->i_bh->b_data + sizeof(struct gfs2_dinode));
397 34060 : for (x = 0; x < sdp->sd_diptrs; x++, bp++)
398 33969 : if (*bp) {
399 0 : new_block = 1;
400 0 : break;
401 : }
402 :
403 91 : if (new_block) {
404 0 : struct gfs2_meta_header mh = {
405 0 : .mh_magic = cpu_to_be32(GFS2_MAGIC),
406 0 : .mh_type = cpu_to_be32(GFS2_METATYPE_IN),
407 0 : .mh_format = cpu_to_be32(GFS2_FORMAT_IN)
408 : };
409 :
410 0 : if (lgfs2_meta_alloc(ip, &block))
411 0 : return -1;
412 0 : bh = lgfs2_bget(sdp, block);
413 0 : memcpy(bh->b_data, &mh, sizeof(mh));
414 0 : buffer_copy_tail(sdp, bh,
415 : sizeof(struct gfs2_meta_header),
416 : ip->i_bh, sizeof(struct gfs2_dinode));
417 0 : lgfs2_bmodified(bh);
418 0 : lgfs2_brelse(bh);
419 : }
420 :
421 91 : buffer_clear_tail(sdp, ip->i_bh, sizeof(struct gfs2_dinode));
422 :
423 91 : if (new_block) {
424 0 : *(__be64 *)(ip->i_bh->b_data + sizeof(struct gfs2_dinode)) = cpu_to_be64(block);
425 : /* no need: lgfs2_bmodified(ip->i_bh);*/
426 0 : ip->i_blocks++;
427 : }
428 :
429 91 : ip->i_height++;
430 : }
431 78 : return 0;
432 : }
433 :
434 4262085 : void lgfs2_find_metapath(struct lgfs2_inode *ip, uint64_t block, struct lgfs2_metapath *mp)
435 : {
436 4262085 : const uint32_t inptrs = ip->i_sbd->sd_inptrs;
437 4262085 : unsigned int i = ip->i_height;
438 :
439 4262085 : memset(mp, 0, sizeof(struct lgfs2_metapath));
440 11127006 : while (i--) {
441 6864921 : mp->mp_list[i] = block % inptrs;
442 6864921 : block /= inptrs;
443 : }
444 4262085 : }
445 :
446 23387564 : void lgfs2_lookup_block(struct lgfs2_inode *ip, struct lgfs2_buffer_head *bh,
447 : unsigned int height, struct lgfs2_metapath *mp,
448 : int create, int *new, uint64_t *block)
449 : {
450 23387564 : __be64 *ptr = metapointer(bh->b_data, height, mp);
451 :
452 23387564 : if (*ptr) {
453 21183353 : *block = be64_to_cpu(*ptr);
454 21183353 : return;
455 : }
456 :
457 2204211 : *block = 0;
458 :
459 2204211 : if (!create)
460 2134300 : return;
461 :
462 69911 : if (lgfs2_meta_alloc(ip, block))
463 0 : return;
464 69911 : *ptr = cpu_to_be64(*block);
465 69911 : lgfs2_bmodified(bh);
466 69911 : ip->i_blocks++;
467 69911 : lgfs2_bmodified(ip->i_bh);
468 :
469 69911 : *new = 1;
470 : }
471 :
472 4268085 : int lgfs2_block_map(struct lgfs2_inode *ip, uint64_t lblock, int *new,
473 : uint64_t *dblock, uint32_t *extlen, int prealloc)
474 : {
475 4268085 : struct lgfs2_sbd *sdp = ip->i_sbd;
476 : struct lgfs2_buffer_head *bh;
477 : struct lgfs2_metapath mp;
478 4268085 : int create = *new;
479 : unsigned int bsize;
480 : unsigned int height;
481 : unsigned int end_of_metadata;
482 : unsigned int x;
483 :
484 4268085 : *new = 0;
485 4268085 : *dblock = 0;
486 4268085 : if (extlen)
487 2140545 : *extlen = 0;
488 :
489 4268085 : if (inode_is_stuffed(ip)) {
490 6077 : if (!lblock) {
491 6077 : *dblock = ip->i_num.in_addr;
492 6077 : if (extlen)
493 6077 : *extlen = 1;
494 : }
495 6077 : return 0;
496 : }
497 :
498 4262008 : bsize = (S_ISDIR(ip->i_mode)) ? sdp->sd_jbsize : sdp->sd_bsize;
499 :
500 4262008 : height = lgfs2_calc_tree_height(ip, (lblock + 1) * bsize);
501 4262008 : if (ip->i_height < height) {
502 0 : if (!create)
503 0 : return 0;
504 :
505 0 : if (lgfs2_build_height(ip, height))
506 0 : return -1;
507 : }
508 :
509 4262008 : lgfs2_find_metapath(ip, lblock, &mp);
510 4262008 : end_of_metadata = ip->i_height - 1;
511 :
512 4262008 : bh = ip->i_bh;
513 :
514 6864756 : for (x = 0; x < end_of_metadata; x++) {
515 2602748 : lgfs2_lookup_block(ip, bh, x, &mp, create, new, dblock);
516 2602748 : if (bh != ip->i_bh)
517 491848 : lgfs2_brelse(bh);
518 2602748 : if (!*dblock)
519 0 : return 0;
520 :
521 2602748 : if (*new) {
522 1468 : struct gfs2_meta_header mh = {
523 367 : .mh_magic = cpu_to_be32(GFS2_MAGIC),
524 367 : .mh_type = cpu_to_be32(GFS2_METATYPE_IN),
525 367 : .mh_format = cpu_to_be32(GFS2_FORMAT_IN)
526 : };
527 367 : bh = lgfs2_bget(sdp, *dblock);
528 367 : memcpy(bh->b_data, &mh, sizeof(mh));
529 367 : lgfs2_bmodified(bh);
530 : } else {
531 2602381 : if (*dblock == ip->i_num.in_addr)
532 0 : bh = ip->i_bh;
533 : else
534 2602381 : bh = lgfs2_bread(sdp, *dblock);
535 : }
536 : }
537 :
538 4262008 : if (!prealloc)
539 4229240 : lgfs2_lookup_block(ip, bh, end_of_metadata, &mp, create, new, dblock);
540 :
541 4262008 : if (extlen && *dblock) {
542 2134468 : *extlen = 1;
543 :
544 2134468 : if (!*new) {
545 : uint64_t tmp_dblock;
546 : int tmp_new;
547 : unsigned int nptrs;
548 :
549 2134300 : nptrs = (end_of_metadata) ? sdp->sd_inptrs : sdp->sd_diptrs;
550 :
551 16555576 : while (++mp.mp_list[end_of_metadata] < nptrs) {
552 16555576 : lgfs2_lookup_block(ip, bh, end_of_metadata, &mp, 0, &tmp_new,
553 : &tmp_dblock);
554 :
555 16555576 : if (*dblock + *extlen != tmp_dblock)
556 2134300 : break;
557 :
558 14421276 : (*extlen)++;
559 : }
560 : }
561 : }
562 :
563 4262008 : if (bh != ip->i_bh)
564 2110900 : lgfs2_brelse(bh);
565 4262008 : return 0;
566 : }
567 :
568 : static void
569 2167105 : copy2mem(struct lgfs2_buffer_head *bh, void **buf, unsigned int offset,
570 : unsigned int size)
571 : {
572 2167105 : char **p = (char **)buf;
573 :
574 2167105 : if (bh)
575 2167105 : memcpy(*p, bh->b_data + offset, size);
576 : else
577 0 : memset(*p, 0, size);
578 :
579 2167105 : *p += size;
580 2167105 : }
581 :
582 2138179 : int lgfs2_readi(struct lgfs2_inode *ip, void *buf, uint64_t offset, unsigned int size)
583 : {
584 2138179 : struct lgfs2_sbd *sdp = ip->i_sbd;
585 : struct lgfs2_buffer_head *bh;
586 : uint64_t lblock, dblock;
587 : unsigned int o;
588 2138179 : uint32_t extlen = 0;
589 : unsigned int amount;
590 2138179 : int not_new = 0;
591 2138179 : int isdir = !!(S_ISDIR(ip->i_mode));
592 2138179 : int copied = 0;
593 :
594 2138179 : if (offset >= ip->i_size)
595 4550 : return 0;
596 :
597 2133629 : if ((offset + size) > ip->i_size)
598 0 : size = ip->i_size - offset;
599 :
600 2133629 : if (!size)
601 0 : return 0;
602 :
603 2133629 : if (isdir) {
604 122 : lblock = offset;
605 122 : o = lblock % sdp->sd_jbsize;
606 122 : lblock /= sdp->sd_jbsize;
607 : } else {
608 2133507 : lblock = offset >> sdp->sd_bsize_shift;
609 2133507 : o = offset & (sdp->sd_bsize - 1);
610 : }
611 :
612 2133629 : if (inode_is_stuffed(ip))
613 3556 : o += sizeof(struct gfs2_dinode);
614 2130073 : else if (isdir)
615 0 : o += sizeof(struct gfs2_meta_header);
616 :
617 4300734 : while (copied < size) {
618 2167105 : amount = size - copied;
619 2167105 : if (amount > sdp->sd_bsize - o)
620 33476 : amount = sdp->sd_bsize - o;
621 :
622 2167105 : if (!extlen) {
623 2133629 : if (lgfs2_block_map(ip, lblock, ¬_new, &dblock, &extlen, 0))
624 0 : return -1;
625 : }
626 :
627 2167105 : if (dblock) {
628 2167105 : if (dblock == ip->i_num.in_addr)
629 3556 : bh = ip->i_bh;
630 : else
631 2163549 : bh = lgfs2_bread(sdp, dblock);
632 2167105 : dblock++;
633 2167105 : extlen--;
634 : } else
635 0 : bh = NULL;
636 :
637 2167105 : copy2mem(bh, &buf, o, amount);
638 2167105 : if (bh && bh != ip->i_bh)
639 2163549 : lgfs2_brelse(bh);
640 :
641 2167105 : copied += amount;
642 2167105 : lblock++;
643 2167105 : o = (isdir) ? sizeof(struct gfs2_meta_header) : 0;
644 : }
645 :
646 2133629 : return copied;
647 : }
648 :
649 6916 : static void copy_from_mem(struct lgfs2_buffer_head *bh, void **buf,
650 : unsigned int offset, unsigned int size)
651 : {
652 6916 : char **p = (char **)buf;
653 :
654 6916 : memcpy(bh->b_data + offset, *p, size);
655 6916 : lgfs2_bmodified(bh);
656 6916 : *p += size;
657 6916 : }
658 :
659 6785 : int __lgfs2_writei(struct lgfs2_inode *ip, void *buf,
660 : uint64_t offset, unsigned int size, int resize)
661 : {
662 6785 : struct lgfs2_sbd *sdp = ip->i_sbd;
663 : struct lgfs2_buffer_head *bh;
664 : uint64_t lblock, dblock;
665 : unsigned int o;
666 6785 : uint32_t extlen = 0;
667 : unsigned int amount;
668 : int new;
669 6785 : int isdir = !!(S_ISDIR(ip->i_mode));
670 6785 : const uint64_t start = offset;
671 6785 : int copied = 0;
672 :
673 6785 : if (!size)
674 0 : return 0;
675 :
676 6785 : if (inode_is_stuffed(ip) &&
677 2581 : ((start + size) > (sdp->sd_bsize - sizeof(struct gfs2_dinode))))
678 60 : if (lgfs2_unstuff_dinode(ip))
679 0 : return -1;
680 :
681 6785 : if (isdir) {
682 2 : lblock = offset;
683 2 : o = lblock % sdp->sd_jbsize;
684 2 : lblock /= sdp->sd_jbsize;
685 : } else {
686 6783 : lblock = offset >> sdp->sd_bsize_shift;
687 6783 : o = offset & (sdp->sd_bsize - 1);
688 : }
689 :
690 6785 : if (inode_is_stuffed(ip))
691 2521 : o += sizeof(struct gfs2_dinode);
692 4264 : else if (isdir)
693 0 : o += sizeof(struct gfs2_meta_header);
694 :
695 13701 : while (copied < size) {
696 6916 : amount = size - copied;
697 6916 : if (amount > sdp->sd_bsize - o)
698 131 : amount = sdp->sd_bsize - o;
699 :
700 6916 : if (!extlen) {
701 6916 : new = 1;
702 6916 : if (lgfs2_block_map(ip, lblock, &new, &dblock, &extlen, 0))
703 0 : return -1;
704 : }
705 :
706 6916 : if (new) {
707 168 : bh = lgfs2_bget(sdp, dblock);
708 168 : if (isdir) {
709 0 : struct gfs2_meta_header mh = {
710 0 : .mh_magic = cpu_to_be32(GFS2_MAGIC),
711 0 : .mh_type = cpu_to_be32(GFS2_METATYPE_JD),
712 0 : .mh_format = cpu_to_be32(GFS2_FORMAT_JD),
713 : };
714 0 : memcpy(bh->b_data, &mh, sizeof(mh));
715 0 : lgfs2_bmodified(bh);
716 : }
717 : } else {
718 6748 : if (dblock == ip->i_num.in_addr)
719 2521 : bh = ip->i_bh;
720 : else
721 4227 : bh = lgfs2_bread(sdp, dblock);
722 : }
723 6916 : copy_from_mem(bh, &buf, o, amount);
724 6916 : if (bh != ip->i_bh)
725 4395 : lgfs2_brelse(bh);
726 :
727 6916 : copied += amount;
728 6916 : lblock++;
729 6916 : dblock++;
730 6916 : extlen--;
731 :
732 6916 : o = (isdir) ? sizeof(struct gfs2_meta_header) : 0;
733 : }
734 :
735 6785 : if (resize && ip->i_size < start + copied) {
736 6709 : lgfs2_bmodified(ip->i_bh);
737 6709 : ip->i_size = start + copied;
738 : }
739 :
740 6785 : return copied;
741 : }
742 :
743 6503 : int lgfs2_dirent_first(struct lgfs2_inode *dip, struct lgfs2_buffer_head *bh,
744 : struct gfs2_dirent **dent)
745 : {
746 6503 : struct gfs2_meta_header *h = (struct gfs2_meta_header *)bh->b_data;
747 :
748 6503 : if (be32_to_cpu(h->mh_type) == GFS2_METATYPE_LF) {
749 110 : *dent = (struct gfs2_dirent *)(bh->b_data + sizeof(struct gfs2_leaf));
750 110 : return LGFS2_IS_LEAF;
751 : } else {
752 6393 : *dent = (struct gfs2_dirent *)(bh->b_data + sizeof(struct gfs2_dinode));
753 6393 : return LGFS2_IS_DINODE;
754 : }
755 : }
756 :
757 34091 : int lgfs2_dirent_next(struct lgfs2_inode *dip, struct lgfs2_buffer_head *bh,
758 : struct gfs2_dirent **dent)
759 : {
760 : char *bh_end;
761 : uint16_t cur_rec_len;
762 :
763 34091 : bh_end = bh->b_data + dip->i_sbd->sd_bsize;
764 34091 : cur_rec_len = be16_to_cpu((*dent)->de_rec_len);
765 :
766 34091 : if (cur_rec_len == 0 || (char *)(*dent) + cur_rec_len >= bh_end)
767 669 : return -ENOENT;
768 :
769 33422 : *dent = (struct gfs2_dirent *)((char *)(*dent) + cur_rec_len);
770 :
771 33422 : return 0;
772 : }
773 :
774 : /**
775 : * Allocate a gfs2 dirent
776 : * Returns 0 on success, with *dent_out pointing to the new dirent,
777 : * or -1 on failure, with errno set
778 : */
779 746 : static int dirent_alloc(struct lgfs2_inode *dip, struct lgfs2_buffer_head *bh,
780 : int name_len, struct gfs2_dirent **dent_out)
781 : {
782 : struct gfs2_dirent *dent, *new;
783 746 : unsigned int rec_len = GFS2_DIRENT_SIZE(name_len);
784 746 : unsigned int entries = 0, offset = 0;
785 : int type;
786 :
787 746 : type = lgfs2_dirent_first(dip, bh, &dent);
788 :
789 746 : if (type == LGFS2_IS_LEAF) {
790 35 : struct gfs2_leaf *leaf = (struct gfs2_leaf *)bh->b_data;
791 35 : entries = be16_to_cpu(leaf->lf_entries);
792 35 : offset = sizeof(struct gfs2_leaf);
793 : } else {
794 711 : struct gfs2_dinode *dinode = (struct gfs2_dinode *)bh->b_data;
795 711 : entries = be32_to_cpu(dinode->di_entries);
796 711 : offset = sizeof(struct gfs2_dinode);
797 : }
798 :
799 746 : if (!entries) {
800 2 : dent->de_rec_len = cpu_to_be16(dip->i_sbd->sd_bsize - offset);
801 2 : dent->de_name_len = cpu_to_be16(name_len);
802 2 : lgfs2_bmodified(bh);
803 2 : *dent_out = dent;
804 2 : dip->i_entries++;
805 2 : lgfs2_bmodified(dip->i_bh);
806 2 : return 0;
807 : }
808 :
809 : do {
810 : uint16_t cur_rec_len;
811 : uint16_t cur_name_len;
812 : uint16_t new_rec_len;
813 :
814 2889 : cur_rec_len = be16_to_cpu(dent->de_rec_len);
815 2889 : cur_name_len = be16_to_cpu(dent->de_name_len);
816 :
817 2889 : if ((!dent->de_inum.no_formal_ino && cur_rec_len >= rec_len) ||
818 2888 : (cur_rec_len >= GFS2_DIRENT_SIZE(cur_name_len) + rec_len)) {
819 :
820 735 : if (dent->de_inum.no_formal_ino) {
821 734 : new = (struct gfs2_dirent *)((char *)dent +
822 734 : GFS2_DIRENT_SIZE(cur_name_len));
823 734 : memset(new, 0, sizeof(struct gfs2_dirent));
824 :
825 734 : new->de_rec_len = cpu_to_be16(cur_rec_len -
826 : GFS2_DIRENT_SIZE(cur_name_len));
827 734 : new->de_name_len = cpu_to_be16(name_len);
828 :
829 734 : new_rec_len = be16_to_cpu(new->de_rec_len);
830 734 : dent->de_rec_len = cpu_to_be16(cur_rec_len - new_rec_len);
831 :
832 734 : *dent_out = new;
833 734 : lgfs2_bmodified(bh);
834 734 : dip->i_entries++;
835 734 : lgfs2_bmodified(dip->i_bh);
836 734 : return 0;
837 : }
838 :
839 1 : dent->de_name_len = cpu_to_be16(name_len);
840 :
841 1 : *dent_out = dent;
842 1 : lgfs2_bmodified(bh);
843 1 : dip->i_entries++;
844 1 : lgfs2_bmodified(dip->i_bh);
845 1 : return 0;
846 : }
847 2154 : } while (lgfs2_dirent_next(dip, bh, &dent) == 0);
848 :
849 9 : errno = ENOSPC;
850 9 : return -1;
851 : }
852 :
853 9 : void lgfs2_dirent2_del(struct lgfs2_inode *dip, struct lgfs2_buffer_head *bh,
854 : struct gfs2_dirent *prev, struct gfs2_dirent *cur)
855 : {
856 : uint16_t cur_rec_len, prev_rec_len;
857 :
858 9 : lgfs2_bmodified(bh);
859 9 : if (lgfs2_check_meta(bh->b_data, GFS2_METATYPE_LF) == 0) {
860 8 : struct gfs2_leaf *lf = (struct gfs2_leaf *)bh->b_data;
861 : uint16_t entries;
862 :
863 8 : entries = be16_to_cpu(lf->lf_entries) - 1;
864 8 : lf->lf_entries = cpu_to_be16(entries);
865 : }
866 :
867 9 : if (dip->i_entries) {
868 9 : lgfs2_bmodified(dip->i_bh);
869 9 : dip->i_entries--;
870 : }
871 9 : if (!prev) {
872 1 : cur->de_inum.no_addr = 0;
873 1 : cur->de_inum.no_formal_ino = 0;
874 1 : return;
875 : }
876 :
877 8 : prev_rec_len = be16_to_cpu(prev->de_rec_len);
878 8 : cur_rec_len = be16_to_cpu(cur->de_rec_len);
879 :
880 8 : prev_rec_len += cur_rec_len;
881 8 : prev->de_rec_len = cpu_to_be16(prev_rec_len);
882 : }
883 :
884 93 : int lgfs2_get_leaf_ptr(struct lgfs2_inode *dip, const uint32_t lindex, uint64_t *ptr)
885 : {
886 : __be64 leaf_no;
887 93 : int count = lgfs2_readi(dip, (char *)&leaf_no, lindex * sizeof(__be64), sizeof(__be64));
888 93 : if (count != sizeof(__be64))
889 0 : return -1;
890 :
891 93 : *ptr = be64_to_cpu(leaf_no);
892 93 : return 0;
893 : }
894 :
895 : /**
896 : * Split a directory leaf.
897 : * Returns 0 on success and non-zero with errno set on failure.
898 : */
899 2 : int lgfs2_dir_split_leaf(struct lgfs2_inode *dip, uint32_t start, uint64_t leaf_no,
900 : struct lgfs2_buffer_head *obh)
901 : {
902 : struct lgfs2_buffer_head *nbh;
903 : struct gfs2_leaf *nleaf, *oleaf;
904 2 : struct gfs2_dirent *dent, *prev = NULL, *next = NULL, *new;
905 : uint32_t len, half_len, divider;
906 : uint16_t depth;
907 : uint64_t bn;
908 : __be64 *lp;
909 : uint32_t name_len;
910 2 : int x, moved = 0;
911 : int count;
912 :
913 2 : if (lgfs2_meta_alloc(dip, &bn)) {
914 0 : errno = EIO;
915 0 : return -1;
916 : }
917 2 : nbh = lgfs2_bget(dip->i_sbd, bn);
918 : {
919 8 : struct gfs2_meta_header mh = {
920 2 : .mh_magic = cpu_to_be32(GFS2_MAGIC),
921 2 : .mh_type = cpu_to_be32(GFS2_METATYPE_LF),
922 2 : .mh_format = cpu_to_be32(GFS2_FORMAT_LF)
923 : };
924 2 : memcpy(nbh->b_data, &mh, sizeof(mh));
925 2 : lgfs2_bmodified(nbh);
926 2 : buffer_clear_tail(dip->i_sbd, nbh,
927 : sizeof(struct gfs2_meta_header));
928 : }
929 :
930 2 : nleaf = (struct gfs2_leaf *)nbh->b_data;
931 2 : nleaf->lf_dirent_format = cpu_to_be32(GFS2_FORMAT_DE);
932 :
933 2 : oleaf = (struct gfs2_leaf *)obh->b_data;
934 :
935 2 : len = 1 << (dip->i_depth - be16_to_cpu(oleaf->lf_depth));
936 2 : half_len = len >> 1;
937 :
938 2 : lp = calloc(1, half_len * sizeof(__be64));
939 2 : if (lp == NULL) {
940 0 : lgfs2_bfree(&nbh);
941 0 : return -1;
942 : }
943 26 : for (x = 0; x < half_len; x++)
944 24 : lp[x] = cpu_to_be64(bn);
945 :
946 2 : count = lgfs2_writei(dip, (char *)lp, start * sizeof(uint64_t),
947 : half_len * sizeof(uint64_t));
948 2 : free(lp);
949 2 : if (count != half_len * sizeof(uint64_t)) {
950 0 : lgfs2_bfree(&nbh);
951 0 : errno = EINVAL;
952 0 : return -1;
953 : }
954 2 : divider = (start + half_len) << (32 - dip->i_depth);
955 :
956 2 : lgfs2_dirent_first(dip, obh, &dent);
957 :
958 : do {
959 14 : next = dent;
960 14 : if (lgfs2_dirent_next(dip, obh, &next))
961 2 : next = NULL;
962 :
963 27 : if (dent->de_inum.no_formal_ino &&
964 13 : be32_to_cpu(dent->de_hash) < divider) {
965 : uint16_t entries;
966 :
967 8 : name_len = be16_to_cpu(dent->de_name_len);
968 :
969 8 : if (dirent_alloc(dip, nbh, name_len, &new)) {
970 0 : lgfs2_bfree(&nbh);
971 0 : errno = ENOSPC;
972 0 : return -1;
973 : }
974 :
975 8 : new->de_inum = dent->de_inum;
976 8 : new->de_hash = dent->de_hash;
977 8 : new->de_type = dent->de_type;
978 8 : memcpy((char *)(new + 1), (char *)(dent + 1), name_len);
979 :
980 8 : entries = be16_to_cpu(nleaf->lf_entries) + 1;
981 8 : nleaf->lf_entries = cpu_to_be16(entries);
982 :
983 8 : lgfs2_dirent2_del(dip, obh, prev, dent);
984 :
985 8 : if (!prev)
986 1 : prev = dent;
987 :
988 8 : moved = 1;
989 : } else
990 6 : prev = dent;
991 :
992 14 : dent = next;
993 14 : } while (dent);
994 :
995 2 : if (!moved) {
996 0 : if (dirent_alloc(dip, nbh, 0, &new)) {
997 0 : lgfs2_bfree(&nbh);
998 0 : errno = ENOSPC;
999 0 : return -1;
1000 : }
1001 0 : new->de_inum.no_formal_ino = 0;
1002 : /* Don't count the sentinel dirent as an entry */
1003 0 : dip->i_entries--;
1004 : }
1005 :
1006 2 : depth = be16_to_cpu(oleaf->lf_depth) + 1;
1007 2 : oleaf->lf_depth = cpu_to_be16(depth);
1008 2 : nleaf->lf_depth = oleaf->lf_depth;
1009 :
1010 2 : nleaf->lf_inode = cpu_to_be64(dip->i_num.in_addr);
1011 2 : dip->i_blocks++;
1012 2 : lgfs2_bmodified(dip->i_bh);
1013 :
1014 2 : lgfs2_bmodified(obh); /* Need to do this in case nothing was moved */
1015 2 : lgfs2_bmodified(nbh);
1016 2 : lgfs2_brelse(nbh);
1017 2 : return 0;
1018 : }
1019 :
1020 0 : static int dir_double_exhash(struct lgfs2_inode *dip)
1021 : {
1022 0 : struct lgfs2_sbd *sdp = dip->i_sbd;
1023 : uint64_t *buf;
1024 : uint64_t *from, *to;
1025 : uint64_t block;
1026 : int x;
1027 : int count;
1028 :
1029 0 : buf = calloc(1, 3 * sdp->sd_hash_bsize);
1030 0 : if (buf == NULL)
1031 0 : return -1;
1032 :
1033 0 : for (block = dip->i_size >> sdp->sd_hash_bsize_shift; block--;) {
1034 0 : count = lgfs2_readi(dip, (char *)buf,
1035 0 : block * sdp->sd_hash_bsize,
1036 : sdp->sd_hash_bsize);
1037 0 : if (count != sdp->sd_hash_bsize) {
1038 0 : free(buf);
1039 0 : return -1;
1040 : }
1041 0 : from = buf;
1042 0 : to = (uint64_t *)((char *)buf + sdp->sd_hash_bsize);
1043 :
1044 0 : for (x = sdp->sd_hash_ptrs; x--; from++) {
1045 0 : *to++ = *from;
1046 0 : *to++ = *from;
1047 : }
1048 0 : count = lgfs2_writei(dip, (char *)buf + sdp->sd_hash_bsize,
1049 : block * sdp->sd_bsize, sdp->sd_bsize);
1050 0 : if (count != sdp->sd_bsize) {
1051 0 : free(buf);
1052 0 : return -1;
1053 : }
1054 : }
1055 :
1056 0 : free(buf);
1057 :
1058 0 : dip->i_depth++;
1059 0 : lgfs2_bmodified(dip->i_bh);
1060 0 : return 0;
1061 : }
1062 :
1063 : /**
1064 : * get_leaf - Get leaf
1065 : * @dip:
1066 : * @leaf_no:
1067 : * @bh_out:
1068 : *
1069 : * Returns: 0 on success, error code otherwise
1070 : */
1071 :
1072 0 : int lgfs2_get_leaf(struct lgfs2_inode *dip, uint64_t leaf_no,
1073 : struct lgfs2_buffer_head **bhp)
1074 : {
1075 0 : int error = 0;
1076 :
1077 0 : *bhp = lgfs2_bread(dip->i_sbd, leaf_no);
1078 0 : error = lgfs2_check_meta((*bhp)->b_data, GFS2_METATYPE_LF);
1079 0 : if(error)
1080 0 : lgfs2_brelse(*bhp);
1081 0 : return error;
1082 : }
1083 :
1084 : /**
1085 : * get_first_leaf - Get first leaf
1086 : * @dip: The GFS2 inode
1087 : * @index:
1088 : * @bh_out:
1089 : *
1090 : * Returns: 0 on success, error code otherwise
1091 : */
1092 :
1093 66 : static int get_first_leaf(struct lgfs2_inode *dip, uint32_t lindex, struct lgfs2_buffer_head **bh_out)
1094 : {
1095 : uint64_t leaf_no;
1096 :
1097 66 : if (lgfs2_get_leaf_ptr(dip, lindex, &leaf_no) != 0)
1098 0 : return -1;
1099 66 : *bh_out = lgfs2_bread(dip->i_sbd, leaf_no);
1100 66 : if (*bh_out == NULL)
1101 0 : return -1;
1102 66 : return 0;
1103 : }
1104 :
1105 : /**
1106 : * get_next_leaf - Get next leaf
1107 : * @dip: The GFS2 inode
1108 : * @bh_in: The buffer
1109 : * @bh_out:
1110 : *
1111 : * Returns: 0 on success, error code otherwise
1112 : */
1113 :
1114 18 : static int get_next_leaf(struct lgfs2_inode *dip,struct lgfs2_buffer_head *bh_in,
1115 : struct lgfs2_buffer_head **bh_out)
1116 : {
1117 : struct gfs2_leaf *leaf;
1118 :
1119 18 : leaf = (struct gfs2_leaf *)bh_in->b_data;
1120 :
1121 18 : if (!leaf->lf_next)
1122 18 : return -1;
1123 : /* Check for a leaf that points to itself as "next" */
1124 0 : if (be64_to_cpu(leaf->lf_next) == bh_in->b_blocknr)
1125 0 : return -1;
1126 0 : *bh_out = lgfs2_bread(dip->i_sbd, be64_to_cpu(leaf->lf_next));
1127 0 : if (*bh_out == NULL)
1128 0 : return -ENOENT;
1129 : /* Check for a leaf pointing to a non-leaf */
1130 0 : if (lgfs2_check_meta((*bh_out)->b_data, GFS2_METATYPE_LF)) {
1131 0 : lgfs2_brelse(*bh_out);
1132 0 : *bh_out = NULL;
1133 0 : return -ENOENT;
1134 : }
1135 0 : return 0;
1136 : }
1137 :
1138 25 : static int dir_e_add(struct lgfs2_inode *dip, const char *filename, int len,
1139 : struct lgfs2_inum *inum, unsigned int type)
1140 : {
1141 : struct lgfs2_buffer_head *bh;
1142 : struct gfs2_leaf *leaf, *nleaf;
1143 : struct gfs2_dirent *dent;
1144 : uint32_t lindex, llen;
1145 : uint32_t hash;
1146 : uint64_t leaf_no, bn;
1147 25 : int err = 0;
1148 :
1149 25 : hash = lgfs2_disk_hash(filename, len);
1150 2 : restart:
1151 : /* (hash >> 32) is undefined behaviour */
1152 27 : if (dip->i_depth)
1153 27 : lindex = hash >> (32 - dip->i_depth);
1154 : else
1155 0 : lindex = 0;
1156 :
1157 27 : err = lgfs2_get_leaf_ptr(dip, lindex, &leaf_no);
1158 27 : if (err)
1159 0 : return err;
1160 :
1161 0 : for (;;) {
1162 : uint16_t entries;
1163 :
1164 27 : bh = lgfs2_bread(dip->i_sbd, leaf_no);
1165 27 : leaf = (struct gfs2_leaf *)bh->b_data;
1166 :
1167 27 : if (dirent_alloc(dip, bh, len, &dent)) {
1168 :
1169 2 : if (be16_to_cpu(leaf->lf_depth) < dip->i_depth) {
1170 4 : llen = 1 << (dip->i_depth -
1171 2 : be16_to_cpu(leaf->lf_depth));
1172 2 : if (lgfs2_dir_split_leaf(dip, lindex & ~(llen - 1), leaf_no, bh)) {
1173 0 : lgfs2_brelse(bh);
1174 0 : return -1;
1175 : }
1176 2 : lgfs2_brelse(bh);
1177 2 : goto restart;
1178 :
1179 0 : } else if (dip->i_depth < GFS2_DIR_MAX_DEPTH) {
1180 0 : lgfs2_brelse(bh);
1181 0 : if (dir_double_exhash(dip))
1182 0 : return -1;
1183 0 : goto restart;
1184 :
1185 0 : } else if (leaf->lf_next) {
1186 0 : leaf_no = be64_to_cpu(leaf->lf_next);
1187 0 : lgfs2_brelse(bh);
1188 0 : continue;
1189 :
1190 : } else {
1191 : struct lgfs2_buffer_head *nbh;
1192 0 : struct gfs2_meta_header mh = {
1193 0 : .mh_magic = cpu_to_be32(GFS2_MAGIC),
1194 0 : .mh_type = cpu_to_be32(GFS2_METATYPE_LF),
1195 0 : .mh_format = cpu_to_be32(GFS2_FORMAT_LF)
1196 : };
1197 0 : if (lgfs2_meta_alloc(dip, &bn)) {
1198 0 : lgfs2_bfree(&bh);
1199 0 : return -1;
1200 : }
1201 0 : nbh = lgfs2_bget(dip->i_sbd, bn);
1202 0 : memcpy(nbh->b_data, &mh, sizeof(mh));
1203 0 : lgfs2_bmodified(nbh);
1204 :
1205 0 : leaf->lf_next = cpu_to_be64(bn);
1206 :
1207 0 : nleaf = (struct gfs2_leaf *)nbh->b_data;
1208 0 : nleaf->lf_depth = leaf->lf_depth;
1209 0 : nleaf->lf_dirent_format = cpu_to_be32(GFS2_FORMAT_DE);
1210 0 : nleaf->lf_inode = cpu_to_be64(dip->i_num.in_addr);
1211 0 : err = dirent_alloc(dip, nbh, len, &dent);
1212 0 : if (err) {
1213 0 : lgfs2_bfree(&nbh);
1214 0 : lgfs2_bfree(&bh);
1215 0 : return err;
1216 : }
1217 0 : dip->i_blocks++;
1218 0 : lgfs2_bmodified(dip->i_bh);
1219 0 : lgfs2_bmodified(bh);
1220 0 : lgfs2_brelse(bh);
1221 0 : bh = nbh;
1222 0 : leaf = nleaf;
1223 : }
1224 : }
1225 :
1226 25 : lgfs2_inum_out(inum, &dent->de_inum);
1227 25 : dent->de_hash = cpu_to_be32(hash);
1228 25 : dent->de_type = cpu_to_be16(type);
1229 25 : memcpy((char *)(dent + 1), filename, len);
1230 :
1231 25 : entries = be16_to_cpu(leaf->lf_entries) + 1;
1232 25 : leaf->lf_entries = cpu_to_be16(entries);
1233 :
1234 25 : lgfs2_bmodified(bh);
1235 25 : lgfs2_brelse(bh);
1236 25 : return err;
1237 : }
1238 : }
1239 :
1240 7 : static int dir_make_exhash(struct lgfs2_inode *dip)
1241 : {
1242 7 : struct lgfs2_sbd *sdp = dip->i_sbd;
1243 : struct gfs2_dirent *dent;
1244 : struct lgfs2_buffer_head *bh;
1245 : struct gfs2_leaf *leaf;
1246 : uint16_t rec_len;
1247 : int y;
1248 : uint32_t x;
1249 : uint64_t bn;
1250 : __be64 *lp;
1251 :
1252 7 : if (lgfs2_meta_alloc(dip, &bn))
1253 0 : return -1;
1254 7 : bh = lgfs2_bget(sdp, bn);
1255 : {
1256 28 : struct gfs2_meta_header mh = {
1257 7 : .mh_magic = cpu_to_be32(GFS2_MAGIC),
1258 7 : .mh_type = cpu_to_be32(GFS2_METATYPE_LF),
1259 7 : .mh_format = cpu_to_be32(GFS2_FORMAT_LF)
1260 : };
1261 7 : memcpy(bh->b_data, &mh, sizeof(mh));
1262 7 : lgfs2_bmodified(bh);
1263 : }
1264 :
1265 7 : leaf = (struct gfs2_leaf *)bh->b_data;
1266 7 : leaf->lf_dirent_format = cpu_to_be32(GFS2_FORMAT_DE);
1267 7 : leaf->lf_entries = cpu_to_be16(dip->i_entries);
1268 7 : leaf->lf_inode = cpu_to_be64(dip->i_num.in_addr);
1269 7 : buffer_copy_tail(sdp, bh, sizeof(struct gfs2_leaf),
1270 : dip->i_bh, sizeof(struct gfs2_dinode));
1271 :
1272 7 : x = 0;
1273 7 : lgfs2_dirent_first(dip, bh, &dent);
1274 :
1275 : do {
1276 35 : if (!dent->de_inum.no_formal_ino)
1277 0 : continue;
1278 35 : if (++x == dip->i_entries)
1279 7 : break;
1280 28 : } while (lgfs2_dirent_next(dip, bh, &dent) == 0);
1281 :
1282 7 : rec_len = be16_to_cpu(dent->de_rec_len) +
1283 : sizeof(struct gfs2_dinode) - sizeof(struct gfs2_leaf);
1284 7 : dent->de_rec_len = cpu_to_be16(rec_len);
1285 :
1286 : /* no need to: lgfs2_bmodified(bh); (buffer_copy_tail does it) */
1287 7 : lgfs2_brelse(bh);
1288 :
1289 7 : buffer_clear_tail(sdp, dip->i_bh, sizeof(struct gfs2_dinode));
1290 :
1291 7 : lp = (__be64 *)(dip->i_bh->b_data + sizeof(struct gfs2_dinode));
1292 :
1293 231 : for (x = sdp->sd_hash_ptrs; x--; lp++)
1294 224 : *lp = cpu_to_be64(bn);
1295 :
1296 7 : dip->i_size = sdp->sd_bsize / 2;
1297 7 : dip->i_blocks++;
1298 7 : dip->i_flags |= GFS2_DIF_EXHASH;
1299 7 : dip->i_payload_format = 0;
1300 : /* no need: lgfs2_bmodified(dip->i_bh); buffer_clear_tail does it. */
1301 :
1302 49 : for (x = sdp->sd_hash_ptrs, y = -1; x; x >>= 1, y++) ;
1303 7 : dip->i_depth = y;
1304 :
1305 7 : lgfs2_dinode_out(dip, dip->i_bh->b_data);
1306 7 : lgfs2_bwrite(dip->i_bh);
1307 7 : return 0;
1308 : }
1309 :
1310 711 : static int dir_l_add(struct lgfs2_inode *dip, const char *filename, int len,
1311 : struct lgfs2_inum *inum, unsigned int type)
1312 : {
1313 : struct gfs2_dirent *dent;
1314 : uint32_t de_hash;
1315 711 : int err = 0;
1316 :
1317 711 : if (dirent_alloc(dip, dip->i_bh, len, &dent)) {
1318 7 : err = dir_make_exhash(dip);
1319 7 : if (err != 0)
1320 0 : return err;
1321 7 : err = dir_e_add(dip, filename, len, inum, type);
1322 7 : return err;
1323 : }
1324 :
1325 704 : lgfs2_inum_out(inum, &dent->de_inum);
1326 704 : de_hash = lgfs2_disk_hash(filename, len);
1327 704 : dent->de_hash = cpu_to_be32(de_hash);
1328 704 : dent->de_type = cpu_to_be16(type);
1329 704 : memcpy((char *)(dent + 1), filename, len);
1330 704 : lgfs2_bmodified(dip->i_bh);
1331 704 : return err;
1332 : }
1333 :
1334 729 : int lgfs2_dir_add(struct lgfs2_inode *dip, const char *filename, int len,
1335 : struct lgfs2_inum *inum, unsigned int type)
1336 : {
1337 729 : int err = 0;
1338 729 : if (dip->i_flags & GFS2_DIF_EXHASH)
1339 18 : err = dir_e_add(dip, filename, len, inum, type);
1340 : else
1341 711 : err = dir_l_add(dip, filename, len, inum, type);
1342 729 : return err;
1343 : }
1344 :
1345 792 : static int __init_dinode(struct lgfs2_sbd *sdp, struct lgfs2_buffer_head **bhp, struct lgfs2_inum *inum,
1346 : unsigned int mode, uint32_t flags, struct lgfs2_inum *parent)
1347 : {
1348 : struct lgfs2_buffer_head *bh;
1349 : struct gfs2_dinode *di;
1350 792 : int is_dir = S_ISDIR(mode);
1351 :
1352 792 : errno = EINVAL;
1353 792 : if (bhp == NULL)
1354 0 : return 1;
1355 :
1356 792 : if (*bhp == NULL) {
1357 792 : *bhp = lgfs2_bget(sdp, inum->in_addr);
1358 792 : if (*bhp == NULL)
1359 0 : return 1;
1360 : }
1361 :
1362 792 : bh = *bhp;
1363 :
1364 792 : di = (struct gfs2_dinode *)bh->b_data;
1365 :
1366 792 : di->di_header.mh_magic = cpu_to_be32(GFS2_MAGIC);
1367 792 : di->di_header.mh_type = cpu_to_be32(GFS2_METATYPE_DI);
1368 792 : di->di_header.mh_format = cpu_to_be32(GFS2_FORMAT_DI);
1369 792 : di->di_num.no_formal_ino = cpu_to_be64(inum->in_formal_ino);
1370 792 : di->di_num.no_addr = cpu_to_be64(inum->in_addr);
1371 792 : di->di_mode = cpu_to_be32(mode);
1372 792 : di->di_nlink = cpu_to_be32(1);
1373 792 : di->di_blocks = cpu_to_be64(1);
1374 792 : di->di_atime = di->di_mtime = di->di_ctime = cpu_to_be64(sdp->sd_time);
1375 792 : di->di_goal_meta = di->di_goal_data = cpu_to_be64(bh->b_blocknr);
1376 792 : di->di_flags = cpu_to_be32(flags);
1377 :
1378 792 : if (is_dir) {
1379 280 : char *p = bh->b_data + sizeof(*di);
1380 280 : struct gfs2_dirent de = {0};
1381 : uint32_t hash;
1382 : uint16_t len;
1383 :
1384 280 : hash = lgfs2_disk_hash(".", 1);
1385 280 : len = GFS2_DIRENT_SIZE(1);
1386 280 : de.de_inum = di->di_num;
1387 280 : de.de_hash = cpu_to_be32(hash);
1388 280 : de.de_rec_len = cpu_to_be16(len);
1389 280 : de.de_name_len = cpu_to_be16(1);
1390 280 : de.de_type = cpu_to_be16(IF2DT(S_IFDIR));
1391 280 : memcpy(p, &de, sizeof(de));
1392 280 : p[sizeof(de)] = '.';
1393 280 : p += len;
1394 :
1395 280 : hash = lgfs2_disk_hash("..", 2);
1396 280 : len = sdp->sd_bsize - (p - bh->b_data);
1397 280 : de.de_inum.no_formal_ino = cpu_to_be64(parent->in_formal_ino);
1398 280 : de.de_inum.no_addr = cpu_to_be64(parent->in_addr);
1399 280 : de.de_hash = cpu_to_be32(hash);
1400 280 : de.de_rec_len = cpu_to_be16(len);
1401 280 : de.de_name_len = cpu_to_be16(2);
1402 280 : de.de_type = cpu_to_be16(IF2DT(S_IFDIR));
1403 280 : memcpy(p, &de, sizeof(de));
1404 280 : p += sizeof(de);
1405 280 : *p++ = '.';
1406 280 : *p = '.';
1407 :
1408 280 : di->di_nlink = cpu_to_be32(2);
1409 280 : di->di_size = cpu_to_be64(sdp->sd_bsize - sizeof(struct gfs2_dinode));
1410 280 : di->di_flags = cpu_to_be32(flags | GFS2_DIF_JDATA);
1411 280 : di->di_payload_format = cpu_to_be32(GFS2_FORMAT_DE);
1412 280 : di->di_entries = cpu_to_be32(2);
1413 : }
1414 792 : lgfs2_bmodified(bh);
1415 792 : return 0;
1416 : }
1417 :
1418 140 : int lgfs2_init_dinode(struct lgfs2_sbd *sdp, struct lgfs2_buffer_head **bhp, struct lgfs2_inum *inum,
1419 : unsigned int mode, uint32_t flags, struct lgfs2_inum *parent)
1420 : {
1421 140 : return __init_dinode(sdp, bhp, inum, mode, flags, parent);
1422 : }
1423 :
1424 8223 : static void lgfs2_fill_indir(char *start, char *end, uint64_t ptr0, unsigned n, unsigned *p)
1425 : {
1426 : char *bp;
1427 8223 : memset(start, 0, end - start);
1428 2400241 : for (bp = start; bp < end && *p < n; bp += sizeof(uint64_t)) {
1429 2392018 : uint64_t pn = ptr0 + *p;
1430 2392018 : *(__be64 *)bp = cpu_to_be64(pn);
1431 2392018 : (*p)++;
1432 : }
1433 8223 : }
1434 :
1435 : /**
1436 : * Calculate and write the indirect blocks for a single-extent file of a given
1437 : * size.
1438 : * ip: The inode for which to write indirect blocks, with fields already set
1439 : * appropriately (see lgfs2_file_alloc).
1440 : * Returns 0 on success or non-zero with errno set on failure.
1441 : */
1442 77 : int lgfs2_write_filemeta(struct lgfs2_inode *ip)
1443 : {
1444 77 : unsigned height = 0;
1445 : struct lgfs2_metapath mp;
1446 77 : struct lgfs2_sbd *sdp = ip->i_sbd;
1447 77 : uint64_t dblocks = (ip->i_size + sdp->sd_bsize - 1) / sdp->sd_bsize;
1448 77 : uint64_t ptr0 = ip->i_num.in_addr + 1;
1449 77 : unsigned ptrs = 1;
1450 308 : struct gfs2_meta_header mh = {
1451 77 : .mh_magic = cpu_to_be32(GFS2_MAGIC),
1452 77 : .mh_type = cpu_to_be32(GFS2_METATYPE_IN),
1453 77 : .mh_format = cpu_to_be32(GFS2_FORMAT_IN)
1454 : };
1455 77 : struct lgfs2_buffer_head *bh = lgfs2_bget(sdp, ip->i_num.in_addr);
1456 77 : if (bh == NULL)
1457 0 : return 1;
1458 :
1459 : /* Using lgfs2_find_metapath() to find the last data block in the file will
1460 : effectively give a remainder for the number of pointers at each
1461 : height. Just need to add 1 to convert ptr index to quantity later. */
1462 77 : lgfs2_find_metapath(ip, dblocks - 1, &mp);
1463 :
1464 242 : for (height = 0; height < ip->i_height; height++) {
1465 : unsigned p;
1466 : /* The number of pointers in this height will be the number of
1467 : full indirect blocks pointed to by the previous height
1468 : multiplied by the pointer capacity of an indirect block,
1469 : plus the remainder which lgfs2_find_metapath() gave us. */
1470 165 : ptrs = ((ptrs - 1) * sdp->sd_inptrs) + mp.mp_list[height] + 1;
1471 :
1472 8388 : for (p = 0; p < ptrs; bh->b_blocknr++) {
1473 8223 : char *start = bh->b_data;
1474 8223 : if (height == 0) {
1475 77 : start += sizeof(struct gfs2_dinode);
1476 77 : lgfs2_dinode_out(ip, bh->b_data);
1477 : } else {
1478 8146 : start += sizeof(struct gfs2_meta_header);
1479 8146 : memcpy(bh->b_data, &mh, sizeof(mh));
1480 : }
1481 8223 : lgfs2_fill_indir(start, bh->b_data + sdp->sd_bsize, ptr0, ptrs, &p);
1482 8223 : if (lgfs2_bwrite(bh)) {
1483 0 : free(bh);
1484 0 : return 1;
1485 : }
1486 : }
1487 165 : ptr0 += ptrs;
1488 : }
1489 77 : free(bh);
1490 77 : return 0;
1491 : }
1492 :
1493 652 : static struct lgfs2_inode *do_createi(struct lgfs2_inode *dip, const char *filename,
1494 : unsigned int mode, uint32_t flags)
1495 : {
1496 652 : struct lgfs2_inum parent = dip->i_num;
1497 652 : struct lgfs2_sbd *sdp = dip->i_sbd;
1498 : uint64_t bn;
1499 : struct lgfs2_inum inum;
1500 652 : struct lgfs2_buffer_head *bh = NULL;
1501 : struct lgfs2_inode *ip;
1502 652 : int err = 0;
1503 : int is_dir;
1504 :
1505 652 : err = lgfs2_dinode_alloc(sdp, 1, &bn);
1506 652 : if (err != 0)
1507 0 : return NULL;
1508 :
1509 652 : inum.in_formal_ino = sdp->md.next_inum++;
1510 652 : inum.in_addr = bn;
1511 :
1512 652 : err = lgfs2_dir_add(dip, filename, strlen(filename), &inum, IF2DT(mode));
1513 652 : if (err)
1514 0 : return NULL;
1515 :
1516 652 : is_dir = S_ISDIR(mode);
1517 652 : if (is_dir) {
1518 140 : lgfs2_bmodified(dip->i_bh);
1519 140 : dip->i_nlink++;
1520 : }
1521 652 : err = __init_dinode(sdp, &bh, &inum, mode, flags, &parent);
1522 652 : if (err != 0)
1523 0 : return NULL;
1524 :
1525 652 : ip = lgfs2_inode_get(sdp, bh);
1526 652 : if (ip == NULL)
1527 0 : return NULL;
1528 652 : lgfs2_bmodified(bh);
1529 652 : ip->bh_owned = 1;
1530 652 : return ip;
1531 : }
1532 :
1533 : /**
1534 : * Create an inode and link it into a directory. If it already exists, return
1535 : * the existing inode. To create gfs1 inodes, dip->i_sbd->gfs1 must be set.
1536 : * @dip: The inode of the parent directory.
1537 : * @filename: The new inode's filename.
1538 : * @mode: The mode of the new inode.
1539 : * @flags: The flags of the new inode.
1540 : * Returns the new or existing inode on success or NULL on failure with errno set.
1541 : */
1542 652 : struct lgfs2_inode *lgfs2_createi(struct lgfs2_inode *dip, const char *filename,
1543 : unsigned int mode, uint32_t flags)
1544 : {
1545 652 : struct lgfs2_inode *ip = lgfs2_lookupi(dip, filename, strlen(filename));
1546 :
1547 652 : if (ip != NULL) {
1548 0 : ip->bh_owned = 1;
1549 0 : return ip;
1550 : }
1551 652 : return do_createi(dip, filename, mode, flags);
1552 : }
1553 :
1554 : /**
1555 : * gfs2_filecmp - Compare two filenames
1556 : * @file1: The first filename
1557 : * @file2: The second filename
1558 : * @len_of_file2: The length of the second file
1559 : *
1560 : * This routine compares two filenames and returns 1 if they are equal.
1561 : *
1562 : * Returns: 1 if the files are the same, otherwise 0.
1563 : */
1564 :
1565 10832 : static int gfs2_filecmp(const char *file1, const char *file2, int len_of_file2)
1566 : {
1567 10832 : if (strlen(file1) != len_of_file2)
1568 5741 : return 0;
1569 5091 : if (memcmp(file1, file2, len_of_file2))
1570 0 : return 0;
1571 5091 : return 1;
1572 : }
1573 :
1574 : /**
1575 : * leaf_search
1576 : * @bh:
1577 : * @id:
1578 : * @dent_out:
1579 : * @dent_prev:
1580 : *
1581 : * Returns:
1582 : */
1583 5748 : static int leaf_search(struct lgfs2_inode *dip, struct lgfs2_buffer_head *bh,
1584 : const char *filename, int len,
1585 : struct gfs2_dirent **dent_out,
1586 : struct gfs2_dirent **dent_prev)
1587 : {
1588 : uint32_t hash;
1589 5748 : struct gfs2_dirent *dent, *prev = NULL;
1590 5748 : unsigned int entries = 0, x = 0;
1591 : int type;
1592 :
1593 5748 : type = lgfs2_dirent_first(dip, bh, &dent);
1594 :
1595 5748 : if (type == LGFS2_IS_LEAF){
1596 66 : struct gfs2_leaf *leaf = (struct gfs2_leaf *)bh->b_data;
1597 66 : entries = be16_to_cpu(leaf->lf_entries);
1598 5682 : } else if (type == LGFS2_IS_DINODE)
1599 5682 : entries = dip->i_entries;
1600 : else
1601 0 : return -1;
1602 :
1603 5748 : hash = lgfs2_disk_hash(filename, len);
1604 :
1605 : do{
1606 36985 : if (!dent->de_inum.no_formal_ino){
1607 4 : prev = dent;
1608 4 : continue;
1609 : }
1610 :
1611 42071 : if (be32_to_cpu(dent->de_hash) == hash &&
1612 5090 : gfs2_filecmp(filename, (char *)(dent + 1),
1613 5090 : be16_to_cpu(dent->de_name_len))) {
1614 5090 : *dent_out = dent;
1615 5090 : if (dent_prev)
1616 1 : *dent_prev = prev;
1617 5090 : return 0;
1618 : }
1619 :
1620 31891 : if(x >= entries)
1621 0 : return -1;
1622 31891 : x++;
1623 31891 : prev = dent;
1624 31895 : } while (lgfs2_dirent_next(dip, bh, &dent) == 0);
1625 :
1626 658 : return -ENOENT;
1627 : }
1628 :
1629 : /**
1630 : * linked_leaf_search - Linked leaf search
1631 : * @dip: The GFS2 inode
1632 : * @id:
1633 : * @dent_out:
1634 : * @dent_prev:
1635 : * @bh_out:
1636 : *
1637 : * Returns: 0 on sucess, error code otherwise
1638 : */
1639 :
1640 66 : static int linked_leaf_search(struct lgfs2_inode *dip, const char *filename,
1641 : int len, struct gfs2_dirent **dent_out,
1642 : struct lgfs2_buffer_head **bh_out)
1643 : {
1644 66 : struct lgfs2_buffer_head *bh = NULL, *bh_next;
1645 : uint32_t hsize, lindex;
1646 : uint32_t hash;
1647 66 : int error = 0;
1648 :
1649 66 : hsize = 1 << dip->i_depth;
1650 66 : if(hsize * sizeof(uint64_t) != dip->i_size)
1651 0 : return -1;
1652 :
1653 : /* Figure out the address of the leaf node. */
1654 :
1655 66 : hash = lgfs2_disk_hash(filename, len);
1656 66 : lindex = hash >> (32 - dip->i_depth);
1657 :
1658 66 : error = get_first_leaf(dip, lindex, &bh_next);
1659 66 : if (error)
1660 0 : return error;
1661 66 : if (bh_next == NULL)
1662 0 : return errno;
1663 :
1664 : /* Find the entry */
1665 : do{
1666 66 : if (bh && bh != dip->i_bh)
1667 0 : lgfs2_brelse(bh);
1668 :
1669 66 : bh = bh_next;
1670 :
1671 66 : error = leaf_search(dip, bh, filename, len, dent_out, NULL);
1672 66 : switch (error){
1673 48 : case 0:
1674 48 : *bh_out = bh;
1675 48 : return 0;
1676 :
1677 18 : case -ENOENT:
1678 18 : break;
1679 :
1680 0 : default:
1681 0 : if (bh && bh != dip->i_bh)
1682 0 : lgfs2_brelse(bh);
1683 0 : return error;
1684 : }
1685 :
1686 18 : error = get_next_leaf(dip, bh, &bh_next);
1687 18 : } while (!error && bh_next != NULL);
1688 :
1689 18 : if (bh && bh != dip->i_bh)
1690 18 : lgfs2_brelse(bh);
1691 :
1692 18 : return error;
1693 : }
1694 :
1695 : /**
1696 : * dir_e_search -
1697 : * @dip: The GFS2 inode
1698 : * @id:
1699 : * @inode:
1700 : *
1701 : * Returns:
1702 : */
1703 66 : static int dir_e_search(struct lgfs2_inode *dip, const char *filename,
1704 : int len, unsigned int *type, struct lgfs2_inum *inum)
1705 : {
1706 66 : struct lgfs2_buffer_head *bh = NULL;
1707 : struct gfs2_dirent *dent;
1708 : int error;
1709 :
1710 66 : error = linked_leaf_search(dip, filename, len, &dent, &bh);
1711 66 : if (error)
1712 18 : return error;
1713 :
1714 48 : lgfs2_inum_in(inum, &dent->de_inum);
1715 48 : if (type)
1716 0 : *type = be16_to_cpu(dent->de_type);
1717 :
1718 48 : lgfs2_brelse(bh);
1719 :
1720 48 : return 0;
1721 : }
1722 :
1723 :
1724 : /**
1725 : * dir_l_search -
1726 : * @dip: The GFS2 inode
1727 : * @id:
1728 : * @inode:
1729 : *
1730 : * Returns:
1731 : */
1732 5681 : static int dir_l_search(struct lgfs2_inode *dip, const char *filename,
1733 : int len, unsigned int *type, struct lgfs2_inum *inum)
1734 : {
1735 : struct gfs2_dirent *dent;
1736 : int error;
1737 :
1738 5681 : if(!inode_is_stuffed(dip))
1739 0 : return -1;
1740 :
1741 5681 : error = leaf_search(dip, dip->i_bh, filename, len, &dent, NULL);
1742 5681 : if (!error) {
1743 5041 : lgfs2_inum_in(inum, &dent->de_inum);
1744 5041 : if(type)
1745 0 : *type = be16_to_cpu(dent->de_type);
1746 : }
1747 5681 : return error;
1748 : }
1749 :
1750 : /**
1751 : * lgfs2_dir_search - Search a directory
1752 : * @dip: The GFS inode
1753 : * @id
1754 : * @type:
1755 : *
1756 : * This routine searches a directory for a file or another directory
1757 : * given its filename. The component of the identifier that is
1758 : * not being used to search will be filled in and must be freed by
1759 : * the caller.
1760 : *
1761 : * Returns: 0 if found, -1 on failure, -ENOENT if not found.
1762 : */
1763 5747 : int lgfs2_dir_search(struct lgfs2_inode *dip, const char *filename, int len,
1764 : unsigned int *type, struct lgfs2_inum *inum)
1765 : {
1766 : int error;
1767 :
1768 5747 : if (!S_ISDIR(dip->i_mode))
1769 0 : return -1;
1770 :
1771 5747 : if (dip->i_flags & GFS2_DIF_EXHASH)
1772 66 : error = dir_e_search(dip, filename, len, type, inum);
1773 : else
1774 5681 : error = dir_l_search(dip, filename, len, type, inum);
1775 :
1776 5747 : return error;
1777 : }
1778 :
1779 0 : static int dir_e_del(struct lgfs2_inode *dip, const char *filename, int len)
1780 : {
1781 : int lindex;
1782 : int error;
1783 0 : int found = 0;
1784 : uint64_t leaf_no;
1785 0 : struct lgfs2_buffer_head *bh = NULL;
1786 : struct gfs2_dirent *cur, *prev;
1787 :
1788 0 : lindex = (1 << (dip->i_depth))-1;
1789 :
1790 0 : for(; (lindex >= 0) && !found; lindex--){
1791 0 : error = lgfs2_get_leaf_ptr(dip, lindex, &leaf_no);
1792 0 : if (error)
1793 0 : return error;
1794 :
1795 0 : while(leaf_no && !found){
1796 0 : bh = lgfs2_bread(dip->i_sbd, leaf_no);
1797 0 : error = leaf_search(dip, bh, filename, len, &cur, &prev);
1798 0 : if (error) {
1799 0 : if(error != -ENOENT){
1800 0 : lgfs2_brelse(bh);
1801 0 : return -1;
1802 : }
1803 0 : leaf_no = be64_to_cpu(((struct gfs2_leaf *)bh->b_data)->lf_next);
1804 0 : lgfs2_brelse(bh);
1805 : } else
1806 0 : found = 1;
1807 : }
1808 : }
1809 :
1810 0 : if(!found)
1811 0 : return 1;
1812 :
1813 0 : if (bh) {
1814 0 : lgfs2_dirent2_del(dip, bh, prev, cur);
1815 0 : lgfs2_brelse(bh);
1816 : }
1817 0 : return 0;
1818 : }
1819 :
1820 1 : static int dir_l_del(struct lgfs2_inode *dip, const char *filename, int len)
1821 : {
1822 1 : int error=0;
1823 : struct gfs2_dirent *cur, *prev;
1824 :
1825 1 : if(!inode_is_stuffed(dip))
1826 0 : return -1;
1827 :
1828 1 : error = leaf_search(dip, dip->i_bh, filename, len, &cur, &prev);
1829 1 : if (error) {
1830 0 : if (error == -ENOENT)
1831 0 : return 1;
1832 : else
1833 0 : return -1;
1834 : }
1835 :
1836 1 : lgfs2_dirent2_del(dip, dip->i_bh, prev, cur);
1837 1 : return 0;
1838 : }
1839 :
1840 :
1841 : /*
1842 : * lgfs2_dirent_del
1843 : * @dip
1844 : * filename
1845 : *
1846 : * Delete a directory entry from a directory. This _only_
1847 : * removes the directory entry - leaving the dinode in
1848 : * place. (Likely without a link.)
1849 : *
1850 : * Returns: 0 on success (or if it doesn't already exist), -1 on failure
1851 : */
1852 1 : int lgfs2_dirent_del(struct lgfs2_inode *dip, const char *filename, int len)
1853 : {
1854 : int error;
1855 :
1856 1 : if(!S_ISDIR(dip->i_mode))
1857 0 : return -1;
1858 :
1859 1 : if (dip->i_flags & GFS2_DIF_EXHASH)
1860 0 : error = dir_e_del(dip, filename, len);
1861 : else
1862 1 : error = dir_l_del(dip, filename, len);
1863 1 : lgfs2_bmodified(dip->i_bh);
1864 1 : return error;
1865 : }
1866 :
1867 : /**
1868 : * Look up a filename in a directory and return its inode, which can be the
1869 : * the directory inode when "." is looked up.
1870 : * @dip: The directory to search
1871 : * @name: The name of the inode to look for
1872 : * @len: The length of name
1873 : *
1874 : * Returns: The inode on success or NULL on failure with errno set.
1875 : */
1876 5744 : struct lgfs2_inode *lgfs2_lookupi(struct lgfs2_inode *dip, const char *filename, int len)
1877 : {
1878 : struct lgfs2_sbd *sdp;
1879 : struct lgfs2_inum inum;
1880 5744 : int error = 0;
1881 :
1882 5744 : errno = EINVAL;
1883 5744 : if (dip == NULL)
1884 0 : return NULL;
1885 5744 : sdp = dip->i_sbd;
1886 5744 : errno = ENAMETOOLONG;
1887 5744 : if (!len || len > GFS2_FNAMESIZE)
1888 2 : return NULL;
1889 :
1890 5742 : if (gfs2_filecmp(filename, ".", 1))
1891 1 : return dip;
1892 :
1893 5741 : error = lgfs2_dir_search(dip, filename, len, NULL, &inum);
1894 5741 : if (error)
1895 658 : return NULL;
1896 5083 : return lgfs2_inode_read(sdp, inum.in_addr);
1897 : }
1898 :
1899 : /**
1900 : * lgfs2_free_block - free up a block given its block number
1901 : */
1902 0 : void lgfs2_free_block(struct lgfs2_sbd *sdp, uint64_t block)
1903 : {
1904 : struct lgfs2_rgrp_tree *rgd;
1905 :
1906 : /* Adjust the free space count for the freed block */
1907 0 : rgd = lgfs2_blk2rgrpd(sdp, block); /* find the rg for indir block */
1908 0 : if (rgd) {
1909 0 : lgfs2_set_bitmap(rgd, block, GFS2_BLKST_FREE);
1910 0 : rgd->rt_free++; /* adjust the free count */
1911 0 : lgfs2_rgrp_out(rgd, rgd->rt_bits[0].bi_data);
1912 0 : rgd->rt_bits[0].bi_modified = 1;
1913 0 : sdp->blks_alloced--;
1914 : }
1915 0 : }
|