LCOV - code coverage report
Current view: top level - libgfs2 - fs_ops.c (source / functions) Coverage Total Hit
Test: gfs2-utils.info Lines: 77.0 % 1047 806
Test Date: 2024-03-07 16:24:06 Functions: 91.2 % 57 52

            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     23453917 : static __inline__ __be64 *metapointer(char *buf,
      18              :                                         unsigned int height,
      19              :                                         struct lgfs2_metapath *mp)
      20              : {
      21     23453917 :         unsigned int head_size = (height > 0) ?
      22              :                 sizeof(struct gfs2_meta_header) : sizeof(struct gfs2_dinode);
      23              : 
      24     23453917 :         return ((__be64 *)(buf + head_size)) + mp->mp_list[height];
      25              : }
      26              : 
      27              : /* Detect directory is a stuffed inode */
      28      6454632 : static int inode_is_stuffed(const struct lgfs2_inode *ip)
      29              : {
      30      6454632 :         return !ip->i_height;
      31              : }
      32              : 
      33        15220 : struct lgfs2_inode *lgfs2_inode_get(struct lgfs2_sbd *sdp, struct lgfs2_buffer_head *bh)
      34              : {
      35              :         struct lgfs2_inode *ip;
      36              : 
      37        15220 :         ip = calloc(1, sizeof(struct lgfs2_inode));
      38        15220 :         if (ip == NULL) {
      39            0 :                 return NULL;
      40              :         }
      41        15220 :         lgfs2_dinode_in(ip, bh->b_data);
      42        15220 :         ip->i_bh = bh;
      43        15220 :         ip->i_sbd = sdp;
      44        15220 :         return ip;
      45              : }
      46              : 
      47        14146 : struct lgfs2_inode *lgfs2_inode_read(struct lgfs2_sbd *sdp, uint64_t di_addr)
      48              : {
      49              :         struct lgfs2_inode *ip;
      50        14146 :         struct lgfs2_buffer_head *bh = lgfs2_bread(sdp, di_addr);
      51        14146 :         if (bh == NULL) {
      52            0 :                 return NULL;
      53              :         }
      54        14146 :         ip = lgfs2_inode_get(sdp, bh);
      55        14146 :         if (ip == NULL) {
      56            0 :                 lgfs2_brelse(bh);
      57            0 :                 return NULL;
      58              :         }
      59        14146 :         ip->bh_owned = 1; /* We did the lgfs2_bread so we own the bh */
      60        14146 :         return ip;
      61              : }
      62              : 
      63         2343 : struct lgfs2_inode *lgfs2_is_system_inode(struct lgfs2_sbd *sdp, uint64_t block)
      64              : {
      65              :         int j;
      66              : 
      67         2343 :         if (sdp->md.inum && block == sdp->md.inum->i_num.in_addr)
      68          114 :                 return sdp->md.inum;
      69         2229 :         if (sdp->md.statfs && block == sdp->md.statfs->i_num.in_addr)
      70          114 :                 return sdp->md.statfs;
      71         2115 :         if (sdp->md.jiinode && block == sdp->md.jiinode->i_num.in_addr)
      72          171 :                 return sdp->md.jiinode;
      73         1944 :         if (sdp->md.riinode && block == sdp->md.riinode->i_num.in_addr)
      74          114 :                 return sdp->md.riinode;
      75         1830 :         if (sdp->md.qinode && block == sdp->md.qinode->i_num.in_addr)
      76          114 :                 return sdp->md.qinode;
      77         1716 :         if (sdp->md.pinode && block == sdp->md.pinode->i_num.in_addr)
      78          171 :                 return sdp->md.pinode;
      79         1545 :         if (sdp->md.rooti && block == sdp->md.rooti->i_num.in_addr)
      80          171 :                 return sdp->md.rooti;
      81         1374 :         if (sdp->master_dir && block == sdp->master_dir->i_num.in_addr)
      82          285 :                 return sdp->master_dir;
      83         2467 :         for (j = 0; j < sdp->md.journals; j++)
      84         1505 :                 if (sdp->md.journal && sdp->md.journal[j] &&
      85         1501 :                     block == sdp->md.journal[j]->i_num.in_addr)
      86          127 :                         return sdp->md.journal[j];
      87          962 :         return NULL;
      88              : }
      89              : 
      90         6253 : void lgfs2_inode_put(struct lgfs2_inode **ip_in)
      91              : {
      92         6253 :         struct lgfs2_inode *ip = *ip_in;
      93         6253 :         uint64_t block = ip->i_num.in_addr;
      94         6253 :         struct lgfs2_sbd *sdp = ip->i_sbd;
      95              : 
      96         6253 :         if (ip->i_bh != NULL) {
      97         6253 :                 if (ip->i_bh->b_modified) {
      98          805 :                         lgfs2_dinode_out(ip, ip->i_bh->b_data);
      99          805 :                         if (!ip->bh_owned && lgfs2_is_system_inode(sdp, block))
     100            0 :                                 fprintf(stderr, "Warning: Changes made to inode were discarded.\n");
     101              :                 }
     102         6253 :                 if (ip->bh_owned)
     103         6054 :                         lgfs2_brelse(ip->i_bh);
     104         6253 :                 ip->i_bh = NULL;
     105              :         }
     106         6253 :         free(ip);
     107         6253 :         *ip_in = NULL; /* make sure the memory isn't accessed again */
     108         6253 : }
     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        71043 : static uint64_t find_free_block(struct lgfs2_rgrp_tree *rgd)
     124              : {
     125              :         unsigned bm;
     126        71043 :         uint64_t blkno = 0;
     127              : 
     128        71043 :         if (rgd == NULL || rgd->rt_free == 0) {
     129            0 :                 errno = ENOSPC;
     130            0 :                 return 0;
     131              :         }
     132              : 
     133       116960 :         for (bm = 0; bm < rgd->rt_length; bm++) {
     134       116960 :                 unsigned long blk = 0;
     135       116960 :                 struct lgfs2_bitmap *bits = &rgd->rt_bits[bm];
     136              : 
     137       116960 :                 blk = lgfs2_bitfit((uint8_t *)bits->bi_data + bits->bi_offset,
     138              :                                   bits->bi_len, blk, GFS2_BLKST_FREE);
     139       116960 :                 if (blk != LGFS2_BFITNOENT) {
     140        71043 :                         blkno = blk + (bits->bi_start * GFS2_NBBY) + rgd->rt_data0;
     141        71043 :                         break;
     142              :                 }
     143              :         }
     144        71043 :         return blkno;
     145              : }
     146              : 
     147        71043 : static int blk_alloc_in_rg(struct lgfs2_sbd *sdp, unsigned state, struct lgfs2_rgrp_tree *rgd, uint64_t blkno, int dinode)
     148              : {
     149        71043 :         if (blkno == 0)
     150            0 :                 return -1;
     151              : 
     152        71043 :         if (lgfs2_set_bitmap(rgd, blkno, state))
     153            0 :                 return -1;
     154              : 
     155        71043 :         if (state == GFS2_BLKST_DINODE) {
     156          804 :                 if (dinode)
     157          804 :                         rgd->rt_dinodes++;
     158              :         }
     159              : 
     160        71043 :         rgd->rt_free--;
     161        71043 :         lgfs2_rgrp_out(rgd, rgd->rt_bits[0].bi_data);
     162        71043 :         rgd->rt_bits[0].bi_modified = 1;
     163        71043 :         sdp->blks_alloced++;
     164        71043 :         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        71044 : static int block_alloc(struct lgfs2_sbd *sdp, const uint64_t blksreq, int state, uint64_t *blkno, int dinode)
     173              : {
     174              :         int ret;
     175        71044 :         int release = 0;
     176        71044 :         struct lgfs2_rgrp_tree *rgt = NULL;
     177        71044 :         struct osi_node *n = NULL;
     178        71044 :         uint64_t bn = 0;
     179              : 
     180       169188 :         for (n = osi_first(&sdp->rgtree); n; n = osi_next(n)) {
     181       169187 :                 rgt = (struct lgfs2_rgrp_tree *)n;
     182       169187 :                 if (rgt->rt_free >= blksreq)
     183        71043 :                         break;
     184              :         }
     185        71044 :         if (n == NULL)
     186            1 :                 return -1;
     187              : 
     188        71043 :         if (rgt->rt_bits[0].bi_data == NULL) {
     189        38207 :                 if (lgfs2_rgrp_read(sdp, rgt))
     190            0 :                         return -1;
     191        38207 :                 release = 1;
     192              :         }
     193              : 
     194        71043 :         bn = find_free_block(rgt);
     195        71043 :         ret = blk_alloc_in_rg(sdp, state, rgt, bn, dinode);
     196        71043 :         if (release)
     197        38207 :                 lgfs2_rgrp_relse(sdp, rgt);
     198        71043 :         *blkno = bn;
     199        71043 :         return ret;
     200              : }
     201              : 
     202          805 : int lgfs2_dinode_alloc(struct lgfs2_sbd *sdp, const uint64_t blksreq, uint64_t *blkno)
     203              : {
     204          805 :         int ret = block_alloc(sdp, blksreq, GFS2_BLKST_DINODE, blkno, 1);
     205          805 :         if (ret == 0)
     206          804 :                 sdp->dinodes_alloced++;
     207          805 :         return ret;
     208              : }
     209              : 
     210        70239 : int lgfs2_meta_alloc(struct lgfs2_inode *ip, uint64_t *blkno)
     211              : {
     212        70239 :         int ret = block_alloc(ip->i_sbd, 1, GFS2_BLKST_USED, blkno, 0);
     213        70239 :         if (ret == 0) {
     214        70239 :                 ip->i_goal_meta = *blkno;
     215        70239 :                 lgfs2_bmodified(ip->i_bh);
     216              :         }
     217        70239 :         return ret;
     218              : }
     219              : 
     220          162 : static __inline__ void buffer_clear_tail(struct lgfs2_sbd *sdp,
     221              :                                          struct lgfs2_buffer_head *bh, int head)
     222              : {
     223          162 :         memset(bh->b_data + head, 0, sdp->sd_bsize - head);
     224          162 :         lgfs2_bmodified(bh);
     225          162 : }
     226              : 
     227              : static __inline__ void
     228           68 : 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           68 :         memcpy(to_bh->b_data + to_head, from_bh->b_data + from_head,
     233           68 :                sdp->sd_bsize - from_head);
     234           68 :         memset(to_bh->b_data + sdp->sd_bsize + to_head - from_head, 0,
     235           68 :                from_head - to_head);
     236           68 :         lgfs2_bmodified(to_bh);
     237           68 : }
     238              : 
     239           61 : int lgfs2_unstuff_dinode(struct lgfs2_inode *ip)
     240              : {
     241           61 :         struct lgfs2_sbd *sdp = ip->i_sbd;
     242              :         struct lgfs2_buffer_head *bh;
     243           61 :         uint64_t block = 0;
     244           61 :         int isdir = S_ISDIR(ip->i_mode);
     245              : 
     246           61 :         if (ip->i_size) {
     247           61 :                 if (lgfs2_meta_alloc(ip, &block))
     248            0 :                         return -1;
     249           61 :                 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           61 :                         bh = lgfs2_bget(sdp, block);
     266              : 
     267           61 :                         buffer_copy_tail(sdp, bh, 0,
     268              :                                          ip->i_bh, sizeof(struct gfs2_dinode));
     269           61 :                         lgfs2_brelse(bh);
     270              :                 }
     271              :         }
     272              : 
     273           61 :         buffer_clear_tail(sdp, ip->i_bh, sizeof(struct gfs2_dinode));
     274              : 
     275           61 :         if (ip->i_size) {
     276           61 :                 *(__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           61 :                 ip->i_blocks++;
     279              :         }
     280              : 
     281           61 :         ip->i_height = 1;
     282           61 :         return 0;
     283              : }
     284              : 
     285              : /**
     286              :  * Calculate the total number of blocks required by a file containing 'bytes' bytes of data.
     287              :  */
     288          149 : uint64_t lgfs2_space_for_data(const struct lgfs2_sbd *sdp, const unsigned bsize, const uint64_t bytes)
     289              : {
     290          149 :         uint64_t blks = (bytes + bsize - 1) / bsize;
     291          149 :         uint64_t ptrs = blks;
     292              : 
     293          149 :         if (bytes <= bsize - sizeof(struct gfs2_dinode))
     294            0 :                 return 1;
     295              : 
     296          317 :         while (ptrs > sdp->sd_diptrs) {
     297          168 :                 ptrs = (ptrs + sdp->sd_inptrs - 1) / sdp->sd_inptrs;
     298          168 :                 blks += ptrs;
     299              :         }
     300          149 :         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           78 : 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           78 :         struct lgfs2_sbd *sdp = rg->rt_rgrps->rgs_sdp;
     320           78 :         struct lgfs2_rbm rbm = { .rgd = rg, .offset = 0, .bii = 0 };
     321           78 :         uint32_t blocks = lgfs2_space_for_data(sdp, sdp->sd_bsize, di_size);
     322              : 
     323           78 :         if (ip->i_num.in_addr != 0) {
     324           78 :                 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           78 :         extlen = lgfs2_alloc_extent(&rbm, GFS2_BLKST_DINODE, blocks);
     331           78 :         if (extlen < blocks) {
     332            0 :                 errno = EINVAL;
     333            0 :                 return 1;
     334              :         }
     335              : 
     336           78 :         ip->i_sbd = sdp;
     337              : 
     338           78 :         ip->i_magic = GFS2_MAGIC;
     339           78 :         ip->i_mh_type = GFS2_METATYPE_DI;
     340           78 :         ip->i_format = GFS2_FORMAT_DI;
     341           78 :         ip->i_size = di_size;
     342           78 :         ip->i_num.in_addr = lgfs2_rbm_to_block(&rbm);
     343           78 :         ip->i_num.in_formal_ino = sdp->md.next_inum++;
     344           78 :         ip->i_mode = mode;
     345           78 :         ip->i_nlink = 1;
     346           78 :         ip->i_blocks = blocks;
     347           78 :         ip->i_atime = ip->i_mtime = ip->i_ctime = sdp->sd_time;
     348           78 :         ip->i_goal_data = ip->i_num.in_addr + ip->i_blocks - 1;
     349           78 :         ip->i_goal_meta = ip->i_goal_data - ((di_size + sdp->sd_bsize - 1) / sdp->sd_bsize);
     350           78 :         ip->i_height = lgfs2_calc_tree_height(ip, di_size);
     351           78 :         ip->i_flags = flags;
     352              : 
     353           78 :         rg->rt_free -= blocks;
     354           78 :         rg->rt_dinodes += 1;
     355              : 
     356           78 :         sdp->dinodes_alloced++;
     357           78 :         sdp->blks_alloced += blocks;
     358              : 
     359           78 :         return 0;
     360              : }
     361              : 
     362      4295427 : unsigned int lgfs2_calc_tree_height(struct lgfs2_inode *ip, uint64_t size)
     363              : {
     364      4295427 :         struct lgfs2_sbd *sdp = ip->i_sbd;
     365              :         uint64_t *arr;
     366              :         unsigned int max, height;
     367              : 
     368      4295427 :         if (ip->i_size > size)
     369      4032285 :                 size = ip->i_size;
     370              : 
     371      4295427 :         if (S_ISDIR(ip->i_mode)) {
     372            0 :                 arr = sdp->sd_jheightsize;
     373            0 :                 max = sdp->sd_max_jheight;
     374              :         } else {
     375      4295427 :                 arr = sdp->sd_heightsize;
     376      4295427 :                 max = sdp->sd_max_height;
     377              :         }
     378              : 
     379     11224735 :         for (height = 0; height < max; height++)
     380     11224735 :                 if (arr[height] >= size)
     381      4295427 :                         break;
     382              : 
     383      4295427 :         return height;
     384              : }
     385              : 
     386           79 : int lgfs2_build_height(struct lgfs2_inode *ip, int height)
     387              : {
     388           79 :         struct lgfs2_sbd *sdp = ip->i_sbd;
     389              :         struct lgfs2_buffer_head *bh;
     390           79 :         uint64_t block = 0, *bp;
     391              :         unsigned int x;
     392              :         int new_block;
     393              : 
     394          171 :         while (ip->i_height < height) {
     395           92 :                 new_block = 0;
     396           92 :                 bp = (uint64_t *)(ip->i_bh->b_data + sizeof(struct gfs2_dinode));
     397        34544 :                 for (x = 0; x < sdp->sd_diptrs; x++, bp++)
     398        34452 :                         if (*bp) {
     399            0 :                                 new_block = 1;
     400            0 :                                 break;
     401              :                         }
     402              : 
     403           92 :                 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           92 :                 buffer_clear_tail(sdp, ip->i_bh, sizeof(struct gfs2_dinode));
     422              : 
     423           92 :                 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           92 :                 ip->i_height++;
     430              :         }
     431           79 :         return 0;
     432              : }
     433              : 
     434      4295348 : void lgfs2_find_metapath(struct lgfs2_inode *ip, uint64_t block, struct lgfs2_metapath *mp)
     435              : {
     436      4295348 :         const uint32_t inptrs = ip->i_sbd->sd_inptrs;
     437      4295348 :         unsigned int i = ip->i_height;
     438              : 
     439      4295348 :         memset(mp, 0, sizeof(struct lgfs2_metapath));
     440     11226334 :         while (i--) {
     441      6930986 :                 mp->mp_list[i] = block % inptrs;
     442      6930986 :                 block /= inptrs;
     443              :         }
     444      4295348 : }
     445              : 
     446     23453917 : 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     23453917 :         __be64 *ptr = metapointer(bh->b_data, height, mp);
     451              : 
     452     23453917 :         if (*ptr) {
     453     21249245 :                 *block = be64_to_cpu(*ptr);
     454     21249245 :                 return;
     455              :         }
     456              : 
     457      2204672 :         *block = 0;
     458              : 
     459      2204672 :         if (!create)
     460      2134504 :                 return;
     461              : 
     462        70168 :         if (lgfs2_meta_alloc(ip, block))
     463            0 :                 return;
     464        70168 :         *ptr = cpu_to_be64(*block);
     465        70168 :         lgfs2_bmodified(bh);
     466        70168 :         ip->i_blocks++;
     467        70168 :         lgfs2_bmodified(ip->i_bh);
     468              : 
     469        70168 :         *new = 1;
     470              : }
     471              : 
     472      4301394 : int lgfs2_block_map(struct lgfs2_inode *ip, uint64_t lblock, int *new,
     473              :                      uint64_t *dblock, uint32_t *extlen, int prealloc)
     474              : {
     475      4301394 :         struct lgfs2_sbd *sdp = ip->i_sbd;
     476              :         struct lgfs2_buffer_head *bh;
     477              :         struct lgfs2_metapath mp;
     478      4301394 :         int create = *new;
     479              :         unsigned int bsize;
     480              :         unsigned int height;
     481              :         unsigned int end_of_metadata;
     482              :         unsigned int x;
     483              : 
     484      4301394 :         *new = 0;
     485      4301394 :         *dblock = 0;
     486      4301394 :         if (extlen)
     487      2140797 :                 *extlen = 0;
     488              : 
     489      4301394 :         if (inode_is_stuffed(ip)) {
     490         6124 :                 if (!lblock) {
     491         6124 :                         *dblock = ip->i_num.in_addr;
     492         6124 :                         if (extlen)
     493         6124 :                                 *extlen = 1;
     494              :                 }
     495         6124 :                 return 0;
     496              :         }
     497              : 
     498      4295270 :         bsize = (S_ISDIR(ip->i_mode)) ? sdp->sd_jbsize : sdp->sd_bsize;
     499              : 
     500      4295270 :         height = lgfs2_calc_tree_height(ip, (lblock + 1) * bsize);
     501      4295270 :         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      4295270 :         lgfs2_find_metapath(ip, lblock, &mp);
     510      4295270 :         end_of_metadata = ip->i_height - 1;
     511              : 
     512      4295270 :         bh = ip->i_bh;
     513              : 
     514      6930819 :         for (x = 0; x < end_of_metadata; x++) {
     515      2635549 :                 lgfs2_lookup_block(ip, bh, x, &mp, create, new, dblock);
     516      2635549 :                 if (bh != ip->i_bh)
     517       491848 :                         lgfs2_brelse(bh);
     518      2635549 :                 if (!*dblock)
     519            0 :                         return 0;
     520              : 
     521      2635549 :                 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      2635182 :                         if (*dblock == ip->i_num.in_addr)
     532            0 :                                 bh = ip->i_bh;
     533              :                         else
     534      2635182 :                                 bh = lgfs2_bread(sdp, *dblock);
     535              :                 }
     536              :         }
     537              : 
     538      4295270 :         if (!prealloc)
     539      4262502 :                 lgfs2_lookup_block(ip, bh, end_of_metadata, &mp, create, new, dblock);
     540              : 
     541      4295270 :         if (extlen && *dblock) {
     542      2134673 :                 *extlen = 1;
     543              : 
     544      2134673 :                 if (!*new) {
     545              :                         uint64_t tmp_dblock;
     546              :                         int tmp_new;
     547              :                         unsigned int nptrs;
     548              : 
     549      2134504 :                         nptrs = (end_of_metadata) ? sdp->sd_inptrs : sdp->sd_diptrs;
     550              : 
     551     16555866 :                         while (++mp.mp_list[end_of_metadata] < nptrs) {
     552     16555866 :                                 lgfs2_lookup_block(ip, bh, end_of_metadata, &mp, 0, &tmp_new,
     553              :                                                          &tmp_dblock);
     554              : 
     555     16555866 :                                 if (*dblock + *extlen != tmp_dblock)
     556      2134504 :                                         break;
     557              : 
     558     14421362 :                                 (*extlen)++;
     559              :                         }
     560              :                 }
     561              :         }
     562              : 
     563      4295270 :         if (bh != ip->i_bh)
     564      2143701 :                 lgfs2_brelse(bh);
     565      4295270 :         return 0;
     566              : }
     567              : 
     568              : static void
     569      2167272 : copy2mem(struct lgfs2_buffer_head *bh, void **buf, unsigned int offset,
     570              :          unsigned int size)
     571              : {
     572      2167272 :         char **p = (char **)buf;
     573              : 
     574      2167272 :         if (bh)
     575      2167272 :                 memcpy(*p, bh->b_data + offset, size);
     576              :         else
     577            0 :                 memset(*p, 0, size);
     578              : 
     579      2167272 :         *p += size;
     580      2167272 : }
     581              : 
     582      2138346 : int lgfs2_readi(struct lgfs2_inode *ip, void *buf, uint64_t offset, unsigned int size)
     583              : {
     584      2138346 :         struct lgfs2_sbd *sdp = ip->i_sbd;
     585              :         struct lgfs2_buffer_head *bh;
     586              :         uint64_t lblock, dblock;
     587              :         unsigned int o;
     588      2138346 :         uint32_t extlen = 0;
     589              :         unsigned int amount;
     590      2138346 :         int not_new = 0;
     591      2138346 :         int isdir = !!(S_ISDIR(ip->i_mode));
     592      2138346 :         int copied = 0;
     593              : 
     594      2138346 :         if (offset >= ip->i_size)
     595         4552 :                 return 0;
     596              : 
     597      2133794 :         if ((offset + size) > ip->i_size)
     598            0 :                 size = ip->i_size - offset;
     599              : 
     600      2133794 :         if (!size)
     601            0 :                 return 0;
     602              : 
     603      2133794 :         if (isdir) {
     604          122 :                 lblock = offset;
     605          122 :                 o = lblock % sdp->sd_jbsize;
     606          122 :                 lblock /= sdp->sd_jbsize;
     607              :         } else {
     608      2133672 :                 lblock = offset >> sdp->sd_bsize_shift;
     609      2133672 :                 o = offset & (sdp->sd_bsize - 1);
     610              :         }
     611              : 
     612      2133794 :         if (inode_is_stuffed(ip))
     613         3559 :                 o += sizeof(struct gfs2_dinode);
     614      2130235 :         else if (isdir)
     615            0 :                 o += sizeof(struct gfs2_meta_header);
     616              : 
     617      4301066 :         while (copied < size) {
     618      2167272 :                 amount = size - copied;
     619      2167272 :                 if (amount > sdp->sd_bsize - o)
     620        33478 :                         amount = sdp->sd_bsize - o;
     621              : 
     622      2167272 :                 if (!extlen) {
     623      2133794 :                         if (lgfs2_block_map(ip, lblock, &not_new, &dblock, &extlen, 0))
     624            0 :                                 return -1;
     625              :                 }
     626              : 
     627      2167272 :                 if (dblock) {
     628      2167272 :                         if (dblock == ip->i_num.in_addr)
     629         3559 :                                 bh = ip->i_bh;
     630              :                         else
     631      2163713 :                                 bh = lgfs2_bread(sdp, dblock);
     632      2167272 :                         dblock++;
     633      2167272 :                         extlen--;
     634              :                 } else
     635            0 :                         bh = NULL;
     636              : 
     637      2167272 :                 copy2mem(bh, &buf, o, amount);
     638      2167272 :                 if (bh && bh != ip->i_bh)
     639      2163713 :                         lgfs2_brelse(bh);
     640              : 
     641      2167272 :                 copied += amount;
     642      2167272 :                 lblock++;
     643      2167272 :                 o = (isdir) ? sizeof(struct gfs2_meta_header) : 0;
     644              :         }
     645              : 
     646      2133794 :         return copied;
     647              : }
     648              : 
     649         7003 : static void copy_from_mem(struct lgfs2_buffer_head *bh, void **buf,
     650              :                           unsigned int offset, unsigned int size)
     651              : {
     652         7003 :         char **p = (char **)buf;
     653              : 
     654         7003 :         memcpy(bh->b_data + offset, *p, size);
     655         7003 :         lgfs2_bmodified(bh);
     656         7003 :         *p += size;
     657         7003 : }
     658              : 
     659         6871 : int __lgfs2_writei(struct lgfs2_inode *ip, void *buf,
     660              :                   uint64_t offset, unsigned int size, int resize)
     661              : {
     662         6871 :         struct lgfs2_sbd *sdp = ip->i_sbd;
     663              :         struct lgfs2_buffer_head *bh;
     664              :         uint64_t lblock, dblock;
     665              :         unsigned int o;
     666         6871 :         uint32_t extlen = 0;
     667              :         unsigned int amount;
     668              :         int new;
     669         6871 :         int isdir = !!(S_ISDIR(ip->i_mode));
     670         6871 :         const uint64_t start = offset;
     671         6871 :         int copied = 0;
     672              : 
     673         6871 :         if (!size)
     674            0 :                 return 0;
     675              : 
     676         6871 :         if (inode_is_stuffed(ip) &&
     677         2626 :             ((start + size) > (sdp->sd_bsize - sizeof(struct gfs2_dinode))))
     678           61 :                 if (lgfs2_unstuff_dinode(ip))
     679            0 :                         return -1;
     680              : 
     681         6871 :         if (isdir) {
     682            2 :                 lblock = offset;
     683            2 :                 o = lblock % sdp->sd_jbsize;
     684            2 :                 lblock /= sdp->sd_jbsize;
     685              :         } else {
     686         6869 :                 lblock = offset >> sdp->sd_bsize_shift;
     687         6869 :                 o = offset & (sdp->sd_bsize - 1);
     688              :         }
     689              : 
     690         6871 :         if (inode_is_stuffed(ip))
     691         2565 :                 o += sizeof(struct gfs2_dinode);
     692         4306 :         else if (isdir)
     693            0 :                 o += sizeof(struct gfs2_meta_header);
     694              : 
     695        13874 :         while (copied < size) {
     696         7003 :                 amount = size - copied;
     697         7003 :                 if (amount > sdp->sd_bsize - o)
     698          132 :                         amount = sdp->sd_bsize - o;
     699              : 
     700         7003 :                 if (!extlen) {
     701         7003 :                         new = 1;
     702         7003 :                         if (lgfs2_block_map(ip, lblock, &new, &dblock, &extlen, 0))
     703            0 :                                 return -1;
     704              :                 }
     705              : 
     706         7003 :                 if (new) {
     707          169 :                         bh = lgfs2_bget(sdp, dblock);
     708          169 :                         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         6834 :                         if (dblock == ip->i_num.in_addr)
     719         2565 :                                 bh = ip->i_bh;
     720              :                         else
     721         4269 :                                 bh = lgfs2_bread(sdp, dblock);
     722              :                 }
     723         7003 :                 copy_from_mem(bh, &buf, o, amount);
     724         7003 :                 if (bh != ip->i_bh)
     725         4438 :                         lgfs2_brelse(bh);
     726              : 
     727         7003 :                 copied += amount;
     728         7003 :                 lblock++;
     729         7003 :                 dblock++;
     730         7003 :                 extlen--;
     731              : 
     732         7003 :                 o = (isdir) ? sizeof(struct gfs2_meta_header) : 0;
     733              :         }
     734              : 
     735         6871 :         if (resize && ip->i_size < start + copied) {
     736         6794 :                 lgfs2_bmodified(ip->i_bh);
     737         6794 :                 ip->i_size = start + copied;
     738              :         }
     739              : 
     740         6871 :         return copied;
     741              : }
     742              : 
     743         6533 : int lgfs2_dirent_first(struct lgfs2_inode *dip, struct lgfs2_buffer_head *bh,
     744              :                                           struct gfs2_dirent **dent)
     745              : {
     746         6533 :         struct gfs2_meta_header *h = (struct gfs2_meta_header *)bh->b_data;
     747              : 
     748         6533 :         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         6423 :                 *dent = (struct gfs2_dirent *)(bh->b_data + sizeof(struct gfs2_dinode));
     753         6423 :                 return LGFS2_IS_DINODE;
     754              :         }
     755              : }
     756              : 
     757        34199 : 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        34199 :         bh_end = bh->b_data + dip->i_sbd->sd_bsize;
     764        34199 :         cur_rec_len = be16_to_cpu((*dent)->de_rec_len);
     765              : 
     766        34199 :         if (cur_rec_len == 0 || (char *)(*dent) + cur_rec_len >= bh_end)
     767          678 :                 return -ENOENT;
     768              : 
     769        33521 :         *dent = (struct gfs2_dirent *)((char *)(*dent) + cur_rec_len);
     770              : 
     771        33521 :         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          756 : 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          756 :         unsigned int rec_len = GFS2_DIRENT_SIZE(name_len);
     784          756 :         unsigned int entries = 0, offset = 0;
     785              :         int type;
     786              : 
     787          756 :         type = lgfs2_dirent_first(dip, bh, &dent);
     788              : 
     789          756 :         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          721 :                 struct gfs2_dinode *dinode = (struct gfs2_dinode *)bh->b_data;
     795          721 :                 entries = be32_to_cpu(dinode->di_entries);
     796          721 :                 offset = sizeof(struct gfs2_dinode);
     797              :         }
     798              : 
     799          756 :         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         2927 :                 cur_rec_len = be16_to_cpu(dent->de_rec_len);
     815         2927 :                 cur_name_len = be16_to_cpu(dent->de_name_len);
     816              : 
     817         2927 :                 if ((!dent->de_inum.no_formal_ino && cur_rec_len >= rec_len) ||
     818         2926 :                     (cur_rec_len >= GFS2_DIRENT_SIZE(cur_name_len) + rec_len)) {
     819              : 
     820          745 :                         if (dent->de_inum.no_formal_ino) {
     821          744 :                                 new = (struct gfs2_dirent *)((char *)dent +
     822          744 :                                                             GFS2_DIRENT_SIZE(cur_name_len));
     823          744 :                                 memset(new, 0, sizeof(struct gfs2_dirent));
     824              : 
     825          744 :                                 new->de_rec_len = cpu_to_be16(cur_rec_len -
     826              :                                           GFS2_DIRENT_SIZE(cur_name_len));
     827          744 :                                 new->de_name_len = cpu_to_be16(name_len);
     828              : 
     829          744 :                                 new_rec_len = be16_to_cpu(new->de_rec_len);
     830          744 :                                 dent->de_rec_len = cpu_to_be16(cur_rec_len - new_rec_len);
     831              : 
     832          744 :                                 *dent_out = new;
     833          744 :                                 lgfs2_bmodified(bh);
     834          744 :                                 dip->i_entries++;
     835          744 :                                 lgfs2_bmodified(dip->i_bh);
     836          744 :                                 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         2182 :         } 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          721 : 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          721 :         int err = 0;
    1316              : 
    1317          721 :         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          714 :         lgfs2_inum_out(inum, &dent->de_inum);
    1326          714 :         de_hash = lgfs2_disk_hash(filename, len);
    1327          714 :         dent->de_hash = cpu_to_be32(de_hash);
    1328          714 :         dent->de_type = cpu_to_be16(type);
    1329          714 :         memcpy((char *)(dent + 1), filename, len);
    1330          714 :         lgfs2_bmodified(dip->i_bh);
    1331          714 :         return err;
    1332              : }
    1333              : 
    1334          739 : int lgfs2_dir_add(struct lgfs2_inode *dip, const char *filename, int len,
    1335              :                   struct lgfs2_inum *inum, unsigned int type)
    1336              : {
    1337          739 :         int err = 0;
    1338          739 :         if (dip->i_flags & GFS2_DIF_EXHASH)
    1339           18 :                 err = dir_e_add(dip, filename, len, inum, type);
    1340              :         else
    1341          721 :                 err = dir_l_add(dip, filename, len, inum, type);
    1342          739 :         return err;
    1343              : }
    1344              : 
    1345          803 : 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          803 :         int is_dir = S_ISDIR(mode);
    1351              : 
    1352          803 :         errno = EINVAL;
    1353          803 :         if (bhp == NULL)
    1354            0 :                 return 1;
    1355              : 
    1356          803 :         if (*bhp == NULL) {
    1357          803 :                 *bhp = lgfs2_bget(sdp, inum->in_addr);
    1358          803 :                 if (*bhp == NULL)
    1359            0 :                         return 1;
    1360              :         }
    1361              : 
    1362          803 :         bh = *bhp;
    1363              : 
    1364          803 :         di = (struct gfs2_dinode *)bh->b_data;
    1365              : 
    1366          803 :         di->di_header.mh_magic = cpu_to_be32(GFS2_MAGIC);
    1367          803 :         di->di_header.mh_type = cpu_to_be32(GFS2_METATYPE_DI);
    1368          803 :         di->di_header.mh_format = cpu_to_be32(GFS2_FORMAT_DI);
    1369          803 :         di->di_num.no_formal_ino = cpu_to_be64(inum->in_formal_ino);
    1370          803 :         di->di_num.no_addr = cpu_to_be64(inum->in_addr);
    1371          803 :         di->di_mode = cpu_to_be32(mode);
    1372          803 :         di->di_nlink = cpu_to_be32(1);
    1373          803 :         di->di_blocks = cpu_to_be64(1);
    1374          803 :         di->di_atime = di->di_mtime = di->di_ctime = cpu_to_be64(sdp->sd_time);
    1375          803 :         di->di_goal_meta = di->di_goal_data = cpu_to_be64(bh->b_blocknr);
    1376          803 :         di->di_flags = cpu_to_be32(flags);
    1377              : 
    1378          803 :         if (is_dir) {
    1379          284 :                 char *p = bh->b_data + sizeof(*di);
    1380          284 :                 struct gfs2_dirent de = {0};
    1381              :                 uint32_t hash;
    1382              :                 uint16_t len;
    1383              : 
    1384          284 :                 hash = lgfs2_disk_hash(".", 1);
    1385          284 :                 len = GFS2_DIRENT_SIZE(1);
    1386          284 :                 de.de_inum = di->di_num;
    1387          284 :                 de.de_hash = cpu_to_be32(hash);
    1388          284 :                 de.de_rec_len = cpu_to_be16(len);
    1389          284 :                 de.de_name_len = cpu_to_be16(1);
    1390          284 :                 de.de_type = cpu_to_be16(IF2DT(S_IFDIR));
    1391          284 :                 memcpy(p, &de, sizeof(de));
    1392          284 :                 p[sizeof(de)] = '.';
    1393          284 :                 p += len;
    1394              : 
    1395          284 :                 hash = lgfs2_disk_hash("..", 2);
    1396          284 :                 len = sdp->sd_bsize - (p - bh->b_data);
    1397          284 :                 de.de_inum.no_formal_ino = cpu_to_be64(parent->in_formal_ino);
    1398          284 :                 de.de_inum.no_addr = cpu_to_be64(parent->in_addr);
    1399          284 :                 de.de_hash = cpu_to_be32(hash);
    1400          284 :                 de.de_rec_len = cpu_to_be16(len);
    1401          284 :                 de.de_name_len = cpu_to_be16(2);
    1402          284 :                 de.de_type = cpu_to_be16(IF2DT(S_IFDIR));
    1403          284 :                 memcpy(p, &de, sizeof(de));
    1404          284 :                 p += sizeof(de);
    1405          284 :                 *p++ = '.';
    1406          284 :                 *p = '.';
    1407              : 
    1408          284 :                 di->di_nlink = cpu_to_be32(2);
    1409          284 :                 di->di_size = cpu_to_be64(sdp->sd_bsize - sizeof(struct gfs2_dinode));
    1410          284 :                 di->di_flags = cpu_to_be32(flags | GFS2_DIF_JDATA);
    1411          284 :                 di->di_payload_format = cpu_to_be32(GFS2_FORMAT_DE);
    1412          284 :                 di->di_entries = cpu_to_be32(2);
    1413              :         }
    1414          803 :         lgfs2_bmodified(bh);
    1415          803 :         return 0;
    1416              : }
    1417              : 
    1418          142 : 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          142 :         return __init_dinode(sdp, bhp, inum, mode, flags, parent);
    1422              : }
    1423              : 
    1424         8289 : static void lgfs2_fill_indir(char *start, char *end, uint64_t ptr0, unsigned n, unsigned *p)
    1425              : {
    1426              :         char *bp;
    1427         8289 :         memset(start, 0, end - start);
    1428      2433140 :         for (bp = start; bp < end && *p < n; bp += sizeof(uint64_t)) {
    1429      2424851 :                 uint64_t pn = ptr0 + *p;
    1430      2424851 :                 *(__be64 *)bp = cpu_to_be64(pn);
    1431      2424851 :                 (*p)++;
    1432              :         }
    1433         8289 : }
    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           78 : int lgfs2_write_filemeta(struct lgfs2_inode *ip)
    1443              : {
    1444           78 :         unsigned height = 0;
    1445              :         struct lgfs2_metapath mp;
    1446           78 :         struct lgfs2_sbd *sdp = ip->i_sbd;
    1447           78 :         uint64_t dblocks = (ip->i_size + sdp->sd_bsize - 1) / sdp->sd_bsize;
    1448           78 :         uint64_t ptr0 = ip->i_num.in_addr + 1;
    1449           78 :         unsigned ptrs = 1;
    1450          312 :         struct gfs2_meta_header mh = {
    1451           78 :                 .mh_magic = cpu_to_be32(GFS2_MAGIC),
    1452           78 :                 .mh_type = cpu_to_be32(GFS2_METATYPE_IN),
    1453           78 :                 .mh_format = cpu_to_be32(GFS2_FORMAT_IN)
    1454              :         };
    1455           78 :         struct lgfs2_buffer_head *bh = lgfs2_bget(sdp, ip->i_num.in_addr);
    1456           78 :         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           78 :         lgfs2_find_metapath(ip, dblocks - 1, &mp);
    1463              : 
    1464          245 :         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          167 :                 ptrs = ((ptrs - 1) * sdp->sd_inptrs) + mp.mp_list[height] + 1;
    1471              : 
    1472         8456 :                 for (p = 0; p < ptrs; bh->b_blocknr++) {
    1473         8289 :                         char *start = bh->b_data;
    1474         8289 :                         if (height == 0) {
    1475           78 :                                 start += sizeof(struct gfs2_dinode);
    1476           78 :                                 lgfs2_dinode_out(ip, bh->b_data);
    1477              :                         } else {
    1478         8211 :                                 start += sizeof(struct gfs2_meta_header);
    1479         8211 :                                 memcpy(bh->b_data, &mh, sizeof(mh));
    1480              :                         }
    1481         8289 :                         lgfs2_fill_indir(start, bh->b_data + sdp->sd_bsize, ptr0, ptrs, &p);
    1482         8289 :                         if (lgfs2_bwrite(bh)) {
    1483            0 :                                 free(bh);
    1484            0 :                                 return 1;
    1485              :                         }
    1486              :                 }
    1487          167 :                 ptr0 += ptrs;
    1488              :         }
    1489           78 :         free(bh);
    1490           78 :         return 0;
    1491              : }
    1492              : 
    1493          661 : static struct lgfs2_inode *do_createi(struct lgfs2_inode *dip, const char *filename,
    1494              :                                       unsigned int mode, uint32_t flags)
    1495              : {
    1496          661 :         struct lgfs2_inum parent = dip->i_num;
    1497          661 :         struct lgfs2_sbd *sdp = dip->i_sbd;
    1498              :         uint64_t bn;
    1499              :         struct lgfs2_inum inum;
    1500          661 :         struct lgfs2_buffer_head *bh = NULL;
    1501              :         struct lgfs2_inode *ip;
    1502          661 :         int err = 0;
    1503              :         int is_dir;
    1504              : 
    1505          661 :         err = lgfs2_dinode_alloc(sdp, 1, &bn);
    1506          661 :         if (err != 0)
    1507            0 :                 return NULL;
    1508              : 
    1509          661 :         inum.in_formal_ino = sdp->md.next_inum++;
    1510          661 :         inum.in_addr = bn;
    1511              : 
    1512          661 :         err = lgfs2_dir_add(dip, filename, strlen(filename), &inum, IF2DT(mode));
    1513          661 :         if (err)
    1514            0 :                 return NULL;
    1515              : 
    1516          661 :         is_dir = S_ISDIR(mode);
    1517          661 :         if (is_dir) {
    1518          142 :                 lgfs2_bmodified(dip->i_bh);
    1519          142 :                 dip->i_nlink++;
    1520              :         }
    1521          661 :         err = __init_dinode(sdp, &bh, &inum, mode, flags, &parent);
    1522          661 :         if (err != 0)
    1523            0 :                 return NULL;
    1524              : 
    1525          661 :         ip = lgfs2_inode_get(sdp, bh);
    1526          661 :         if (ip == NULL)
    1527            0 :                 return NULL;
    1528          661 :         lgfs2_bmodified(bh);
    1529          661 :         ip->bh_owned = 1;
    1530          661 :         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          661 : struct lgfs2_inode *lgfs2_createi(struct lgfs2_inode *dip, const char *filename,
    1543              :                                  unsigned int mode, uint32_t flags)
    1544              : {
    1545          661 :         struct lgfs2_inode *ip = lgfs2_lookupi(dip, filename, strlen(filename));
    1546              : 
    1547          661 :         if (ip != NULL) {
    1548            0 :                 ip->bh_owned = 1;
    1549            0 :                 return ip;
    1550              :         }
    1551          661 :         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        10863 : static int gfs2_filecmp(const char *file1, const char *file2, int len_of_file2)
    1566              : {
    1567        10863 :         if (strlen(file1) != len_of_file2)
    1568         5761 :                 return 0;
    1569         5102 :         if (memcmp(file1, file2, len_of_file2))
    1570            0 :                 return 0;
    1571         5102 :         return 1;
    1572              : }
    1573              : 
    1574              : /**
    1575              :  * leaf_search
    1576              :  * @bh:
    1577              :  * @id:
    1578              :  * @dent_out:
    1579              :  * @dent_prev:
    1580              :  *
    1581              :  * Returns:
    1582              :  */
    1583         5768 : 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         5768 :         struct gfs2_dirent *dent, *prev = NULL;
    1590         5768 :         unsigned int entries = 0, x = 0;
    1591              :         int type;
    1592              : 
    1593         5768 :         type = lgfs2_dirent_first(dip, bh, &dent);
    1594              : 
    1595         5768 :         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         5702 :         } else if (type == LGFS2_IS_DINODE)
    1599         5702 :                 entries = dip->i_entries;
    1600              :         else
    1601            0 :                 return -1;
    1602              : 
    1603         5768 :         hash = lgfs2_disk_hash(filename, len);
    1604              : 
    1605              :         do{
    1606        37076 :                 if (!dent->de_inum.no_formal_ino){
    1607            4 :                         prev = dent;
    1608            4 :                         continue;
    1609              :                 }
    1610              : 
    1611        42173 :                 if (be32_to_cpu(dent->de_hash) == hash &&
    1612         5101 :                         gfs2_filecmp(filename, (char *)(dent + 1),
    1613         5101 :                                      be16_to_cpu(dent->de_name_len))) {
    1614         5101 :                         *dent_out = dent;
    1615         5101 :                         if (dent_prev)
    1616            1 :                                 *dent_prev = prev;
    1617         5101 :                         return 0;
    1618              :                 }
    1619              : 
    1620        31971 :                 if(x >= entries)
    1621            0 :                         return -1;
    1622        31971 :                 x++;
    1623        31971 :                 prev = dent;
    1624        31975 :         } while (lgfs2_dirent_next(dip, bh, &dent) == 0);
    1625              : 
    1626          667 :         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         5701 : 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         5701 :         if(!inode_is_stuffed(dip))
    1739            0 :                 return -1;
    1740              : 
    1741         5701 :         error = leaf_search(dip, dip->i_bh, filename, len, &dent, NULL);
    1742         5701 :         if (!error) {
    1743         5052 :                 lgfs2_inum_in(inum, &dent->de_inum);
    1744         5052 :                 if(type)
    1745            0 :                         *type = be16_to_cpu(dent->de_type);
    1746              :         }
    1747         5701 :         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         5767 : 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         5767 :         if (!S_ISDIR(dip->i_mode))
    1769            0 :                 return -1;
    1770              : 
    1771         5767 :         if (dip->i_flags & GFS2_DIF_EXHASH)
    1772           66 :                 error = dir_e_search(dip, filename, len, type, inum);
    1773              :         else
    1774         5701 :                 error = dir_l_search(dip, filename, len, type, inum);
    1775              : 
    1776         5767 :         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         5764 : 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         5764 :         int error = 0;
    1881              : 
    1882         5764 :         errno = EINVAL;
    1883         5764 :         if (dip == NULL)
    1884            0 :                 return NULL;
    1885         5764 :         sdp = dip->i_sbd;
    1886         5764 :         errno = ENAMETOOLONG;
    1887         5764 :         if (!len || len > GFS2_FNAMESIZE)
    1888            2 :                 return NULL;
    1889              : 
    1890         5762 :         if (gfs2_filecmp(filename, ".", 1))
    1891            1 :                 return dip;
    1892              : 
    1893         5761 :         error = lgfs2_dir_search(dip, filename, len, NULL, &inum);
    1894         5761 :         if (error)
    1895          667 :                 return NULL;
    1896         5094 :         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 : }
        

Generated by: LCOV version 2.0-1