Changes in uspace/srv/volsrv/empty.c [5772aa1:363a504] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/srv/volsrv/empty.c
r5772aa1 r363a504 38 38 #include <errno.h> 39 39 #include <io/log.h> 40 #include <label/empty.h>41 40 #include <loc.h> 42 41 #include <stdlib.h> … … 44 43 #include "empty.h" 45 44 46 static int empty_get_bsize(void *, size_t *); 47 static int empty_get_nblocks(void *, aoff64_t *); 48 static int empty_read(void *, aoff64_t, size_t, void *); 49 static int empty_write(void *, aoff64_t, size_t, const void *); 50 51 /** Provide disk access to liblabel */ 52 static label_bd_ops_t empty_bd_ops = { 53 .get_bsize = empty_get_bsize, 54 .get_nblocks = empty_get_nblocks, 55 .read = empty_read, 56 .write = empty_write 45 /* 46 * The partition will be considered empty if at least a minimum number of 47 * bytes *and* blocks (whichever is larger) at the beginning and end of 48 * the partition is zero. 49 */ 50 enum { 51 min_empty_bytes = 16384, 52 /* 53 * First block in ISO 9660 that cannot be empty is the first 54 * volume descriptor at LBA 16 55 */ 56 min_empty_blocks = 17 57 57 }; 58 58 59 static bool mem_is_zero(void *buf, size_t size) 60 { 61 uint8_t *bp; 62 size_t i; 63 64 bp = (uint8_t *)buf; 65 for (i = 0; i < size; i++) { 66 if (bp[i] != 0) 67 return false; 68 } 69 70 return true; 71 } 72 73 /** Calculate number of blocks to check. 74 * 75 * Will store to @a *ncb the number of blocks that should be checked 76 * at the beginning and end of device each. 77 * 78 * @param nblocks Total number of blocks on block device 79 * @param block_size Block size 80 * @param ncb Place to store number of blocks to check. 81 */ 82 static void calc_num_check_blocks(aoff64_t nblocks, size_t block_size, 83 aoff64_t *ncb) 84 { 85 aoff64_t n; 86 87 /* Check first 16 kiB / 16 blocks, whichever is more */ 88 n = (min_empty_bytes + block_size - 1) / block_size; 89 if (n < min_empty_blocks) 90 n = min_empty_blocks; 91 /* 92 * Limit to half of the device so we do not process the same blocks 93 * twice 94 */ 95 if (n > (nblocks + 1) / 2) 96 n = (nblocks + 1) / 2; 97 98 *ncb = n; 99 } 100 59 101 int volsrv_part_is_empty(service_id_t sid, bool *rempty) 60 102 { 61 103 int rc; 62 label_bd_t lbd; 104 bool block_inited = false; 105 void *buf = NULL; 106 aoff64_t nblocks; 107 aoff64_t n; 108 aoff64_t i; 109 size_t block_size; 110 bool empty; 63 111 64 112 rc = block_init(sid, 2048); … … 66 114 log_msg(LOG_DEFAULT, LVL_ERROR, "Error opening " 67 115 "block device service %zu", sid); 68 return EIO; 69 } 70 71 lbd.ops = &empty_bd_ops; 72 lbd.arg = (void *)&sid; 73 74 rc = label_bd_is_empty(&lbd, rempty); 75 116 rc = EIO; 117 goto error; 118 } 119 120 block_inited = true; 121 122 rc = block_get_bsize(sid, &block_size); 123 if (rc != EOK) { 124 log_msg(LOG_DEFAULT, LVL_ERROR, "Error getting " 125 "block size."); 126 rc = EIO; 127 goto error; 128 } 129 130 rc = block_get_nblocks(sid, &nblocks); 131 if (rc != EOK) { 132 log_msg(LOG_DEFAULT, LVL_ERROR, "Error getting " 133 "number of blocks."); 134 rc = EIO; 135 goto error; 136 } 137 138 calc_num_check_blocks(nblocks, block_size, &n); 139 140 buf = calloc(block_size, 1); 141 if (buf == NULL) { 142 log_msg(LOG_DEFAULT, LVL_ERROR, "Error allocating buffer."); 143 rc = ENOMEM; 144 goto error; 145 } 146 147 empty = true; 148 149 for (i = 0; i < n; i++) { 150 rc = block_read_direct(sid, i, 1, buf); 151 if (rc != EOK) { 152 log_msg(LOG_DEFAULT, LVL_ERROR, "Error " 153 "reading blocks."); 154 rc = EIO; 155 goto error; 156 } 157 158 if (!mem_is_zero(buf, block_size)) { 159 empty = false; 160 goto done; 161 } 162 } 163 164 for (i = 0; i < n; i++) { 165 rc = block_read_direct(sid, nblocks - n + i, 1, buf); 166 if (rc != EOK) { 167 log_msg(LOG_DEFAULT, LVL_ERROR, "Error " 168 "reading blocks."); 169 rc = EIO; 170 goto error; 171 } 172 173 if (!mem_is_zero(buf, block_size)) { 174 empty = false; 175 goto done; 176 } 177 } 178 179 done: 76 180 block_fini(sid); 181 free(buf); 182 *rempty = empty; 183 return EOK; 184 error: 185 if (block_inited) 186 block_fini(sid); 187 if (buf != NULL) 188 free(buf); 77 189 return rc; 78 190 } … … 81 193 { 82 194 int rc; 83 label_bd_t lbd; 195 bool block_inited = false; 196 void *buf = NULL; 197 aoff64_t nblocks; 198 aoff64_t n; 199 aoff64_t i; 200 size_t block_size; 84 201 85 202 rc = block_init(sid, 2048); … … 87 204 log_msg(LOG_DEFAULT, LVL_ERROR, "Error opening " 88 205 "block device service %zu", sid); 89 return EIO; 90 } 91 92 lbd.ops = &empty_bd_ops; 93 lbd.arg = (void *)&sid; 94 95 rc = label_bd_empty(&lbd); 206 rc = EIO; 207 goto error; 208 } 209 210 block_inited = true; 211 212 rc = block_get_bsize(sid, &block_size); 213 if (rc != EOK) { 214 log_msg(LOG_DEFAULT, LVL_ERROR, "Error getting " 215 "block size."); 216 rc = EIO; 217 goto error; 218 } 219 220 rc = block_get_nblocks(sid, &nblocks); 221 if (rc != EOK) { 222 log_msg(LOG_DEFAULT, LVL_ERROR, "Error getting " 223 "number of blocks."); 224 rc = EIO; 225 goto error; 226 } 227 228 calc_num_check_blocks(nblocks, block_size, &n); 229 230 buf = calloc(block_size, 1); 231 if (buf == NULL) { 232 log_msg(LOG_DEFAULT, LVL_ERROR, "Error allocating buffer."); 233 rc = ENOMEM; 234 goto error; 235 } 236 237 for (i = 0; i < n; i++) { 238 rc = block_write_direct(sid, i, 1, buf); 239 if (rc != EOK) { 240 log_msg(LOG_DEFAULT, LVL_ERROR, "Error " 241 "reading blocks."); 242 rc = EIO; 243 goto error; 244 } 245 } 246 247 for (i = 0; i < n; i++) { 248 rc = block_write_direct(sid, nblocks - n + i, 1, buf); 249 if (rc != EOK) { 250 log_msg(LOG_DEFAULT, LVL_ERROR, "Error " 251 "reading blocks."); 252 rc = EIO; 253 goto error; 254 } 255 } 96 256 97 257 block_fini(sid); 258 free(buf); 259 return EOK; 260 error: 261 if (block_inited) 262 block_fini(sid); 263 if (buf != NULL) 264 free(buf); 98 265 return rc; 99 266 } 100 267 101 /** Get block size wrapper for liblabel */102 static int empty_get_bsize(void *arg, size_t *bsize)103 {104 service_id_t svc_id = *(service_id_t *)arg;105 return block_get_bsize(svc_id, bsize);106 }107 108 /** Get number of blocks wrapper for liblabel */109 static int empty_get_nblocks(void *arg, aoff64_t *nblocks)110 {111 service_id_t svc_id = *(service_id_t *)arg;112 return block_get_nblocks(svc_id, nblocks);113 }114 115 /** Read blocks wrapper for liblabel */116 static int empty_read(void *arg, aoff64_t ba, size_t cnt, void *buf)117 {118 service_id_t svc_id = *(service_id_t *)arg;119 return block_read_direct(svc_id, ba, cnt, buf);120 }121 122 /** Write blocks wrapper for liblabel */123 static int empty_write(void *arg, aoff64_t ba, size_t cnt, const void *data)124 {125 service_id_t svc_id = *(service_id_t *)arg;126 return block_write_direct(svc_id, ba, cnt, data);127 }128 129 268 /** @} 130 269 */
Note:
See TracChangeset
for help on using the changeset viewer.