OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

Compare Revisions

  • This comparison shows the changes necessary to convert path
    /or1k/tags/before_ORP/uclinux/uClinux-2.0.x/fs/ufs
    from Rev 901 to Rev 1765
    Reverse comparison

Rev 901 → Rev 1765

/ufs_symlink.c
0,0 → 1,183
/*
* linux/fs/ufs/ufs_symlink.c
*
* Copyright (C) 1996
* Adrian Rodriguez (adrian@franklins-tower.rutgers.edu)
* Laboratory for Computer Science Research Computing Facility
* Rutgers, The State University of New Jersey
*
* $Id: ufs_symlink.c,v 1.1.1.1 2001-09-10 07:44:40 simons Exp $
*
*/
 
#include <linux/fs.h>
#include <linux/sched.h>
 
#include <asm/segment.h>
 
extern int ufs_bmap (struct inode *, int);
 
static int
ufs_readlink(struct inode * inode, char * buffer, int buflen)
{
unsigned long int block;
struct buffer_head * bh = NULL;
char * link;
int i;
char c;
 
if (inode->i_sb->u.ufs_sb.s_flags & (UFS_DEBUG|UFS_DEBUG_LINKS)) {
printk("ufs_readlink: called on ino %lu dev %u/%u\n",
inode->i_ino, MAJOR(inode->i_dev), MINOR(inode->i_dev));
}
 
if (!S_ISLNK(inode->i_mode)) {
iput (inode);
return -EINVAL;
}
if (buflen > inode->i_sb->s_blocksize - 1)
buflen = inode->i_sb->s_blocksize - 1;
if (inode->i_blocks) {
/* XXX - error checking */
block = ufs_bmap(inode, 0);
if (inode->i_sb->u.ufs_sb.s_flags &(UFS_DEBUG|UFS_DEBUG_LINKS)) {
printk("ufs_readlink: bmap got %lu for ino %lu\n",
block, inode->i_ino);
}
bh = bread(inode->i_dev, block, BLOCK_SIZE);
if (!bh) {
iput (inode);
printk("ufs_readlink: can't read block 0 for ino %lu on dev %u/%u\n",
inode->i_ino, MAJOR(inode->i_dev),
MINOR(inode->i_dev));
return 0;
}
link = bh->b_data;
}
else {
link = (char *)&(inode->u.ufs_i.ui_db[0]);
}
i = 0;
while (i < buflen && (c = link[i])) {
i++;
put_user (c, buffer++);
}
iput (inode);
if (bh)
brelse (bh);
return i;
}
 
/*
* XXX - blatantly stolen from ext2fs
*/
static int
ufs_follow_link(struct inode * dir, struct inode * inode,
int flag, int mode, struct inode ** res_inode)
{
unsigned long int block;
int error;
struct buffer_head * bh;
char * link;
 
bh = NULL;
 
if (inode->i_sb->u.ufs_sb.s_flags & (UFS_DEBUG|UFS_DEBUG_LINKS)) {
printk("ufs_follow_link: called on ino %lu dev %u/%u\n",
dir->i_ino, MAJOR(dir->i_dev), MINOR(dir->i_dev));
}
 
*res_inode = NULL;
if (!dir) {
dir = current->fs->root;
dir->i_count++;
}
if (!inode) {
iput (dir);
return -ENOENT;
}
if (!S_ISLNK(inode->i_mode)) {
iput (dir);
*res_inode = inode;
return 0;
}
if (current->link_count > 5) {
iput (dir);
iput (inode);
return -ELOOP;
}
if (inode->i_blocks) {
/* read the link from disk */
/* XXX - error checking */
block = ufs_bmap(inode, 0);
bh = bread(inode->i_dev, block, BLOCK_SIZE);
if (bh == NULL) {
printk("ufs_follow_link: can't read block 0 for ino %lu on dev %u/%u\n",
inode->i_ino, MAJOR(inode->i_dev),
MINOR(inode->i_dev));
iput(dir);
iput(inode);
return(-EIO);
}
link = bh->b_data;
} else {
/* fast symlink */
link = (char *)&(inode->u.ufs_i.ui_db[0]);
}
current->link_count++;
error = open_namei (link, flag, mode, res_inode, dir);
current->link_count--;
iput (inode);
if (bh) {
brelse (bh);
}
return(error);
}
 
 
static struct file_operations ufs_symlink_operations = {
NULL, /* lseek */
NULL, /* read */
NULL, /* write */
NULL, /* readdir */
NULL, /* select */
NULL, /* ioctl */
NULL, /* mmap */
NULL, /* open */
NULL, /* release */
NULL, /* fsync */ /* XXX - is this ok? */
NULL, /* fasync */
NULL, /* check_media_change */
NULL, /* revalidate */
};
 
struct inode_operations ufs_symlink_inode_operations = {
&ufs_symlink_operations, /* default directory file operations */
NULL, /* create */
NULL, /* lookup */
NULL, /* link */
NULL, /* unlink */
NULL, /* symlink */
NULL, /* mkdir */
NULL, /* rmdir */
NULL, /* mknod */
NULL, /* rename */
&ufs_readlink, /* readlink */
&ufs_follow_link, /* follow_link */
NULL, /* readpage */
NULL, /* writepage */
NULL, /* bmap */
NULL, /* truncate */
NULL, /* permission */
NULL, /* smap */
};
 
/*
* Local Variables: ***
* c-indent-level: 8 ***
* c-continued-statement-offset: 8 ***
* c-brace-offset: -8 ***
* c-argdecl-indent: 0 ***
* c-label-offset: -8 ***
* End: ***
*/
/ufs_namei.c
0,0 → 1,154
/*
* linux/fs/ufs/ufs_namei.c
*
* Copyright (C) 1996
* Adrian Rodriguez (adrian@franklins-tower.rutgers.edu)
* Laboratory for Computer Science Research Computing Facility
* Rutgers, The State University of New Jersey
*
* $Id: ufs_namei.c,v 1.1.1.1 2001-09-10 07:44:40 simons Exp $
*
*/
 
#include <linux/fs.h>
 
extern unsigned int ufs_bmap(struct inode * inode, int block); /* XXX */
 
/*
* NOTE! unlike strncmp, ext2_match returns 1 for success, 0 for failure.
* stolen from ext2fs
*/
static int ufs_match (int len, const char * const name, struct ufs_direct * d)
{
if (!d || len > UFS_MAXNAMLEN)
return 0;
/*
* "" means "." ---> so paths like "/usr/lib//libc.a" work
*/
if (!len && (d->d_namlen == 1) && (d->d_name[0] == '.') &&
(d->d_name[1] == '\0'))
return 1;
if (len != d->d_namlen)
return 0;
return !memcmp(name, d->d_name, len);
}
 
/* XXX - this is a mess, especially for endianity */
int ufs_lookup (struct inode * dir, const char * name, int len,
struct inode ** result)
{
unsigned long int lfragno, fragno;
struct buffer_head * bh;
struct ufs_direct * d;
 
/*
* Touching /xyzzy in a filesystem toggles debugging messages.
*/
if ((len == 5) && !(memcmp(name, "xyzzy", len)) &&
(dir->i_ino == UFS_ROOTINO)) {
dir->i_sb->u.ufs_sb.s_flags ^= UFS_DEBUG;
printk("UFS debugging %s\n",
(dir->i_sb->u.ufs_sb.s_flags & UFS_DEBUG) ?
"on": "off");
return(-ENOENT);
}
 
/*
* Touching /xyzzy.i in a filesystem toggles debugging for ufs_inode.c.
*/
if ((len == 7) && !(memcmp(name, "xyzzy.i", len)) &&
(dir->i_ino == UFS_ROOTINO)) {
dir->i_sb->u.ufs_sb.s_flags ^= UFS_DEBUG_INODE;
printk("UFS inode debugging %s\n",
(dir->i_sb->u.ufs_sb.s_flags & UFS_DEBUG_INODE) ?
"on": "off");
return(-ENOENT);
}
 
if ((len == 7) && !(memcmp(name, "xyzzy.n", len)) &&
(dir->i_ino == UFS_ROOTINO)) {
dir->i_sb->u.ufs_sb.s_flags ^= UFS_DEBUG_NAMEI;
printk("UFS namei debugging %s\n",
(dir->i_sb->u.ufs_sb.s_flags & UFS_DEBUG_NAMEI) ?
"on": "off");
return(-ENOENT);
}
 
if ((len == 7) && !(memcmp(name, "xyzzy.l", len)) &&
(dir->i_ino == UFS_ROOTINO)) {
dir->i_sb->u.ufs_sb.s_flags ^= UFS_DEBUG_LINKS;
printk("UFS symlink debugging %s\n",
(dir->i_sb->u.ufs_sb.s_flags & UFS_DEBUG_LINKS) ?
"on": "off");
return(-ENOENT);
}
 
if (dir->i_sb->u.ufs_sb.s_flags & (UFS_DEBUG|UFS_DEBUG_NAMEI)) {
printk("ufs_lookup: called for ino %lu name %s\n",
dir->i_ino, name);
}
 
/* XXX - do I want i_blocks in 512-blocks or 1024-blocks? */
for (lfragno = 0; lfragno < (dir->i_blocks)>>1; lfragno++) {
fragno = ufs_bmap(dir, lfragno);
/* XXX - ufs_bmap() call needs error checking */
/* XXX - s_blocksize is actually the UFS frag size */
if (dir->i_sb->u.ufs_sb.s_flags & UFS_DEBUG) {
printk("ufs_lookup: ino %lu lfragno %lu fragno %lu\n",
dir->i_ino, lfragno, fragno);
}
if (fragno == 0) {
/* XXX - bug bug bug */
return(-ENOENT);
}
bh = bread(dir->i_dev, fragno, dir->i_sb->s_blocksize);
if (bh == NULL) {
printk("ufs_lookup: bread failed: ino %lu, lfragno %lu",
dir->i_ino, lfragno);
return(-EIO);
}
d = (struct ufs_direct *)(bh->b_data);
while (((char *)d - bh->b_data + d->d_reclen) <=
dir->i_sb->s_blocksize) {
/* XXX - skip block if d_reclen or d_namlen is 0 */
if ((d->d_reclen == 0) || (d->d_namlen == 0)) {
if (dir->i_sb->u.ufs_sb.s_flags & UFS_DEBUG) {
printk("ufs_lookup: skipped space in directory, ino %lu\n",
dir->i_ino);
}
break;
}
if (dir->i_sb->u.ufs_sb.s_flags & UFS_DEBUG) {
printk("lfragno 0x%lx direct d 0x%x d_ino %u d_reclen %u d_namlen %u d_name `%s'\n",
lfragno, (unsigned int)d, d->d_ino, d->d_reclen, d->d_namlen, d->d_name);
}
if ((d->d_namlen == len) &&
/* XXX - don't use strncmp() - see ext2fs */
(ufs_match(len, name, d))) {
/* We have a match */
*result = iget(dir->i_sb, d->d_ino);
brelse(bh);
return(0);
} else {
/* XXX - bounds checking */
if (dir->i_sb->u.ufs_sb.s_flags & UFS_DEBUG) {
printk("ufs_lookup: wanted (%s,%d) got (%s,%d)\n",
name, len, d->d_name, d->d_namlen);
}
}
d = (struct ufs_direct *)((char *)d + d->d_reclen);
}
brelse(bh);
}
return(-ENOENT);
}
 
/*
* Local Variables: ***
* c-indent-level: 8 ***
* c-continued-statement-offset: 8 ***
* c-brace-offset: -8 ***
* c-argdecl-indent: 0 ***
* c-label-offset: -8 ***
* End: ***
*/
/ufs_dir.c
0,0 → 1,189
/*
* linux/fs/ufs/ufs_dir.c
*
* Copyright (C) 1996
* Adrian Rodriguez (adrian@franklins-tower.rutgers.edu)
* Laboratory for Computer Science Research Computing Facility
* Rutgers, The State University of New Jersey
*
* $Id: ufs_dir.c,v 1.1.1.1 2001-09-10 07:44:40 simons Exp $
*
*/
 
#include <linux/fs.h>
 
/* XXX */
extern int ufs_lookup (struct inode *, const char *, int, struct inode **);
extern int ufs_bmap (struct inode *, int);
extern void ufs_print_inode (struct inode *);
 
/*
* This is blatantly stolen from ext2fs
*/
static int
ufs_readdir (struct inode * inode, struct file * filp, void * dirent,
filldir_t filldir)
{
int error = 0;
unsigned long offset, lblk, blk;
int i, stored;
struct buffer_head * bh;
struct ufs_direct * de;
struct super_block * sb;
 
if (!inode || !S_ISDIR(inode->i_mode))
return -EBADF;
sb = inode->i_sb;
 
if (inode->i_sb->u.ufs_sb.s_flags & UFS_DEBUG) {
printk("ufs_readdir: ino %lu f_pos %lu\n",
inode->i_ino, (unsigned long) filp->f_pos);
ufs_print_inode(inode);
}
 
stored = 0;
bh = NULL;
offset = filp->f_pos & (sb->s_blocksize - 1);
 
while (!error && !stored && filp->f_pos < inode->i_size) {
lblk = (filp->f_pos) >> sb->s_blocksize_bits;
blk = ufs_bmap(inode, lblk);
/* XXX - ufs_bmap() call needs error checking */
blk = ufs_bmap(inode, lblk);
bh = bread (sb->s_dev, blk, sb->s_blocksize);
if (!bh) {
/* XXX - error - skip to the next block */
printk("ufs_readdir: dir inode %lu has a hole at offset %lu\n",
inode->i_ino, (unsigned long int)filp->f_pos);
filp->f_pos += sb->s_blocksize - offset;
continue;
}
 
revalidate:
/* If the dir block has changed since the last call to
* readdir(2), then we might be pointing to an invalid
* dirent right now. Scan from the start of the block
* to make sure. */
if (filp->f_version != inode->i_version) {
for (i = 0; i < sb->s_blocksize && i < offset; ) {
de = (struct ufs_direct *)
(bh->b_data + i);
/* It's too expensive to do a full
* dirent test each time round this
* loop, but we do have to test at
* least that it is non-zero. A
* failure will be detected in the
* dirent test below. */
if (de->d_reclen < 1)
break;
i += de->d_reclen;
}
offset = i;
filp->f_pos = (filp->f_pos & ~(sb->s_blocksize - 1))
| offset;
filp->f_version = inode->i_version;
}
while (!error && filp->f_pos < inode->i_size
&& offset < sb->s_blocksize) {
de = (struct ufs_direct *) (bh->b_data + offset);
/* XXX - put in a real ufs_check_dir_entry() */
if ((de->d_reclen == 0) || (de->d_namlen == 0)) {
filp->f_pos = (filp->f_pos & (sb->s_blocksize - 1)) + sb->s_blocksize;
brelse(bh);
return stored;
}
#if 0
if (!ext2_check_dir_entry ("ext2_readdir", inode, de,
bh, offset)) {
/* On error, skip the f_pos to the
next block. */
filp->f_pos = (filp->f_pos & (sb->s_blocksize - 1))
+ sb->s_blocksize;
brelse (bh);
return stored;
}
#endif /* XXX */
offset += de->d_reclen;
if (de->d_ino) {
/* We might block in the next section
* if the data destination is
* currently swapped out. So, use a
* version stamp to detect whether or
* not the directory has been modified
* during the copy operation. */
unsigned long version;
dcache_add(inode, de->d_name, de->d_namlen,
de->d_ino);
version = inode->i_version;
if (inode->i_sb->u.ufs_sb.s_flags & UFS_DEBUG) {
printk("ufs_readdir: filldir(%s,%u)\n",
de->d_name, de->d_ino);
}
error = filldir(dirent, de->d_name, de->d_namlen, filp->f_pos, de->d_ino);
if (error)
break;
if (version != inode->i_version)
goto revalidate;
stored ++;
}
filp->f_pos += de->d_reclen;
}
offset = 0;
brelse (bh);
}
#if 0 /* XXX */
if (!IS_RDONLY(inode)) {
inode->i_atime = CURRENT_TIME;
inode->i_dirt = 1;
}
#endif /* XXX */
return 0;
}
 
static struct file_operations ufs_dir_operations = {
NULL, /* lseek */
NULL, /* read */
NULL, /* write */
ufs_readdir, /* readdir */
NULL, /* select */
NULL, /* ioctl */
NULL, /* mmap */
NULL, /* open */
NULL, /* release */
file_fsync, /* fsync */
NULL, /* fasync */
NULL, /* check_media_change */
NULL, /* revalidate */
};
 
struct inode_operations ufs_dir_inode_operations = {
&ufs_dir_operations, /* default directory file operations */
NULL, /* create */
ufs_lookup, /* lookup */
NULL, /* link */
NULL, /* unlink */
NULL, /* symlink */
NULL, /* mkdir */
NULL, /* rmdir */
NULL, /* mknod */
NULL, /* rename */
NULL, /* readlink */
NULL, /* follow_link */
NULL, /* readpage */
NULL, /* writepage */
NULL, /* bmap */
NULL, /* truncate */
NULL, /* permission */
NULL, /* smap */
};
 
/*
* Local Variables: ***
* c-indent-level: 8 ***
* c-continued-statement-offset: 8 ***
* c-brace-offset: -8 ***
* c-argdecl-indent: 0 ***
* c-label-offset: -8 ***
* End: ***
*/
/ufs_inode.c
0,0 → 1,237
/*
* linux/fs/ufs/ufs_inode.c
*
* Copyright (C) 1996
* Adrian Rodriguez (adrian@franklins-tower.rutgers.edu)
* Laboratory for Computer Science Research Computing Facility
* Rutgers, The State University of New Jersey
*
* $Id: ufs_inode.c,v 1.1.1.1 2001-09-10 07:44:40 simons Exp $
*
*/
 
#include <linux/fs.h>
#include <linux/ufs_fs.h>
#include <linux/sched.h>
 
extern struct inode_operations ufs_file_inode_operations;
extern struct inode_operations ufs_dir_inode_operations;
extern struct inode_operations ufs_symlink_inode_operations;
extern struct file_operations ufs_file_operations;
extern struct file_operations ufs_dir_operations;
extern struct file_operations ufs_symlink_operations;
 
void ufs_print_inode(struct inode * inode)
{
printk("ino %lu mode 0%6.6o lk %d uid %d gid %d sz %lu blks %lu cnt %lu\n",
inode->i_ino, inode->i_mode, inode->i_nlink, inode->i_uid, inode->i_gid, inode->i_size, inode->i_blocks, inode->i_count);
printk(" db <0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x>\n",
inode->u.ufs_i.ui_db[0], inode->u.ufs_i.ui_db[1],
inode->u.ufs_i.ui_db[2], inode->u.ufs_i.ui_db[3],
inode->u.ufs_i.ui_db[4], inode->u.ufs_i.ui_db[5],
inode->u.ufs_i.ui_db[6], inode->u.ufs_i.ui_db[7],
inode->u.ufs_i.ui_db[8], inode->u.ufs_i.ui_db[9],
inode->u.ufs_i.ui_db[10], inode->u.ufs_i.ui_db[11]);
printk(" gen 0x%8.8x ib <0x%x 0x%x 0x%x>\n",
inode->u.ufs_i.ui_gen, inode->u.ufs_i.ui_ib[0],
inode->u.ufs_i.ui_ib[1], inode->u.ufs_i.ui_ib[2]);
}
 
/* XXX - ufs_read_inode is a mess */
void ufs_read_inode(struct inode * inode)
{
struct super_block * sb;
struct ufs_inode * ufsip;
struct buffer_head * bh;
 
sb = inode->i_sb;
 
if (ufs_ino_ok(inode)) {
printk("ufs_read_inode: bad inum %lu", inode->i_ino);
 
return;
}
 
#if 0
printk("ufs_read_inode: ino %lu cg %u cgino %u ipg %u inopb %u\n",
inode->i_ino, ufs_ino2cg(inode),
(inode->i_ino%sb->u.ufs_sb.s_inopb),
sb->u.ufs_sb.s_ipg, sb->u.ufs_sb.s_inopb);
#endif
bh = bread(inode->i_dev,
ufs_cgimin(inode->i_sb, ufs_ino2cg(inode)) +
(inode->i_ino%sb->u.ufs_sb.s_ipg)/(sb->u.ufs_sb.s_inopb/sb->u.ufs_sb.s_fsfrag),
BLOCK_SIZE);
if (!bh) {
printk("ufs_read_inode: can't read inode %lu from dev %d/%d",
inode->i_ino, MAJOR(inode->i_dev), MINOR(inode->i_dev));
return;
}
 
ufsip = (struct ufs_inode *)bh->b_data;
ufsip += (inode->i_ino%(sb->u.ufs_sb.s_inopb/sb->u.ufs_sb.s_fsfrag));
 
/*
* Copy data to the in-core inode.
*/
inode->i_mode = ufsip->ui_mode;
inode->i_nlink = ufsip->ui_nlink;
if (inode->i_nlink == 0) {
/* XXX */
printk("ufs_read_inode: zero nlink ino %lu dev %u/%u\n",
inode->i_ino, MAJOR(inode->i_dev), MINOR(inode->i_dev));
inode->i_nlink = 1;
printk("ufs_read_inode: fishy ino %lu pblk %lu dev %u/%u\n",
inode->i_ino,
ufs_cgimin(inode->i_sb, ufs_ino2cg(inode)) +
(inode->i_ino%sb->u.ufs_sb.s_ipg)/sb->u.ufs_sb.s_inopb,
MAJOR(inode->i_dev), MINOR(inode->i_dev));
}
/* XXX - debugging */
if (ufsip->ui_gen == 0) {
printk("ufs_read_inode: zero gen ino %lu pblk %lu dev %u/%u\n",
inode->i_ino,
ufs_cgimin(inode->i_sb, ufs_ino2cg(inode)) +
(inode->i_ino%sb->u.ufs_sb.s_ipg)/sb->u.ufs_sb.s_inopb,
MAJOR(inode->i_dev), MINOR(inode->i_dev));
}
/*
* Since Linux currently only has 16-bit uid_t and gid_t, we can't
* really support EFTs. For the moment, we use 0 as the uid and gid
* if an inode has a uid or gid that won't fit in 16 bits. This way
* random users can't get at these files, since they get dynamically
* "chown()ed" to root.
*/
if (ufsip->ui_suid == UFS_USEEFT) {
/* EFT */
inode->i_uid = 0;
printk("ufs_read_inode: EFT uid %u ino %lu dev %u/%u, using %u\n",
ufsip->ui_uid, inode->i_ino, MAJOR(inode->i_dev), MINOR(inode->i_dev),
inode->i_uid);
} else {
inode->i_uid = ufsip->ui_suid;
}
if (ufsip->ui_suid == UFS_USEEFT) {
/* EFT */
inode->i_uid = 0;
printk("ufs_read_inode: EFT gid %u ino %lu dev %u/%u, using %u\n",
ufsip->ui_gid, inode->i_ino, MAJOR(inode->i_dev), MINOR(inode->i_dev),
inode->i_gid);
} else {
inode->i_gid = ufsip->ui_sgid;
}
 
/*
* Linux i_size is 32 bits, so some files on a UFS filesystem may not
* be readable. I let people access the first 32 bits worth of them.
* for the rw code, we may want to mark these inodes as read-only.
* XXX - bug Linus to make i_size a __u64 instead of a __u32.
*/
inode->u.ufs_i.ui_size = ((__u64)(ufsip->ui_size.val[0])<<32) | (__u64)(ufsip->ui_size.val[1]);
inode->i_size = ufsip->ui_size.val[1]; /* XXX - endianity */
if (ufsip->ui_size.val[0] != 0) {
inode->i_size = 0xffffffff;
printk("ufs_read_inode: file too big ino %lu dev %u/%u, faking size\n",
inode->i_ino, MAJOR(inode->i_dev), MINOR(inode->i_dev));
}
/*
* Linux doesn't keep tv_usec around in the kernel, so we discard it.
* XXX - I'm not sure what I should do about writing things. I may
* want to keep this data, but for the moment I think I'll just write
* zeros for these fields when writing out inodes.
*/
inode->i_atime = ufsip->ui_atime.tv_sec;
inode->i_mtime = ufsip->ui_mtime.tv_sec;
inode->i_ctime = ufsip->ui_ctime.tv_sec;
inode->i_blksize = sb->u.ufs_sb.s_fsize;
inode->i_blocks = ufsip->ui_blocks;
inode->i_version = ++event; /* see linux/kernel/sched.c */
 
if (S_ISREG(inode->i_mode)) {
inode->i_op = &ufs_file_inode_operations;
} else if (S_ISDIR(inode->i_mode)) {
inode->i_op = &ufs_dir_inode_operations;
} else if (S_ISLNK(inode->i_mode)) {
inode->i_op = &ufs_symlink_inode_operations;
} else if (S_ISCHR(inode->i_mode)) {
inode->i_op = &chrdev_inode_operations;
} else if (S_ISBLK(inode->i_mode)) {
inode->i_op = &blkdev_inode_operations;
} else if (S_ISFIFO(inode->i_mode)) {
init_fifo(inode);
} else {
printk("ufs_read_inode: unknown file type 0%o ino %lu dev %d/%d\n",
inode->i_mode, inode->i_ino, MAJOR(inode->i_dev),
MINOR(inode->i_dev));
/* XXX - debugging */
ufs_print_inode(inode);
inode->i_op = &ufs_file_inode_operations;
}
 
/*
* ufs_read_super makes sure that UFS_NDADDR and UFS_NINDIR are sane.
*/
if (S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) ||
S_ISLNK(inode->i_mode)) {
int i;
 
for (i = 0; i < UFS_NDADDR; i++) {
inode->u.ufs_i.ui_db[i] = ufsip->ui_db[i];
}
for (i = 0; i < UFS_NINDIR; i++) {
inode->u.ufs_i.ui_ib[i] = ufsip->ui_ib[i];
}
}
 
if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode)) {
/* XXX - should be ui_db[1] on little endian ufs filesystems */
inode->i_rdev = to_kdev_t(ufsip->ui_db[0]);
}
 
/* XXX - implement fast and slow symlinks */
 
inode->u.ufs_i.ui_flags = ufsip->ui_flags;
inode->u.ufs_i.ui_gen = ufsip->ui_gen; /* XXX - is this i_version? */
inode->u.ufs_i.ui_shadow = ufsip->ui_shadow; /* XXX */
inode->u.ufs_i.ui_uid = ufsip->ui_uid;
inode->u.ufs_i.ui_gid = ufsip->ui_gid;
inode->u.ufs_i.ui_oeftflag = ufsip->ui_oeftflag;
 
brelse(bh);
 
if (inode->i_sb->u.ufs_sb.s_flags & (UFS_DEBUG|UFS_DEBUG_INODE)) {
ufs_print_inode(inode);
}
 
return;
}
 
void ufs_put_inode (struct inode * inode)
{
if (inode->i_nlink)
return;
 
printk("ufs_put_inode: nlink == 0 for inum %lu on dev %d/%d\n",
inode->i_ino, MAJOR(inode->i_dev), MINOR(inode->i_dev));
ufs_print_inode(inode);
panic("ufs_put_inode: fs is read only, and nlink == 0");
 
/* XXX - this code goes here eventually
inode->i_size = 0;
if (inode->i_blocks)
ufs_truncate(inode);
ufs_free_inode(inode);
*/
 
return;
}
 
/*
* Local Variables: ***
* c-indent-level: 8 ***
* c-continued-statement-offset: 8 ***
* c-brace-offset: -8 ***
* c-argdecl-indent: 0 ***
* c-label-offset: -8 ***
* End: ***
*/
/ufs_super.c
0,0 → 1,305
/*
* linux/fs/ufs/ufs_super.c
*
* Copyright (C) 1996
* Adrian Rodriguez (adrian@franklins-tower.rutgers.edu)
* Laboratory for Computer Science Research Computing Facility
* Rutgers, The State University of New Jersey
*
* $Id: ufs_super.c,v 1.1.1.1 2001-09-10 07:44:40 simons Exp $
*
*/
 
/*
* Kernel module support added on 96/04/26 by
* Stefan Reinauer <stepan@home.culture.mipt.ru>
*
* Module usage counts added on 96/04/29 by
* Gertjan van Wingerde <gertjan@cs.vu.nl>
*/
 
#include <linux/module.h>
 
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/ufs_fs.h>
#include <linux/module.h>
#include <linux/locks.h>
 
#include <asm/segment.h>
 
struct super_block * ufs_read_super(struct super_block * sb, void * data, int silent);
void ufs_put_super (struct super_block * sb);
void ufs_statfs(struct super_block * sb, struct statfs * buf, int bufsize);
 
extern void ufs_read_inode(struct inode * inode);
extern void ufs_put_inode(struct inode * inode);
 
static struct super_operations ufs_super_ops = {
ufs_read_inode,
NULL, /* notify_change() */
NULL, /* XXX - ufs_write_inode() */
ufs_put_inode,
ufs_put_super,
NULL, /* XXX - ufs_write_super() */
ufs_statfs,
NULL, /* XXX - ufs_remount() */
};
 
static struct file_system_type ufs_fs_type = {
ufs_read_super, "ufs", 1, NULL
};
 
int
init_ufs_fs(void)
{
return(register_filesystem(&ufs_fs_type));
}
 
#ifdef MODULE
int init_module(void)
{
int status;
 
if ((status = init_ufs_fs()) == 0)
register_symtab(0);
return status;
}
 
void cleanup_module(void)
{
unregister_filesystem(&ufs_fs_type);
}
#endif
 
#if 0 /* unused */
static void
ufs_print_super_stuff(struct super_block * sb, struct ufs_superblock * usb)
{
 
printk("fs_sblkno: 0x%8.8x\n", usb->fs_sblkno);
printk("fs_size: 0x%8.8x\n", usb->fs_size);
printk("fs_ncg: 0x%8.8x\n", usb->fs_ncg);
printk("fs_bsize: 0x%8.8x\n", usb->fs_bsize);
printk("fs_frag: 0x%8.8x\n", usb->fs_frag);
printk("fs_nindir: 0x%8.8x\n", usb->fs_nindir);
printk("fs_inopb: 0x%8.8x\n", usb->fs_inopb);
printk("fs_optim: 0x%8.8x\n", usb->fs_optim);
printk("fs_ncyl: 0x%8.8x\n", usb->fs_ncyl);
printk("fs_state: 0x%8.8x\n", usb->fs_state);
printk("fs_magic: 0x%8.8x\n", usb->fs_magic);
printk("fs_fsmnt: `%s'\n", usb->fs_fsmnt);
 
return;
}
#endif
 
struct super_block *
ufs_read_super(struct super_block * sb, void * data, int silent)
{
struct ufs_superblock * usb;
struct buffer_head * bh1, *bh2;
 
/* sb->s_dev and sb->s_flags are set by our caller
* data is the mystery argument to sys_mount()
*
* Our caller also sets s_dev, s_covered, s_rd_only, s_dirt,
* and s_type when we return.
*/
 
MOD_INC_USE_COUNT;
lock_super (sb);
 
/* XXX - make everything read only for testing */
sb->s_flags |= MS_RDONLY;
 
if (!(bh1 = bread(sb->s_dev, UFS_SBLOCK/BLOCK_SIZE, BLOCK_SIZE)) ||
!(bh2 = bread(sb->s_dev, (UFS_SBLOCK + BLOCK_SIZE)/BLOCK_SIZE,
BLOCK_SIZE))) {
sb->s_dev = 0;
unlock_super (sb);
if (bh1) {
brelse(bh1);
}
printk ("ufs_read_super: unable to read superblock\n");
 
MOD_DEC_USE_COUNT;
return(NULL);
}
/* XXX - redo this so we can free it later... */
usb = (struct ufs_superblock *)__get_free_page(GFP_KERNEL);
if (usb == NULL) {
sb->s_dev=0;
unlock_super(sb);
brelse(bh1);
brelse(bh2);
printk ("ufs_read_super: get_free_page() failed\n");
MOD_DEC_USE_COUNT;
return (NULL);
}
 
memcpy((char *)usb, bh1->b_data, BLOCK_SIZE);
memcpy((char *)usb + BLOCK_SIZE, bh2->b_data,
sizeof(struct ufs_superblock) - BLOCK_SIZE);
 
brelse(bh1);
brelse(bh2);
 
if (usb->fs_magic != UFS_MAGIC) {
/* XXX - replace hard-coded constant with a byte-swap macro */
if (usb->fs_magic == 0x54190100) {
printk ("ufs_read_super: can't grok byteswapped fs on dev %d/%d\n",
MAJOR(sb->s_dev), MINOR(sb->s_dev));
silent = 1;
}
sb->s_dev = 0;
unlock_super (sb);
if (!silent)
printk ("ufs_read_super: bad magic number 0x%8.8x on dev %d/%d\n",
usb->fs_magic, MAJOR(sb->s_dev),
MINOR(sb->s_dev));
MOD_DEC_USE_COUNT;
return(NULL);
}
 
/* We found a UFS filesystem on this device. */
 
/* XXX - parse args */
 
if (usb->fs_bsize != UFS_BSIZE) {
printk("ufs_read_super: fs_bsize %d != %d\n", usb->fs_bsize,
UFS_BSIZE);
goto ufs_read_super_lose;
}
 
if (usb->fs_fsize != UFS_FSIZE) {
printk("ufs_read_super: fs_fsize %d != %d\n", usb->fs_fsize,
UFS_FSIZE);
goto ufs_read_super_lose;
}
 
if (usb->fs_nindir != UFS_NINDIR) {
printk("ufs_read_super: fs_nindir %d != %d\n", usb->fs_nindir,
UFS_NINDIR);
printk("ufs_read_super: fucking Sun blows me\n");
}
 
printk("ufs_read_super: fs last mounted on \"%s\"\n", usb->fs_fsmnt);
 
if (usb->fs_state == UFS_FSOK - usb->fs_time) {
switch(usb->fs_clean) {
case UFS_FSCLEAN:
printk("ufs_read_super: fs is clean\n");
break;
case UFS_FSSTABLE:
printk("ufs_read_super: fs is stable\n");
break;
case UFS_FSACTIVE:
printk("ufs_read_super: fs is active\n");
sb->s_flags |= MS_RDONLY;
break;
case UFS_FSBAD:
printk("ufs_read_super: fs is bad\n");
sb->s_flags |= MS_RDONLY;
break;
default:
printk("ufs_read_super: can't grok fs_clean 0x%x\n",
usb->fs_clean);
sb->s_flags |= MS_RDONLY;
break;
}
} else {
printk("ufs_read_super: fs needs fsck\n");
sb->s_flags |= MS_RDONLY;
/* XXX - make it read only or barf if it's not (/, /usr) */
}
 
/* XXX - sanity check sb fields */
 
sb->s_blocksize = usb->fs_fsize;
sb->s_blocksize_bits = 10; /* XXX */
/* XXX - sb->s_lock */
sb->s_op = &ufs_super_ops;
sb->dq_op = 0; /* XXX */
sb->s_magic = usb->fs_magic;
/* sb->s_time */
/* sb->s_wait */
/* XXX - sb->u.ufs_sb */
sb->u.ufs_sb.s_raw_sb = usb; /* XXX - maybe move this to the top */
sb->u.ufs_sb.s_flags = 0;
sb->u.ufs_sb.s_ncg = usb->fs_ncg;
sb->u.ufs_sb.s_ipg = usb->fs_ipg;
sb->u.ufs_sb.s_fpg = usb->fs_fpg;
sb->u.ufs_sb.s_fsize = usb->fs_fsize;
sb->u.ufs_sb.s_bsize = usb->fs_bsize;
sb->u.ufs_sb.s_iblkno = usb->fs_iblkno;
sb->u.ufs_sb.s_dblkno = usb->fs_dblkno;
sb->u.ufs_sb.s_cgoffset = usb->fs_cgoffset;
sb->u.ufs_sb.s_cgmask = usb->fs_cgmask;
sb->u.ufs_sb.s_inopb = usb->fs_inopb;
sb->u.ufs_sb.s_fsfrag = usb->fs_frag; /* XXX - rename this later */
sb->s_mounted = iget(sb, UFS_ROOTINO);
 
printk("ufs_read_super: inopb %u\n", sb->u.ufs_sb.s_inopb);
/*
* XXX - read cg structs?
*/
 
unlock_super(sb);
return(sb);
 
ufs_read_super_lose:
/* XXX - clean up */
MOD_DEC_USE_COUNT;
return(NULL);
}
 
void ufs_put_super (struct super_block * sb)
{
 
printk("ufs_put_super\n"); /* XXX */
 
lock_super (sb);
/* XXX - sync fs data, set state to ok, and flush buffers */
sb->s_dev = 0;
 
/* XXX - free allocated kernel memory */
 
unlock_super (sb);
MOD_DEC_USE_COUNT;
 
return;
}
 
void ufs_statfs(struct super_block * sb, struct statfs * buf, int bufsiz)
{
struct statfs tmp;
 
printk("ufs_statfs\n"); /* XXX */
tmp.f_type = sb->s_magic;
tmp.f_bsize = PAGE_SIZE;
tmp.f_blocks = sb->u.ufs_sb.s_raw_sb->fs_dsize;
tmp.f_bfree = sb->u.ufs_sb.s_raw_sb->fs_cstotal.cs_nbfree;
tmp.f_bavail = sb->u.ufs_sb.s_raw_sb->fs_cstotal.cs_nbfree; /* XXX */
tmp.f_files = sb->u.ufs_sb.s_ncg * sb->u.ufs_sb.s_ipg;
tmp.f_ffree = sb->u.ufs_sb.s_raw_sb->fs_cstotal.cs_nifree;
tmp.f_fsid.val[0] = sb->u.ufs_sb.s_raw_sb->fs_id[0];
tmp.f_fsid.val[1] = sb->u.ufs_sb.s_raw_sb->fs_id[1];
tmp.f_namelen = UFS_MAXNAMLEN;
/* tmp.f_spare[6] */
 
memcpy_tofs(buf, &tmp, bufsiz);
 
return;
}
 
 
/*
* Local Variables: ***
* c-indent-level: 8 ***
* c-continued-statement-offset: 8 ***
* c-brace-offset: -8 ***
* c-argdecl-indent: 0 ***
* c-label-offset: -8 ***
* End: ***
*/
/Makefile
0,0 → 1,15
#
# Makefile for the linux ufs-filesystem routines.
#
# Note! Dependencies are done automagically by 'make dep', which also
# removes any old dependencies. DON'T put your own dependencies here
# unless it's something special (ie not a .c file).
#
# Note 2! The CFLAGS definitions are now in the main makefile...
 
O_TARGET := ufs.o
O_OBJS := ufs_dir.o ufs_file.o ufs_inode.o ufs_namei.o \
ufs_super.o ufs_symlink.o
M_OBJS := $(O_TARGET)
 
include $(TOPDIR)/Rules.make
/ufs_file.c
0,0 → 1,143
/*
* linux/fs/ufs/ufs_file.c
*
* Copyright (C) 1996
* Adrian Rodriguez (adrian@franklins-tower.rutgers.edu)
* Laboratory for Computer Science Research Computing Facility
* Rutgers, The State University of New Jersey
*
* $Id: ufs_file.c,v 1.1.1.1 2001-09-10 07:44:40 simons Exp $
*
*/
 
#include <linux/fs.h>
 
/*
* Return values:
* 0: bmap failed
* nonzero: absolute "block" number
*/
int ufs_bmap (struct inode * inode, int block)
{
unsigned long int fsblkno, phys_block, lfsblkno;
struct buffer_head * bh;
 
/*
* Note that contrary to what the BSD source calls these things,
* blkno and lblkno are *frags* (1024), not UFS blocks (8192).
* XXX - maybe I'm wrong, and ui_blocks is really 512-blocks...
*/
 
/*
* Ok, I think I figured out what is going on. ui_blocks is the
* number of 512-byte blocks that are allocated to the file. The
* elements in ui_db[UFS_NDADDR] are pointers to 1024-byte aligned
* 8192 byte objects. The entire 8192 bytes (16 512-blocks) may
* not be allocated to the file in question - use ui_blocks to see
* how many of the blocks are allocated. Also, use ui_size to see
* what fraction of the last block is allocated to the file, and
* what fraction is unused. I have not yet seen a file with a
* hole in it, but I'd guess that a hole must be at least 8192
* bytes of zeros, and it's represented by a zero in ui_db[X].
*
* Yes, this means that there is more than one way to name a given
* 512-byte block on the disk. Because of the 1024-byte alignment
* of 8192-byte filesystem blocks, a given 512-byte disk block
* could be referred to in eight different ways.
*/
 
/*
* block is the logical 1024-block in the file
* lfsblkno is the logical 8192-block in the file
* fsblkno is the physical 8192-block
* phys_block is the 1024-block
*/
lfsblkno = block>>3;
 
if (block < UFS_NDADDR) {
/* It's a direct block */
fsblkno = inode->u.ufs_i.ui_db[lfsblkno]; /* XXX */
#if 0
phys_block = ufs_cgdmin(inode->i_sb, ufs_ino2cg(inode)) +
blkno%(inode->i_sb->u.ufs_sb.s_fpg);
#endif
phys_block = fsblkno + ((block & 0x7)<<10); /* XXX */
if (inode->i_sb->u.ufs_sb.s_flags & UFS_DEBUG) {
printk("ufs_bmap: mapped ino %lu logical %u to %lu (phys %lu)\n",
inode->i_ino, block, fsblkno, phys_block);
}
return(phys_block);
} else {
/* Need to use indirect blocks */
/* XXX - bmap through indirect blocks not implemented */
block -= UFS_NDADDR;
if (block < (inode->i_sb->s_blocksize/sizeof(__u32))) {
bh = bread(inode->i_dev, inode->u.ufs_i.ui_ib[0],
BLOCK_SIZE);
if (bh == NULL) {
printk("ufs_bmap: can't map block %u, ino %lu\n",
block + UFS_NDADDR, inode->i_ino);
return(0);
}
phys_block = ((__u32 *)bh->b_data)[block];
brelse(bh);
printk("ufs_bmap: imap ino %lu block %u phys %lu\n",
inode->i_ino, block + UFS_NDADDR, phys_block);
return(phys_block);
} else {
printk("ufs_bmap: ino %lu: indirect blocks not implemented\n",
inode->i_ino);
return(0);
}
}
 
return(0);
}
 
static struct file_operations ufs_file_operations = {
NULL, /* lseek */
generic_file_read, /* read */
NULL, /* write */
NULL, /* readdir */
NULL, /* select */
NULL, /* ioctl */
generic_file_mmap, /* mmap */
NULL, /* open */
NULL, /* release */
file_fsync, /* fsync */
NULL, /* fasync */
NULL, /* check_media_change */
NULL, /* revalidate */
};
 
struct inode_operations ufs_file_inode_operations = {
&ufs_file_operations, /* default directory file operations */
NULL, /* create */
NULL, /* lookup */
NULL, /* link */
NULL, /* unlink */
NULL, /* symlink */
NULL, /* mkdir */
NULL, /* rmdir */
NULL, /* mknod */
NULL, /* rename */
NULL, /* readlink */
NULL, /* follow_link */
generic_readpage, /* readpage */
NULL, /* writepage */
ufs_bmap, /* bmap */
NULL, /* truncate */
NULL, /* permission */
NULL, /* smap */
};
 
 
/*
* Local Variables: ***
* c-indent-level: 8 ***
* c-continued-statement-offset: 8 ***
* c-brace-offset: -8 ***
* c-argdecl-indent: 0 ***
* c-label-offset: -8 ***
* End: ***
*/

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.