1/* 2 * Copyright 2016, NICTA 3 * 4 * This software may be distributed and modified according to the terms of 5 * the GNU General Public License version 2. Note that NO WARRANTY is provided. 6 * See "LICENSE_GPLv2.txt" for details. 7 * 8 * @TAG(NICTA_GPL) 9 */ 10 11#include <bilbyfs.h> 12 13static u8 inode_mode_to_dent_type(umode_t mode) 14{ 15 switch (mode & S_IFMT) { 16 case S_IFREG: return BILBYFS_ITYPE_REG; 17 case S_IFDIR: return BILBYFS_ITYPE_DIR; 18 case S_IFLNK: return BILBYFS_ITYPE_LNK; 19 case S_IFSOCK: return BILBYFS_ITYPE_SOCK; 20 case S_IFIFO: return BILBYFS_ITYPE_FIFO; 21 case S_IFBLK: return BILBYFS_ITYPE_BLK; 22 case S_IFCHR: return BILBYFS_ITYPE_CHR; 23 default: bilbyfs_assert(0); 24 } 25 return 0; 26} 27 28int check_obj_header(void *obj, int max_obj_sz) 29{ 30 struct obj_ch *ch = obj; 31 u32 offs; 32 u32 crc; 33 34 if (max_obj_sz < BILBYFS_CH_SZ) 35 return -ENOENT; 36 if (le32_to_cpu(ch->magic) != BILBYFS_OBJ_MAGIC) 37 return -ENOENT; 38 if (le32_to_cpu(ch->len) < BILBYFS_CH_SZ || 39 le32_to_cpu(ch->len) > max_obj_sz) { 40 bilbyfs_err("Invalid object size (%d vs %d)", le32_to_cpu(ch->len), max_obj_sz); 41 return -EINVAL; 42 } 43 offs = offsetof(struct obj_ch, crc) + sizeof(ch->crc); 44 crc = crc32(BILBYFS_CRC32_INIT, obj + offs, le32_to_cpu(ch->len) - offs); 45 if (crc != le32_to_cpu(ch->crc)) { 46 bilbyfs_err("Invalid CRC32 for object %x != %x, obj->type=%d\n", crc, le32_to_cpu(ch->crc), ch->type); 47 return -EINVAL; 48 } 49 /* FIXME: More sanity checking?? */ 50 return 0; 51} 52 53void pack_obj_header(void *obj, u64 sqnum, u8 trans_pos) 54{ 55 struct obj_ch *ch = obj; 56 uint32_t crc; 57 int offs; 58 59 bilbyfs_assert(ch->type < BILBYFS_OBJ_TYPES_CNT); 60 61 ch->magic = cpu_to_le32(BILBYFS_OBJ_MAGIC); 62 ch->sqnum = cpu_to_le64(sqnum); 63 ch->trans = trans_pos; 64 zero_obj_ch_unused(ch); 65 66 /* we CRC right after the field crc to the end of the object */ 67 offs = offsetof(struct obj_ch, crc) + sizeof(ch->crc); 68 crc = crc32(BILBYFS_CRC32_INIT, obj + offs, le32_to_cpu(ch->len) - offs); 69 ch->crc = cpu_to_le32(crc); 70} 71 72__le32 len_to_le32(int len) 73{ 74 bilbyfs_assert(len >= BILBYFS_CH_SZ); 75 return cpu_to_le32(ALIGN(len, BILBYFS_OBJ_PADDING)); 76} 77 78void pack_obj_inode(struct obj_inode *ino, struct inode *inode) 79{ 80 struct bilbyfs_inode *binode = inode_to_binode(inode); 81 82 ino->ch.type = BILBYFS_INODE_OBJ; 83 ino->ch.len = len_to_le32(BILBYFS_INODE_SZ); 84 85 ino->id = cpu_to_le64(inode_id_init(inode->i_ino)); 86 ino->creat_sqnum = cpu_to_le64(binode->creat_sqnum); 87 ino->size = cpu_to_le64(inode->i_size); 88 ino->atime_sec = cpu_to_le64(inode->i_atime.tv_sec); 89 ino->ctime_sec = cpu_to_le64(inode->i_ctime.tv_sec); 90 ino->mtime_sec = cpu_to_le64(inode->i_mtime.tv_sec); 91 ino->nlink = cpu_to_le32(inode->i_nlink); 92 ino->uid = cpu_to_le32(i_uid_read(inode)); 93 ino->gid = cpu_to_le32(i_gid_read(inode)); 94 ino->mode = cpu_to_le32(inode->i_mode); 95 ino->flags = cpu_to_le32(binode->flags); 96 zero_obj_inode_unused(ino); 97} 98 99void pack_obj_dentarr(struct obj_dentarr *dentarr, obj_id id, 100 int nbdentry, int size) 101{ 102 dentarr->ch.type = BILBYFS_DENTARR_OBJ; 103 dentarr->ch.len = len_to_le32(size); 104 105 dentarr->id = cpu_to_le64(id); 106 dentarr->nb_dentry = cpu_to_le32(nbdentry); 107 dentarr->size = cpu_to_le32(size); 108 zero_obj_dentarr_unused(dentarr); 109} 110 111void pack_obj_data(struct obj_data *odata, obj_id id, int sz_data, 112 const void *data) 113{ 114 odata->ch.type = BILBYFS_DATA_OBJ; 115 odata->ch.len = len_to_le32(BILBYFS_DATA_SZ + sz_data); 116 117 odata->id = cpu_to_le64(id); 118 odata->size = cpu_to_le32(sz_data); 119 memcpy(odata->data, data, sz_data); 120 zero_obj_data_unused(odata); 121} 122 123void pack_obj_dentry(struct obj_dentry *de, struct inode *inode, 124 const char *name) 125{ 126 de->ino = cpu_to_le32(inode->i_ino); 127 de->type = inode_mode_to_dent_type(inode->i_mode); 128 /* The dentry.nlen field does not include the \0 */ 129 de->nlen = cpu_to_le16(strlen(name)); 130 strcpy(de->name, name); 131 zero_obj_dentry_unused(de); 132} 133 134void pack_obj_pad(struct obj_ch *pad, int pad_sz) 135{ 136 pad->type = BILBYFS_PAD_OBJ; 137 pad->len = len_to_le32(pad_sz); 138 139 memset(pad + 1, BILBYFS_PAD_BYTE, pad_sz - BILBYFS_CH_SZ); 140} 141 142void unpack_obj_inode(struct inode *inode, struct obj_inode *ino) 143{ 144 struct bilbyfs_inode *binode = inode_to_binode(inode); 145 146 inode->i_flags |= (S_NOCMTIME | S_NOATIME); 147 set_nlink(inode, le32_to_cpu(ino->nlink)); 148 i_uid_write(inode, le32_to_cpu(ino->uid)); 149 i_gid_write(inode, le32_to_cpu(ino->gid)); 150 inode->i_atime.tv_sec = (int64_t)le64_to_cpu(ino->atime_sec); 151 inode->i_mtime.tv_sec = (int64_t)le64_to_cpu(ino->mtime_sec); 152 inode->i_ctime.tv_sec = (int64_t)le64_to_cpu(ino->ctime_sec); 153 inode->i_mode = le32_to_cpu(ino->mode); 154 inode->i_size = le64_to_cpu(ino->size); 155 156 binode->flags = le32_to_cpu(ino->flags); 157 binode->creat_sqnum = le64_to_cpu(ino->creat_sqnum); 158} 159 160void pack_obj_super(struct obj_super *super, const struct bilbyfs_super *bsuper) 161{ 162 super->ch.type = BILBYFS_SUP_OBJ; 163 super->ch.len = len_to_le32(BILBYFS_SUPER_SZ); 164 165 super->flags = cpu_to_le32(bsuper->flags); 166 super->leb_cnt = cpu_to_le32(bsuper->leb_cnt); 167 super->nb_reserved_del = cpu_to_le32(bsuper->nb_reserved_del); 168 super->nb_reserved_gc = cpu_to_le32(bsuper->nb_reserved_gc); 169 super->leb_size = cpu_to_le32(bsuper->leb_size); 170 super->log_head_leb = cpu_to_le32(bsuper->log_lnum); 171 super->log_head_offs = cpu_to_le32(bsuper->log_offs); 172 super->lowest_sqnum = cpu_to_le64(bsuper->lowest_sqnum); 173 zero_obj_super_unused(super); 174} 175 176void unpack_obj_super(struct bilbyfs_super *bsuper, struct obj_super *super) 177{ 178 bsuper->sqnum = le64_to_cpu(super->ch.sqnum); 179 bsuper->flags = le32_to_cpu(super->flags); 180 bsuper->leb_cnt = le32_to_cpu(super->leb_cnt); 181 bsuper->nb_reserved_del = le32_to_cpu(super->nb_reserved_del); 182 bsuper->nb_reserved_gc = le32_to_cpu(super->nb_reserved_gc); 183 bsuper->leb_size = le32_to_cpu(super->leb_size); 184 bsuper->log_lnum = le32_to_cpu(super->log_head_leb); 185 bsuper->log_offs = le32_to_cpu(super->log_head_offs); 186 bsuper->lowest_sqnum = le64_to_cpu(super->lowest_sqnum); 187 bsuper->last_inum = le64_to_cpu(super->last_inum); 188} 189 190void pack_obj_del(void *obj, obj_id id) 191{ 192 struct obj_del *del = (struct obj_del *) obj; 193 194 del->ch.type = BILBYFS_DEL_OBJ; 195 del->ch.len = len_to_le32(BILBYFS_DEL_SZ); 196 197 del->id = cpu_to_le64(id); 198 199 zero_obj_del_unused(del); 200} 201 202void pack_obj_sum(struct obj_sum *sum, u32 offs) 203{ 204 u32 len = obj_sum_size(sum); 205 206 sum->ch.type = BILBYFS_SUM_OBJ; 207 sum->ch.len = len_to_le32(len); 208 memset((void *)sum + len, BILBYFS_PAD_BYTE, le32_to_cpu(sum->ch.len) - len); 209 *obj_sum_offs(sum) = cpu_to_le32(offs); 210 211 zero_obj_sum_unused(sum); 212} 213