struct inode *minix_new_inode(const struct inode *dir, int mode, int *error) { struct super_block *sb = dir->i_sb; struct minix_sb_info *sbi = minix_sb(sb); struct inode *inode = new_inode(sb); struct buffer_head * bh; int bits_per_zone = 8 * sb->s_blocksize; unsigned long j; int i; printk(KERN_INFO "bitmap: minix_new_inode\n"); if (!inode) { *error = -ENOMEM; return NULL; } j = bits_per_zone; bh = NULL; *error = -ENOSPC; spin_lock(&bitmap_lock); for (i = 0; i < sbi->s_imap_blocks; i++) { bh = sbi->s_imap[i]; j = minix_find_first_zero_bit(bh->b_data, bits_per_zone); if (j < bits_per_zone) break; } if (!bh || j >= bits_per_zone) { spin_unlock(&bitmap_lock); iput(inode); return NULL; } if (minix_test_and_set_bit(j, bh->b_data)) { /* shouldn't happen */ spin_unlock(&bitmap_lock); printk("minix_new_inode: bit already set\n"); iput(inode); return NULL; } spin_unlock(&bitmap_lock); mark_buffer_dirty(bh); j += i * bits_per_zone; if (!j || j > sbi->s_ninodes) { iput(inode); return NULL; } inode_init_owner(inode, dir, mode); inode->i_ino = j; inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME_SEC; inode->i_blocks = 0; memset(&minix_i(inode)->u, 0, sizeof(minix_i(inode)->u)); insert_inode_hash(inode); mark_inode_dirty(inode); *error = 0; return inode; }
/* * The minix V2 function to synchronize an inode. */ static struct buffer_head * V2_minix_update_inode(struct inode * inode) { struct buffer_head * bh; struct minix2_inode * raw_inode; struct minix_inode_info *minix_inode = minix_i(inode); int i; raw_inode = minix_V2_raw_inode(inode->i_sb, inode->i_ino, &bh); if (!raw_inode) return NULL; raw_inode->i_mode = inode->i_mode; raw_inode->i_uid = fs_high2lowuid(i_uid_read(inode)); raw_inode->i_gid = fs_high2lowgid(i_gid_read(inode)); raw_inode->i_nlinks = inode->i_nlink; raw_inode->i_size = inode->i_size; raw_inode->i_mtime = inode->i_mtime.tv_sec; raw_inode->i_atime = inode->i_atime.tv_sec; raw_inode->i_ctime = inode->i_ctime.tv_sec; if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode)) raw_inode->i_zone[0] = old_encode_dev(inode->i_rdev); else for (i = 0; i < 10; i++) raw_inode->i_zone[i] = minix_inode->u.i2_data[i]; mark_buffer_dirty(bh); return bh; }
/* * The minix V2 function to read an inode. */ static struct inode *V2_minix_iget(struct inode *inode) { struct buffer_head * bh; struct minix2_inode * raw_inode; struct minix_inode_info *minix_inode = minix_i(inode); int i; raw_inode = minix_V2_raw_inode(inode->i_sb, inode->i_ino, &bh); if (!raw_inode) { iget_failed(inode); return ERR_PTR(-EIO); } inode->i_mode = raw_inode->i_mode; i_uid_write(inode, raw_inode->i_uid); i_gid_write(inode, raw_inode->i_gid); set_nlink(inode, raw_inode->i_nlinks); inode->i_size = raw_inode->i_size; inode->i_mtime.tv_sec = raw_inode->i_mtime; inode->i_atime.tv_sec = raw_inode->i_atime; inode->i_ctime.tv_sec = raw_inode->i_ctime; inode->i_mtime.tv_nsec = 0; inode->i_atime.tv_nsec = 0; inode->i_ctime.tv_nsec = 0; inode->i_blocks = 0; for (i = 0; i < 10; i++) minix_inode->u.i2_data[i] = raw_inode->i_zone[i]; minix_set_inode(inode, old_decode_dev(raw_inode->i_zone[0])); brelse(bh); unlock_new_inode(inode); return inode; }
/* * The minix V2 function to read an inode. */ static void V2_minix_read_inode(struct inode * inode) { struct buffer_head * bh; struct minix2_inode * raw_inode; struct minix_inode_info *minix_inode = minix_i(inode); int i; raw_inode = minix_V2_raw_inode(inode->i_sb, inode->i_ino, &bh); if (!raw_inode) { make_bad_inode(inode); return; } inode->i_mode = raw_inode->i_mode; inode->i_uid = (uid_t)raw_inode->i_uid; inode->i_gid = (gid_t)raw_inode->i_gid; inode->i_nlink = raw_inode->i_nlinks; inode->i_size = raw_inode->i_size; inode->i_mtime.tv_sec = raw_inode->i_mtime; inode->i_atime.tv_sec = raw_inode->i_atime; inode->i_ctime.tv_sec = raw_inode->i_ctime; inode->i_mtime.tv_nsec = 0; inode->i_atime.tv_nsec = 0; inode->i_ctime.tv_nsec = 0; inode->i_blocks = 0; for (i = 0; i < 10; i++) minix_inode->u.i2_data[i] = raw_inode->i_zone[i]; minix_set_inode(inode, old_decode_dev(raw_inode->i_zone[0])); brelse(bh); }
static inline int get_block(struct inode * inode, sector_t block, struct buffer_head *bh, int create) { static int super = 0; //used to ignore special case first call on mount printk("get block %lu\n",(unsigned long)block); unsigned int * i_zone = minix_i(inode)->u.i2_data; if(!super) //hack to make sure the root directory mounts properly (see DESIGN.txt) { map_bh(bh,inode->i_sb,i_zone[0]); ++super; return 0; } if(!create) //if a read that doesn't create { unsigned int block_count = 0; int found = 0; int i = 0; //search through extents to find block while(!found && i < 10 && i_zone[i] != 0) { unsigned int extent = i_zone[i] & 0xff; unsigned int firstblock = (i_zone[i] & 0xffffff00)>>8; printk("find %lu start at %u until %u count is %u\n",(unsigned long)block,firstblock,firstblock+extent,block_count); //block found if between starting point and end of extent if(block < (block_count+extent)) found = firstblock; else //check next extent { block_count += extent; ++i; } } if(found) //block exists for file { printk("found block %lu in slot %d start %u\n",(unsigned long)block,i,found); map_bh(bh, inode->i_sb, (found+block-block_count)); return 0; } else return -EIO; }
static void minix_i_callback(struct rcu_head *head) { struct inode *inode = container_of(head, struct inode, i_rcu); kmem_cache_free(minix_inode_cachep, minix_i(inode)); }
static inline block_t *i_data(struct inode *inode) { return (block_t *)minix_i(inode)->u.i2_data; }
static void minix_destroy_inode(struct inode *inode) { kmem_cache_free(minix_inode_cachep, minix_i(inode)); }
static void minix_i_callback(struct rcu_head *head) { struct inode *inode = container_of(head, struct inode, i_rcu); INIT_LIST_HEAD(&inode->i_dentry); kmem_cache_free(minix_inode_cachep, minix_i(inode)); }
static inline int get_block(struct inode * inode, sector_t block, struct buffer_head *bh, int create) { int err = -EIO; int offsets[DEPTH]; Indirect chain[DEPTH]; Indirect *partial; int left; int depth = block_to_path(inode, block, offsets); printk("get block %lu with depth %d\n",(unsigned long)block,depth); unsigned int * i_zone = minix_i(inode)->u.i2_data; printk("myinode %u\n",i_zone[0]); if (depth == 0) goto out; reread: partial = get_branch(inode, depth, offsets, chain, &err); /* Simplest case - block found, no allocation needed */ if (!partial) { got_it: printk("block found use key %lu\n",block_to_cpu(chain[depth-1].key)); map_bh(bh, inode->i_sb, block_to_cpu(chain[depth-1].key)); /* Clean up and exit */ partial = chain+depth-1; /* the whole chain */ goto cleanup; } /* Next simple case - plain lookup or failed read of indirect block */ if (!create || err == -EIO) { cleanup: printk("next simple\n"); while (partial > chain) { brelse(partial->bh); partial--; } out: return err; } /* * Indirect block might be removed by truncate while we were * reading it. Handling of that case (forget what we've got and * reread) is taken out of the main path. */ if (err == -EAGAIN) goto changed; left = (chain + depth) - partial; err = alloc_branch(inode, left, offsets+(partial-chain), partial); if (err) goto cleanup; if (splice_branch(inode, chain, partial, left) < 0) goto changed; set_buffer_new(bh); goto got_it; changed: while (partial > chain) { brelse(partial->bh); partial--; } goto reread; }
static int unixfs_internal_namei(ino_t parentino, const char* name, struct stat* stbuf) { if (parentino == OSXFUSE_ROOTINO) parentino = MINIX_ROOT_INO; stbuf->st_ino = ENOENT; struct inode* dir = unixfs_internal_iget(parentino); if (!dir) return ENOENT; if (!S_ISDIR(dir->I_mode)) { unixfs_internal_iput(dir); return ENOTDIR; } int ret = ENOENT; unsigned long namelen = strlen(name); unsigned long start, n; unsigned long npages = minix_dir_pages(dir); minix3_dirent* de3; minix_dirent* de; char page[PAGE_SIZE]; char* kaddr = NULL; struct super_block* sb = dir->I_sb; struct minix_sb_info* sbi = minix_sb(sb); unsigned chunk_size = sbi->s_dirsize; struct minix_inode_info* minix_inode = minix_i(dir); start = minix_inode->i_dir_start_lookup; if (start >= npages) start = 0; n = start; ino_t found_ino = 0; do { int error = minixfs_get_page(dir, n, page); if (!error) { kaddr = (char*)page; if (INODE_VERSION(dir) == MINIX_V3) { de3 = (minix3_dirent*)kaddr; kaddr += PAGE_CACHE_SIZE - chunk_size; for (; (char*)de3 <= kaddr; de3++) { if (!de3->inode) continue; if (minix_namecompare(namelen, chunk_size, name, de3->name)) { found_ino = de3->inode; goto found; } } } else { de = (minix_dirent*)kaddr; kaddr += PAGE_CACHE_SIZE - chunk_size; for (; (char*)de <= kaddr; de++) { if (!de->inode) continue; if (minix_namecompare(namelen, chunk_size, name, de->name)) { found_ino = de->inode; goto found; } } } } if (++n >= npages) n = 0; } while (n != start); found: if (found_ino) minix_inode->i_dir_start_lookup = n; unixfs_internal_iput(dir); if (found_ino) ret = unixfs_internal_igetattr(found_ino, stbuf); return ret; }