X-Git-Url: http://git.rot13.org/?a=blobdiff_plain;f=fs%2Flibfs.c;h=5294de1f40c41ba3c2dfcd992c725202967b0dce;hb=c9184f58cac9efa5d7d90a0e979f398a99d91641;hp=ac02ea602c3df2d7194e21c87f133786731bf7ee;hpb=972d19e837833b93466c6f6a8ef2a7d653000aa3;p=powerpc.git diff --git a/fs/libfs.c b/fs/libfs.c index ac02ea602c..5294de1f40 100644 --- a/fs/libfs.c +++ b/fs/libfs.c @@ -63,7 +63,7 @@ int dcache_dir_open(struct inode *inode, struct file *file) { static struct qstr cursor_name = {.len = 1, .name = "."}; - file->private_data = d_alloc(file->f_dentry, &cursor_name); + file->private_data = d_alloc(file->f_path.dentry, &cursor_name); return file->private_data ? 0 : -ENOMEM; } @@ -76,7 +76,7 @@ int dcache_dir_close(struct inode *inode, struct file *file) loff_t dcache_dir_lseek(struct file *file, loff_t offset, int origin) { - mutex_lock(&file->f_dentry->d_inode->i_mutex); + mutex_lock(&file->f_path.dentry->d_inode->i_mutex); switch (origin) { case 1: offset += file->f_pos; @@ -84,7 +84,7 @@ loff_t dcache_dir_lseek(struct file *file, loff_t offset, int origin) if (offset >= 0) break; default: - mutex_unlock(&file->f_dentry->d_inode->i_mutex); + mutex_unlock(&file->f_path.dentry->d_inode->i_mutex); return -EINVAL; } if (offset != file->f_pos) { @@ -96,8 +96,8 @@ loff_t dcache_dir_lseek(struct file *file, loff_t offset, int origin) spin_lock(&dcache_lock); list_del(&cursor->d_u.d_child); - p = file->f_dentry->d_subdirs.next; - while (n && p != &file->f_dentry->d_subdirs) { + p = file->f_path.dentry->d_subdirs.next; + while (n && p != &file->f_path.dentry->d_subdirs) { struct dentry *next; next = list_entry(p, struct dentry, d_u.d_child); if (!d_unhashed(next) && next->d_inode) @@ -108,7 +108,7 @@ loff_t dcache_dir_lseek(struct file *file, loff_t offset, int origin) spin_unlock(&dcache_lock); } } - mutex_unlock(&file->f_dentry->d_inode->i_mutex); + mutex_unlock(&file->f_path.dentry->d_inode->i_mutex); return offset; } @@ -126,7 +126,7 @@ static inline unsigned char dt_type(struct inode *inode) int dcache_readdir(struct file * filp, void * dirent, filldir_t filldir) { - struct dentry *dentry = filp->f_dentry; + struct dentry *dentry = filp->f_path.dentry; struct dentry *cursor = filp->private_data; struct list_head *p, *q = &cursor->d_u.d_child; ino_t ino; @@ -159,7 +159,10 @@ int dcache_readdir(struct file * filp, void * dirent, filldir_t filldir) continue; spin_unlock(&dcache_lock); - if (filldir(dirent, next->d_name.name, next->d_name.len, filp->f_pos, next->d_inode->i_ino, dt_type(next->d_inode)) < 0) + if (filldir(dirent, next->d_name.name, + next->d_name.len, filp->f_pos, + next->d_inode->i_ino, + dt_type(next->d_inode)) < 0) return 0; spin_lock(&dcache_lock); /* next is still alive */ @@ -186,20 +189,23 @@ const struct file_operations simple_dir_operations = { .fsync = simple_sync_file, }; -struct inode_operations simple_dir_inode_operations = { +const struct inode_operations simple_dir_inode_operations = { .lookup = simple_lookup, }; +static const struct super_operations simple_super_operations = { + .statfs = simple_statfs, +}; + /* * Common helper for pseudo-filesystems (sockfs, pipefs, bdev - stuff that * will never be mountable) */ int get_sb_pseudo(struct file_system_type *fs_type, char *name, - struct super_operations *ops, unsigned long magic, + const struct super_operations *ops, unsigned long magic, struct vfsmount *mnt) { struct super_block *s = sget(fs_type, NULL, set_anon_super, NULL); - static struct super_operations default_ops = {.statfs = simple_statfs}; struct dentry *dentry; struct inode *root; struct qstr d_name = {.name = name, .len = strlen(name)}; @@ -212,11 +218,17 @@ int get_sb_pseudo(struct file_system_type *fs_type, char *name, s->s_blocksize = 1024; s->s_blocksize_bits = 10; s->s_magic = magic; - s->s_op = ops ? ops : &default_ops; + s->s_op = ops ? ops : &simple_super_operations; s->s_time_gran = 1; root = new_inode(s); if (!root) goto Enomem; + /* + * since this is the first inode, make it number 1. New inodes created + * after this must take care not to collide with it (by passing + * max_reserved of 1 to iunique). + */ + root->i_ino = 1; root->i_mode = S_IFDIR | S_IRUSR | S_IWUSR; root->i_uid = root->i_gid = 0; root->i_atime = root->i_mtime = root->i_ctime = CURRENT_TIME; @@ -243,7 +255,7 @@ int simple_link(struct dentry *old_dentry, struct inode *dir, struct dentry *den struct inode *inode = old_dentry->d_inode; inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME; - inode->i_nlink++; + inc_nlink(inode); atomic_inc(&inode->i_count); dget(dentry); d_instantiate(dentry, inode); @@ -275,7 +287,7 @@ int simple_unlink(struct inode *dir, struct dentry *dentry) struct inode *inode = dentry->d_inode; inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME; - inode->i_nlink--; + drop_nlink(inode); dput(dentry); return 0; } @@ -285,9 +297,9 @@ int simple_rmdir(struct inode *dir, struct dentry *dentry) if (!simple_empty(dentry)) return -ENOTEMPTY; - dentry->d_inode->i_nlink--; + drop_nlink(dentry->d_inode); simple_unlink(dir, dentry); - dir->i_nlink--; + drop_nlink(dir); return 0; } @@ -303,10 +315,10 @@ int simple_rename(struct inode *old_dir, struct dentry *old_dentry, if (new_dentry->d_inode) { simple_unlink(new_dir, new_dentry); if (they_are_dirs) - old_dir->i_nlink--; + drop_nlink(old_dir); } else if (they_are_dirs) { - old_dir->i_nlink--; - new_dir->i_nlink++; + drop_nlink(old_dir); + inc_nlink(new_dir); } old_dir->i_ctime = old_dir->i_mtime = new_dir->i_ctime = @@ -317,17 +329,9 @@ int simple_rename(struct inode *old_dir, struct dentry *old_dentry, int simple_readpage(struct file *file, struct page *page) { - void *kaddr; - - if (PageUptodate(page)) - goto out; - - kaddr = kmap_atomic(page, KM_USER0); - memset(kaddr, 0, PAGE_CACHE_SIZE); - kunmap_atomic(kaddr, KM_USER0); + clear_highpage(page); flush_dcache_page(page); SetPageUptodate(page); -out: unlock_page(page); return 0; } @@ -343,17 +347,18 @@ int simple_prepare_write(struct file *file, struct page *page, flush_dcache_page(page); kunmap_atomic(kaddr, KM_USER0); } - SetPageUptodate(page); } return 0; } int simple_commit_write(struct file *file, struct page *page, - unsigned offset, unsigned to) + unsigned from, unsigned to) { struct inode *inode = page->mapping->host; loff_t pos = ((loff_t)page->index << PAGE_CACHE_SHIFT) + to; + if (!PageUptodate(page)) + SetPageUptodate(page); /* * No need to use i_size_read() here, the i_size * cannot change under us because we hold the i_mutex. @@ -364,9 +369,13 @@ int simple_commit_write(struct file *file, struct page *page, return 0; } +/* + * the inodes created here are not hashed. If you use iunique to generate + * unique inode values later for this filesystem, then you must take care + * to pass it an appropriate max_reserved value to avoid collisions. + */ int simple_fill_super(struct super_block *s, int magic, struct tree_descr *files) { - static struct super_operations s_ops = {.statfs = simple_statfs}; struct inode *inode; struct dentry *root; struct dentry *dentry; @@ -375,15 +384,19 @@ int simple_fill_super(struct super_block *s, int magic, struct tree_descr *files s->s_blocksize = PAGE_CACHE_SIZE; s->s_blocksize_bits = PAGE_CACHE_SHIFT; s->s_magic = magic; - s->s_op = &s_ops; + s->s_op = &simple_super_operations; s->s_time_gran = 1; inode = new_inode(s); if (!inode) return -ENOMEM; + /* + * because the root inode is 1, the files array must not contain an + * entry at index 1 + */ + inode->i_ino = 1; inode->i_mode = S_IFDIR | 0755; inode->i_uid = inode->i_gid = 0; - inode->i_blksize = PAGE_CACHE_SIZE; inode->i_blocks = 0; inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME; inode->i_op = &simple_dir_inode_operations; @@ -397,6 +410,13 @@ int simple_fill_super(struct super_block *s, int magic, struct tree_descr *files for (i = 0; !files->name || files->name[0]; i++, files++) { if (!files->name) continue; + + /* warn if it tries to conflict with the root inode */ + if (unlikely(i == 1)) + printk(KERN_WARNING "%s: %s passed in a files array" + "with an index of 1!\n", __func__, + s->s_type->name); + dentry = d_alloc_name(root, files->name); if (!dentry) goto out; @@ -405,7 +425,6 @@ int simple_fill_super(struct super_block *s, int magic, struct tree_descr *files goto out; inode->i_mode = S_IFREG | files->mode; inode->i_uid = inode->i_gid = 0; - inode->i_blksize = PAGE_CACHE_SIZE; inode->i_blocks = 0; inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME; inode->i_fop = files->ops; @@ -547,7 +566,7 @@ int simple_attr_open(struct inode *inode, struct file *file, attr->get = get; attr->set = set; - attr->data = inode->u.generic_ip; + attr->data = inode->i_private; attr->fmt = fmt; mutex_init(&attr->mutex);