From 4cd9a486c8091de019dadee71cb80d4b53d8bd6d Mon Sep 17 00:00:00 2001 From: Al Smith Date: Wed, 31 Mar 1999 11:28:49 +0000 Subject: Updated efs support to revision 0.97. --- fs/Config.in | 5 ++- fs/Makefile | 18 +++++----- fs/efs/Makefile | 3 +- fs/efs/dir.c | 85 ++++++++++++++++++++++++-------------------- fs/efs/file.c | 2 +- fs/efs/inode.c | 86 +++++++++++++++++++++++++++++--------------- fs/efs/namei.c | 4 +-- fs/efs/super.c | 106 +++++++++++++++++++++++++++++++------------------------ fs/efs/symlink.c | 14 ++++---- 9 files changed, 186 insertions(+), 137 deletions(-) (limited to 'fs') diff --git a/fs/Config.in b/fs/Config.in index ab75a102a..216e7bf46 100644 --- a/fs/Config.in +++ b/fs/Config.in @@ -55,7 +55,10 @@ if [ "$CONFIG_UFS_FS" != "n" ]; then bool ' UFS filesystem write support (experimental)' CONFIG_UFS_FS_WRITE fi if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then - tristate 'SGI EFS filesystem support' CONFIG_EFS_FS + tristate 'SGI EFS filesystem support (read only) (experimental)' CONFIG_EFS_FS + if [ "$CONFIG_EFS_FS" != "n" ]; then + define_bool CONFIG_SGI_PARTITION y + fi fi if [ "$CONFIG_NET" = "y" ]; then diff --git a/fs/Makefile b/fs/Makefile index 1bbf1cbab..2394b8cca 100644 --- a/fs/Makefile +++ b/fs/Makefile @@ -18,7 +18,7 @@ O_OBJS = open.o read_write.o devices.o file_table.o buffer.o \ MOD_LIST_NAME := FS_MODULES ALL_SUB_DIRS = coda minix ext2 fat msdos vfat proc isofs nfs umsdos ntfs \ hpfs sysv smbfs ncpfs ufs affs romfs autofs hfs lockd nfsd \ - nls devpts adfs qnx4 + nls devpts adfs qnx4 efs ifeq ($(CONFIG_QUOTA),y) O_OBJS += dquot.o @@ -215,14 +215,6 @@ else endif endif -ifeq ($(CONFIG_AUTOFS_FS),y) -SUB_DIRS += autofs -else - ifeq ($(CONFIG_AUTOFS_FS),m) - MOD_SUB_DIRS += autofs - endif -endif - ifeq ($(CONFIG_EFS_FS),y) SUB_DIRS += efs else @@ -231,6 +223,14 @@ else endif endif +ifeq ($(CONFIG_AUTOFS_FS),y) +SUB_DIRS += autofs +else + ifeq ($(CONFIG_AUTOFS_FS),m) + MOD_SUB_DIRS += autofs + endif +endif + ifeq ($(CONFIG_ADFS_FS),y) SUB_DIRS += adfs else diff --git a/fs/efs/Makefile b/fs/efs/Makefile index af04e0324..e41be23f1 100644 --- a/fs/efs/Makefile +++ b/fs/efs/Makefile @@ -8,8 +8,7 @@ # Note 2! The CFLAGS definitions are now in the main makefile... O_TARGET := efs.o -O_OBJS := dir.o file.o inode.o namei.o \ - symlink.o +O_OBJS := super.o inode.o namei.o dir.o file.o symlink.o M_OBJS := $(O_TARGET) include $(TOPDIR)/Rules.make diff --git a/fs/efs/dir.c b/fs/efs/dir.c index 483efd85a..00d1f3e2e 100644 --- a/fs/efs/dir.c +++ b/fs/efs/dir.c @@ -2,11 +2,9 @@ * dir.c * * Copyright (c) 1999 Al Smith - * - * Portions derived from work (c) 1995,1996 Christian Vogelgsang. */ -#include +#include static int efs_readdir(struct file *, void *, filldir_t); @@ -47,73 +45,82 @@ struct inode_operations efs_dir_inode_operations = { static int efs_readdir(struct file *filp, void *dirent, filldir_t filldir) { struct inode *inode = filp->f_dentry->d_inode; - struct efs_in_info *ini = (struct efs_in_info *) &inode->u.generic_ip; + struct efs_inode_info *ini = (struct efs_inode_info *) &inode->u.generic_ip; struct buffer_head *bh; struct efs_dir *dirblock; struct efs_dentry *dirslot; efs_ino_t inodenum; efs_block_t block; - int slot, namelen, numslots; + int slot, namelen; char *nameptr; - if (!inode || !S_ISDIR(inode->i_mode)) + if (!inode || !S_ISDIR(inode->i_mode)) return -EBADF; - + if (ini->numextents != 1) printk("EFS: WARNING: readdir(): more than one extent\n"); if (inode->i_size & (EFS_BLOCKSIZE-1)) printk("EFS: WARNING: readdir(): directory size not a multiple of EFS_BLOCKSIZE\n"); - /* work out the block where this entry can be found */ + /* work out where this entry can be found */ block = filp->f_pos >> EFS_BLOCKSIZE_BITS; - - /* don't read past last entry */ - if (block > inode->i_blocks) return 0; + slot = filp->f_pos & 0xff; - /* read the dir block */ - bh = bread(inode->i_dev, efs_bmap(inode, block), EFS_BLOCKSIZE); + /* look at all blocks */ + while (block <= inode->i_blocks) { + /* read the dir block */ + bh = bread(inode->i_dev, efs_bmap(inode, block), EFS_BLOCKSIZE); - if (!bh) { - printk("EFS: readdir(): failed to read dir block %d\n", block); - return 0; - } + if (!bh) { + printk("EFS: readdir(): failed to read dir block %d\n", block); + break; + } - dirblock = (struct efs_dir *) bh->b_data; + dirblock = (struct efs_dir *) bh->b_data; - if (be16_to_cpu(dirblock->magic) != EFS_DIRBLK_MAGIC) { - printk("EFS: readdir(): invalid directory block\n"); - brelse(bh); - return(0); - } + if (be16_to_cpu(dirblock->magic) != EFS_DIRBLK_MAGIC) { + printk("EFS: readdir(): invalid directory block\n"); + brelse(bh); + break; + } - slot = filp->f_pos & 0xff; + while(slot < dirblock->slots) { + dirslot = (struct efs_dentry *) (((char *) bh->b_data) + EFS_SLOTAT(dirblock, slot)); - dirslot = (struct efs_dentry *) (((char *) bh->b_data) + EFS_SLOTAT(dirblock, slot)); - - numslots = dirblock->slots; - inodenum = be32_to_cpu(dirslot->inode); - namelen = dirslot->namelen; - nameptr = dirslot->name; + inodenum = be32_to_cpu(dirslot->inode); + namelen = dirslot->namelen; + nameptr = dirslot->name; #ifdef DEBUG - printk("EFS: dent #%d: inode %u, name \"%s\", namelen %u\n", slot, inodenum, nameptr, namelen); + printk("EFS: block %d slot %d/%d: inode %u, name \"%s\", namelen %u\n", block, slot, numslots, inodenum, nameptr, namelen); #endif + if (namelen > 0) { + /* found the next entry */ + filp->f_pos = (block << EFS_BLOCKSIZE_BITS) | slot; + + /* copy filename and data in dirslot */ + filldir(dirent, nameptr, namelen, filp->f_pos, inodenum); + + /* store position of next slot */ + if (++slot == dirblock->slots) { + slot = 0; + block++; + } + brelse(bh); + filp->f_pos = (block << EFS_BLOCKSIZE_BITS) | slot; + return 0; + } + slot++; + } + brelse(bh); - /* copy filename and data in dirslot */ - filldir(dirent, nameptr, namelen, filp->f_pos, inodenum); - - brelse(bh); - - /* store position of next slot */ - if (++slot == numslots) { slot = 0; block++; } filp->f_pos = (block << EFS_BLOCKSIZE_BITS) | slot; - return 0; } diff --git a/fs/efs/file.c b/fs/efs/file.c index 405143225..e43af509c 100644 --- a/fs/efs/file.c +++ b/fs/efs/file.c @@ -6,7 +6,7 @@ * Portions derived from work (c) 1995,1996 Christian Vogelgsang. */ -#include +#include static struct file_operations efs_file_operations = { NULL, /* lseek */ diff --git a/fs/efs/inode.c b/fs/efs/inode.c index 9e7da7934..81c8e81c7 100644 --- a/fs/efs/inode.c +++ b/fs/efs/inode.c @@ -7,14 +7,33 @@ * and from work (c) 1998 Mike Shaver. */ -#include +#include +#include + +static inline void extent_copy(efs_extent *src, efs_extent *dst) { + /* + * this is slightly evil. it doesn't just copy the + * efs_extent from src to dst, it also mangles the bits + * so that dst ends up in cpu byte-order. + */ + + dst->cooked.ex_magic = (unsigned int) src->raw[0]; + dst->cooked.ex_bn = ((unsigned int) src->raw[1] << 16) | + ((unsigned int) src->raw[2] << 8) | + ((unsigned int) src->raw[3] << 0); + dst->cooked.ex_length = (unsigned int) src->raw[4]; + dst->cooked.ex_offset = ((unsigned int) src->raw[5] << 16) | + ((unsigned int) src->raw[6] << 8) | + ((unsigned int) src->raw[7] << 0); + return; +} void efs_read_inode(struct inode *in) { int i, extents, inode_index; dev_t device; struct buffer_head *bh; - struct efs_spb *sbp = (struct efs_spb *)&in->i_sb->u.generic_sbp; - struct efs_in_info *ini = (struct efs_in_info *)&in->u.generic_ip; + struct efs_sb_info *sbp = (struct efs_sb_info *)&in->i_sb->u.generic_sbp; + struct efs_inode_info *ini = (struct efs_inode_info *)&in->u.generic_ip; efs_block_t block, offset; struct efs_dinode *efs_inode; @@ -70,10 +89,8 @@ void efs_read_inode(struct inode *in) { /* copy the first 12 extents directly from the inode */ for(i = 0; i < EFS_DIRECTEXTENTS; i++) { - /* ick. horrible (ab)use of union */ - ini->extents[i].u1.l = be32_to_cpu(efs_inode->di_u.di_extents[i].u1.l); - ini->extents[i].u2.l = be32_to_cpu(efs_inode->di_u.di_extents[i].u2.l); - if (i < extents && ini->extents[i].u1.s.ex_magic != 0) { + extent_copy(&(efs_inode->di_u.di_extents[i]), &(ini->extents[i])); + if (i < extents && ini->extents[i].cooked.ex_magic != 0) { printk("EFS: extent %d has bad magic number in inode %lu\n", i, in->i_ino); brelse(bh); goto read_inode_error; @@ -136,7 +153,7 @@ read_inode_error: } static inline efs_block_t -efs_extent_check(efs_extent *ptr, efs_block_t block, struct efs_spb *sbi, struct efs_in_info *ini) { +efs_extent_check(efs_extent *ptr, efs_block_t block, struct efs_sb_info *sbp, struct efs_inode_info *ini) { efs_block_t start; efs_block_t length; efs_block_t offset; @@ -145,12 +162,12 @@ efs_extent_check(efs_extent *ptr, efs_block_t block, struct efs_spb *sbi, struct ** given an extent and a logical block within a file, ** can this block be found within this extent ? */ - start = ptr->u1.s.ex_bn; - length = ptr->u2.s.ex_length; - offset = ptr->u2.s.ex_offset; + start = ptr->cooked.ex_bn; + length = ptr->cooked.ex_length; + offset = ptr->cooked.ex_offset; if ((block >= offset) && (block < offset+length)) { - return(sbi->fs_start + start + block - offset); + return(sbp->fs_start + start + block - offset); } else { return 0; } @@ -159,23 +176,23 @@ efs_extent_check(efs_extent *ptr, efs_block_t block, struct efs_spb *sbi, struct /* find the disk block number for a given logical file block number */ efs_block_t efs_read_block(struct inode *inode, efs_block_t block) { - struct efs_spb *sbi = (struct efs_spb *) &inode->i_sb->u.generic_sbp; - struct efs_in_info *ini = (struct efs_in_info *) &inode->u.generic_ip; + struct efs_sb_info *sbp = (struct efs_sb_info *) &inode->i_sb->u.generic_sbp; + struct efs_inode_info *ini = (struct efs_inode_info *) &inode->u.generic_ip; struct buffer_head *bh; efs_block_t result = 0; int indirexts, indirext, imagic; efs_block_t istart, iblock, ilen; - int i, last, total, checked; + int i, cur, last, total, checked; efs_extent *exts; - efs_extent tmp; + efs_extent ext; last = ini->lastextent; total = ini->numextents; if (total <= EFS_DIRECTEXTENTS) { /* first check the last extent we returned */ - if ((result = efs_extent_check(&ini->extents[last], block, sbi, ini))) + if ((result = efs_extent_check(&ini->extents[last], block, sbp, ini))) return result; /* if we only have one extent then nothing can be found */ @@ -186,8 +203,8 @@ efs_block_t efs_read_block(struct inode *inode, efs_block_t block) { /* check the stored extents in the inode */ /* start with next extent and check forwards */ - for(i = 0; i < total - 1; i++) { - if ((result = efs_extent_check(&ini->extents[(last + i) % total], block, sbi, ini))) { + for(i = 1; i < total; i++) { + if ((result = efs_extent_check(&ini->extents[(last + i) % total], block, sbp, ini))) { ini->lastextent = i; return result; } @@ -200,13 +217,19 @@ efs_block_t efs_read_block(struct inode *inode, efs_block_t block) { #ifdef DEBUG printk("EFS: indirect search for logical block %u\n", block); #endif - indirexts = ini->extents[0].u2.s.ex_offset; + + /* + * OPT: this lot is inefficient. + */ + + indirexts = ini->extents[0].cooked.ex_offset; checked = 0; for(indirext = 0; indirext < indirexts; indirext++) { - imagic = ini->extents[indirext].u1.s.ex_magic; - istart = ini->extents[indirext].u1.s.ex_bn + sbi->fs_start; - ilen = ini->extents[indirext].u2.s.ex_length; + cur = (last + indirext) % indirexts; + imagic = ini->extents[cur].cooked.ex_magic; + istart = ini->extents[cur].cooked.ex_bn + sbp->fs_start; + ilen = ini->extents[cur].cooked.ex_length; for(iblock = istart; iblock < istart + ilen; iblock++) { bh = bread(inode->i_dev, iblock, EFS_BLOCKSIZE); @@ -214,20 +237,27 @@ efs_block_t efs_read_block(struct inode *inode, efs_block_t block) { printk("EFS: bread() failed at block %d\n", block); return 0; } +#ifdef DEBUG + printk("EFS: read indirect extent block %d\n", iblock-istart); +#endif - exts = (struct extent *) bh->b_data; + exts = (efs_extent *) bh->b_data; for(i = 0; i < EFS_BLOCKSIZE / sizeof(efs_extent) && checked < total; i++, checked++) { - tmp.u1.l = be32_to_cpu(exts[i].u1.l); - tmp.u2.l = be32_to_cpu(exts[i].u2.l); + /* + * this block might be read-cached + * so fiddle the endianness in a private copy + */ + extent_copy(&(exts[i]), &ext); - if (tmp.u1.s.ex_magic != 0) { + if (ext.cooked.ex_magic != 0) { printk("EFS: extent %d has bad magic number in block %d\n", i, iblock); brelse(bh); return 0; } - if ((result = efs_extent_check(&tmp, block, sbi, ini))) { + if ((result = efs_extent_check(&ext, block, sbp, ini))) { brelse(bh); + ini->lastextent = cur; return result; } } diff --git a/fs/efs/namei.c b/fs/efs/namei.c index 5d7cc9aa1..d73392ac7 100644 --- a/fs/efs/namei.c +++ b/fs/efs/namei.c @@ -6,12 +6,12 @@ * Portions derived from work (c) 1995,1996 Christian Vogelgsang. */ -#include +#include /* search an efs directory inode for the given name */ static uint32_t efs_find_entry(struct inode *inode, const char *name, int len) { - struct efs_in_info *ini = (struct efs_in_info *) &inode->u.generic_ip; + struct efs_inode_info *ini = (struct efs_inode_info *) &inode->u.generic_ip; struct buffer_head *bh; int slot, namelen; diff --git a/fs/efs/super.c b/fs/efs/super.c index f897a2ebb..2bc259d51 100644 --- a/fs/efs/super.c +++ b/fs/efs/super.c @@ -7,7 +7,11 @@ */ #include -#include +#include + +#include +#include +#include void efs_read_inode(struct inode *); void efs_put_super(struct super_block *); @@ -33,22 +37,36 @@ static struct super_operations efs_superblock_operations = { NULL /* remount */ }; -int init_module(void) { +__initfunc(int init_efs_fs(void)) { + printk(cprt); + printk(" - http://aeschi.ch.eu.org/efs/\n"); return register_filesystem(&efs_fs_type); } +#ifdef MODULE +EXPORT_NO_SYMBOLS; + +int init_module(void) { + return init_efs_fs(); +} + void cleanup_module(void) { unregister_filesystem(&efs_fs_type); } +#endif -static long efs_validate_vh(struct volume_header *vh, int slice) { +static long efs_validate_vh(struct volume_header *vh) { int i, j; - int32_t sblock = 0; - int type; + int32_t sblock = -1; + int type, slice = -1; char name[VDNAMESIZE+1]; if (be32_to_cpu(vh->vh_magic) != VHMAGIC) { - printk("EFS: invalid volume descriptor\n"); + /* + * assume that we're dealing with a partition and allow + * read_super() to try and detect a valid superblock + * on the next block. + */ return 0; } @@ -64,7 +82,7 @@ static long efs_validate_vh(struct volume_header *vh, int slice) { #ifdef DEBUG if (name[0]) { - printk("EFS: vh: 0x%8s block: 0x%08x size: 0x%08x\n", + printk("EFS: vh: %8s block: 0x%08x size: 0x%08x\n", name, (int) be32_to_cpu(vh->vh_vd[i].vd_lbn), (int) be32_to_cpu(vh->vh_vd[i].vd_nbytes)); @@ -80,25 +98,21 @@ static long efs_validate_vh(struct volume_header *vh, int slice) { (int) be32_to_cpu(vh->vh_pt[i].pt_nblks), type); #endif - if (slice == i && (type == 5 || type == 7)) { + if (type == 5 || type == 7) { sblock = be32_to_cpu(vh->vh_pt[i].pt_firstlbn); - } else if (slice == -1 && sblock == 0) { - if (type == 5 || type == 7) { - sblock = be32_to_cpu(vh->vh_pt[i].pt_firstlbn); - slice = i; - } + slice = i; } } - if (sblock) { - printk("EFS: using slice %d (offset 0x%x)\n", slice, sblock); - } else if (slice != -1) { - printk("EFS: no efs filesystem found on slice %d\n", slice); + if (sblock < 0) { + printk("EFS: found valid partition table but no EFS partitions\n"); + } else { + printk("EFS: using CD slice %d (offset 0x%x)\n", slice, sblock); } return(sblock); } -static int efs_validate_super(struct efs_spb *sb, struct efs *super) { +static int efs_validate_super(struct efs_sb_info *sb, struct efs_super *super) { if (!IS_EFS_MAGIC(be32_to_cpu(super->fs_magic))) return -1; @@ -106,6 +120,8 @@ static int efs_validate_super(struct efs_spb *sb, struct efs *super) { sb->total_blocks = be32_to_cpu(super->fs_size); sb->first_block = be32_to_cpu(super->fs_firstcg); sb->group_size = be32_to_cpu(super->fs_cgfsize); + sb->data_free = be32_to_cpu(super->fs_tfree); + sb->inode_free = be32_to_cpu(super->fs_tinode); sb->inode_blocks = be16_to_cpu(super->fs_cgisize); sb->total_groups = be16_to_cpu(super->fs_ncg); @@ -113,27 +129,16 @@ static int efs_validate_super(struct efs_spb *sb, struct efs *super) { } struct super_block *efs_read_super(struct super_block *s, void *d, int verbose) { - int slice = -1; kdev_t dev = s->s_dev; struct inode *root_inode; - struct efs_spb *spb; + struct efs_sb_info *spb; struct buffer_head *bh; - if (d) { - /* parse mount option */ - if (!strncmp(d, "slice=", 6)) { - slice = simple_strtoul(d+6, NULL, 10); - } else if (strcmp(d, "")) { - printk("EFS: invalid mount option\n"); - return(NULL); - } - } - MOD_INC_USE_COUNT; lock_super(s); /* approx 230 bytes available in this union */ - spb = (struct efs_spb *) &(s->u.generic_sbp); + spb = (struct efs_sb_info *) &(s->u.generic_sbp); set_blocksize(dev, EFS_BLOCKSIZE); @@ -145,11 +150,15 @@ struct super_block *efs_read_super(struct super_block *s, void *d, int verbose) goto out_no_fs_ul; } - spb->fs_start = efs_validate_vh((struct volume_header *) bh->b_data, slice); + /* + * if this returns zero then we didn't find any partition table. + * this isn't (yet) an error - just assume for the moment that + * the device is valid and go on to search for a superblock. + */ + spb->fs_start = efs_validate_vh((struct volume_header *) bh->b_data); brelse(bh); - if(!spb->fs_start) { - printk("EFS: invalid volume descriptor\n"); + if (spb->fs_start < 0) { goto out_no_fs_ul; } @@ -159,7 +168,7 @@ struct super_block *efs_read_super(struct super_block *s, void *d, int verbose) goto out_no_fs_ul; } - if (efs_validate_super(spb, (struct efs *) bh->b_data)) { + if (efs_validate_super(spb, (struct efs_super *) bh->b_data)) { printk("EFS: invalid superblock\n"); brelse(bh); goto out_no_fs_ul; @@ -214,18 +223,21 @@ void efs_put_super(struct super_block *s) { int efs_statfs(struct super_block *s, struct statfs *buf, int bufsiz) { struct statfs tmp; - struct efs_spb *sbp = (struct efs_spb *)&s->u.generic_sbp; - - tmp.f_type = EFS_SUPER_MAGIC; - tmp.f_bsize = EFS_BLOCKSIZE; - tmp.f_blocks = sbp->total_blocks; - tmp.f_bfree = 0; - tmp.f_bavail = 0; - tmp.f_files = 0; /* ? */ - tmp.f_ffree = 0; - tmp.f_fsid.val[0] = (sbp->fs_magic >> 16) & 0xffff; - tmp.f_fsid.val[1] = sbp->fs_magic & 0xffff; - tmp.f_namelen = EFS_MAXNAMELEN; + struct efs_sb_info *sbp = (struct efs_sb_info *)&s->u.generic_sbp; + + tmp.f_type = EFS_SUPER_MAGIC; /* efs magic number */ + tmp.f_bsize = EFS_BLOCKSIZE; /* blocksize */ + tmp.f_blocks = sbp->total_groups * /* total data blocks */ + (sbp->group_size - sbp->inode_blocks); + tmp.f_bfree = sbp->data_free; /* free data blocks */ + tmp.f_bavail = sbp->data_free; /* free blocks for non-root */ + tmp.f_files = sbp->total_groups * /* total inodes */ + sbp->inode_blocks * + (EFS_BLOCKSIZE / sizeof(struct efs_dinode)); + tmp.f_ffree = sbp->inode_free; /* free inodes */ + tmp.f_fsid.val[0] = (sbp->fs_magic >> 16) & 0xffff; /* fs ID */ + tmp.f_fsid.val[1] = sbp->fs_magic & 0xffff; /* fs ID */ + tmp.f_namelen = EFS_MAXNAMELEN; /* max filename length */ return copy_to_user(buf, &tmp, bufsiz) ? -EFAULT : 0; } diff --git a/fs/efs/symlink.c b/fs/efs/symlink.c index f5c11792b..c2783100b 100644 --- a/fs/efs/symlink.c +++ b/fs/efs/symlink.c @@ -6,7 +6,7 @@ * Portions derived from work (c) 1995,1996 Christian Vogelgsang. */ -#include +#include static int efs_readlink(struct dentry *, char *, int); @@ -33,7 +33,7 @@ struct inode_operations efs_symlink_inode_operations = { NULL /* permission */ }; -static char *efs_linktarget(struct inode *in) { +static char *efs_linktarget(struct inode *in, int *len) { char *name; struct buffer_head * bh; efs_block_t size = in->i_size; @@ -69,6 +69,7 @@ static char *efs_linktarget(struct inode *in) { } name[size] = (char) 0; + if (len) *len = size; return name; } @@ -77,7 +78,7 @@ static struct dentry *efs_follow_link(struct dentry *dentry, struct dentry *base char *name; struct inode *inode = dentry->d_inode; - name = efs_linktarget(inode); + name = efs_linktarget(inode, NULL); base = lookup_dentry(name, base, follow); kfree(name); @@ -89,11 +90,8 @@ static int efs_readlink(struct dentry * dir, char * buf, int bufsiz) { char *name; struct inode *inode = dir->d_inode; - if (bufsiz > 1023) bufsiz = 1023; - - if (!(name = efs_linktarget(inode))) return 0; - - rc = copy_to_user(buf, name, bufsiz) ? -EFAULT : 0; + if (!(name = efs_linktarget(inode, &bufsiz))) return 0; + rc = copy_to_user(buf, name, bufsiz) ? -EFAULT : bufsiz; kfree(name); return rc; -- cgit v1.2.3