diff options
author | Ralf Baechle <ralf@linux-mips.org> | 1997-07-29 03:58:24 +0000 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 1997-07-29 03:58:24 +0000 |
commit | 1c5c0c934f91fbce2825acbb849e98781e774c1d (patch) | |
tree | 12b5ae03516d4103bc070e4579ae1f7f71c27d24 /fs/romfs | |
parent | 4fe70c31de87823ac9e804f4795589ba74dc6971 (diff) |
Merge with 2.1.47. Some more cleanup and module fixes.
Diffstat (limited to 'fs/romfs')
-rw-r--r-- | fs/romfs/inode.c | 124 |
1 files changed, 97 insertions, 27 deletions
diff --git a/fs/romfs/inode.c b/fs/romfs/inode.c index 5d936ee59..d9a334f85 100644 --- a/fs/romfs/inode.c +++ b/fs/romfs/inode.c @@ -18,12 +18,19 @@ * Changes * Changed for 2.1.19 modules * Jan 1997 Initial release + * Jun 1997 2.1.43+ changes + * Jul 1997 proper page locking in readpage + * Changed to work with 2.1.45+ fs + * Fixed follow_link */ /* todo: - * use malloced memory for file names? - * considering write access... - * network (tftp) files? + * - see Documentation/filesystems/romfs.txt + * - use malloced memory for file names? + * - considering write access... + * - network (tftp) files? + * - in the ancient times something leaked to made umounts + * impossible, but I've not seen it in the last months */ /* @@ -74,7 +81,7 @@ romfs_read_super(struct super_block *s, void *data, int silent) MOD_INC_USE_COUNT; - /* I would parse the options, but there are none.. :) */ + /* I would parse the options here, but there are none.. :) */ lock_super(s); set_blocksize(dev, ROMBSIZE); @@ -82,6 +89,7 @@ romfs_read_super(struct super_block *s, void *data, int silent) s->s_blocksize_bits = ROMBSBITS; bh = bread(dev, 0, ROMBSIZE); if (!bh) { + /* XXX merge with other printk? */ printk ("romfs: unable to read superblock\n"); goto outnobh; } @@ -113,10 +121,11 @@ romfs_read_super(struct super_block *s, void *data, int silent) brelse(bh); s->s_op = &romfs_ops; + s->s_root = d_alloc_root(iget(s, sz), NULL); unlock_super(s); - if (!(s->s_mounted = iget(s, sz))) + if (!s->s_root) goto outnobh; /* Ehrhm; sorry.. :) And thanks to Hans-Joachim Widmaier :) */ @@ -145,10 +154,9 @@ romfs_put_super(struct super_block *sb) return; } - /* That's simple too. */ -static void +static int romfs_statfs(struct super_block *sb, struct statfs *buf, int bufsize) { struct statfs tmp; @@ -157,9 +165,12 @@ romfs_statfs(struct super_block *sb, struct statfs *buf, int bufsize) tmp.f_type = ROMFS_MAGIC; tmp.f_bsize = ROMBSIZE; tmp.f_blocks = (sb->u.romfs_sb.s_maxsize+ROMBSIZE-1)>>ROMBSBITS; - copy_to_user(buf, &tmp, bufsize); + /* XXX tmp.f_namelen = relevant? */ + return copy_to_user(buf, &tmp, bufsize) ? -EFAULT : 0; } +/* some helper routines */ + static int romfs_strnlen(struct inode *i, unsigned long offset, unsigned long count) { @@ -238,8 +249,6 @@ romfs_copyfrom(struct inode *i, void *dest, unsigned long offset, unsigned long return res; } -/* Directory operations */ - static int romfs_readdir(struct inode *i, struct file *filp, void *dirent, filldir_t filldir) { @@ -295,14 +304,16 @@ romfs_readdir(struct inode *i, struct file *filp, void *dirent, filldir_t filldi } static int -romfs_lookup(struct inode *dir, const char *name, int len, struct inode **result) +romfs_lookup(struct inode *dir, struct dentry *dentry) { unsigned long offset, maxoff; int fslen, res; + struct inode *inode; char fsname[ROMFS_MAXFN]; /* XXX dynamic? */ struct romfs_inode ri; + const char *name; /* got from dentry */ + int len; - *result = NULL; if (!dir || !S_ISDIR(dir->i_mode)) { res = -EBADF; goto out; @@ -317,6 +328,12 @@ romfs_lookup(struct inode *dir, const char *name, int len, struct inode **result maxoff = dir->i_sb->u.romfs_sb.s_maxsize; offset = ntohl(ri.spec) & ROMFH_MASK; + /* ok, now find the file, whose name is in "dentry", in the + * directory specified by "dir". */ + + name = dentry->d_name.name; + len = dentry->d_name.len; + for(;;) { if (!offset || offset >= maxoff || romfs_copyfrom(dir, &ri, offset, ROMFH_SIZE) <= 0) { @@ -350,20 +367,19 @@ romfs_lookup(struct inode *dir, const char *name, int len, struct inode **result if ((ntohl(ri.next) & ROMFH_TYPE) == ROMFH_HRD) offset = ntohl(ri.spec) & ROMFH_MASK; - res = 0; - if (!(*result = iget(dir->i_sb, offset))) - res = -EACCES; + res = -EACCES; + if ((inode = iget(dir->i_sb, offset))!=NULL) { + res = 0; + d_add(dentry, inode); + } out: - iput(dir); return res; } /* * Ok, we do readpage, to be able to execute programs. Unfortunately, - * bmap is not applicable, since we have looser alignments. - * - * XXX I'm not quite sure that I need to muck around the PG_xx bits.. + * we can't use bmap, since we have looser alignments. */ static int @@ -373,8 +389,12 @@ romfs_readpage(struct inode * inode, struct page * page) unsigned long offset, avail, readlen; int result = -EIO; - buf = page_address(page); atomic_inc(&page->count); + set_bit(PG_locked, &page->flags); + + buf = page_address(page); + clear_bit(PG_uptodate, &page->flags); + clear_bit(PG_error, &page->flags); offset = page->offset; if (offset < inode->i_size) { avail = inode->i_size-offset; @@ -383,13 +403,19 @@ romfs_readpage(struct inode * inode, struct page * page) if (readlen < PAGE_SIZE) { memset((void *)(buf+readlen),0,PAGE_SIZE-readlen); } - result = 0; set_bit(PG_uptodate, &page->flags); - } else { - memset((void *)buf, 0, PAGE_SIZE); + result = 0; } } + if (result) { + set_bit(PG_error, &page->flags); + memset((void *)buf, 0, PAGE_SIZE); + } + + clear_bit(PG_locked, &page->flags); + wake_up(&page->wait); free_page(buf); + return result; } @@ -417,6 +443,46 @@ out: return mylen; } +static struct dentry *romfs_follow_link(struct inode *inode, struct dentry *base) +{ + char *link; + int len, cnt; + struct dentry *dentry; + + /* Note: 2.1.46+ calls this for our strange directories... + * What I do is not really right, but I like it better for now, + * than a separate i_op table. Anyway, our directories won't + * have multiple "real" links to them, so it maybe loses nothing. */ + if (!S_ISLNK(inode->i_mode)) { + dentry = dget(i_dentry(inode)); + goto outnobuf; + } + + len = inode->i_size; + + dentry = ERR_PTR(-EAGAIN); /* correct? */ + if (!(link = kmalloc(len+1, GFP_KERNEL))) + goto outnobuf; + + cnt = romfs_copyfrom(inode, link, inode->u.romfs_i.i_dataoffset, len); + if (len != cnt) { + dentry = ERR_PTR(-EIO); + goto out; + } else + link[len] = 0; + + dentry = lookup_dentry(link, base, 1); + kfree(link); + + if (0) { +out: + kfree(link); +outnobuf: + dput(base); + } + return dentry; +} + /* Mapping from our types to the kernel */ static struct file_operations romfs_file_operations = { @@ -447,6 +513,7 @@ static struct inode_operations romfs_file_inode_operations = { NULL, /* mknod */ NULL, /* rename */ NULL, /* readlink */ + NULL, /* follow_link */ romfs_readpage, /* readpage */ NULL, /* writepage */ NULL, /* bmap -- not really */ @@ -471,7 +538,7 @@ static struct file_operations romfs_dir_operations = { NULL /* revalidate */ }; -/* Merged dir/symlink op table. readdir/lookup/readlink +/* Merged dir/symlink op table. readdir/lookup/readlink/follow_link * will protect from type mismatch. */ @@ -487,6 +554,7 @@ static struct inode_operations romfs_dirlink_inode_operations = { NULL, /* mknod */ NULL, /* rename */ romfs_readlink, /* readlink */ + romfs_follow_link, /* follow_link */ NULL, /* readpage */ NULL, /* writepage */ NULL, /* bmap */ @@ -519,9 +587,9 @@ romfs_read_inode(struct inode *i) int nextfh, ino; struct romfs_inode ri; - i->i_op = NULL; - ino = i->i_ino & ROMFH_MASK; + i->i_op = NULL; + i->i_mode = 0; /* Loop for finding the real hard link */ for(;;) { @@ -549,6 +617,7 @@ romfs_read_inode(struct inode *i) ino = ((ROMFH_SIZE+ino+1+ROMFH_PAD)&ROMFH_MASK); else ino = 0; + i->u.romfs_i.i_metasize = ino; i->u.romfs_i.i_dataoffset = ino+(i->i_ino&ROMFH_MASK); @@ -573,9 +642,10 @@ romfs_read_inode(struct inode *i) static struct super_operations romfs_ops = { romfs_read_inode, /* read inode */ - NULL, /* notify change */ NULL, /* write inode */ NULL, /* put inode */ + NULL, /* delete inode */ + NULL, /* notify change */ romfs_put_super, /* put super */ NULL, /* write super */ romfs_statfs, /* statfs */ |