Changeset f5af635 in mainline
- Timestamp:
- 2009-10-01T11:53:17Z (15 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- d57e08f
- Parents:
- bbf88db (diff), 8810c63 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the(diff)
links above to see all the changes relative to each parent. - Location:
- uspace/srv/fs/fat
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/srv/fs/fat/fat.h
rbbf88db rf5af635 215 215 extern void fat_sync(ipc_callid_t, ipc_call_t *); 216 216 217 extern fat_idx_t *fat_idx_get_new(dev_handle_t);217 extern int fat_idx_get_new(fat_idx_t **, 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
rbbf88db rf5af635 339 339 } 340 340 341 static fat_idx_t *fat_idx_create(dev_handle_t dev_handle)341 static int fat_idx_create(fat_idx_t **fidxp, 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 NULL;347 return ENOMEM; 348 348 if (!fat_index_alloc(dev_handle, &fidx->index)) { 349 349 free(fidx); 350 return NULL;350 return ENOSPC; 351 351 } 352 352 … … 359 359 fidx->nodep = NULL; 360 360 361 return fidx; 362 } 363 364 fat_idx_t *fat_idx_get_new(dev_handle_t dev_handle) 361 *fidxp = fidx; 362 return EOK; 363 } 364 365 int fat_idx_get_new(fat_idx_t **fidxp, dev_handle_t dev_handle) 365 366 { 366 367 fat_idx_t *fidx; 368 int rc; 367 369 368 370 fibril_mutex_lock(&used_lock); 369 fidx = fat_idx_create(dev_handle);370 if ( !fidx) {371 rc = fat_idx_create(&fidx, dev_handle); 372 if (rc != EOK) { 371 373 fibril_mutex_unlock(&used_lock); 372 return NULL;374 return rc; 373 375 } 374 376 … … 382 384 fibril_mutex_unlock(&used_lock); 383 385 384 return fidx; 386 *fidxp = fidx; 387 return EOK; 385 388 } 386 389 … … 401 404 fidx = hash_table_get_instance(l, fat_idx_t, uph_link); 402 405 } else { 403 fidx = fat_idx_create(dev_handle); 404 if (!fidx) { 406 int rc; 407 408 rc = fat_idx_create(&fidx, dev_handle); 409 if (rc != EOK) { 405 410 fibril_mutex_unlock(&used_lock); 406 411 return NULL; -
uspace/srv/fs/fat/fat_ops.c
rbbf88db rf5af635 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 the217 * root directory itself. The root directory node is handled218 * and initialized elsewhere.219 */220 nodep->type = FAT_DIRECTORY;221 /*222 * Unfortunately, the 'size' field of the FAT dentry is not223 * defined for the directory entry type. We must determine the224 * 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 249 67 /* 250 68 * Forward declarations of FAT libfs operations. … … 267 85 268 86 /* 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 the 254 * root directory itself. The root directory node is handled 255 * and initialized elsewhere. 256 */ 257 nodep->type = FAT_DIRECTORY; 258 /* 259 * Unfortunately, the 'size' field of the FAT dentry is not 260 * defined for the directory entry type. We must determine the 261 * 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 /* 269 294 * FAT libfs operations. 270 295 */ … … 306 331 continue; 307 332 case FAT_DENTRY_LAST: 333 /* miss */ 308 334 rc = block_put(b); 309 /* expect EOK as b was not dirty */310 assert(rc == EOK);311 335 fibril_mutex_unlock(&parentp->idx->lock); 312 336 *rfn = NULL; 313 return EOK;337 return rc; 314 338 default: 315 339 case FAT_DENTRY_VALID: … … 336 360 */ 337 361 rc = block_put(b); 338 /* expect EOK as b was not dirty */ 339 assert(rc == EOK); 340 return ENOMEM; 362 return (rc == EOK) ? ENOMEM : rc; 341 363 } 342 nodep = fat_node_get_core(idx); 364 rc = fat_node_get_core(&nodep, idx); 365 assert(rc == EOK); 343 366 fibril_mutex_unlock(&idx->lock); 344 rc = block_put(b); 345 /* expect EOK as b was not dirty */ 346 assert(rc == EOK); 367 (void) block_put(b); 347 368 *rfn = FS_NODE(nodep); 348 369 return EOK; … … 350 371 } 351 372 rc = block_put(b); 352 assert(rc == EOK); /* expect EOK as b was not dirty */ 373 if (rc != EOK) { 374 fibril_mutex_unlock(&parentp->idx->lock); 375 return rc; 376 } 353 377 } 354 378 … … 363 387 fat_node_t *nodep; 364 388 fat_idx_t *idxp; 389 int rc; 365 390 366 391 idxp = fat_idx_get_by_index(dev_handle, index); … … 370 395 } 371 396 /* idxp->lock held */ 372 nodep = fat_node_get_core(idxp);397 rc = fat_node_get_core(&nodep, idxp); 373 398 fibril_mutex_unlock(&idxp->lock); 374 *rfn = FS_NODE(nodep); 375 return EOK; 399 if (rc == EOK) 400 *rfn = FS_NODE(nodep); 401 return rc; 376 402 } 377 403 … … 429 455 } 430 456 431 nodep = fat_node_get_new();432 if ( !nodep) {457 rc = fat_node_get_new(&nodep); 458 if (rc != EOK) { 433 459 (void) fat_free_clusters(bs, dev_handle, mcl); 434 return ENOMEM; /* FIXME: determine the true error code */435 } 436 idxp = fat_idx_get_new(dev_handle);437 if ( !idxp) {460 return rc; 461 } 462 rc = fat_idx_get_new(&idxp, dev_handle); 463 if (rc != EOK) { 438 464 (void) fat_free_clusters(bs, dev_handle, mcl); 439 465 (void) fat_node_put(FS_NODE(nodep)); 440 return ENOMEM; /* FIXME: determine the true error code */466 return rc; 441 467 } 442 468 /* idxp->lock held */ … … 782 808 case FAT_DENTRY_LAST: 783 809 rc = block_put(b); 784 /* expect EOK as b was not dirty */785 assert(rc == EOK);786 810 fibril_mutex_unlock(&nodep->idx->lock); 787 811 *has_children = false; 788 return EOK;812 return rc; 789 813 default: 790 814 case FAT_DENTRY_VALID: 791 815 rc = block_put(b); 792 /* expect EOK as b was not dirty */793 assert(rc == EOK);794 816 fibril_mutex_unlock(&nodep->idx->lock); 795 817 *has_children = true; 796 return EOK;818 return rc; 797 819 } 798 820 } 799 821 rc = block_put(b); 800 assert(rc == EOK); /* expect EOK as b was not dirty */ 822 if (rc != EOK) { 823 fibril_mutex_unlock(&nodep->idx->lock); 824 return rc; 825 } 801 826 } 802 827
Note:
See TracChangeset
for help on using the changeset viewer.