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 13struct obj_dentry *dentarr_first_dentry(struct obj_dentarr *dentarr) 14{ 15 if (le32_to_cpu(dentarr->nb_dentry) == 0) 16 return NULL; 17 return (void *)dentarr + BILBYFS_DENTARR_SZ; 18} 19 20static struct obj_dentry *dentarr_end(struct obj_dentarr *dentarr) 21{ 22 return ((void *)dentarr + obj_dentarr_size(dentarr)); 23} 24 25struct obj_dentry *dentarr_next_dentry(struct obj_dentarr *dentarr, 26 struct obj_dentry *dentry) 27{ 28 struct obj_dentry *next_de; 29 30 next_de = (void *) dentry + obj_dentry_size(dentry); 31 if (next_de == dentarr_end(dentarr)) 32 return NULL; 33 return next_de; 34} 35 36int dentarr_check_empty(struct bilbyfs_info *bi, struct obj_dentarr *dentarr) 37{ 38 return (!dentarr_first_dentry(dentarr) ? 0 : -ENOTEMPTY); 39} 40 41int dentarr_add_dentry(struct bilbyfs_info *bi, struct obj_dentarr *dentarr, 42 struct inode *inode, const char *name) 43{ 44 struct obj_dentry *de; 45 int sz_change; 46 int nb_dentry; 47 obj_id id; 48 int len; 49 50 sz_change = obj_dentry_size_from_nm(name); 51 id = le64_to_cpu(dentarr->id); 52 nb_dentry = le32_to_cpu(dentarr->nb_dentry) + 1; 53 len = obj_dentarr_size(dentarr); 54 de = dentarr_end(dentarr); 55 56 pack_obj_dentry(de, inode, name); 57 pack_obj_dentarr(dentarr, id, nb_dentry, len + sz_change); 58 return sz_change; 59} 60 61int dentarr_del_dentry(struct bilbyfs_info *bi, struct obj_dentarr *dentarr, 62 const char *name) 63{ 64 struct obj_dentarr *copy_dentarr; 65 struct obj_dentry *de; 66 struct obj_dentry *copy_de; 67 int sz_change; 68 int nb_dentry; 69 obj_id id; 70 int delen; 71 int len; 72 73 sz_change = obj_dentry_size_from_nm(name); 74 id = le64_to_cpu(dentarr->id); 75 nb_dentry = le32_to_cpu(dentarr->nb_dentry); 76 len = obj_dentarr_size(dentarr); 77 78 copy_dentarr = kmalloc(len); 79 if (!copy_dentarr) 80 return -ENOMEM; 81 memcpy(copy_dentarr, dentarr, len); 82 83 copy_de = dentarr_lookup_nm(bi, copy_dentarr, name); 84 de = dentarr_lookup_nm(bi, dentarr, name); 85 if (nb_dentry <= 0 || !copy_de) { 86 kfree(copy_dentarr); 87 return 0; 88 } 89 90 copy_de = dentarr_next_dentry(copy_dentarr, copy_de); 91 while (copy_de) { 92 delen = obj_dentry_size(de); 93 memcpy(de, copy_de, delen); 94 de = (void *) de + delen; 95 copy_de = dentarr_next_dentry(copy_dentarr, copy_de); 96 } 97 kfree(copy_dentarr); 98 99 nb_dentry--; 100 if (nb_dentry == 0) { 101 memset(dentarr, 0, len); 102 pack_obj_del(dentarr, id); 103 } else { 104 pack_obj_dentarr(dentarr, id, nb_dentry, len - sz_change); 105 } 106 return sz_change; 107} 108 109struct obj_dentry *dentarr_lookup_nm(struct bilbyfs_info *bi, 110 struct obj_dentarr *dentarr, 111 const char *name) 112{ 113 struct obj_dentry *de; 114 115 de = dentarr_first_dentry(dentarr); 116 while (de) { 117 if (!strcmp(de->name, name)) 118 return de; 119 de = dentarr_next_dentry(dentarr, de); 120 } 121 return ERR_PTR(-ENOENT); 122} 123 124struct obj_dentarr *dentarr_read(struct bilbyfs_info *bi, obj_id id) 125{ 126 struct obj_dentarr *dentarr; 127 int err; 128 /* We need to allocate enough to be able to add an entry */ 129 int size = BILBYFS_MAX_DENTARR_SZ; 130 131 bilbyfs_debug("[S] dentarr_read(0x%llx)\n", id); 132 dentarr = kmalloc(size); 133 if (!dentarr) 134 return ERR_PTR(-ENOMEM); 135 136 err = ostore_read_obj(bi, id, dentarr, size); 137 if (err) { 138 kfree(dentarr); 139 return ERR_PTR(err); 140 } 141 /* Sanity checking */ 142 if (le32_to_cpu(dentarr->nb_dentry) > BILBYFS_MAX_DENTARR_ENTRIES || 143 le32_to_cpu(dentarr->size) > BILBYFS_MAX_DENTARR_SZ) { 144 kfree(dentarr); 145 bilbyfs_err("dentarr_read: lookup err nb_dentry=%d, size=%d\n", le32_to_cpu(dentarr->nb_dentry), le32_to_cpu(dentarr->size)); 146 return ERR_PTR(-EINVAL); 147 } 148 return dentarr; 149} 150 151struct obj_dentarr *dentarr_read_or_create(struct bilbyfs_info *bi, obj_id id) 152{ 153 struct obj_dentarr *dentarr; 154 155 dentarr = dentarr_read(bi, id); 156 if (IS_ERR(dentarr)) { 157 if (PTR_ERR(dentarr) != -ENOENT) 158 return dentarr; 159 dentarr = kmalloc(BILBYFS_DENTARR_SZ + BILBYFS_MAX_DENTRY_SZ); 160 if (!dentarr) 161 return ERR_PTR(-ENOMEM); 162 pack_obj_dentarr(dentarr, id, 0, BILBYFS_DENTARR_SZ); 163 } 164 return dentarr; 165} 166