struct inode vfs_inode;
};
+static struct inode *romfs_iget(struct super_block *, unsigned long);
+
/* instead of private superblock data */
static inline unsigned long romfs_maxsize(struct super_block *sb)
{
static inline struct romfs_inode_info *ROMFS_I(struct inode *inode)
{
- return list_entry(inode, struct romfs_inode_info, vfs_inode);
+ return container_of(inode, struct romfs_inode_info, vfs_inode);
}
static __u32
return sum;
}
-static struct super_operations romfs_ops;
+static const struct super_operations romfs_ops;
static int romfs_fill_super(struct super_block *s, void *data, int silent)
{
struct buffer_head *bh;
struct romfs_super_block *rsb;
struct inode *root;
- int sz;
+ int sz, ret = -EINVAL;
/* I would parse the options here, but there are none.. :) */
& ROMFH_MASK;
s->s_op = &romfs_ops;
- root = iget(s, sz);
- if (!root)
+ root = romfs_iget(s, sz);
+ if (IS_ERR(root)) {
+ ret = PTR_ERR(root);
goto out;
+ }
+ ret = -ENOMEM;
s->s_root = d_alloc_root(root);
if (!s->s_root)
goto outiput;
out:
brelse(bh);
outnobh:
- return -EINVAL;
+ return ret;
}
/* That's simple too. */
static int
-romfs_statfs(struct super_block *sb, struct kstatfs *buf)
+romfs_statfs(struct dentry *dentry, struct kstatfs *buf)
{
buf->f_type = ROMFS_MAGIC;
buf->f_bsize = ROMBSIZE;
buf->f_bfree = buf->f_bavail = buf->f_ffree;
- buf->f_blocks = (romfs_maxsize(sb)+ROMBSIZE-1)>>ROMBSBITS;
+ buf->f_blocks = (romfs_maxsize(dentry->d_sb)+ROMBSIZE-1)>>ROMBSBITS;
buf->f_namelen = ROMFS_MAXFN;
return 0;
}
static int
romfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
{
- struct inode *i = filp->f_dentry->d_inode;
+ struct inode *i = filp->f_path.dentry->d_inode;
struct romfs_inode ri;
unsigned long offset, maxoff;
int j, ino, nextfh;
romfs_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
{
unsigned long offset, maxoff;
- int fslen, res;
- struct inode *inode;
+ long res;
+ int fslen;
+ struct inode *inode = NULL;
char fsname[ROMFS_MAXFN]; /* XXX dynamic? */
struct romfs_inode ri;
const char *name; /* got from dentry */
offset = dir->i_ino & ROMFH_MASK;
lock_kernel();
if (romfs_copyfrom(dir, &ri, offset, ROMFH_SIZE) <= 0)
- goto out;
+ goto error;
maxoff = romfs_maxsize(dir->i_sb);
offset = be32_to_cpu(ri.spec) & ROMFH_MASK;
for(;;) {
if (!offset || offset >= maxoff)
- goto out0;
+ goto success; /* negative success */
if (romfs_copyfrom(dir, &ri, offset, ROMFH_SIZE) <= 0)
- goto out;
+ goto error;
/* try to match the first 16 bytes of name */
fslen = romfs_strnlen(dir, offset+ROMFH_SIZE, ROMFH_SIZE);
if ((be32_to_cpu(ri.next) & ROMFH_TYPE) == ROMFH_HRD)
offset = be32_to_cpu(ri.spec) & ROMFH_MASK;
- if ((inode = iget(dir->i_sb, offset)))
- goto outi;
-
- /*
- * it's a bit funky, _lookup needs to return an error code
- * (negative) or a NULL, both as a dentry. ENOENT should not
- * be returned, instead we need to create a negative dentry by
- * d_add(dentry, NULL); and return 0 as no error.
- * (Although as I see, it only matters on writable file
- * systems).
- */
-
-out0: inode = NULL;
-outi: res = 0;
- d_add (dentry, inode);
+ inode = romfs_iget(dir->i_sb, offset);
+ if (IS_ERR(inode)) {
+ res = PTR_ERR(inode);
+ goto error;
+ }
-out: unlock_kernel();
+success:
+ d_add(dentry, inode);
+ res = 0;
+error:
+ unlock_kernel();
return ERR_PTR(res);
}
romfs_readpage(struct file *file, struct page * page)
{
struct inode *inode = page->mapping->host;
- loff_t offset, avail, readlen;
+ loff_t offset, size;
+ unsigned long filled;
void *buf;
int result = -EIO;
/* 32 bit warning -- but not for us :) */
offset = page_offset(page);
- if (offset < i_size_read(inode)) {
- avail = inode->i_size-offset;
- readlen = min_t(unsigned long, avail, PAGE_SIZE);
- if (romfs_copyfrom(inode, buf, ROMFS_I(inode)->i_dataoffset+offset, readlen) == readlen) {
- if (readlen < PAGE_SIZE) {
- memset(buf + readlen,0,PAGE_SIZE-readlen);
- }
- SetPageUptodate(page);
- result = 0;
+ size = i_size_read(inode);
+ filled = 0;
+ result = 0;
+ if (offset < size) {
+ unsigned long readlen;
+
+ size -= offset;
+ readlen = size > PAGE_SIZE ? PAGE_SIZE : size;
+
+ filled = romfs_copyfrom(inode, buf, ROMFS_I(inode)->i_dataoffset+offset, readlen);
+
+ if (filled != readlen) {
+ SetPageError(page);
+ filled = 0;
+ result = -EIO;
}
}
- if (result) {
- memset(buf, 0, PAGE_SIZE);
- SetPageError(page);
- }
+
+ if (filled < PAGE_SIZE)
+ memset(buf + filled, 0, PAGE_SIZE-filled);
+
+ if (!result)
+ SetPageUptodate(page);
flush_dcache_page(page);
unlock_page(page);
/* Mapping from our types to the kernel */
-static struct address_space_operations romfs_aops = {
+static const struct address_space_operations romfs_aops = {
.readpage = romfs_readpage
};
-static struct file_operations romfs_dir_operations = {
+static const struct file_operations romfs_dir_operations = {
.read = generic_read_dir,
.readdir = romfs_readdir,
};
-static struct inode_operations romfs_dir_inode_operations = {
+static const struct inode_operations romfs_dir_inode_operations = {
.lookup = romfs_lookup,
};
S_IFBLK+0600, S_IFCHR+0600, S_IFSOCK+0644, S_IFIFO+0644
};
-static void
-romfs_read_inode(struct inode *i)
+static struct inode *
+romfs_iget(struct super_block *sb, unsigned long ino)
{
- int nextfh, ino;
+ int nextfh;
struct romfs_inode ri;
+ struct inode *i;
+
+ ino &= ROMFH_MASK;
+ i = iget_locked(sb, ino);
+ if (!i)
+ return ERR_PTR(-ENOMEM);
+ if (!(i->i_state & I_NEW))
+ return i;
- ino = i->i_ino & ROMFH_MASK;
i->i_mode = 0;
/* Loop for finding the real hard link */
for(;;) {
if (romfs_copyfrom(i, &ri, ino, ROMFH_SIZE) <= 0) {
- printk("romfs: read error for inode 0x%x\n", ino);
- return;
+ printk(KERN_ERR "romfs: read error for inode 0x%lx\n",
+ ino);
+ iget_failed(i);
+ return ERR_PTR(-EIO);
}
/* XXX: do romfs_checksum here too (with name) */
i->i_size = be32_to_cpu(ri.size);
i->i_mtime.tv_sec = i->i_atime.tv_sec = i->i_ctime.tv_sec = 0;
i->i_mtime.tv_nsec = i->i_atime.tv_nsec = i->i_ctime.tv_nsec = 0;
- i->i_uid = i->i_gid = 0;
/* Precalculate the data offset */
ino = romfs_strnlen(i, ino+ROMFH_SIZE, ROMFS_MAXFN);
init_special_inode(i, ino,
MKDEV(nextfh>>16,nextfh&0xffff));
}
+ unlock_new_inode(i);
+ return i;
}
-static kmem_cache_t * romfs_inode_cachep;
+static struct kmem_cache * romfs_inode_cachep;
static struct inode *romfs_alloc_inode(struct super_block *sb)
{
struct romfs_inode_info *ei;
- ei = (struct romfs_inode_info *)kmem_cache_alloc(romfs_inode_cachep, SLAB_KERNEL);
+ ei = kmem_cache_alloc(romfs_inode_cachep, GFP_KERNEL);
if (!ei)
return NULL;
return &ei->vfs_inode;
kmem_cache_free(romfs_inode_cachep, ROMFS_I(inode));
}
-static void init_once(void * foo, kmem_cache_t * cachep, unsigned long flags)
+static void init_once(void *foo)
{
- struct romfs_inode_info *ei = (struct romfs_inode_info *) foo;
+ struct romfs_inode_info *ei = foo;
- if ((flags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) ==
- SLAB_CTOR_CONSTRUCTOR)
- inode_init_once(&ei->vfs_inode);
+ inode_init_once(&ei->vfs_inode);
}
-
+
static int init_inodecache(void)
{
romfs_inode_cachep = kmem_cache_create("romfs_inode_cache",
sizeof(struct romfs_inode_info),
- 0, SLAB_RECLAIM_ACCOUNT|SLAB_MEM_SPREAD,
- init_once, NULL);
+ 0, (SLAB_RECLAIM_ACCOUNT|
+ SLAB_MEM_SPREAD),
+ init_once);
if (romfs_inode_cachep == NULL)
return -ENOMEM;
return 0;
static void destroy_inodecache(void)
{
- if (kmem_cache_destroy(romfs_inode_cachep))
- printk(KERN_INFO "romfs_inode_cache: not all structures were freed\n");
+ kmem_cache_destroy(romfs_inode_cachep);
}
static int romfs_remount(struct super_block *sb, int *flags, char *data)
return 0;
}
-static struct super_operations romfs_ops = {
+static const struct super_operations romfs_ops = {
.alloc_inode = romfs_alloc_inode,
.destroy_inode = romfs_destroy_inode,
- .read_inode = romfs_read_inode,
.statfs = romfs_statfs,
.remount_fs = romfs_remount,
};
-static struct super_block *romfs_get_sb(struct file_system_type *fs_type,
- int flags, const char *dev_name, void *data)
+static int romfs_get_sb(struct file_system_type *fs_type,
+ int flags, const char *dev_name, void *data, struct vfsmount *mnt)
{
- return get_sb_bdev(fs_type, flags, dev_name, data, romfs_fill_super);
+ return get_sb_bdev(fs_type, flags, dev_name, data, romfs_fill_super,
+ mnt);
}
static struct file_system_type romfs_fs_type = {