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: *** |
*/ |