Jared Hulbert wrote:
+ +static int axfs_iget5_test(struct inode *inode, void *opaque) +{ + u64 *inode_number = (u64 *) opaque; + + if (inode->i_sb == NULL) { + printk(KERN_ERR "axfs_iget5_test:" + " the super block is set to null\n"); + } + if (inode->i_ino == *inode_number) + return 1; /* matches */ + else + return 0; /* does not match */ +} +
This implies inode_numbers are unique in AXFS? If so you can get rid of the axfs_iget5_set/test logic. This is only necessary for filesystems with non-unique inode numbers like cramfs.
+ +struct inode *axfs_create_vfs_inode(struct super_block *sb, int ino) +{ + struct axfs_super *sbi = AXFS_SB(sb); + struct inode *inode; + u64 size; + + inode = iget5_locked(sb, ino, axfs_iget5_test, axfs_iget5_set, &ino);
If inode_numbers are unique, use iget_locked here.
+ + if (!(inode && (inode->i_state & I_NEW))) + return inode; + + inode->i_mode = AXFS_GET_MODE(sbi, ino); + inode->i_uid = AXFS_GET_UID(sbi, ino); + size = AXFS_GET_INODE_FILE_SIZE(sbi, ino); + inode->i_size = size;
What's the reason for splitting this into two lines, rather than inode->i_size = AXFS_GET_INODE_FILE_SIZE(sbi, ino);
+ inode->i_blocks = AXFS_GET_INODE_NUM_ENTRIES(sbi, ino); + inode->i_blkbits = PAGE_CACHE_SIZE * 8; + inode->i_gid = AXFS_GET_GID(sbi, ino); + + inode->i_mtime = inode->i_atime = inode->i_ctime = sbi->timestamp;
No unique per inode time? Will cause problems using AXFS for archives etc. where preserving timestamps is important.
+ inode->i_ino = ino; +
Unnecessary, set by iget_locked/iget_locked5
+ +static int axfs_readdir(struct file *filp, void *dirent, filldir_t filldir) +{ + struct inode *inode = filp->f_dentry->d_inode; + struct super_block *sb = inode->i_sb; + struct axfs_super *sbi = AXFS_SB(sb); + u64 ino_number = inode->i_ino; + u64 entry; + loff_t dir_index; + char *name; + int namelen, mode; + int err = 0; + + /* Get the current index into the directory and verify it is not beyond + the end of the list */ + dir_index = filp->f_pos; + if (dir_index >= AXFS_GET_INODE_NUM_ENTRIES(sbi, ino_number)) + goto out; + + /* Verify the inode is for a directory */ + if (!(S_ISDIR(inode->i_mode))) { + err = -EINVAL; + goto out; + } + + while (dir_index < AXFS_GET_INODE_NUM_ENTRIES(sbi, ino_number)) { + entry = AXFS_GET_INODE_ARRAY_INDEX(sbi, ino_number) + dir_index; + + name = (char *)AXFS_GET_INODE_NAME(sbi, entry);
One to one mapping between inode number and inode name? No hard link support...?
+ namelen = strlen(name); + + mode = (int)AXFS_GET_MODE(sbi, entry); + err = filldir(dirent, name, namelen, dir_index, entry, mode); + + if (err) + break; + + dir_index++; + filp->f_pos = dir_index; + } + +out: + return 0; +}
Are "." and ".." stored in the directory? If not then axfs_readdir should fabricate them to avoid confusing applications that expect readdir(3) to return them.
+static ssize_t axfs_file_read(struct file *filp, char __user *buf, size_t len, + loff_t *ppos)
+ actual_size = len > remaining ? remaining : len; + readlength = actual_size < PAGE_SIZE ? actual_size : PAGE_SIZE;
Use min() or min_t()
+ +static int axfs_readpage(struct file *file, struct page *page) +{ + + if (node_type == Compressed) { + /* node is in compessed region */ + cnode_offset = AXFS_GET_CNODE_OFFSET(sbi, node_index); + cnode_index = AXFS_GET_CNODE_INDEX(sbi, node_index); + down_write(&sbi->lock); + if (cnode_index != sbi->current_cnode_index) { + /* uncompress only necessary if different cblock */ + ofs = AXFS_GET_CBLOCK_OFFSET(sbi, cnode_index); + len = AXFS_GET_CBLOCK_OFFSET(sbi, cnode_index + 1); + len -= ofs; + axfs_copy_data(sb, cblk1, &(sbi->compressed), ofs, len); + axfs_uncompress_block(cblk0, cblk_size, cblk1, len); + sbi->current_cnode_index = cnode_index;
I assume compressed blocks can be larger than PAGE_CACHE_SIZE? This suffers from the rather obvious inefficiency that you decompress a big block > PAGE_CACHE_SIZE, but only copy one PAGE_CACHE_SIZE page out of it. If multiple files are being read simultaneously (a common occurrence), then each is going to replace your one cached uncompressed block (sbi->current_cnode_index), leading to decompressing the same blocks over and over again on sequential file access.
readpage file A, index 1 -> decompress block X readpage file B, index 1 -> decompress block Y (replaces X) readpage file A, index 2 -> repeated decompress of block X (replaces Y) readpage file B, index 2 -> repeated decompress of block Y (replaces X) and so on.
+ } + downgrade_write(&sbi->lock); + max_len = cblk_size - cnode_offset; + len = max_len > PAGE_CACHE_SIZE ? PAGE_CACHE_SIZE : max_len;
Again, min() or min_t(). Lots of these. Phillip -- To unsubscribe from this list: send the line "unsubscribe linux-embedded" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html