LCOV - code coverage report
Current view: top level - libgfs2 - fs_ops.c (source / functions) Hit Total Coverage
Test: gfs2-utils.info Lines: 806 1047 77.0 %
Date: 2023-10-25 12:04:14 Functions: 52 57 91.2 %

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

Generated by: LCOV version 1.14