Changes in / [f5af635:bbf88db] in mainline
- Location:
- uspace/srv/fs/fat
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/srv/fs/fat/fat.h
rf5af635 rbbf88db 215 215 extern void fat_sync(ipc_callid_t, ipc_call_t *); 216 216 217 extern int fat_idx_get_new(fat_idx_t **,dev_handle_t);217 extern fat_idx_t *fat_idx_get_new(dev_handle_t); 218 218 extern fat_idx_t *fat_idx_get_by_pos(dev_handle_t, fat_cluster_t, unsigned); 219 219 extern fat_idx_t *fat_idx_get_by_index(dev_handle_t, fs_index_t); -
uspace/srv/fs/fat/fat_idx.c
rf5af635 rbbf88db 339 339 } 340 340 341 static int fat_idx_create(fat_idx_t **fidxp,dev_handle_t dev_handle)341 static fat_idx_t *fat_idx_create(dev_handle_t dev_handle) 342 342 { 343 343 fat_idx_t *fidx; … … 345 345 fidx = (fat_idx_t *) malloc(sizeof(fat_idx_t)); 346 346 if (!fidx) 347 return ENOMEM;347 return NULL; 348 348 if (!fat_index_alloc(dev_handle, &fidx->index)) { 349 349 free(fidx); 350 return ENOSPC;350 return NULL; 351 351 } 352 352 … … 359 359 fidx->nodep = NULL; 360 360 361 *fidxp = fidx; 362 return EOK; 363 } 364 365 int fat_idx_get_new(fat_idx_t **fidxp, dev_handle_t dev_handle) 361 return fidx; 362 } 363 364 fat_idx_t *fat_idx_get_new(dev_handle_t dev_handle) 366 365 { 367 366 fat_idx_t *fidx; 368 int rc;369 367 370 368 fibril_mutex_lock(&used_lock); 371 rc = fat_idx_create(&fidx,dev_handle);372 if ( rc != EOK) {369 fidx = fat_idx_create(dev_handle); 370 if (!fidx) { 373 371 fibril_mutex_unlock(&used_lock); 374 return rc;372 return NULL; 375 373 } 376 374 … … 384 382 fibril_mutex_unlock(&used_lock); 385 383 386 *fidxp = fidx; 387 return EOK; 384 return fidx; 388 385 } 389 386 … … 404 401 fidx = hash_table_get_instance(l, fat_idx_t, uph_link); 405 402 } else { 406 int rc; 407 408 rc = fat_idx_create(&fidx, dev_handle); 409 if (rc != EOK) { 403 fidx = fat_idx_create(dev_handle); 404 if (!fidx) { 410 405 fibril_mutex_unlock(&used_lock); 411 406 return NULL; -
uspace/srv/fs/fat/fat_ops.c
rf5af635 rbbf88db 65 65 static LIST_INITIALIZE(ffn_head); 66 66 67 static void fat_node_initialize(fat_node_t *node) 68 { 69 fibril_mutex_initialize(&node->lock); 70 node->bp = NULL; 71 node->idx = NULL; 72 node->type = 0; 73 link_initialize(&node->ffn_link); 74 node->size = 0; 75 node->lnkcnt = 0; 76 node->refcnt = 0; 77 node->dirty = false; 78 } 79 80 static int fat_node_sync(fat_node_t *node) 81 { 82 block_t *b; 83 fat_bs_t *bs; 84 fat_dentry_t *d; 85 uint16_t bps; 86 unsigned dps; 87 int rc; 88 89 assert(node->dirty); 90 91 bs = block_bb_get(node->idx->dev_handle); 92 bps = uint16_t_le2host(bs->bps); 93 dps = bps / sizeof(fat_dentry_t); 94 95 /* Read the block that contains the dentry of interest. */ 96 rc = _fat_block_get(&b, bs, node->idx->dev_handle, node->idx->pfc, 97 (node->idx->pdi * sizeof(fat_dentry_t)) / bps, BLOCK_FLAGS_NONE); 98 if (rc != EOK) 99 return rc; 100 101 d = ((fat_dentry_t *)b->data) + (node->idx->pdi % dps); 102 103 d->firstc = host2uint16_t_le(node->firstc); 104 if (node->type == FAT_FILE) { 105 d->size = host2uint32_t_le(node->size); 106 } else if (node->type == FAT_DIRECTORY) { 107 d->attr = FAT_ATTR_SUBDIR; 108 } 109 110 /* TODO: update other fields? (e.g time fields) */ 111 112 b->dirty = true; /* need to sync block */ 113 rc = block_put(b); 114 return rc; 115 } 116 117 static fat_node_t *fat_node_get_new(void) 118 { 119 fs_node_t *fn; 120 fat_node_t *nodep; 121 int rc; 122 123 fibril_mutex_lock(&ffn_mutex); 124 if (!list_empty(&ffn_head)) { 125 /* Try to use a cached free node structure. */ 126 fat_idx_t *idxp_tmp; 127 nodep = list_get_instance(ffn_head.next, fat_node_t, ffn_link); 128 if (!fibril_mutex_trylock(&nodep->lock)) 129 goto skip_cache; 130 idxp_tmp = nodep->idx; 131 if (!fibril_mutex_trylock(&idxp_tmp->lock)) { 132 fibril_mutex_unlock(&nodep->lock); 133 goto skip_cache; 134 } 135 list_remove(&nodep->ffn_link); 136 fibril_mutex_unlock(&ffn_mutex); 137 if (nodep->dirty) { 138 rc = fat_node_sync(nodep); 139 assert(rc == EOK); 140 } 141 idxp_tmp->nodep = NULL; 142 fibril_mutex_unlock(&nodep->lock); 143 fibril_mutex_unlock(&idxp_tmp->lock); 144 fn = FS_NODE(nodep); 145 } else { 146 skip_cache: 147 /* Try to allocate a new node structure. */ 148 fibril_mutex_unlock(&ffn_mutex); 149 fn = (fs_node_t *)malloc(sizeof(fs_node_t)); 150 if (!fn) 151 return NULL; 152 nodep = (fat_node_t *)malloc(sizeof(fat_node_t)); 153 if (!nodep) { 154 free(fn); 155 return NULL; 156 } 157 } 158 fat_node_initialize(nodep); 159 fs_node_initialize(fn); 160 fn->data = nodep; 161 nodep->bp = fn; 162 163 return nodep; 164 } 165 166 /** Internal version of fat_node_get(). 167 * 168 * @param idxp Locked index structure. 169 */ 170 static fat_node_t *fat_node_get_core(fat_idx_t *idxp) 171 { 172 block_t *b; 173 fat_bs_t *bs; 174 fat_dentry_t *d; 175 fat_node_t *nodep = NULL; 176 unsigned bps; 177 unsigned spc; 178 unsigned dps; 179 int rc; 180 181 if (idxp->nodep) { 182 /* 183 * We are lucky. 184 * The node is already instantiated in memory. 185 */ 186 fibril_mutex_lock(&idxp->nodep->lock); 187 if (!idxp->nodep->refcnt++) 188 list_remove(&idxp->nodep->ffn_link); 189 fibril_mutex_unlock(&idxp->nodep->lock); 190 return idxp->nodep; 191 } 192 193 /* 194 * We must instantiate the node from the file system. 195 */ 196 197 assert(idxp->pfc); 198 199 nodep = fat_node_get_new(); 200 if (!nodep) 201 return NULL; 202 203 bs = block_bb_get(idxp->dev_handle); 204 bps = uint16_t_le2host(bs->bps); 205 spc = bs->spc; 206 dps = bps / sizeof(fat_dentry_t); 207 208 /* Read the block that contains the dentry of interest. */ 209 rc = _fat_block_get(&b, bs, idxp->dev_handle, idxp->pfc, 210 (idxp->pdi * sizeof(fat_dentry_t)) / bps, BLOCK_FLAGS_NONE); 211 assert(rc == EOK); 212 213 d = ((fat_dentry_t *)b->data) + (idxp->pdi % dps); 214 if (d->attr & FAT_ATTR_SUBDIR) { 215 /* 216 * The only directory which does not have this bit set is the 217 * root directory itself. The root directory node is handled 218 * and initialized elsewhere. 219 */ 220 nodep->type = FAT_DIRECTORY; 221 /* 222 * Unfortunately, the 'size' field of the FAT dentry is not 223 * defined for the directory entry type. We must determine the 224 * size of the directory by walking the FAT. 225 */ 226 uint16_t clusters; 227 rc = fat_clusters_get(&clusters, bs, idxp->dev_handle, 228 uint16_t_le2host(d->firstc)); 229 assert(rc == EOK); 230 nodep->size = bps * spc * clusters; 231 } else { 232 nodep->type = FAT_FILE; 233 nodep->size = uint32_t_le2host(d->size); 234 } 235 nodep->firstc = uint16_t_le2host(d->firstc); 236 nodep->lnkcnt = 1; 237 nodep->refcnt = 1; 238 239 rc = block_put(b); 240 assert(rc == EOK); 241 242 /* Link the idx structure with the node structure. */ 243 nodep->idx = idxp; 244 idxp->nodep = nodep; 245 246 return nodep; 247 } 248 67 249 /* 68 250 * Forward declarations of FAT libfs operations. … … 85 267 86 268 /* 87 * Helper functions.88 */89 static void fat_node_initialize(fat_node_t *node)90 {91 fibril_mutex_initialize(&node->lock);92 node->bp = NULL;93 node->idx = NULL;94 node->type = 0;95 link_initialize(&node->ffn_link);96 node->size = 0;97 node->lnkcnt = 0;98 node->refcnt = 0;99 node->dirty = false;100 }101 102 static int fat_node_sync(fat_node_t *node)103 {104 block_t *b;105 fat_bs_t *bs;106 fat_dentry_t *d;107 uint16_t bps;108 unsigned dps;109 int rc;110 111 assert(node->dirty);112 113 bs = block_bb_get(node->idx->dev_handle);114 bps = uint16_t_le2host(bs->bps);115 dps = bps / sizeof(fat_dentry_t);116 117 /* Read the block that contains the dentry of interest. */118 rc = _fat_block_get(&b, bs, node->idx->dev_handle, node->idx->pfc,119 (node->idx->pdi * sizeof(fat_dentry_t)) / bps, BLOCK_FLAGS_NONE);120 if (rc != EOK)121 return rc;122 123 d = ((fat_dentry_t *)b->data) + (node->idx->pdi % dps);124 125 d->firstc = host2uint16_t_le(node->firstc);126 if (node->type == FAT_FILE) {127 d->size = host2uint32_t_le(node->size);128 } else if (node->type == FAT_DIRECTORY) {129 d->attr = FAT_ATTR_SUBDIR;130 }131 132 /* TODO: update other fields? (e.g time fields) */133 134 b->dirty = true; /* need to sync block */135 rc = block_put(b);136 return rc;137 }138 139 static int fat_node_get_new(fat_node_t **nodepp)140 {141 fs_node_t *fn;142 fat_node_t *nodep;143 int rc;144 145 fibril_mutex_lock(&ffn_mutex);146 if (!list_empty(&ffn_head)) {147 /* Try to use a cached free node structure. */148 fat_idx_t *idxp_tmp;149 nodep = list_get_instance(ffn_head.next, fat_node_t, ffn_link);150 if (!fibril_mutex_trylock(&nodep->lock))151 goto skip_cache;152 idxp_tmp = nodep->idx;153 if (!fibril_mutex_trylock(&idxp_tmp->lock)) {154 fibril_mutex_unlock(&nodep->lock);155 goto skip_cache;156 }157 list_remove(&nodep->ffn_link);158 fibril_mutex_unlock(&ffn_mutex);159 if (nodep->dirty) {160 rc = fat_node_sync(nodep);161 if (rc != EOK) {162 idxp_tmp->nodep = NULL;163 fibril_mutex_unlock(&nodep->lock);164 fibril_mutex_unlock(&idxp_tmp->lock);165 free(nodep->bp);166 free(nodep);167 return rc;168 }169 }170 idxp_tmp->nodep = NULL;171 fibril_mutex_unlock(&nodep->lock);172 fibril_mutex_unlock(&idxp_tmp->lock);173 fn = FS_NODE(nodep);174 } else {175 skip_cache:176 /* Try to allocate a new node structure. */177 fibril_mutex_unlock(&ffn_mutex);178 fn = (fs_node_t *)malloc(sizeof(fs_node_t));179 if (!fn)180 return ENOMEM;181 nodep = (fat_node_t *)malloc(sizeof(fat_node_t));182 if (!nodep) {183 free(fn);184 return ENOMEM;185 }186 }187 fat_node_initialize(nodep);188 fs_node_initialize(fn);189 fn->data = nodep;190 nodep->bp = fn;191 192 *nodepp = nodep;193 return EOK;194 }195 196 /** Internal version of fat_node_get().197 *198 * @param idxp Locked index structure.199 */200 static int fat_node_get_core(fat_node_t **nodepp, fat_idx_t *idxp)201 {202 block_t *b;203 fat_bs_t *bs;204 fat_dentry_t *d;205 fat_node_t *nodep = NULL;206 unsigned bps;207 unsigned spc;208 unsigned dps;209 int rc;210 211 if (idxp->nodep) {212 /*213 * We are lucky.214 * The node is already instantiated in memory.215 */216 fibril_mutex_lock(&idxp->nodep->lock);217 if (!idxp->nodep->refcnt++) {218 fibril_mutex_lock(&ffn_mutex);219 list_remove(&idxp->nodep->ffn_link);220 fibril_mutex_unlock(&ffn_mutex);221 }222 fibril_mutex_unlock(&idxp->nodep->lock);223 *nodepp = idxp->nodep;224 return EOK;225 }226 227 /*228 * We must instantiate the node from the file system.229 */230 231 assert(idxp->pfc);232 233 rc = fat_node_get_new(&nodep);234 if (rc != EOK)235 return rc;236 237 bs = block_bb_get(idxp->dev_handle);238 bps = uint16_t_le2host(bs->bps);239 spc = bs->spc;240 dps = bps / sizeof(fat_dentry_t);241 242 /* Read the block that contains the dentry of interest. */243 rc = _fat_block_get(&b, bs, idxp->dev_handle, idxp->pfc,244 (idxp->pdi * sizeof(fat_dentry_t)) / bps, BLOCK_FLAGS_NONE);245 if (rc != EOK) {246 (void) fat_node_put(FS_NODE(nodep));247 return rc;248 }249 250 d = ((fat_dentry_t *)b->data) + (idxp->pdi % dps);251 if (d->attr & FAT_ATTR_SUBDIR) {252 /*253 * The only directory which does not have this bit set is the254 * root directory itself. The root directory node is handled255 * and initialized elsewhere.256 */257 nodep->type = FAT_DIRECTORY;258 /*259 * Unfortunately, the 'size' field of the FAT dentry is not260 * defined for the directory entry type. We must determine the261 * size of the directory by walking the FAT.262 */263 uint16_t clusters;264 rc = fat_clusters_get(&clusters, bs, idxp->dev_handle,265 uint16_t_le2host(d->firstc));266 if (rc != EOK) {267 (void) fat_node_put(FS_NODE(nodep));268 return rc;269 }270 nodep->size = bps * spc * clusters;271 } else {272 nodep->type = FAT_FILE;273 nodep->size = uint32_t_le2host(d->size);274 }275 nodep->firstc = uint16_t_le2host(d->firstc);276 nodep->lnkcnt = 1;277 nodep->refcnt = 1;278 279 rc = block_put(b);280 if (rc != EOK) {281 (void) fat_node_put(FS_NODE(nodep));282 return rc;283 }284 285 /* Link the idx structure with the node structure. */286 nodep->idx = idxp;287 idxp->nodep = nodep;288 289 *nodepp = nodep;290 return EOK;291 }292 293 /*294 269 * FAT libfs operations. 295 270 */ … … 331 306 continue; 332 307 case FAT_DENTRY_LAST: 333 /* miss */334 308 rc = block_put(b); 309 /* expect EOK as b was not dirty */ 310 assert(rc == EOK); 335 311 fibril_mutex_unlock(&parentp->idx->lock); 336 312 *rfn = NULL; 337 return rc;313 return EOK; 338 314 default: 339 315 case FAT_DENTRY_VALID: … … 360 336 */ 361 337 rc = block_put(b); 362 return (rc == EOK) ? ENOMEM : rc; 338 /* expect EOK as b was not dirty */ 339 assert(rc == EOK); 340 return ENOMEM; 363 341 } 364 rc = fat_node_get_core(&nodep, idx); 342 nodep = fat_node_get_core(idx); 343 fibril_mutex_unlock(&idx->lock); 344 rc = block_put(b); 345 /* expect EOK as b was not dirty */ 365 346 assert(rc == EOK); 366 fibril_mutex_unlock(&idx->lock);367 (void) block_put(b);368 347 *rfn = FS_NODE(nodep); 369 348 return EOK; … … 371 350 } 372 351 rc = block_put(b); 373 if (rc != EOK) { 374 fibril_mutex_unlock(&parentp->idx->lock); 375 return rc; 376 } 352 assert(rc == EOK); /* expect EOK as b was not dirty */ 377 353 } 378 354 … … 387 363 fat_node_t *nodep; 388 364 fat_idx_t *idxp; 389 int rc;390 365 391 366 idxp = fat_idx_get_by_index(dev_handle, index); … … 395 370 } 396 371 /* idxp->lock held */ 397 rc = fat_node_get_core(&nodep,idxp);372 nodep = fat_node_get_core(idxp); 398 373 fibril_mutex_unlock(&idxp->lock); 399 if (rc == EOK) 400 *rfn = FS_NODE(nodep); 401 return rc; 374 *rfn = FS_NODE(nodep); 375 return EOK; 402 376 } 403 377 … … 455 429 } 456 430 457 rc = fat_node_get_new(&nodep);458 if ( rc != EOK) {431 nodep = fat_node_get_new(); 432 if (!nodep) { 459 433 (void) fat_free_clusters(bs, dev_handle, mcl); 460 return rc;461 } 462 rc = fat_idx_get_new(&idxp,dev_handle);463 if ( rc != EOK) {434 return ENOMEM; /* FIXME: determine the true error code */ 435 } 436 idxp = fat_idx_get_new(dev_handle); 437 if (!idxp) { 464 438 (void) fat_free_clusters(bs, dev_handle, mcl); 465 439 (void) fat_node_put(FS_NODE(nodep)); 466 return rc;440 return ENOMEM; /* FIXME: determine the true error code */ 467 441 } 468 442 /* idxp->lock held */ … … 808 782 case FAT_DENTRY_LAST: 809 783 rc = block_put(b); 784 /* expect EOK as b was not dirty */ 785 assert(rc == EOK); 810 786 fibril_mutex_unlock(&nodep->idx->lock); 811 787 *has_children = false; 812 return rc;788 return EOK; 813 789 default: 814 790 case FAT_DENTRY_VALID: 815 791 rc = block_put(b); 792 /* expect EOK as b was not dirty */ 793 assert(rc == EOK); 816 794 fibril_mutex_unlock(&nodep->idx->lock); 817 795 *has_children = true; 818 return rc;796 return EOK; 819 797 } 820 798 } 821 799 rc = block_put(b); 822 if (rc != EOK) { 823 fibril_mutex_unlock(&nodep->idx->lock); 824 return rc; 825 } 800 assert(rc == EOK); /* expect EOK as b was not dirty */ 826 801 } 827 802
Note:
See TracChangeset
for help on using the changeset viewer.