/* Get a free block number from the disk and mark the block used */ blocknum_t balloc(disk_t* disk) { blocknum_t free_bit = -1; blocknum_t block_offset = -1; /* Get super block */ fs_lock(mainsb); if (mainsb->free_blocks <= 0) { fs_unlock(mainsb); return -1; } /* Get free block number */ free_bit = bitmap_next_zero(mainsb->block_bitmap, mainsb->disk_num_blocks); block_offset = free_bit / BITS_PER_BLOCK; if (block_offset < 0 || block_offset >= mainsb->disk_num_blocks) { fs_unlock(mainsb); return -1; } /* Set the free block to used */ bitmap_set(mainsb->block_bitmap, free_bit); bpush(block_offset + mainsb->block_bitmap_first, (char*) mainsb->block_bitmap + block_offset * DISK_BLOCK_SIZE); mainsb->free_blocks--; fs_unlock(mainsb); return free_bit; }
/* Set a block to used */ void bset(blocknum_t blocknum) { blocknum_t bit = -1; blocknum_t block_offset; fs_lock(mainsb); if (blocknum <= mainsb->block_bitmap_last || blocknum >=mainsb->disk_num_blocks) { fs_unlock(mainsb); return; } /* Set the block to free */ bit = blocknum; block_offset = bit / BITS_PER_BLOCK; if (bitmap_get(mainsb->block_bitmap, bit) == 0) { bitmap_set(mainsb->block_bitmap, bit); bpush(block_offset + mainsb->block_bitmap_first, (char*) mainsb->block_bitmap + block_offset * DISK_BLOCK_SIZE); mainsb->free_blocks--; } fs_unlock(mainsb); }
/* * Allocate a free inode and return a pointer to free inode * Return NULL if fail. */ inodenum_t ialloc(disk_t* disk) { inodenum_t free_bit = -1; inodenum_t block_offset = -1; fs_lock(mainsb); if (mainsb->free_inodes <= 0) { fs_unlock(mainsb); return -1; } /* Get free inode number */ free_bit = bitmap_next_zero(mainsb->inode_bitmap, mainsb->disk_num_blocks); block_offset = free_bit / BITS_PER_BLOCK; if (free_bit < 0 || block_offset >= mainsb->disk_num_blocks) { fs_unlock(mainsb); return -1; } /* Set the free inode to used */ bitmap_set(mainsb->inode_bitmap, free_bit); bpush(block_offset + mainsb->inode_bitmap_first, (char*) mainsb->inode_bitmap + block_offset * DISK_BLOCK_SIZE); mainsb->free_inodes--; fs_unlock(mainsb); return free_bit; }
static int sc_hdlr_open(void *_p){ char path[((sc_fs_t*)(_p))->data_len]; sc_fs_t *p; fs_node_t *root; process_t *this_p; this_p = sched_running()->parent; /* initials */ p = (sc_fs_t*)_p; copy_from_user(path, p->data, p->data_len, this_p); /* identify file system and call its open callback */ mutex_lock(&this_p->mtx); root = (path[0] == '/') ? (fs_root) : this_p->cwd; mutex_unlock(&this_p->mtx); if(root->ops->open == 0x0) return_errno(E_NOIMP); DEBUG("path \"%s\", mode %#x\n", path, p->mode); fs_lock(); p->fd = root->ops->open(root, path, p->mode, this_p); fs_unlock(); DEBUG("created fd with id %d, \"%s\"\n", p->fd, strerror(errno)); return E_OK; }
static int sc_hdlr_rmnode(void *_p){ char path[((sc_fs_t*)(_p))->data_len]; sc_fs_t *p; fs_node_t *root; process_t *this_p; this_p = sched_running()->parent; /* initials */ p = (sc_fs_t*)_p; copy_from_user(path, p->data, p->data_len, this_p); DEBUG("%s\n", path); /* identify file system and call its rmnode callback */ mutex_lock(&this_p->mtx); root = (path[0] == '/') ? (fs_root) : this_p->cwd; mutex_unlock(&this_p->mtx); if(root->ops->node_rm == 0x0) return_errno(E_NOIMP); fs_lock(); (void)root->ops->node_rm(root, path); fs_unlock(); return -errno; }
static int sc_hdlr_close(void *_p){ sc_fs_t *p; fs_filed_t *fd; process_t *this_p; this_p = sched_running()->parent; /* initials */ p = (sc_fs_t*)_p; fd = fs_fd_acquire(p->fd, this_p); DEBUG("fd %d%s\n", p->fd, (fd == 0x0 ? " (invalid)" : "")); if(fd == 0x0) return_errno(E_INVAL); /* handle close */ fs_lock(); (void)fd->node->ops->close(fd, this_p); fs_unlock(); // NOTE fs_fd_release must not be called, since // close has already deleted the decriptor return E_OK; }
static void fs_hotplug_alarm(void *arg) { struct rte_eth_dev *dev = arg; struct sub_device *sdev; int ret; uint8_t i; if (!PRIV(dev)->pending_alarm) return; PRIV(dev)->pending_alarm = 0; FOREACH_SUBDEV(sdev, i, dev) if (sdev->state != PRIV(dev)->state) break; /* if we have non-probed device */ if (i != PRIV(dev)->subs_tail) { if (fs_lock(dev, 1) != 0) goto reinstall; ret = failsafe_eth_dev_state_sync(dev); fs_unlock(dev, 1); if (ret) ERROR("Unable to synchronize sub_device state"); } failsafe_dev_remove(dev); reinstall: ret = failsafe_hotplug_alarm_install(dev); if (ret) ERROR("Unable to set up next alarm"); }
static int _no_lock_resource(struct cmd_context *cmd, const char *resource, uint32_t flags, struct logical_volume *lv) { switch (flags & LCK_SCOPE_MASK) { case LCK_VG: if (!strcmp(resource, VG_SYNC_NAMES)) fs_unlock(); break; case LCK_LV: switch (flags & LCK_TYPE_MASK) { case LCK_NULL: return lv_deactivate(cmd, resource, lv_ondisk(lv)); case LCK_UNLOCK: return lv_resume_if_active(cmd, resource, (flags & LCK_ORIGIN_ONLY) ? 1: 0, 0, (flags & LCK_REVERT) ? 1 : 0, lv_ondisk(lv)); case LCK_READ: return lv_activate_with_filter(cmd, resource, 0, lv_ondisk(lv)); case LCK_WRITE: return lv_suspend_if_active(cmd, resource, (flags & LCK_ORIGIN_ONLY) ? 1 : 0, 0, lv_ondisk(lv), lv); case LCK_EXCL: return lv_activate_with_filter(cmd, resource, 1, lv_ondisk(lv)); default: break; } break; default: log_error("Unrecognised lock scope: %d", flags & LCK_SCOPE_MASK); return 0; } return 1; }
int do_unlock(const char *filename,uint64_t lv,uint32_t ts,char *ptr) { uint64_t chunkid; (void)ts; EAT(ptr,filename,lv,'('); GETU64(chunkid,ptr); EAT(ptr,filename,lv,')'); return fs_unlock(chunkid); }
uint8_t do_unlock(uint64_t lv,uint32_t ts,char *ptr) { uint64_t chunkid; (void)ts; EAT(ptr,lv,'('); GETU64(chunkid,ptr); EAT(ptr,lv,')'); return fs_unlock(chunkid); }
/* Establish the file system and write it to disk */ int fs_format(mem_sblock_t sbp) { blocknum_t inode_bitmap_size; blocknum_t block_bitmap_size; blocknum_t i; sbp->filesys_lock = semaphore_new(1); if (NULL == sbp->filesys_lock) { return -1; } fs_lock(sbp); /* Format super block */ sblock_get(maindisk, sbp); sblock_format(sbp, disk_size); sblock_update(sbp); /* Format inode and block bitmaps */ inode_bitmap_size = sbp->inode_bitmap_last - sbp->inode_bitmap_first + 1; sbp->inode_bitmap = malloc(inode_bitmap_size * DISK_BLOCK_SIZE); block_bitmap_size = sbp->block_bitmap_last - sbp->block_bitmap_first + 1; sbp->block_bitmap = malloc(block_bitmap_size * DISK_BLOCK_SIZE); if (NULL == sbp->block_bitmap || NULL == sbp->inode_bitmap) { semaphore_V(sbp->filesys_lock); return -1; } /* Clear bitmaps */ bitmap_zeroall(sbp->inode_bitmap, inode_bitmap_size * BITS_PER_BLOCK); bitmap_zeroall(sbp->block_bitmap, block_bitmap_size * BITS_PER_BLOCK); /* Set file system blocks to be occupied */ for (i = 0; i <= sbp->block_bitmap_last; ++i) { bitmap_set(sbp->block_bitmap, i); } /* Set inode 0 to be occupied */ bitmap_set(sbp->inode_bitmap, 0); /* Push updates to disk */ for (i = sbp->inode_bitmap_first; i <= sbp->inode_bitmap_last; ++i) { bpush(i, (char*) sbp->inode_bitmap + (i - sbp->inode_bitmap_first) * DISK_BLOCK_SIZE); } for (i = sbp->block_bitmap_first; i <= sbp->block_bitmap_last; ++i) { bpush(i, (char*) sbp->block_bitmap + (i - sbp->block_bitmap_first) * DISK_BLOCK_SIZE); } /* Count free inodes and free blocks */ mainsb->free_inodes = bitmap_count_zero(mainsb->inode_bitmap, mainsb->total_inodes); mainsb->free_blocks = bitmap_count_zero(mainsb->block_bitmap, mainsb->disk_num_blocks); fs_unlock(sbp); return 0; }
static int _lock_resource(struct cmd_context *cmd, const char *resource, uint32_t flags) { if (!_lock_fn) return 0; if (!strcmp(resource, VG_SYNC_NAMES)) { /* Hide this lock request from external locking */ fs_unlock(); return 1; } return _lock_fn(cmd, resource, flags); }
/* Initialize the file system structure from disk */ int fs_init(mem_sblock_t sbp) { blocknum_t inode_bitmap_size; blocknum_t block_bitmap_size; blocknum_t i; sbp->filesys_lock = semaphore_new(1); if (NULL == sbp->filesys_lock) { return -1; } fs_lock(sbp); sblock_get(maindisk, sbp); sblock_put(sbp); if (sblock_isvalid(sbp) != 1) { sblock_print(sbp); kprintf("File system is not recognized. "); kprintf("Recommend running './mkfs <blocks>'.\n"); return -2; } inode_bitmap_size = sbp->inode_bitmap_last - sbp->inode_bitmap_first + 1; sbp->inode_bitmap = malloc(inode_bitmap_size * DISK_BLOCK_SIZE); block_bitmap_size = sbp->block_bitmap_last - sbp->block_bitmap_first + 1; sbp->block_bitmap = malloc(block_bitmap_size * DISK_BLOCK_SIZE); if (NULL == sbp->block_bitmap || NULL == sbp->inode_bitmap) { semaphore_V(sbp->filesys_lock); return -1; } /* Get disk bitmap */ for (i = sbp->inode_bitmap_first; i <= sbp->inode_bitmap_last; ++i) { bpull(i, (char*) sbp->inode_bitmap + (i - sbp->inode_bitmap_first) * DISK_BLOCK_SIZE); } for (i = sbp->block_bitmap_first; i <= sbp->block_bitmap_last; ++i) { bpull(i, (char*) sbp->block_bitmap + (i - sbp->block_bitmap_first) * DISK_BLOCK_SIZE); } /* Count free inodes and free blocks */ mainsb->free_inodes = bitmap_count_zero(mainsb->inode_bitmap, mainsb->total_inodes); mainsb->free_blocks = bitmap_count_zero(mainsb->block_bitmap, mainsb->disk_num_blocks); fs_unlock(sbp); return 0; }
static int sc_hdlr_chdir(void *_p){ char path[((sc_fs_t*)(_p))->data_len]; sc_fs_t *p; fs_node_t *root; process_t *this_p; this_p = sched_running()->parent; /* initials */ p = (sc_fs_t*)_p; copy_from_user(path, p->data, p->data_len, this_p); DEBUG("sc chdir: %s\n", path); /* identify file system and call its findnode callback */ fs_lock(); mutex_lock(&this_p->mtx); root = (path[0] == '/') ? (fs_root) : this_p->cwd; if(root->ops->node_find == 0x0) goto_errno(end, E_NOIMP); root = root->ops->node_find(root, path); if(root == 0x0) goto end; if(root->type != FT_DIR) goto_errno(end, E_INVAL); // update current working directory this_p->cwd->ref_cnt--; this_p->cwd = root; root->ref_cnt++; end: mutex_unlock(&this_p->mtx); fs_unlock(); DEBUG("new cwd \"%s\", \"%s\"\n", this_p->cwd->name, strerror(errno)); return -errno; }
static int sc_hdlr_dup(void *_p){ int old_id; sc_fs_t *p; fs_filed_t *old_fd; process_t *this_p; this_p = sched_running()->parent; /* initiali */ p = (sc_fs_t*)_p; old_id = (int)p->data; old_fd = fs_fd_acquire(old_id, this_p); DEBUG("oldfd %d%s, newfd %d\n", old_id, (old_fd == 0x0 ? " (invalid)" : ""), p->fd); // exit if oldfd does not exist or old and new fd are the same if(old_fd == 0x0 || old_fd->id == p->fd) return_errno(E_INVAL); /* close the desired fd if one is given */ if(p->fd >= 0) sc_hdlr_close(_p); // E_INVAL is expected in case the desired fd // was not open before if(errno && errno != E_INVAL) return -errno; errno = E_OK; /* duplicate old fd */ fs_lock(); p->fd = fs_fd_dup(old_fd, p->fd, this_p); fs_unlock(); fs_fd_release(old_fd); DEBUG("created fd with id %d\n", p->fd); return E_OK; }
/* Add an inode back to free list */ void ifree(inodenum_t inum) { blocknum_t bit = -1; blocknum_t block_offset; fs_lock(mainsb); /* Set the inode to free */ bit = inum; block_offset = bit / BITS_PER_BLOCK; if (bitmap_get(mainsb->inode_bitmap, bit) == 1) { mainsb->free_inodes++; } bitmap_clear(mainsb->inode_bitmap, bit); bpush(block_offset + mainsb->inode_bitmap_first, (char*) mainsb->inode_bitmap + block_offset * DISK_BLOCK_SIZE); fs_unlock(mainsb); }
void log_brew(FIL *file, char *fmt, ...) { #if 0 if (file->fs) { fs_lock(); char message[40]; UINT written; va_list ap; va_start(ap, fmt); int len = vsnprintf(message, sizeof(message) - 1, fmt, ap); va_end(ap); f_write(file, message, len, &written); f_sync(file); fs_unlock(); } #endif }
static int _file_lock_resource(struct cmd_context *cmd, const char *resource, uint32_t flags, struct logical_volume *lv) { char lockfile[PATH_MAX]; unsigned origin_only = (flags & LCK_ORIGIN_ONLY) ? 1 : 0; unsigned revert = (flags & LCK_REVERT) ? 1 : 0; switch (flags & LCK_SCOPE_MASK) { case LCK_ACTIVATION: if (dm_snprintf(lockfile, sizeof(lockfile), "%s/A_%s", _lock_dir, resource + 1) < 0) { log_error("Too long locking filename %s/A_%s.", _lock_dir, resource + 1); return 0; } if (!lock_file(lockfile, flags)) return_0; break; case LCK_VG: /* Skip cache refresh for VG_GLOBAL - the caller handles it */ if (strcmp(resource, VG_GLOBAL)) lvmcache_drop_metadata(resource, 0); if (!strcmp(resource, VG_SYNC_NAMES)) fs_unlock(); /* LCK_CACHE does not require a real lock */ if (flags & LCK_CACHE) break; if (is_orphan_vg(resource) || is_global_vg(resource)) { if (dm_snprintf(lockfile, sizeof(lockfile), "%s/P_%s", _lock_dir, resource + 1) < 0) { log_error("Too long locking filename %s/P_%s.", _lock_dir, resource + 1); return 0; } } else if (dm_snprintf(lockfile, sizeof(lockfile), "%s/V_%s", _lock_dir, resource) < 0) { log_error("Too long locking filename %s/V_%s.", _lock_dir, resource); return 0; } if (!lock_file(lockfile, flags)) return_0; break; case LCK_LV: switch (flags & LCK_TYPE_MASK) { case LCK_UNLOCK: log_very_verbose("Unlocking LV %s%s%s", resource, origin_only ? " without snapshots" : "", revert ? " (reverting)" : ""); if (!lv_resume_if_active(cmd, resource, origin_only, 0, revert, lv_ondisk(lv))) return 0; break; case LCK_NULL: log_very_verbose("Locking LV %s (NL)", resource); if (!lv_deactivate(cmd, resource, lv_ondisk(lv))) return 0; break; case LCK_READ: log_very_verbose("Locking LV %s (R)", resource); if (!lv_activate_with_filter(cmd, resource, 0, lv->status & LV_NOSCAN ? 1 : 0, lv->status & LV_TEMPORARY ? 1 : 0, lv_ondisk(lv))) return 0; break; case LCK_PREAD: log_very_verbose("Locking LV %s (PR) - ignored", resource); break; case LCK_WRITE: log_very_verbose("Locking LV %s (W)%s", resource, origin_only ? " without snapshots" : ""); if (!lv_suspend_if_active(cmd, resource, origin_only, 0, lv_ondisk(lv), lv)) return 0; break; case LCK_EXCL: log_very_verbose("Locking LV %s (EX)", resource); if (!lv_activate_with_filter(cmd, resource, 1, lv->status & LV_NOSCAN ? 1 : 0, lv->status & LV_TEMPORARY ? 1 : 0, lv_ondisk(lv))) return 0; break; default: break; } break; default: log_error("Unrecognised lock scope: %d", flags & LCK_SCOPE_MASK); return 0; } return 1; }