diff options
author | Ralf Baechle <ralf@linux-mips.org> | 2000-11-28 03:58:46 +0000 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2000-11-28 03:58:46 +0000 |
commit | b63ad0882a16a5d28003e57f2b0b81dee3fb322b (patch) | |
tree | 0a343ce219e2b8b38a5d702d66032c57b83d9720 /fs | |
parent | a9d7bff9a84dba79609a0002e5321b74c4d64c64 (diff) |
Merge with 2.4.0-test11.
Diffstat (limited to 'fs')
71 files changed, 516 insertions, 897 deletions
diff --git a/fs/Config.in b/fs/Config.in index d728d2166..53380d067 100644 --- a/fs/Config.in +++ b/fs/Config.in @@ -117,6 +117,7 @@ if [ "$CONFIG_NET" = "y" ]; then else # for fs/nls/Config.in define_bool CONFIG_NCPFS_NLS n + define_bool CONFIG_SMB_FS n fi mainmenu_option next_comment diff --git a/fs/adfs/inode.c b/fs/adfs/inode.c index c1c621179..42f19e292 100644 --- a/fs/adfs/inode.c +++ b/fs/adfs/inode.c @@ -245,13 +245,11 @@ adfs_iget(struct super_block *sb, struct object_info *obj) { struct inode *inode; - inode = get_empty_inode(); + inode = new_inode(sb); if (!inode) goto out; inode->i_version = ++event; - inode->i_sb = sb; - inode->i_dev = sb->s_dev; inode->i_uid = sb->u.adfs_sb.s_uid; inode->i_gid = sb->u.adfs_sb.s_gid; inode->i_ino = obj->file_id; diff --git a/fs/affs/inode.c b/fs/affs/inode.c index 2f8c36aa5..fcb7e103a 100644 --- a/fs/affs/inode.c +++ b/fs/affs/inode.c @@ -306,18 +306,19 @@ affs_new_inode(const struct inode *dir) struct super_block *sb; s32 block; - if (!dir || !(inode = get_empty_inode())) + if (!dir) return NULL; sb = dir->i_sb; - inode->i_sb = sb; + inode = new_inode(sb); + if (!inode) + return NULL; if (!(block = affs_new_header((struct inode *)dir))) { iput(inode); return NULL; } - inode->i_dev = sb->s_dev; inode->i_uid = current->fsuid; inode->i_gid = current->fsgid; inode->i_ino = block; diff --git a/fs/affs/symlink.c b/fs/affs/symlink.c index f7e78a75d..b125dee4e 100644 --- a/fs/affs/symlink.c +++ b/fs/affs/symlink.c @@ -20,7 +20,7 @@ static int affs_symlink_readpage(struct file *file, struct page *page) { struct buffer_head *bh; struct inode *inode = (struct inode*)page->mapping->host; - char *link = (char*)kmap(page); + char *link = kmap(page); struct slink_front *lf; int err; int i, j; diff --git a/fs/autofs/inode.c b/fs/autofs/inode.c index ae157d1ac..0eb91f3c2 100644 --- a/fs/autofs/inode.c +++ b/fs/autofs/inode.c @@ -211,7 +211,6 @@ static void autofs_read_inode(struct inode *inode) inode->i_fop = &autofs_dir_operations; inode->i_mode = S_IFDIR | S_IRUGO | S_IXUGO; inode->i_nlink = 2; - inode->i_size = 0; inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME; inode->i_blocks = 0; inode->i_blksize = 1024; diff --git a/fs/autofs4/inode.c b/fs/autofs4/inode.c index 077df4c2b..dd7dd07ac 100644 --- a/fs/autofs4/inode.c +++ b/fs/autofs4/inode.c @@ -292,14 +292,12 @@ static int autofs4_statfs(struct super_block *sb, struct statfs *buf) struct inode *autofs4_get_inode(struct super_block *sb, struct autofs_info *inf) { - struct inode *inode = get_empty_inode(); + struct inode *inode = new_inode(sb); if (inode == NULL) return NULL; inf->inode = inode; - inode->i_sb = sb; - inode->i_dev = sb->s_dev; inode->i_mode = inf->mode; if (sb->s_root) { inode->i_uid = sb->s_root->d_inode->i_uid; @@ -308,13 +306,9 @@ struct inode *autofs4_get_inode(struct super_block *sb, inode->i_uid = 0; inode->i_gid = 0; } - inode->i_size = 0; inode->i_blksize = PAGE_CACHE_SIZE; inode->i_blocks = 0; inode->i_rdev = 0; - inode->i_nlink = 1; - inode->i_op = NULL; - inode->i_fop = NULL; inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME; if (S_ISDIR(inf->mode)) { diff --git a/fs/bfs/dir.c b/fs/bfs/dir.c index 1a0532420..5caf04a7b 100644 --- a/fs/bfs/dir.c +++ b/fs/bfs/dir.c @@ -80,10 +80,9 @@ static int bfs_create(struct inode * dir, struct dentry * dentry, int mode) struct super_block * s = dir->i_sb; unsigned long ino; - inode = get_empty_inode(); + inode = new_inode(s); if (!inode) return -ENOSPC; - inode->i_sb = s; ino = find_first_zero_bit(s->su_imap, s->su_lasti); if (ino > s->su_lasti) { iput(inode); @@ -91,7 +90,6 @@ static int bfs_create(struct inode * dir, struct dentry * dentry, int mode) } set_bit(ino, s->su_imap); s->su_freei--; - inode->i_dev = s->s_dev; inode->i_uid = current->fsuid; inode->i_gid = (dir->i_mode & S_ISGID) ? dir->i_gid : current->fsgid; inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME; diff --git a/fs/buffer.c b/fs/buffer.c index 4de38a0e4..9f9fbbfbd 100644 --- a/fs/buffer.c +++ b/fs/buffer.c @@ -707,11 +707,8 @@ void set_blocksize(kdev_t dev, int size) */ static void refill_freelist(int size) { - if (!grow_buffers(size)) { + if (!grow_buffers(size)) wakeup_bdflush(1); /* Sets task->state to TASK_RUNNING */ - current->policy |= SCHED_YIELD; - schedule(); - } } void init_buffer(struct buffer_head *bh, bh_end_io_t *handler, void *private) @@ -1470,7 +1467,7 @@ static int __block_prepare_write(struct inode *inode, struct page *page, int err = 0; unsigned blocksize, bbits; struct buffer_head *bh, *head, *wait[2], **wait_bh=wait; - char *kaddr = (char *)kmap(page); + char *kaddr = kmap(page); blocksize = inode->i_sb->s_blocksize; if (!page->buffers) @@ -1585,7 +1582,7 @@ int block_read_full_page(struct page *page, get_block_t *get_block) unsigned long iblock, lblock; struct buffer_head *bh, *head, *arr[MAX_BUF_PER_PAGE]; unsigned int blocksize, blocks; - unsigned long kaddr = 0; + char *kaddr = NULL; int nr, i; if (!PageLocked(page)) @@ -1614,7 +1611,7 @@ int block_read_full_page(struct page *page, get_block_t *get_block) if (!buffer_mapped(bh)) { if (!kaddr) kaddr = kmap(page); - memset((char *)(kaddr + i*blocksize), 0, blocksize); + memset(kaddr + i*blocksize, 0, blocksize); flush_dcache_page(page); set_bit(BH_Uptodate, &bh->b_state); continue; @@ -1818,7 +1815,7 @@ int block_truncate_page(struct address_space *mapping, loff_t from, get_block_t goto unlock; } - memset((char *) kmap(page) + offset, 0, length); + memset(kmap(page) + offset, 0, length); flush_dcache_page(page); kunmap(page); diff --git a/fs/coda/symlink.c b/fs/coda/symlink.c index dbdc946f4..2df6cf719 100644 --- a/fs/coda/symlink.c +++ b/fs/coda/symlink.c @@ -28,7 +28,7 @@ static int coda_symlink_filler(struct file *file, struct page *page) int error; struct coda_inode_info *cnp; unsigned int len = PAGE_SIZE; - char *p = (char*)kmap(page); + char *p = kmap(page); lock_kernel(); cnp = ITOC(inode); diff --git a/fs/cramfs/inode.c b/fs/cramfs/inode.c index 4b34da094..51eff1caa 100644 --- a/fs/cramfs/inode.c +++ b/fs/cramfs/inode.c @@ -34,7 +34,7 @@ static struct address_space_operations cramfs_aops; static struct inode *get_cramfs_inode(struct super_block *sb, struct cramfs_inode * cramfs_inode) { - struct inode * inode = get_empty_inode(); + struct inode * inode = new_inode(sb); if (inode) { inode->i_mode = cramfs_inode->mode; @@ -42,14 +42,10 @@ static struct inode *get_cramfs_inode(struct super_block *sb, struct cramfs_inod inode->i_size = cramfs_inode->size; inode->i_gid = cramfs_inode->gid; inode->i_ino = CRAMINO(cramfs_inode); - inode->i_sb = sb; - inode->i_dev = sb->s_dev; - inode->i_nlink = 1; /* arguably wrong for directories, - but it's the best we can do - without reading the directory - contents. 1 yields the right - result in GNU find, even - without -noleaf option. */ + /* inode->i_nlink is left 1 - arguably wrong for directories, + but it's the best we can do without reading the directory + contents. 1 yields the right result in GNU find, even + without -noleaf option. */ insert_inode_hash(inode); if (S_ISREG(inode->i_mode)) { inode->i_fop = &generic_ro_fops; diff --git a/fs/devfs/base.c b/fs/devfs/base.c index 264992d3f..5c412e301 100644 --- a/fs/devfs/base.c +++ b/fs/devfs/base.c @@ -2250,7 +2250,6 @@ static void devfs_read_inode (struct inode *inode) printk ("%s: read_inode(%d): VFS inode: %p devfs_entry: %p\n", DEVFS_NAME, (int) inode->i_ino, inode, de); #endif - inode->i_size = 0; inode->i_blocks = 0; inode->i_blksize = 1024; inode->i_op = &devfs_iops; @@ -2416,11 +2415,6 @@ static int devfs_readdir (struct file *file, void *dirent, filldir_t filldir) struct devfs_entry *parent, *de; struct inode *inode = file->f_dentry->d_inode; - if (inode == NULL) - { - printk ("%s: readdir(): NULL inode\n", DEVFS_NAME); - return -EBADF; - } if ( !S_ISDIR (inode->i_mode) ) { printk ("%s: readdir(): inode is not a directory\n", DEVFS_NAME); @@ -3185,6 +3179,7 @@ static ssize_t devfsd_read (struct file *file, char *buf, size_t len, current->state = TASK_RUNNING; return -EINTR; } + set_current_state(TASK_INTERRUPTIBLE); } remove_wait_queue (&fs_info->devfsd_wait_queue, &wait); current->state = TASK_RUNNING; diff --git a/fs/devpts/inode.c b/fs/devpts/inode.c index c3667b208..0bb8826d8 100644 --- a/fs/devpts/inode.c +++ b/fs/devpts/inode.c @@ -140,14 +140,11 @@ struct super_block *devpts_read_super(struct super_block *s, void *data, goto fail_free; } - inode = get_empty_inode(); + inode = new_inode(s); if (!inode) goto fail_free; - inode->i_sb = s; - inode->i_dev = s->s_dev; inode->i_ino = 1; inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME; - inode->i_size = 0; inode->i_blocks = 0; inode->i_blksize = 1024; inode->i_uid = inode->i_gid = 0; @@ -192,11 +189,9 @@ void devpts_pty_new(int number, kdev_t device) if ( sbi->inodes[number] ) return; /* Already registered, this does happen */ - inode = get_empty_inode(); + inode = new_inode(sb); if (!inode) return; - inode->i_sb = sb; - inode->i_dev = sb->s_dev; inode->i_ino = number+2; inode->i_blocks = 0; inode->i_blksize = 1024; diff --git a/fs/dnotify.c b/fs/dnotify.c index 90fd86b06..5711e6b41 100644 --- a/fs/dnotify.c +++ b/fs/dnotify.c @@ -103,14 +103,14 @@ void __inode_dir_notify(struct inode *inode, unsigned long event) write_lock(&dn_lock); prev = &inode->i_dnotify; while ((dn = *prev) != NULL) { - if ((dn->dn_mask & event) == 0) { - prev = &dn->dn_next; - continue; - } if (dn->dn_magic != DNOTIFY_MAGIC) { printk(KERN_ERR "__inode_dir_notify: bad magic " "number in dnotify_struct!\n"); - return; + goto out; + } + if ((dn->dn_mask & event) == 0) { + prev = &dn->dn_next; + continue; } fown = &dn->dn_filp->f_owner; if (fown->pid) @@ -125,6 +125,7 @@ void __inode_dir_notify(struct inode *inode, unsigned long event) } if (changed) redo_inode_mask(inode); +out: write_unlock(&dn_lock); } diff --git a/fs/dquot.c b/fs/dquot.c index ef1f15016..1bcd12ceb 100644 --- a/fs/dquot.c +++ b/fs/dquot.c @@ -679,8 +679,6 @@ restart: if (!filp->f_dentry) continue; inode = filp->f_dentry->d_inode; - if (!inode) - continue; if (filp->f_mode & FMODE_WRITE && dqinit_needed(inode, type)) { file_list_unlock(); sb->dq_op->initialize(inode, type); diff --git a/fs/efs/dir.c b/fs/efs/dir.c index ac64b8aeb..9bba7a2cb 100644 --- a/fs/efs/dir.c +++ b/fs/efs/dir.c @@ -28,9 +28,6 @@ static int efs_readdir(struct file *filp, void *dirent, filldir_t filldir) { int slot, namelen; char *nameptr; - if (!inode || !S_ISDIR(inode->i_mode)) - return -EBADF; - if (inode->i_size & (EFS_DIRBSIZE-1)) printk(KERN_WARNING "EFS: WARNING: readdir(): directory size not a multiple of EFS_DIRBSIZE\n"); diff --git a/fs/efs/symlink.c b/fs/efs/symlink.c index 20840409d..d1c788cc2 100644 --- a/fs/efs/symlink.c +++ b/fs/efs/symlink.c @@ -13,7 +13,7 @@ static int efs_symlink_readpage(struct file *file, struct page *page) { - char *link = (char*)kmap(page); + char *link = kmap(page); struct buffer_head * bh; struct inode * inode = (struct inode*)page->mapping->host; efs_block_t size = inode->i_size; @@ -212,7 +212,7 @@ int copy_strings(int argc,char ** argv, struct linux_binprm *bprm) return -ENOMEM; new = 1; } - kaddr = (char *)kmap(page); + kaddr = kmap(page); if (new && offset) memset(kaddr, 0, offset); @@ -748,7 +748,7 @@ void remove_arg_zero(struct linux_binprm *bprm) kunmap(page); inside: page = bprm->page[bprm->p/PAGE_SIZE]; - kaddr = (char *)kmap(page); + kaddr = kmap(page); } kunmap(page); bprm->argc--; diff --git a/fs/ext2/ialloc.c b/fs/ext2/ialloc.c index adaab9c74..cf8fa5154 100644 --- a/fs/ext2/ialloc.c +++ b/fs/ext2/ialloc.c @@ -274,15 +274,13 @@ struct inode * ext2_new_inode (const struct inode * dir, int mode, int * err) return NULL; } - inode = get_empty_inode (); + sb = dir->i_sb; + inode = new_inode(sb); if (!inode) { *err = -ENOMEM; return NULL; } - sb = dir->i_sb; - inode->i_sb = sb; - inode->i_flags = 0; lock_super (sb); es = sb->u.ext2_sb.s_es; repeat: @@ -430,9 +428,6 @@ repeat: mark_buffer_dirty(sb->u.ext2_sb.s_sbh); sb->s_dirt = 1; inode->i_mode = mode; - inode->i_sb = sb; - inode->i_nlink = 1; - inode->i_dev = sb->s_dev; inode->i_uid = current->fsuid; if (test_opt (sb, GRPID)) inode->i_gid = dir->i_gid; diff --git a/fs/fat/inode.c b/fs/fat/inode.c index d1e8557f7..7537ee569 100644 --- a/fs/fat/inode.c +++ b/fs/fat/inode.c @@ -138,13 +138,11 @@ struct inode *fat_build_inode(struct super_block *sb, inode = fat_iget(sb, ino); if (inode) goto out; - inode = get_empty_inode(); + inode = new_inode(sb); *res = -ENOMEM; if (!inode) goto out; *res = 0; - inode->i_sb = sb; - inode->i_dev = sb->s_dev; inode->i_ino = iunique(sb, MSDOS_ROOT_INO); fat_fill_inode(inode, de); fat_attach(inode, ino); @@ -658,11 +656,9 @@ fat_read_super(struct super_block *sb, void *data, int silent, if (! sbi->nls_io) sbi->nls_io = load_nls_default(); - root_inode=get_empty_inode(); + root_inode=new_inode(sb); if (!root_inode) goto out_unload_nls; - root_inode->i_sb = sb; - root_inode->i_dev = sb->s_dev; root_inode->i_ino = MSDOS_ROOT_INO; fat_read_root(root_inode); insert_inode_hash(root_inode); @@ -798,7 +794,6 @@ static void fat_fill_inode(struct inode *inode, struct msdos_dir_entry *de) inode->i_nlink = 1; } #endif - inode->i_size = 0; if ((nr = MSDOS_I(inode)->i_start) != 0) while (nr != -1) { inode->i_size += SECTOR_SIZE*sbi->cluster_size; @@ -822,7 +817,6 @@ static void fat_fill_inode(struct inode *inode, struct msdos_dir_entry *de) (CF_LE_W(de->starthi) << 16); } MSDOS_I(inode)->i_logstart = MSDOS_I(inode)->i_start; - inode->i_nlink = 1; inode->i_size = CF_LE_L(de->size); inode->i_op = &fat_file_inode_operations; inode->i_fop = &fat_file_operations; diff --git a/fs/fcntl.c b/fs/fcntl.c index d075c5c4e..9c9fcafbc 100644 --- a/fs/fcntl.c +++ b/fs/fcntl.c @@ -391,13 +391,13 @@ static void send_sigio_to_task(struct task_struct *p, back to SIGIO in that case. --sct */ si.si_signo = fown->signum; si.si_errno = 0; - si.si_code = reason; + si.si_code = reason & ~__SI_MASK; /* Make sure we are called with one of the POLL_* reasons, otherwise we could leak kernel stack into userspace. */ if ((reason & __SI_MASK) != __SI_POLL) BUG(); - if (reason - POLL_IN > NSIGPOLL) + if (reason - POLL_IN >= NSIGPOLL) si.si_band = ~0L; else si.si_band = band_table[reason - POLL_IN]; diff --git a/fs/file_table.c b/fs/file_table.c index 931314661..09b28574d 100644 --- a/fs/file_table.c +++ b/fs/file_table.c @@ -176,10 +176,13 @@ int fs_may_remount_ro(struct super_block *sb) file_list_lock(); for (p = sb->s_files.next; p != &sb->s_files; p = p->next) { struct file *file = list_entry(p, struct file, f_list); - struct inode *inode = file->f_dentry->d_inode; - if (!inode) + struct inode *inode; + + if (!file->f_dentry) continue; + inode = file->f_dentry->d_inode; + /* File with pending delete? */ if (inode->i_nlink == 0) goto too_bad; diff --git a/fs/hpfs/namei.c b/fs/hpfs/namei.c index 3438cdb85..0d38b408c 100644 --- a/fs/hpfs/namei.c +++ b/fs/hpfs/namei.c @@ -401,7 +401,7 @@ int hpfs_rmdir(struct inode *dir, struct dentry *dentry) int hpfs_symlink_readpage(struct file *file, struct page *page) { - char *link = (char*)kmap(page); + char *link = kmap(page); struct inode *i = (struct inode*)page->mapping->host; struct fnode *fnode; struct buffer_head *bh; diff --git a/fs/isofs/dir.c b/fs/isofs/dir.c index 41b201767..c9915cf80 100644 --- a/fs/isofs/dir.c +++ b/fs/isofs/dir.c @@ -40,14 +40,17 @@ struct inode_operations isofs_dir_inode_operations = lookup: isofs_lookup, }; -static int isofs_name_translate(char * old, int len, char * new) +int isofs_name_translate(struct iso_directory_record *de, char *new, struct inode *inode) { - int i, c; + char * old = de->name; + int len = de->name_len[0]; + int i; for (i = 0; i < len; i++) { - c = old[i]; + unsigned char c = old[i]; if (!c) break; + if (c >= 'A' && c <= 'Z') c |= 0x20; /* lower case */ @@ -74,8 +77,7 @@ int get_acorn_filename(struct iso_directory_record * de, { int std; unsigned char * chr; - int retnamlen = isofs_name_translate(de->name, - de->name_len[0], retname); + int retnamlen = isofs_name_translate(de, retname, inode); if (retnamlen == 0) return 0; std = sizeof(struct iso_directory_record) + de->name_len[0]; if (std & 1) std++; @@ -105,7 +107,7 @@ static int do_isofs_readdir(struct inode *inode, struct file *filp, unsigned char bufbits = ISOFS_BUFFER_BITS(inode); unsigned int block, offset; int inode_number = 0; /* Quiet GCC */ - struct buffer_head *bh; + struct buffer_head *bh = NULL; int len; int map; int high_sierra; @@ -117,46 +119,22 @@ static int do_isofs_readdir(struct inode *inode, struct file *filp, return 0; offset = filp->f_pos & (bufsize - 1); - block = isofs_bmap(inode, filp->f_pos >> bufbits); + block = filp->f_pos >> bufbits; high_sierra = inode->i_sb->u.isofs_sb.s_high_sierra; - if (!block) - return 0; - - if (!(bh = breada(inode->i_dev, block, bufsize, filp->f_pos, inode->i_size))) - return 0; - while (filp->f_pos < inode->i_size) { int de_len; -#ifdef DEBUG - printk("Block, offset, f_pos: %x %x %x\n", - block, offset, filp->f_pos); - printk("inode->i_size = %x\n",inode->i_size); -#endif - /* Next directory_record on next CDROM sector */ - if (offset >= bufsize) { -#ifdef DEBUG - printk("offset >= bufsize\n"); -#endif - brelse(bh); - offset = 0; - block = isofs_bmap(inode, (filp->f_pos) >> bufbits); - if (!block) - return 0; - bh = breada(inode->i_dev, block, bufsize, filp->f_pos, inode->i_size); + + if (!bh) { + bh = isofs_bread(inode, bufsize, block); if (!bh) return 0; - continue; } de = (struct iso_directory_record *) (bh->b_data + offset); - if(first_de) inode_number = (block << bufbits) + (offset & (bufsize - 1)); + if (first_de) inode_number = (bh->b_blocknr << bufbits) + offset; de_len = *(unsigned char *) de; -#ifdef DEBUG - printk("de_len = %d\n", de_len); -#endif - /* If the length byte is zero, we should move on to the next CDROM sector. If we are at the end of the directory, we @@ -164,36 +142,33 @@ static int do_isofs_readdir(struct inode *inode, struct file *filp, if (de_len == 0) { brelse(bh); - filp->f_pos = ((filp->f_pos & ~(ISOFS_BLOCK_SIZE - 1)) - + ISOFS_BLOCK_SIZE); + bh = NULL; + filp->f_pos = (filp->f_pos + ISOFS_BLOCK_SIZE) & ~(ISOFS_BLOCK_SIZE - 1); + block = filp->f_pos >> bufbits; offset = 0; - - if (filp->f_pos >= inode->i_size) - return 0; - - block = isofs_bmap(inode, (filp->f_pos) >> bufbits); - if (!block) - return 0; - bh = breada(inode->i_dev, block, bufsize, filp->f_pos, inode->i_size); - if (!bh) - return 0; continue; } - offset += de_len; - if (offset > bufsize) { - /* - * This would only normally happen if we had - * a buggy cdrom image. All directory - * entries should terminate with a null size - * or end exactly at the end of the sector. - */ - printk("next_offset (%x) > bufsize (%lx)\n", - offset,bufsize); - break; + offset += de_len; + + /* Make sure we have a full directory entry */ + if (offset >= bufsize) { + int slop = bufsize - offset + de_len; + memcpy(tmpde, de, slop); + offset &= bufsize - 1; + block++; + brelse(bh); + bh = NULL; + if (offset) { + bh = isofs_bread(inode, bufsize, block); + if (!bh) + return 0; + memcpy((void *) tmpde + slop, bh->b_data, offset); + } + de = tmpde; } - if(de->flags[-high_sierra] & 0x80) { + if (de->flags[-high_sierra] & 0x80) { first_de = 0; filp->f_pos += de_len; continue; @@ -240,7 +215,7 @@ static int do_isofs_readdir(struct inode *inode, struct file *filp, if (map) { #ifdef CONFIG_JOLIET if (inode->i_sb->u.isofs_sb.s_joliet_level) { - len = get_joliet_filename(de, inode, tmpname); + len = get_joliet_filename(de, tmpname, inode); p = tmpname; } else #endif @@ -249,8 +224,7 @@ static int do_isofs_readdir(struct inode *inode, struct file *filp, p = tmpname; } else if (inode->i_sb->u.isofs_sb.s_mapping == 'n') { - len = isofs_name_translate(de->name, - de->name_len[0], tmpname); + len = isofs_name_translate(de, tmpname, inode); p = tmpname; } else { p = de->name; @@ -265,7 +239,7 @@ static int do_isofs_readdir(struct inode *inode, struct file *filp, continue; } - brelse(bh); + if (bh) brelse(bh); return 0; } diff --git a/fs/isofs/inode.c b/fs/isofs/inode.c index 157b8ebba..453e4a456 100644 --- a/fs/isofs/inode.c +++ b/fs/isofs/inode.c @@ -972,14 +972,24 @@ int isofs_bmap(struct inode *inode, int block) return 0; } +struct buffer_head *isofs_bread(struct inode *inode, unsigned int bufsize, unsigned int block) +{ + unsigned int blknr = isofs_bmap(inode, block); + if (!blknr) + return NULL; + return bread(inode->i_dev, blknr, bufsize); +} + static int isofs_readpage(struct file *file, struct page *page) { return block_read_full_page(page,isofs_get_block); } + static int _isofs_bmap(struct address_space *mapping, long block) { return generic_block_bmap(mapping,block,isofs_get_block); } + static struct address_space_operations isofs_aops = { readpage: isofs_readpage, sync_page: block_sync_page, @@ -1002,93 +1012,89 @@ static inline void test_and_set_gid(gid_t *p, gid_t value) static int isofs_read_level3_size(struct inode * inode) { - unsigned long ino = inode->i_ino; + unsigned long f_pos = inode->i_ino; unsigned long bufsize = ISOFS_BUFFER_SIZE(inode); int high_sierra = inode->i_sb->u.isofs_sb.s_high_sierra; struct buffer_head * bh = NULL; - int block = 0; + unsigned long block, offset; int i = 0; int more_entries = 0; - void *cpnt; - struct iso_directory_record * raw_inode; + struct iso_directory_record * tmpde = kmalloc(256, GFP_KERNEL); + + if (!tmpde) + return -ENOMEM; inode->i_size = 0; inode->u.isofs_i.i_next_section_ino = 0; + + block = f_pos >> ISOFS_BUFFER_BITS(inode); + offset = f_pos & (bufsize-1); + do { - unsigned char *pnt; - unsigned int reclen; - int offset = (ino & (bufsize - 1)); - - cpnt = NULL; - /* Check whether to update our buffer */ - if (block != ino >> ISOFS_BUFFER_BITS(inode)) { - block = ino >> ISOFS_BUFFER_BITS(inode); - brelse(bh); + struct iso_directory_record * de; + unsigned int de_len; + + if (!bh) { bh = bread(inode->i_dev, block, bufsize); if (!bh) goto out_noread; } - pnt = ((unsigned char *) bh->b_data + offset); - /* - * Note: this is invariant even if the record - * spans buffers and must be copied ... - */ - reclen = *pnt; + de = (struct iso_directory_record *) (bh->b_data + offset); + de_len = *(unsigned char *) de; - /* N.B. this test doesn't trigger the i++ code ... */ - if(reclen == 0) { - ino = (ino & ~(ISOFS_BLOCK_SIZE - 1)) + ISOFS_BLOCK_SIZE; + if (de_len == 0) { + brelse(bh); + bh = NULL; + f_pos = (f_pos + ISOFS_BLOCK_SIZE) & ~(ISOFS_BLOCK_SIZE - 1); + block = f_pos >> ISOFS_BUFFER_BITS(inode); + offset = 0; continue; } - raw_inode = ((struct iso_directory_record *) pnt); - - /* Check whether the raw inode spans the buffer ... */ - if (offset + reclen > bufsize){ - int frag1 = bufsize - offset; - - cpnt = kmalloc(reclen, GFP_KERNEL); - if (cpnt == NULL) - goto out_nomem; - memcpy(cpnt, pnt, frag1); + + offset += de_len; + + /* Make sure we have a full directory entry */ + if (offset >= bufsize) { + int slop = bufsize - offset + de_len; + memcpy(tmpde, de, slop); + offset &= bufsize - 1; + block++; brelse(bh); - bh = bread(inode->i_dev, ++block, bufsize); - if (!bh) - goto out_noread; - offset += reclen - bufsize; - memcpy((char *)cpnt+frag1, bh->b_data, offset); - raw_inode = ((struct iso_directory_record *) cpnt); + bh = NULL; + if (offset) { + bh = bread(inode->i_dev, block, bufsize); + if (!bh) + goto out_noread; + memcpy((void *) tmpde + slop, bh->b_data, offset); + } + de = tmpde; } - inode->i_size += isonum_733 (raw_inode->size); - if(i == 1) inode->u.isofs_i.i_next_section_ino = ino; + inode->i_size += isonum_733(de->size); + if (i == 1) + inode->u.isofs_i.i_next_section_ino = f_pos; - more_entries = raw_inode->flags[-high_sierra] & 0x80; + more_entries = de->flags[-high_sierra] & 0x80; - ino += reclen; - if (cpnt) - kfree (cpnt); + f_pos += de_len; i++; if(i > 100) goto out_toomany; } while(more_entries); out: - brelse(bh); + kfree(tmpde); + if (bh) brelse(bh); return 0; -out_nomem: - printk(KERN_INFO "ISOFS: NoMem ISO inode %lu\n", inode->i_ino); - brelse(bh); - return 1; out_noread: - printk(KERN_INFO "ISOFS: unable to read i-node block %d\n", block); - if (cpnt) - kfree(cpnt); + printk(KERN_INFO "ISOFS: unable to read i-node block %lu\n", block); + kfree(tmpde); return 1; out_toomany: printk(KERN_INFO "isofs_read_level3_size: " "More than 100 file sections ?!?, aborting...\n" "isofs_read_level3_size: inode=%lu ino=%lu\n", - inode->i_ino, ino); + inode->i_ino, f_pos); goto out; } @@ -1259,143 +1265,6 @@ static void isofs_read_inode(struct inode * inode) return; } -/* There are times when we need to know the inode number of a parent of - a particular directory. When control passes through a routine that - has access to the parent information, it fills it into the inode structure, - but sometimes the inode gets flushed out of the queue, and someone - remembers the number. When they try to open up again, we have lost - the information. The '..' entry on the disc points to the data area - for a particular inode, so we can follow these links back up, but since - we do not know the inode number, we do not actually know how large the - directory is. The disc is almost always correct, and there is - enough error checking on the drive itself, but an open ended search - makes me a little nervous. - - The BSD iso filesystem uses the extent number for an inode, and this - would work really nicely for us except that the read_inode function - would not have any clean way of finding the actual directory record - that goes with the file. If we had such info, then it would pay - to change the inode numbers and eliminate this function. -*/ - -int isofs_lookup_grandparent(struct inode * parent, int extent) -{ - unsigned long bufsize = ISOFS_BUFFER_SIZE(parent); - unsigned char bufbits = ISOFS_BUFFER_BITS(parent); - unsigned int block,offset; - int parent_dir, inode_number; - int result; - int directory_size; - struct buffer_head * bh; - struct iso_directory_record * de; - - offset = 0; - block = extent << (ISOFS_ZONE_BITS(parent) - bufbits); - if (!(bh = bread(parent->i_dev, block, bufsize))) return -1; - - while (1 == 1) { - de = (struct iso_directory_record *) (bh->b_data + offset); - if (*((unsigned char *) de) == 0) - { - brelse(bh); - printk("Directory .. not found\n"); - return -1; - } - - offset += *((unsigned char *) de); - - if (offset >= bufsize) - { - printk(".. Directory not in first block" - " of directory.\n"); - brelse(bh); - return -1; - } - - if (de->name_len[0] == 1 && de->name[0] == 1) - { - parent_dir = find_rock_ridge_relocation(de, parent); - directory_size = isonum_733 (de->size); - brelse(bh); - break; - } - } -#ifdef DEBUG - printk("Parent dir:%x\n",parent_dir); -#endif - /* Now we know the extent where the parent dir starts on. */ - - result = -1; - - offset = 0; - block = parent_dir << (ISOFS_ZONE_BITS(parent) - bufbits); - if (!block || !(bh = bread(parent->i_dev,block, bufsize))) - { - return -1; - } - - for(;;) - { - de = (struct iso_directory_record *) (bh->b_data + offset); - inode_number = (block << bufbits)+(offset & (bufsize - 1)); - - /* If the length byte is zero, we should move on to the next - CDROM sector. If we are at the end of the directory, we - kick out of the while loop. */ - - if ((*((unsigned char *) de) == 0) || (offset == bufsize) ) - { - brelse(bh); - offset = 0; - block++; - directory_size -= bufsize; - if(directory_size < 0) return -1; - if((block & 1) && (ISOFS_ZONE_BITS(parent) - bufbits) == 1) - { - return -1; - } - if((block & 3) && (ISOFS_ZONE_BITS(parent) - bufbits) == 2) - { - return -1; - } - if (!block - || !(bh = bread(parent->i_dev,block, bufsize))) - { - return -1; - } - continue; - } - - /* Make sure that the entire directory record is in the current - bh block. If not, we malloc a buffer, and put the two - halves together, so that we can cleanly read the block. */ - - offset += *((unsigned char *) de); - - if (offset > bufsize) - { - printk("Directory overrun\n"); - goto out; - } - - if (find_rock_ridge_relocation(de, parent) == extent){ - result = inode_number; - goto out; - } - - } - - /* We go here for any condition we cannot handle. - We also drop through to here at the end of the directory. */ - - out: - brelse(bh); -#ifdef DEBUG - printk("Resultant Inode %d\n",result); -#endif - return result; -} - #ifdef LEAK_CHECK #undef malloc #undef free_s diff --git a/fs/isofs/joliet.c b/fs/isofs/joliet.c index 009314a82..5b93f4581 100644 --- a/fs/isofs/joliet.c +++ b/fs/isofs/joliet.c @@ -70,8 +70,7 @@ wcsntombs_be(__u8 *s, const __u8 *pwcs, int inlen, int maxlen) } int -get_joliet_filename(struct iso_directory_record * de, struct inode * inode, - unsigned char *outname) +get_joliet_filename(struct iso_directory_record * de, unsigned char *outname, struct inode * inode) { unsigned char utf8; struct nls_table *nls; diff --git a/fs/isofs/namei.c b/fs/isofs/namei.c index 7d4ca4e98..4473f7c0d 100644 --- a/fs/isofs/namei.c +++ b/fs/isofs/namei.c @@ -57,147 +57,87 @@ isofs_cmp(struct dentry * dentry, const char * compare, int dlen) * itself (as an inode number). It does NOT read the inode of the * entry - you'll have to do that yourself if you want to. */ -static struct buffer_head * -isofs_find_entry(struct inode *dir, struct dentry *dentry, unsigned long *ino) +static unsigned long +isofs_find_entry(struct inode *dir, struct dentry *dentry, + char * tmpname, struct iso_directory_record * tmpde) { + unsigned long inode_number; unsigned long bufsize = ISOFS_BUFFER_SIZE(dir); unsigned char bufbits = ISOFS_BUFFER_BITS(dir); - unsigned int block, i, f_pos, offset, - inode_number = 0; /* shut gcc up */ - struct buffer_head * bh , * retval = NULL; - unsigned int old_offset; - int dlen, match; - char * dpnt; - unsigned char *page = NULL; - struct iso_directory_record * de = NULL; /* shut gcc up */ - char de_not_in_buf = 0; /* true if de is in kmalloc'd memory */ - char c; - - *ino = 0; - - if (!(block = dir->u.isofs_i.i_first_extent)) return NULL; + unsigned int block, f_pos, offset; + struct buffer_head * bh = NULL; + + if (!dir->u.isofs_i.i_first_extent) + return 0; f_pos = 0; - - offset = f_pos & (bufsize - 1); - block = isofs_bmap(dir,f_pos >> bufbits); - - if (!block || !(bh = bread(dir->i_dev,block,bufsize))) return NULL; + offset = 0; + block = 0; while (f_pos < dir->i_size) { + struct iso_directory_record * de; + int de_len, match, i, dlen; + char *dpnt; - /* if de is in kmalloc'd memory, do not point to the - next de, instead we will move to the next sector */ - if(!de_not_in_buf) { - de = (struct iso_directory_record *) - (bh->b_data + offset); + if (!bh) { + bh = isofs_bread(dir, bufsize, block); + if (!bh) + return 0; } - inode_number = (block << bufbits) + (offset & (bufsize - 1)); - - /* If byte is zero, or we had to fetch this de past - the end of the buffer, this is the end of file, or - time to move to the next sector. Usually 2048 byte - boundaries. */ - - if (*((unsigned char *) de) == 0 || de_not_in_buf) { - if(de_not_in_buf) { - /* james@bpgc.com: Since we slopped - past the end of the last buffer, we - must start some way into the new - one */ - de_not_in_buf = 0; - kfree(de); - f_pos += offset; - } - else { - offset = 0; - f_pos = ((f_pos & ~(ISOFS_BLOCK_SIZE - 1)) - + ISOFS_BLOCK_SIZE); - } - brelse(bh); - bh = NULL; - - if (f_pos >= dir->i_size) - break; - block = isofs_bmap(dir,f_pos>>bufbits); - if (!block || !(bh = bread(dir->i_dev,block,bufsize))) - break; + de = (struct iso_directory_record *) (bh->b_data + offset); + inode_number = (bh->b_blocknr << bufbits) + offset; - continue; /* Will kick out if past end of directory */ + de_len = *(unsigned char *) de; + if (!de_len) { + brelse(bh); + bh = NULL; + f_pos = (f_pos + ISOFS_BLOCK_SIZE) & ~(ISOFS_BLOCK_SIZE - 1); + block = f_pos >> bufbits; + offset = 0; + continue; } - old_offset = offset; - offset += *((unsigned char *) de); - f_pos += *((unsigned char *) de); + offset += de_len; + f_pos += de_len; - /* james@bpgc.com: new code to handle case where the - directory entry spans two blocks. Usually 1024 - byte boundaries */ + /* Make sure we have a full directory entry */ if (offset >= bufsize) { - struct buffer_head *bh_next; - - /* james@bpgc.com: read the next block, and - copy the split de into a newly kmalloc'd - buffer */ - block = isofs_bmap(dir,f_pos>>bufbits); - if (!block || - !(bh_next = bread(dir->i_dev,block,bufsize))) - break; - - de = (struct iso_directory_record *) - kmalloc(offset - old_offset, GFP_KERNEL); - memcpy((char *)de, bh->b_data + old_offset, - bufsize - old_offset); - memcpy((char *)de + bufsize - old_offset, - bh_next->b_data, offset - bufsize); - brelse(bh_next); - de_not_in_buf = 1; - offset -= bufsize; + int slop = bufsize - offset + de_len; + memcpy(tmpde, de, slop); + offset &= bufsize - 1; + block++; + brelse(bh); + bh = NULL; + if (offset) { + bh = isofs_bread(dir, bufsize, block); + if (!bh) + return 0; + memcpy((void *) tmpde + slop, bh->b_data, offset); + } + de = tmpde; } + dlen = de->name_len[0]; dpnt = de->name; - if (dir->i_sb->u.isofs_sb.s_rock || - dir->i_sb->u.isofs_sb.s_joliet_level || - dir->i_sb->u.isofs_sb.s_mapping == 'n' || - dir->i_sb->u.isofs_sb.s_mapping == 'a') { - if (! page) { - page = (unsigned char *) - __get_free_page(GFP_KERNEL); - if (!page) break; - } - } if (dir->i_sb->u.isofs_sb.s_rock && - ((i = get_rock_ridge_filename(de, page, dir)))) { + ((i = get_rock_ridge_filename(de, tmpname, dir)))) { dlen = i; - dpnt = page; + dpnt = tmpname; #ifdef CONFIG_JOLIET } else if (dir->i_sb->u.isofs_sb.s_joliet_level) { - dlen = get_joliet_filename(de, dir, page); - dpnt = page; + dlen = get_joliet_filename(de, tmpname, dir); + dpnt = tmpname; #endif } else if (dir->i_sb->u.isofs_sb.s_mapping == 'a') { - dlen = get_acorn_filename(de, page, dir); - dpnt = page; + dlen = get_acorn_filename(de, tmpname, dir); + dpnt = tmpname; } else if (dir->i_sb->u.isofs_sb.s_mapping == 'n') { - for (i = 0; i < dlen; i++) { - c = dpnt[i]; - /* lower case */ - if (c >= 'A' && c <= 'Z') c |= 0x20; - if (c == ';' && i == dlen-2 && dpnt[i+1] == '1') { - dlen -= 2; - break; - } - if (c == ';') c = '.'; - page[i] = c; - } - /* This allows us to match with and without - * a trailing period. */ - if(page[dlen-1] == '.' && dentry->d_name.len == dlen-1) - dlen--; - dpnt = page; + dlen = isofs_name_translate(de, tmpname, dir); + dpnt = tmpname; } + /* * Skip hidden or associated files unless unhide is set */ @@ -208,43 +148,32 @@ isofs_find_entry(struct inode *dir, struct dentry *dentry, unsigned long *ino) match = (isofs_cmp(dentry,dpnt,dlen) == 0); } if (match) { - if(inode_number == -1) { - /* Should only happen for the '..' entry */ - inode_number = - isofs_lookup_grandparent(dir, - find_rock_ridge_relocation(de,dir)); - } - *ino = inode_number; - retval = bh; - bh = NULL; - break; + if (bh) brelse(bh); + return inode_number; } } - if (page) free_page((unsigned long) page); if (bh) brelse(bh); - if(de_not_in_buf) - kfree(de); - return retval; + return 0; } struct dentry *isofs_lookup(struct inode * dir, struct dentry * dentry) { unsigned long ino; - struct buffer_head * bh; struct inode *inode; + struct page *page; #ifdef DEBUG printk("lookup: %x %s\n",dir->i_ino, dentry->d_name.name); #endif dentry->d_op = dir->i_sb->s_root->d_op; - bh = isofs_find_entry(dir, dentry, &ino); + page = alloc_page(GFP_USER); + ino = isofs_find_entry(dir, dentry, page_address(page), 1024 + page_address(page)); + __free_page(page); inode = NULL; - if (bh) { - brelse(bh); - - inode = iget(dir->i_sb,ino); + if (ino) { + inode = iget(dir->i_sb, ino); if (!inode) return ERR_PTR(-EACCES); } diff --git a/fs/isofs/rock.c b/fs/isofs/rock.c index 1a7cbe374..b2eff877f 100644 --- a/fs/isofs/rock.c +++ b/fs/isofs/rock.c @@ -449,7 +449,7 @@ static char *get_symlink_chunk(char *rpnt, struct rock_ridge *rr) static int rock_ridge_symlink_readpage(struct file *file, struct page *page) { struct inode *inode = (struct inode*)page->mapping->host; - char *link = (char*)kmap(page); + char *link = kmap(page); unsigned long bufsize = ISOFS_BUFFER_SIZE(inode); unsigned char bufbits = ISOFS_BUFFER_BITS(inode); struct buffer_head *bh; diff --git a/fs/jffs/inode-v23.c b/fs/jffs/inode-v23.c index 3ac27df92..f61005aac 100644 --- a/fs/jffs/inode-v23.c +++ b/fs/jffs/inode-v23.c @@ -327,17 +327,15 @@ jffs_new_inode(const struct inode * dir, struct jffs_raw_inode *raw_inode, struct inode * inode; struct jffs_control *c; - inode = get_empty_inode(); + sb = dir->i_sb; + inode = new_inode(sb); if (!inode) { *err = -ENOMEM; return NULL; } - sb = dir->i_sb; c = (struct jffs_control *)sb->u.generic_sbp; - inode->i_sb = sb; - inode->i_dev = sb->s_dev; inode->i_ino = raw_inode->ino; inode->i_mode = raw_inode->mode; inode->i_nlink = raw_inode->nlink; @@ -351,7 +349,6 @@ jffs_new_inode(const struct inode * dir, struct jffs_raw_inode *raw_inode, inode->i_blksize = PAGE_SIZE; inode->i_blocks = (inode->i_size + 511) >> 9; inode->i_version = 0; - inode->i_flags = sb->s_flags; inode->u.generic_ip = (void *)jffs_find_file(c, raw_inode->ino); insert_inode_hash(inode); diff --git a/fs/jffs/intrep.c b/fs/jffs/intrep.c index 5cf82f468..09e88d7ba 100644 --- a/fs/jffs/intrep.c +++ b/fs/jffs/intrep.c @@ -10,7 +10,8 @@ * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * - * $Id: intrep.c,v 1.69 2000/08/24 09:35:47 dwmw2 Exp $ + * - Based on Id: intrep.c,v 1.71 2000/10/27 16:51:29 dwmw2 Exp + * - With the ctype() changes from v1.77. * * Ported to Linux 2.3.x and MTD: * Copyright (C) 2000 Alexander Larsson (alex@cendio.se), Cendio Systems AB @@ -68,15 +69,11 @@ #include <linux/version.h> #include <linux/smp_lock.h> #include <linux/sched.h> - +#include <linux/ctype.h> #include "intrep.h" #include "jffs_fm.h" -#if LINUX_VERSION_CODE < 0x20300 -#define set_current_state(x) do{current->state = x;} while (0) -#endif - #if defined(JFFS_MEMORY_DEBUG) && JFFS_MEMORY_DEBUG long no_jffs_file = 0; long no_jffs_node = 0; @@ -94,48 +91,7 @@ static int jffs_update_file(struct jffs_file *f, struct jffs_node *node); static __u8 flash_read_u8(struct mtd_info *mtd, loff_t from); #if 1 -#define _U 01 -#define _L 02 -#define _N 04 -#define _S 010 -#define _P 020 -#define _C 040 -#define _X 0100 -#define _B 0200 - -const unsigned char jffs_ctype_[1 + 256] = { - 0, - _C, _C, _C, _C, _C, _C, _C, _C, - _C, _C|_S, _C|_S, _C|_S, _C|_S, _C|_S, _C, _C, - _C, _C, _C, _C, _C, _C, _C, _C, - _C, _C, _C, _C, _C, _C, _C, _C, - _S|_B, _P, _P, _P, _P, _P, _P, _P, - _P, _P, _P, _P, _P, _P, _P, _P, - _N, _N, _N, _N, _N, _N, _N, _N, - _N, _N, _P, _P, _P, _P, _P, _P, - _P, _U|_X, _U|_X, _U|_X, _U|_X, _U|_X, _U|_X, _U, - _U, _U, _U, _U, _U, _U, _U, _U, - _U, _U, _U, _U, _U, _U, _U, _U, - _U, _U, _U, _P, _P, _P, _P, _P, - _P, _L|_X, _L|_X, _L|_X, _L|_X, _L|_X, _L|_X, _L, - _L, _L, _L, _L, _L, _L, _L, _L, - _L, _L, _L, _L, _L, _L, _L, _L, - _L, _L, _L, _P, _P, _P, _P, _C -}; - -#define jffs_isalpha(c) ((jffs_ctype_+1)[(int)c]&(_U|_L)) -#define jffs_isupper(c) ((jffs_ctype_+1)[(int)c]&_U) -#define jffs_islower(c) ((jffs_ctype_+1)[(int)c]&_L) -#define jffs_isdigit(c) ((jffs_ctype_+1)[(int)c]&_N) -#define jffs_isxdigit(c) ((jffs_ctype_+1)[(int)c]&(_X|_N)) -#define jffs_isspace(c) ((jffs_ctype_+1)[(int)c]&_S) -#define jffs_ispunct(c) ((jffs_ctype_+1)[(int)c]&_P) -#define jffs_isalnum(c) ((jffs_ctype_+1)[(int)c]&(_U|_L|_N)) -#define jffs_isprint(c) ((jffs_ctype_+1)[(int)c]&(_P|_U|_L|_N|_B)) -#define jffs_isgraph(c) ((jffs_ctype_+1)[(int)c]&(_P|_U|_L|_N)) -#define jffs_iscntrl(c) ((jffs_ctype_+1)[(int)c]&_C) - -void +static void jffs_hexdump(struct mtd_info *mtd, loff_t pos, int size) { char line[16]; @@ -169,7 +125,7 @@ jffs_hexdump(struct mtd_info *mtd, loff_t pos, int size) printk(" "); for (i = 0; i < j; i++) { - if (jffs_isgraph(line[i])) { + if (isgraph(line[i])) { printk("%c", line[i]); } else { @@ -193,9 +149,12 @@ flash_safe_read(struct mtd_info *mtd, loff_t from, size_t retlen; int res; + D3(printk(KERN_NOTICE "flash_safe_read(%p, %08x, %p, %08x)\n", + mtd, from, buf, count)); + res = MTD_READ(mtd, from, count, &retlen, buf); if (retlen != count) { - printk("Didn't read all bytes in flash_safe_read(). Returned %d\n", res); + panic("Didn't read all bytes in flash_safe_read(). Returned %d\n", res); } return res?res:retlen; } @@ -367,9 +326,37 @@ jffs_checksum_flash(struct mtd_info *mtd, loff_t start, int size) { __u32 sum = 0; loff_t ptr = start; - while (size-- > 0) { - sum += flash_read_u8(mtd, ptr++); + __u8 *read_buf; + int i, length; + + /* Allocate read buffer */ + read_buf = (__u8 *) kmalloc (sizeof(__u8) * 4096, GFP_KERNEL); + + /* Loop until checksum done */ + while (size) { + /* Get amount of data to read */ + if (size < 4096) + length = size; + else + length = 4096; + + /* Perform flash read */ + D3(printk(KERN_NOTICE "jffs_checksum_flash\n")); + flash_safe_read(mtd, ptr, &read_buf[0], length); + + /* Compute checksum */ + for (i=0; i < length ; i++) + sum += read_buf[i]; + + /* Update pointer and size */ + size -= length; + ptr += length; } + + /* Free read buffer */ + kfree (read_buf); + + /* Return result */ D3(printk("checksum result: 0x%08x\n", sum)); return sum; } @@ -609,12 +596,17 @@ jffs_scan_flash(struct jffs_control *c) loff_t pos = fmc->flash_start; loff_t start; loff_t end = fmc->flash_start + fmc->flash_size; + __u8 *read_buf; + int i, len, retlen; D1(printk("jffs_scan_flash(): start pos = 0x%lx, end = 0x%lx\n", (long)pos, (long)end)); flash_safe_acquire(fmc->mtd); + /* Allocate read buffer */ + read_buf = (__u8 *) kmalloc (sizeof(__u8) * 4096, GFP_KERNEL); + /* Start the scan. */ while (pos < end) { deleted_file = 0; @@ -629,9 +621,22 @@ jffs_scan_flash(struct jffs_control *c) something else than 0xff is found. */ D1(printk("jffs_scan_flash(): 0xff at pos 0x%lx.\n", (long)pos)); - for (; pos < end - && JFFS_EMPTY_BITMASK == flash_read_u32(fmc->mtd, pos); - pos += 4); + + len = end - pos < 4096 ? end - pos : 4096; + + retlen = flash_safe_read(fmc->mtd, pos, + &read_buf[0], len); + + retlen &= ~3; + + for (i=0 ; i < retlen ; i+=4, pos += 4) { + if(*((__u32 *) &read_buf[i]) != + JFFS_EMPTY_BITMASK) + break; + } + if (i == retlen) + continue; + D1(printk("jffs_scan_flash(): 0xff ended at " "pos 0x%lx.\n", (long)pos)); @@ -748,7 +753,12 @@ jffs_scan_flash(struct jffs_control *c) if (!(node = (struct jffs_node *) kmalloc(sizeof(struct jffs_node), GFP_KERNEL))) { + /* Free read buffer */ + kfree (read_buf); + + /* Release the flash device */ flash_safe_release(fmc->mtd); + return -ENOMEM; } DJM(no_jffs_node++); @@ -893,7 +903,13 @@ jffs_scan_flash(struct jffs_control *c) D(printk("jffs_scan_flash(): !node->fm\n")); kfree(node); DJM(no_jffs_node--); + + /* Free read buffer */ + kfree (read_buf); + + /* Release the flash device */ flash_safe_release(fmc->mtd); + return -ENOMEM; } if ((err = jffs_insert_node(c, 0, &raw_inode, @@ -911,7 +927,13 @@ jffs_scan_flash(struct jffs_control *c) D(printk("jffs_scan_flash: !dl\n")); kfree(node); DJM(no_jffs_node--); + + /* Release the flash device */ flash_safe_release(fmc->flash_part); + + /* Free read buffer */ + kfree (read_buf); + return -ENOMEM; } dl->ino = deleted_file; @@ -936,6 +958,11 @@ jffs_scan_flash(struct jffs_control *c) DJM(no_jffs_node--); } jffs_build_end(fmc); + + /* Free read buffer */ + kfree (read_buf); + + /* Return happy */ D3(printk("jffs_scan_flash(): Leaving...\n")); flash_safe_release(fmc->mtd); return 0; @@ -1598,6 +1625,7 @@ jffs_get_node_data(struct jffs_file *f, struct jffs_node *node, f->name, node->ino, node->version, node_offset)); r = jffs_min(avail, max_size); + D3(printk(KERN_NOTICE "jffs_get_node_data\n")); flash_safe_read(fmc->mtd, pos, buf, r); D3(printk(" jffs_get_node_data(): Read %u byte%s.\n", @@ -3026,9 +3054,8 @@ jffs_garbage_collect_thread(void *ptr) case SIGKILL: D1(printk("jffs_garbage_collect_thread(): SIGKILL received.\n")); c->gc_task = NULL; - up(&c->gc_thread_sem); unlock_kernel(); - return(0); + up_and_exit(&c->gc_thread_sem, 0); } } diff --git a/fs/lockd/clntlock.c b/fs/lockd/clntlock.c index 249e7514d..b5194b561 100644 --- a/fs/lockd/clntlock.c +++ b/fs/lockd/clntlock.c @@ -168,7 +168,6 @@ reclaimer(void *ptr) * reclaim is in progress */ lock_kernel(); lockd_up(); - down(&file_lock_sem); /* First, reclaim all locks that have been granted previously. */ restart: @@ -181,12 +180,11 @@ restart: fl->fl_u.nfs_fl.state != host->h_state && (fl->fl_u.nfs_fl.flags & NFS_LCK_GRANTED)) { fl->fl_u.nfs_fl.flags &= ~ NFS_LCK_GRANTED; - nlmclnt_reclaim(host, fl); + nlmclnt_reclaim(host, fl); /* This sleeps */ goto restart; } tmp = tmp->next; } - up(&file_lock_sem); host->h_reclaiming = 0; wake_up(&host->h_gracewait); diff --git a/fs/lockd/clntproc.c b/fs/lockd/clntproc.c index dbe3f69b5..211b01530 100644 --- a/fs/lockd/clntproc.c +++ b/fs/lockd/clntproc.c @@ -407,19 +407,15 @@ nlmclnt_test(struct nlm_rqst *req, struct file_lock *fl) static void nlmclnt_insert_lock_callback(struct file_lock *fl) { - lock_kernel(); nlm_get_host(fl->fl_u.nfs_fl.host); - unlock_kernel(); } static void nlmclnt_remove_lock_callback(struct file_lock *fl) { - lock_kernel(); if (fl->fl_u.nfs_fl.host) { nlm_release_host(fl->fl_u.nfs_fl.host); fl->fl_u.nfs_fl.host = NULL; } - unlock_kernel(); } /* diff --git a/fs/lockd/svclock.c b/fs/lockd/svclock.c index 5460e8c9f..078f568b7 100644 --- a/fs/lockd/svclock.c +++ b/fs/lockd/svclock.c @@ -468,7 +468,6 @@ nlmsvc_notify_blocked(struct file_lock *fl) dprintk("lockd: VFS unblock notification for block %p\n", fl); posix_unblock_lock(fl); - lock_kernel(); for (bp = &nlm_blocked; (block = *bp); bp = &block->b_next) { if (nlm_compare_locks(&block->b_call.a_args.lock.fl, fl)) { nlmsvc_insert_block(block, 0); @@ -476,7 +475,6 @@ nlmsvc_notify_blocked(struct file_lock *fl) return; } } - unlock_kernel(); printk(KERN_WARNING "lockd: notification for unknown block!\n"); } diff --git a/fs/locks.c b/fs/locks.c index 0e92b740f..7da293a31 100644 --- a/fs/locks.c +++ b/fs/locks.c @@ -125,11 +125,6 @@ #include <asm/semaphore.h> #include <asm/uaccess.h> -DECLARE_MUTEX(file_lock_sem); - -#define acquire_fl_sem() down(&file_lock_sem) -#define release_fl_sem() up(&file_lock_sem) - int leases_enable = 1; int lease_break_time = 45; @@ -428,6 +423,15 @@ static void locks_insert_block(struct file_lock *blocker, list_add(&waiter->fl_link, &blocked_list); } +static inline +void locks_notify_blocked(struct file_lock *waiter) +{ + if (waiter->fl_notify) + waiter->fl_notify(waiter); + else + wake_up(&waiter->fl_wait); +} + /* Wake up processes blocked waiting for blocker. * If told to wait then schedule the processes until the block list * is empty, otherwise empty the block list ourselves. @@ -436,11 +440,9 @@ static void locks_wake_up_blocks(struct file_lock *blocker, unsigned int wait) { while (!list_empty(&blocker->fl_block)) { struct file_lock *waiter = list_entry(blocker->fl_block.next, struct file_lock, fl_block); - /* N.B. Is it possible for the notify function to block?? */ - if (waiter->fl_notify) - waiter->fl_notify(waiter); - wake_up(&waiter->fl_wait); + if (wait) { + locks_notify_blocked(waiter); /* Let the blocked process remove waiter from the * block list when it gets scheduled. */ @@ -451,6 +453,7 @@ static void locks_wake_up_blocks(struct file_lock *blocker, unsigned int wait) * time it wakes up blocker won't exist any more. */ locks_delete_block(waiter); + locks_notify_blocked(waiter); } } } @@ -477,7 +480,6 @@ static void locks_insert_lock(struct file_lock **pos, struct file_lock *fl) */ static void locks_delete_lock(struct file_lock **thisfl_p, unsigned int wait) { - int (*lock)(struct file *, int, struct file_lock *); struct file_lock *fl = *thisfl_p; *thisfl_p = fl->fl_next; @@ -488,7 +490,7 @@ static void locks_delete_lock(struct file_lock **thisfl_p, unsigned int wait) fasync_helper(0, fl->fl_file, 0, &fl->fl_fasync); if (fl->fl_fasync != NULL){ - printk("locks_delete_lock: fasync == %p\n", fl->fl_fasync); + printk(KERN_ERR "locks_delete_lock: fasync == %p\n", fl->fl_fasync); fl->fl_fasync = NULL; } @@ -496,12 +498,24 @@ static void locks_delete_lock(struct file_lock **thisfl_p, unsigned int wait) fl->fl_remove(fl); locks_wake_up_blocks(fl, wait); - lock = fl->fl_file->f_op->lock; - if (lock) { + locks_free_lock(fl); +} + +/* + * Call back client filesystem in order to get it to unregister a lock, + * then delete lock. Essentially useful only in locks_remove_*(). + * Note: this must be called with the semaphore already held! + */ +static inline void locks_unlock_delete(struct file_lock **thisfl_p) +{ + struct file_lock *fl = *thisfl_p; + int (*lock)(struct file *, int, struct file_lock *); + + if ((lock = fl->fl_file->f_op->lock) != NULL) { fl->fl_type = F_UNLCK; lock(fl->fl_file, F_SETLK, fl); } - locks_free_lock(fl); + locks_delete_lock(thisfl_p, 0); } /* Determine if lock sys_fl blocks lock caller_fl. Common functionality @@ -562,22 +576,19 @@ static int flock_locks_conflict(struct file_lock *caller_fl, struct file_lock *s return (locks_conflict(caller_fl, sys_fl)); } -int interruptible_sleep_on_locked(wait_queue_head_t *fl_wait, struct semaphore *sem, int timeout) +static int interruptible_sleep_on_locked(wait_queue_head_t *fl_wait, int timeout) { int result = 0; - wait_queue_t wait; - init_waitqueue_entry(&wait, current); + DECLARE_WAITQUEUE(wait, current); - __add_wait_queue(fl_wait, &wait); current->state = TASK_INTERRUPTIBLE; - up(sem); + add_wait_queue(fl_wait, &wait); if (timeout == 0) schedule(); else result = schedule_timeout(timeout); if (signal_pending(current)) result = -ERESTARTSYS; - down(sem); remove_wait_queue(fl_wait, &wait); current->state = TASK_RUNNING; return result; @@ -587,7 +598,7 @@ static int locks_block_on(struct file_lock *blocker, struct file_lock *waiter) { int result; locks_insert_block(blocker, waiter); - result = interruptible_sleep_on_locked(&waiter->fl_wait, &file_lock_sem, 0); + result = interruptible_sleep_on_locked(&waiter->fl_wait, 0); locks_delete_block(waiter); return result; } @@ -596,7 +607,7 @@ static int locks_block_on_timeout(struct file_lock *blocker, struct file_lock *w { int result; locks_insert_block(blocker, waiter); - result = interruptible_sleep_on_locked(&waiter->fl_wait, &file_lock_sem, time); + result = interruptible_sleep_on_locked(&waiter->fl_wait, time); locks_delete_block(waiter); return result; } @@ -606,14 +617,14 @@ posix_test_lock(struct file *filp, struct file_lock *fl) { struct file_lock *cfl; - acquire_fl_sem(); + lock_kernel(); for (cfl = filp->f_dentry->d_inode->i_flock; cfl; cfl = cfl->fl_next) { if (!(cfl->fl_flags & FL_POSIX)) continue; if (posix_locks_conflict(cfl, fl)) break; } - release_fl_sem(); + unlock_kernel(); return (cfl); } @@ -668,14 +679,14 @@ int locks_mandatory_locked(struct inode *inode) /* * Search the lock list for this inode for any POSIX locks. */ - acquire_fl_sem(); + lock_kernel(); for (fl = inode->i_flock; fl != NULL; fl = fl->fl_next) { if (!(fl->fl_flags & FL_POSIX)) continue; if (fl->fl_owner != owner) break; } - release_fl_sem(); + unlock_kernel(); return fl ? -EAGAIN : 0; } @@ -696,7 +707,7 @@ int locks_mandatory_area(int read_write, struct inode *inode, new_fl->fl_end = offset + count - 1; error = 0; - acquire_fl_sem(); + lock_kernel(); repeat: /* Search the lock list for this inode for locks that conflict with @@ -729,7 +740,7 @@ repeat: } } locks_free_lock(new_fl); - release_fl_sem(); + unlock_kernel(); return error; } @@ -847,7 +858,7 @@ int posix_lock_file(struct file *filp, struct file_lock *caller, if (!(new_fl && new_fl2)) goto out; - acquire_fl_sem(); + lock_kernel(); if (caller->fl_type != F_UNLCK) { repeat: for (fl = inode->i_flock; fl != NULL; fl = fl->fl_next) { @@ -951,7 +962,7 @@ int posix_lock_file(struct file *filp, struct file_lock *caller, * as the change in lock type might satisfy * their needs. */ - locks_wake_up_blocks(fl, 0); + locks_wake_up_blocks(fl, 0); /* This cannot schedule()! */ fl->fl_start = caller->fl_start; fl->fl_end = caller->fl_end; fl->fl_type = caller->fl_type; @@ -992,7 +1003,7 @@ int posix_lock_file(struct file *filp, struct file_lock *caller, locks_wake_up_blocks(left, 0); } out: - release_fl_sem(); + unlock_kernel(); /* * Free any unused locks. */ @@ -1038,7 +1049,7 @@ int __get_lease(struct inode *inode, unsigned int mode) alloc_err = lease_alloc(NULL, 0, &new_fl); - acquire_fl_sem(); + lock_kernel(); flock = inode->i_flock; if (flock->fl_type & F_INPROGRESS) { if ((mode & O_NONBLOCK) @@ -1107,7 +1118,7 @@ restart: } out: - release_fl_sem(); + unlock_kernel(); if (!alloc_err) locks_free_lock(new_fl); return error; @@ -1210,7 +1221,7 @@ int fcntl_setlease(unsigned int fd, struct file *filp, long arg) before = &inode->i_flock; - acquire_fl_sem(); + lock_kernel(); while ((fl = *before) != NULL) { if (fl->fl_flags != FL_LEASE) @@ -1261,7 +1272,7 @@ int fcntl_setlease(unsigned int fd, struct file *filp, long arg) filp->f_owner.uid = current->uid; filp->f_owner.euid = current->euid; out_unlock: - release_fl_sem(); + unlock_kernel(); return error; } @@ -1307,10 +1318,10 @@ asmlinkage long sys_flock(unsigned int fd, unsigned int cmd) && !(filp->f_mode & 3)) goto out_putf; - acquire_fl_sem(); + lock_kernel(); error = flock_lock_file(filp, type, (cmd & (LOCK_UN | LOCK_NB)) ? 0 : 1); - release_fl_sem(); + unlock_kernel(); out_putf: fput(filp); @@ -1643,16 +1654,16 @@ void locks_remove_posix(struct file *filp, fl_owner_t owner) */ return; } - acquire_fl_sem(); + lock_kernel(); before = &inode->i_flock; while ((fl = *before) != NULL) { if ((fl->fl_flags & FL_POSIX) && fl->fl_owner == owner) { - locks_delete_lock(before, 0); + locks_unlock_delete(before); continue; } before = &fl->fl_next; } - release_fl_sem(); + unlock_kernel(); } /* @@ -1667,7 +1678,7 @@ void locks_remove_flock(struct file *filp) if (!inode->i_flock) return; - acquire_fl_sem(); + lock_kernel(); before = &inode->i_flock; while ((fl = *before) != NULL) { @@ -1678,7 +1689,7 @@ void locks_remove_flock(struct file *filp) } before = &fl->fl_next; } - release_fl_sem(); + unlock_kernel(); } /** @@ -1691,9 +1702,7 @@ void locks_remove_flock(struct file *filp) void posix_block_lock(struct file_lock *blocker, struct file_lock *waiter) { - acquire_fl_sem(); locks_insert_block(blocker, waiter); - release_fl_sem(); } /** @@ -1705,12 +1714,8 @@ posix_block_lock(struct file_lock *blocker, struct file_lock *waiter) void posix_unblock_lock(struct file_lock *waiter) { - acquire_fl_sem(); - if (!list_empty(&waiter->fl_block)) { + if (!list_empty(&waiter->fl_block)) locks_delete_block(waiter); - wake_up(&waiter->fl_wait); - } - release_fl_sem(); } static void lock_get_status(char* out, struct file_lock *fl, int id, char *pfx) @@ -1801,7 +1806,7 @@ int get_locks_status(char *buffer, char **start, off_t offset, int length) off_t pos = 0; int i = 0; - acquire_fl_sem(); + lock_kernel(); list_for_each(tmp, &file_lock_list) { struct list_head *btmp; struct file_lock *fl = list_entry(tmp, struct file_lock, fl_link); @@ -1822,7 +1827,7 @@ int get_locks_status(char *buffer, char **start, off_t offset, int length) } } done: - release_fl_sem(); + unlock_kernel(); *start = buffer; if(q-buffer < length) return (q-buffer); @@ -1847,7 +1852,7 @@ int lock_may_read(struct inode *inode, loff_t start, unsigned long len) { struct file_lock *fl; int result = 1; - acquire_fl_sem(); + lock_kernel(); for (fl = inode->i_flock; fl != NULL; fl = fl->fl_next) { if (fl->fl_flags == FL_POSIX) { if (fl->fl_type == F_RDLCK) @@ -1864,7 +1869,7 @@ int lock_may_read(struct inode *inode, loff_t start, unsigned long len) result = 0; break; } - release_fl_sem(); + unlock_kernel(); return result; } @@ -1885,7 +1890,7 @@ int lock_may_write(struct inode *inode, loff_t start, unsigned long len) { struct file_lock *fl; int result = 1; - acquire_fl_sem(); + lock_kernel(); for (fl = inode->i_flock; fl != NULL; fl = fl->fl_next) { if (fl->fl_flags == FL_POSIX) { if ((fl->fl_end < start) || (fl->fl_start > (start + len))) @@ -1900,7 +1905,7 @@ int lock_may_write(struct inode *inode, loff_t start, unsigned long len) result = 0; break; } - release_fl_sem(); + unlock_kernel(); return result; } #endif diff --git a/fs/minix/bitmap.c b/fs/minix/bitmap.c index dce2687ee..49f757e80 100644 --- a/fs/minix/bitmap.c +++ b/fs/minix/bitmap.c @@ -224,14 +224,12 @@ struct inode * minix_new_inode(const struct inode * dir, int * error) struct buffer_head * bh; int i,j; - inode = get_empty_inode(); + sb = dir->i_sb; + inode = new_inode(sb); if (!inode) { *error = -ENOMEM; return NULL; } - sb = dir->i_sb; - inode->i_sb = sb; - inode->i_flags = 0; j = 8192; bh = NULL; *error = -ENOSPC; @@ -259,8 +257,6 @@ struct inode * minix_new_inode(const struct inode * dir, int * error) unlock_super(sb); return NULL; } - inode->i_nlink = 1; - inode->i_dev = sb->s_dev; inode->i_uid = current->fsuid; inode->i_gid = (dir->i_mode & S_ISGID) ? dir->i_gid : current->fsgid; inode->i_ino = j; diff --git a/fs/namei.c b/fs/namei.c index c22fc2ec3..c0d1abc36 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -1381,7 +1381,10 @@ asmlinkage long sys_rmdir(const char * pathname) case LAST_DOTDOT: error = -ENOTEMPTY; goto exit1; - case LAST_ROOT: case LAST_DOT: + case LAST_DOT: + error = -EINVAL; + goto exit1; + case LAST_ROOT: error = -EBUSY; goto exit1; } @@ -1949,7 +1952,7 @@ static char *page_getlink(struct dentry * dentry, struct page **ppage) if (!Page_Uptodate(page)) goto async_fail; *ppage = page; - return (char*) kmap(page); + return kmap(page); async_fail: page_cache_release(page); diff --git a/fs/ncpfs/dir.c b/fs/ncpfs/dir.c index eda3fe6af..a187b1199 100644 --- a/fs/ncpfs/dir.c +++ b/fs/ncpfs/dir.c @@ -462,7 +462,7 @@ static int ncp_readdir(struct file *filp, void *dirent, filldir_t filldir) if (!page) goto read_really; - ctl.cache = cache = (union ncp_dir_cache *) kmap(page); + ctl.cache = cache = kmap(page); ctl.head = cache->head; if (!Page_Uptodate(page) || !ctl.head.eof) @@ -490,7 +490,7 @@ static int ncp_readdir(struct file *filp, void *dirent, filldir_t filldir) ctl.page = find_lock_page(&inode->i_data, ctl.ofs); if (!ctl.page) goto invalid_cache; - ctl.cache = (union ncp_dir_cache *) kmap(ctl.page); + ctl.cache = kmap(ctl.page); if (!Page_Uptodate(ctl.page)) goto invalid_cache; } @@ -635,7 +635,7 @@ ncp_fill_cache(struct file *filp, void *dirent, filldir_t filldir, ctl.ofs += 1; ctl.page = grab_cache_page(&inode->i_data, ctl.ofs); if (ctl.page) - ctl.cache = (union ncp_dir_cache *) kmap(ctl.page); + ctl.cache = kmap(ctl.page); } if (ctl.cache) { ctl.cache->dentry[ctl.idx] = newdent; diff --git a/fs/ncpfs/file.c b/fs/ncpfs/file.c index 139c9262d..ac4de2b83 100644 --- a/fs/ncpfs/file.c +++ b/fs/ncpfs/file.c @@ -120,11 +120,6 @@ ncp_file_read(struct file *file, char *buf, size_t count, loff_t *ppos) DPRINTK("ncp_file_read: enter %s/%s\n", dentry->d_parent->d_name.name, dentry->d_name.name); - error = -EINVAL; - if (inode == NULL) { - DPRINTK("ncp_file_read: inode = NULL\n"); - goto out; - } error = -EIO; if (!ncp_conn_valid(NCP_SERVER(inode))) goto out; @@ -210,10 +205,6 @@ ncp_file_write(struct file *file, const char *buf, size_t count, loff_t *ppos) DPRINTK("ncp_file_write: enter %s/%s\n", dentry->d_parent->d_name.name, dentry->d_name.name); - if (inode == NULL) { - DPRINTK("ncp_file_write: inode = NULL\n"); - return -EINVAL; - } errno = -EIO; if (!ncp_conn_valid(NCP_SERVER(inode))) goto out; diff --git a/fs/ncpfs/inode.c b/fs/ncpfs/inode.c index ff0c1fd03..badfc7817 100644 --- a/fs/ncpfs/inode.c +++ b/fs/ncpfs/inode.c @@ -214,13 +214,11 @@ ncp_iget(struct super_block *sb, struct ncp_entry_info *info) return NULL; } - inode = get_empty_inode(); + inode = new_inode(sb); if (inode) { init_MUTEX(&NCP_FINFO(inode)->open_sem); atomic_set(&NCP_FINFO(inode)->opened, info->opened); - inode->i_sb = sb; - inode->i_dev = sb->s_dev; inode->i_ino = info->ino; ncp_set_attr(inode, info); if (S_ISREG(inode->i_mode)) { diff --git a/fs/ncpfs/ioctl.c b/fs/ncpfs/ioctl.c index 4df91abe3..4b6afe2e9 100644 --- a/fs/ncpfs/ioctl.c +++ b/fs/ncpfs/ioctl.c @@ -86,10 +86,8 @@ int ncp_ioctl(struct inode *inode, struct file *filp, case NCP_IOC_CONN_LOGGED_IN: - if ((permission(inode, MAY_WRITE) != 0) - && (current->uid != server->m.mounted_uid)) { + if (!capable(CAP_SYS_ADMIN)) return -EACCES; - } if (!(server->m.int_flags & NCP_IMOUNT_LOGGEDIN_POSSIBLE)) return -EINVAL; if (server->root_setuped) @@ -207,8 +205,7 @@ int ncp_ioctl(struct inode *inode, struct file *filp, struct nw_info_struct i; struct dentry* dentry; - if ( (permission(inode, MAY_WRITE) != 0) - && (current->uid != server->m.mounted_uid)) + if (!capable(CAP_SYS_ADMIN)) { return -EACCES; } @@ -513,8 +510,7 @@ outrel: * Thanks Petr Vandrovec for idea and many hints. */ case NCP_IOC_SETCHARSETS: - if ((permission(inode, MAY_WRITE) != 0) && - (current->uid != server->m.mounted_uid)) + if (!capable(CAP_SYS_ADMIN)) return -EACCES; if (server->root_setuped) return -EBUSY; diff --git a/fs/ncpfs/mmap.c b/fs/ncpfs/mmap.c index 041dd0785..9261eb453 100644 --- a/fs/ncpfs/mmap.c +++ b/fs/ncpfs/mmap.c @@ -37,7 +37,7 @@ static struct page* ncp_file_mmap_nopage(struct vm_area_struct *area, struct dentry *dentry = file->f_dentry; struct inode *inode = dentry->d_inode; struct page* page; - unsigned long pg_addr; + char *pg_addr; unsigned int already_read; unsigned int count; int bufsize; @@ -71,7 +71,7 @@ static struct page* ncp_file_mmap_nopage(struct vm_area_struct *area, if (ncp_read_kernel(NCP_SERVER(inode), NCP_FINFO(inode)->file_handle, pos, to_read, - (char *) (pg_addr + already_read), + pg_addr + already_read, &read_this_time) != 0) { read_this_time = 0; } @@ -87,8 +87,7 @@ static struct page* ncp_file_mmap_nopage(struct vm_area_struct *area, } if (already_read < PAGE_SIZE) - memset((char*)(pg_addr + already_read), 0, - PAGE_SIZE - already_read); + memset(pg_addr + already_read, 0, PAGE_SIZE - already_read); flush_dcache_page(page); kunmap(page); return page; diff --git a/fs/ncpfs/ncplib_kernel.c b/fs/ncpfs/ncplib_kernel.c index 9272822a4..6e09c8bf2 100644 --- a/fs/ncpfs/ncplib_kernel.c +++ b/fs/ncpfs/ncplib_kernel.c @@ -1005,6 +1005,8 @@ ncp__vol2io(struct ncp_server *server, unsigned char *iname, unsigned int *ilen, /* this is wrong! */ vname_cc = kmalloc(vlen, GFP_KERNEL); + if (!vname_cc) + return -ENOMEM; for (i = 0; i < vlen; i++) vname_cc[i] = ncp_tolower(in, vname[i]); vname = vname_cc; diff --git a/fs/ncpfs/symlink.c b/fs/ncpfs/symlink.c index 0962593da..022cbce78 100644 --- a/fs/ncpfs/symlink.c +++ b/fs/ncpfs/symlink.c @@ -48,7 +48,7 @@ static int ncp_symlink_readpage(struct file *file, struct page *page) struct inode *inode = (struct inode*)page->mapping->host; int error, length, len, cnt; char *link; - char *buf = (char*)kmap(page); + char *buf = kmap(page); error = -ENOMEM; for (cnt = 0; (link=(char *)kmalloc(NCP_MAX_SYMLINK_SIZE, GFP_NFS))==NULL; cnt++) { diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c index 3f6b770aa..c66d870d9 100644 --- a/fs/nfs/dir.c +++ b/fs/nfs/dir.c @@ -97,7 +97,7 @@ int nfs_readdir_filler(nfs_readdir_descriptor_t *desc, struct page *page) { struct file *file = desc->file; struct inode *inode = file->f_dentry->d_inode; - void *buffer = (void *)kmap(page); + void *buffer = kmap(page); int plus = NFS_USE_READDIRPLUS(inode); int error; @@ -145,7 +145,7 @@ static inline int find_dirent(nfs_readdir_descriptor_t *desc, struct page *page) { struct nfs_entry *entry = desc->entry; - char *start = (char *)kmap(page), + char *start = kmap(page), *p = start; int loop_count = 0, status = 0; @@ -251,7 +251,7 @@ int nfs_do_filldir(nfs_readdir_descriptor_t *desc, void *dirent, { struct file *file = desc->file; struct nfs_entry *entry = desc->entry; - char *start = (char *)kmap(desc->page), + char *start = kmap(desc->page), *p = start + desc->page_offset; unsigned long fileid; int loop_count = 0, @@ -323,7 +323,7 @@ int uncached_readdir(nfs_readdir_descriptor_t *desc, void *dirent, status = -ENOMEM; goto out; } - p = (u32 *)kmap(page); + p = kmap(page); status = NFS_PROTO(inode)->readdir(file, desc->target, p, NFS_SERVER(inode)->dtsize, 0); if (status >= 0) { diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c index b21592528..5b582024e 100644 --- a/fs/nfs/inode.c +++ b/fs/nfs/inode.c @@ -720,12 +720,9 @@ nfs_fhget(struct dentry *dentry, struct nfs_fh *fhandle, if ((dentry->d_parent->d_inode->u.nfs_i.flags & NFS_IS_SNAPSHOT) || (dentry->d_name.len == 9 && memcmp(dentry->d_name.name, ".snapshot", 9) == 0)) { - struct inode *inode = get_empty_inode(); + struct inode *inode = new_inode(sb); if (!inode) - goto out; - inode->i_sb = sb; - inode->i_dev = sb->s_dev; - inode->i_flags = 0; + goto out; inode->i_ino = nfs_fattr_to_ino_t(fattr); nfs_read_inode(inode); nfs_fill_inode(inode, fattr); diff --git a/fs/nfs/read.c b/fs/nfs/read.c index 7c1aad253..76fc2f437 100644 --- a/fs/nfs/read.c +++ b/fs/nfs/read.c @@ -101,7 +101,7 @@ nfs_readpage_sync(struct file *file, struct page *page) * This works now because the socket layer never tries to DMA * into this buffer directly. */ - buffer = (char *) kmap(page); + buffer = kmap(page); do { if (count < rsize) rsize = count; @@ -257,7 +257,7 @@ nfs_read_rpcsetup(struct list_head *head, struct nfs_read_data *data) struct nfs_page *req = nfs_list_entry(head->next); nfs_list_remove_request(req); nfs_list_add_request(req, &data->pages); - iov->iov_base = (void *)(kmap(req->wb_page) + req->wb_offset); + iov->iov_base = kmap(req->wb_page) + req->wb_offset; iov->iov_len = req->wb_bytes; count += req->wb_bytes; iov++; diff --git a/fs/nfs/symlink.c b/fs/nfs/symlink.c index 4c9c45e2a..4960526b4 100644 --- a/fs/nfs/symlink.c +++ b/fs/nfs/symlink.c @@ -30,7 +30,7 @@ static int nfs_symlink_filler(struct dentry *dentry, struct page *page) { struct inode *inode = dentry->d_inode; - void *buffer = (void *)kmap(page); + void *buffer = kmap(page); int error; /* We place the length at the beginning of the page, @@ -69,7 +69,7 @@ static char *nfs_getlink(struct dentry *dentry, struct page **ppage) if (!Page_Uptodate(page)) goto getlink_read_error; *ppage = page; - p = (u32 *) kmap(page); + p = kmap(page); return (char*)(p+1); getlink_read_error: diff --git a/fs/nfs/write.c b/fs/nfs/write.c index 5346e6302..230954993 100644 --- a/fs/nfs/write.c +++ b/fs/nfs/write.c @@ -184,7 +184,7 @@ nfs_writepage_sync(struct file *file, struct page *page, dentry->d_parent->d_name.name, dentry->d_name.name, count, (long long)(page_offset(page) + offset)); - buffer = (u8 *) kmap(page) + offset; + buffer = kmap(page) + offset; base = page_offset(page) + offset; flags = ((IS_SWAPFILE(inode)) ? NFS_RW_SWAP : 0) | NFS_RW_SYNC; @@ -601,14 +601,10 @@ nfs_wait_on_request(struct nfs_page *req) { struct inode *inode = req->wb_dentry->d_inode; struct rpc_clnt *clnt = NFS_CLIENT(inode); - int retval; if (!NFS_WBACK_BUSY(req)) return 0; - req->wb_count++; - retval = nfs_wait_event(clnt, req->wb_wait, !NFS_WBACK_BUSY(req)); - nfs_release_request(req); - return retval; + return nfs_wait_event(clnt, req->wb_wait, !NFS_WBACK_BUSY(req)); } /* @@ -1065,7 +1061,7 @@ nfs_write_rpcsetup(struct list_head *head, struct nfs_write_data *data) struct nfs_page *req = nfs_list_entry(head->next); nfs_list_remove_request(req); nfs_list_add_request(req, &data->pages); - iov->iov_base = (void *)(kmap(req->wb_page) + req->wb_offset); + iov->iov_base = kmap(req->wb_page) + req->wb_offset; iov->iov_len = req->wb_bytes; count += req->wb_bytes; iov++; @@ -1239,6 +1235,13 @@ nfs_writeback_done(struct rpc_task *task) } #endif + /* + * Update attributes as result of writeback. + * FIXME: There is an inherent race with invalidate_inode_pages and + * writebacks since the page->count is kept > 1 for as long + * as the page has a write request pending. + */ + nfs_write_attributes(inode, resp->fattr); while (!list_empty(&data->pages)) { req = nfs_list_entry(data->pages.next); nfs_list_remove_request(req); @@ -1278,9 +1281,6 @@ nfs_writeback_done(struct rpc_task *task) next: nfs_unlock_request(req); } - /* Update attributes as result of writeback. */ - nfs_write_attributes(inode, resp->fattr); - } @@ -1395,6 +1395,7 @@ nfs_commit_done(struct rpc_task *task) dprintk("NFS: %4d nfs_commit_done (status %d)\n", task->tk_pid, task->tk_status); + nfs_write_attributes(inode, resp->fattr); while (!list_empty(&data->pages)) { req = nfs_list_entry(data->pages.next); nfs_list_remove_request(req); @@ -1426,8 +1427,6 @@ nfs_commit_done(struct rpc_task *task) next: nfs_unlock_request(req); } - - nfs_write_attributes(inode, resp->fattr); } #endif diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c index f01f1de86..b57b85ca1 100644 --- a/fs/nfsd/vfs.c +++ b/fs/nfsd/vfs.c @@ -1538,6 +1538,8 @@ nfsd_permission(struct svc_export *exp, struct dentry *dentry, int acc) inode->i_uid == current->fsuid) return 0; + acc &= ~ MAY_OWNER_OVERRIDE; /* This bit is no longer needed, + and gets in the way later */ err = permission(inode, acc & (MAY_READ|MAY_WRITE|MAY_EXEC)); diff --git a/fs/ntfs/fs.c b/fs/ntfs/fs.c index f9ffb0a40..49d2160a6 100644 --- a/fs/ntfs/fs.c +++ b/fs/ntfs/fs.c @@ -428,7 +428,7 @@ ntfs_create(struct inode* dir,struct dentry *d,int mode) int error=0; ntfs_attribute *si; - r=get_empty_inode(); + r=new_inode(dir->i_sb); if(!r){ error=ENOMEM; goto fail; @@ -456,8 +456,6 @@ ntfs_create(struct inode* dir,struct dentry *d,int mode) r->i_uid=vol->uid; r->i_gid=vol->gid; - r->i_nlink=1; - r->i_sb=dir->i_sb; /* FIXME: dirty? dev? */ /* get the file modification times from the standard information */ si=ntfs_find_attr(ino,vol->at_standard_information,NULL); @@ -502,7 +500,7 @@ _linux_ntfs_mkdir(struct inode *dir, struct dentry* d, int mode) goto out; error = EIO; - r = get_empty_inode(); + r = new_inode(dir->i_sb); if (!r) goto out; @@ -522,8 +520,6 @@ _linux_ntfs_mkdir(struct inode *dir, struct dentry* d, int mode) goto out; r->i_uid = vol->uid; r->i_gid = vol->gid; - r->i_nlink = 1; - r->i_sb = dir->i_sb; si = ntfs_find_attr(ino,vol->at_standard_information,NULL); if(si){ char *attr = si->d.data; diff --git a/fs/ntfs/inode.c b/fs/ntfs/inode.c index 910ffe095..3fdc84ed1 100644 --- a/fs/ntfs/inode.c +++ b/fs/ntfs/inode.c @@ -1050,7 +1050,7 @@ ntfs_clear_bit (unsigned char *byte, int bit) /* We have to skip the 16 metafiles and the 8 reserved entries */ static int -new_inode (ntfs_volume* vol,int* result) +ntfs_new_inode (ntfs_volume* vol,int* result) { int byte,error; int bit; @@ -1236,11 +1236,11 @@ int ntfs_alloc_inode (ntfs_inode *dir, ntfs_inode *result, ntfs_volume* vol=dir->vol; int byte,bit; - error=new_inode (vol,&(result->i_number)); + error=ntfs_new_inode (vol,&(result->i_number)); if(error==ENOSPC){ error=ntfs_extend_mft(vol); if(error)return error; - error=new_inode(vol,&(result->i_number)); + error=ntfs_new_inode(vol,&(result->i_number)); } if(error){ ntfs_error ("ntfs_get_empty_inode: no free inodes\n"); diff --git a/fs/ntfs/super.c b/fs/ntfs/super.c index 3b7b5b2af..1e6f1c854 100644 --- a/fs/ntfs/super.c +++ b/fs/ntfs/super.c @@ -125,7 +125,7 @@ ntfs_init_upcase(ntfs_inode *upcase) io.param=(char*)upcase->vol->upcase; io.size=2*UPCASE_LENGTH; ntfs_read_attr(upcase,upcase->vol->at_data,0,0,&io); - upcase->vol->upcase_length = io.size; + upcase->vol->upcase_length = io.size / 2; } static int @@ -608,14 +608,12 @@ static struct super_operations pipefs_ops = { static struct super_block * pipefs_read_super(struct super_block *sb, void *data, int silent) { - struct inode *root = get_empty_inode(); + struct inode *root = new_inode(sb); if (!root) return NULL; root->i_mode = S_IFDIR | S_IRUSR | S_IWUSR; root->i_uid = root->i_gid = 0; root->i_atime = root->i_mtime = root->i_ctime = CURRENT_TIME; - root->i_sb = sb; - root->i_dev = sb->s_dev; sb->s_blocksize = 1024; sb->s_blocksize_bits = 10; sb->s_magic = PIPEFS_MAGIC; diff --git a/fs/proc/array.c b/fs/proc/array.c index d12a577fa..e98061fa8 100644 --- a/fs/proc/array.c +++ b/fs/proc/array.c @@ -372,7 +372,7 @@ int proc_pid_stat(struct task_struct *task, char * buffer) task->start_time, vsize, mm ? mm->rss : 0, /* you might want to shift this left 3 */ - task->rlim ? task->rlim[RLIMIT_RSS].rlim_cur : 0, + task->rlim[RLIMIT_RSS].rlim_cur, mm ? mm->start_code : 0, mm ? mm->end_code : 0, mm ? mm->start_stack : 0, diff --git a/fs/proc/base.c b/fs/proc/base.c index a1f7efe0f..c1a960c5d 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c @@ -207,15 +207,12 @@ static int standard_permission(struct inode *inode, int mask) return -EACCES; } -static int proc_permission(struct inode *inode, int mask) +static int proc_check_root(struct inode *inode) { struct dentry *de, *base, *root; struct vfsmount *our_vfsmnt, *vfsmnt, *mnt; int res = 0; - if (standard_permission(inode, mask) != 0) - return -EACCES; - if (proc_root_link(inode, &root, &vfsmnt)) /* Ewww... */ return -ENOENT; read_lock(¤t->fs->lock); @@ -250,6 +247,13 @@ out: goto exit; } +static int proc_permission(struct inode *inode, int mask) +{ + if (standard_permission(inode, mask) != 0) + return -EACCES; + return proc_check_root(inode); +} + static ssize_t pid_maps_read(struct file * file, char * buf, size_t count, loff_t *ppos) { @@ -403,12 +407,14 @@ static struct inode_operations proc_mem_inode_operations = { static int proc_pid_follow_link(struct dentry *dentry, struct nameidata *nd) { struct inode *inode = dentry->d_inode; - int error; + int error = -EACCES; /* We don't need a base pointer in the /proc filesystem */ path_release(nd); - error = proc_permission(inode, MAY_EXEC); + if (current->fsuid != inode->i_uid && !capable(CAP_DAC_OVERRIDE)) + goto out; + error = proc_check_root(inode); if (error) goto out; @@ -441,12 +447,14 @@ static int do_proc_readlink(struct dentry *dentry, struct vfsmount *mnt, static int proc_pid_readlink(struct dentry * dentry, char * buffer, int buflen) { - int error; + int error = -EACCES; struct inode *inode = dentry->d_inode; struct dentry *de; struct vfsmount *mnt = NULL; - error = proc_permission(inode, MAY_EXEC); + if (current->fsuid != inode->i_uid && !capable(CAP_DAC_OVERRIDE)) + goto out; + error = proc_check_root(inode); if (error) goto out; @@ -618,14 +626,12 @@ static struct inode *proc_pid_make_inode(struct super_block * sb, struct task_st /* We need a new inode */ - inode = get_empty_inode(); + inode = new_inode(sb); if (!inode) goto out; /* Common stuff */ - inode->i_sb = sb; - inode->i_dev = sb->s_dev; inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME; inode->i_ino = fake_ino(task->pid, ino); @@ -910,11 +916,9 @@ struct dentry *proc_pid_lookup(struct inode *dir, struct dentry * dentry) name = dentry->d_name.name; len = dentry->d_name.len; if (len == 4 && !memcmp(name, "self", 4)) { - inode = get_empty_inode(); + inode = new_inode(dir->i_sb); if (!inode) return ERR_PTR(-ENOMEM); - inode->i_sb = dir->i_sb; - inode->i_dev = dir->i_sb->s_dev; inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME; inode->i_ino = fake_ino(0, PROC_PID_INO); inode->u.proc_i.file = NULL; diff --git a/fs/proc/generic.c b/fs/proc/generic.c index 0dd6e6063..e58b04e02 100644 --- a/fs/proc/generic.c +++ b/fs/proc/generic.c @@ -215,7 +215,7 @@ static int proc_follow_link(struct dentry *dentry, struct nameidata *nd) static struct inode_operations proc_link_inode_operations = { readlink: proc_readlink, - follow_link: proc_follow_link + follow_link: proc_follow_link, }; /* @@ -396,8 +396,6 @@ static void proc_kill_inodes(struct proc_dir_entry *de) if (dentry->d_op != &proc_dentry_operations) continue; inode = dentry->d_inode; - if (!inode) - continue; if (inode->u.generic_ip != de) continue; fops_put(filp->f_op); @@ -573,12 +571,12 @@ void remove_proc_entry(const char *name, struct proc_dir_entry *parent) (void *) proc_alloc_map); proc_kill_inodes(de); de->nlink = 0; - de->deleted = 1; - if (!de->count) + if (!atomic_read(&de->count)) free_proc_entry(de); else { + de->deleted = 1; printk("remove_proc_entry: %s/%s busy, count=%d\n", - parent->name, de->name, de->count); + parent->name, de->name, atomic_read(&de->count)); } break; } diff --git a/fs/proc/inode.c b/fs/proc/inode.c index 7b571398a..3453bf88b 100644 --- a/fs/proc/inode.c +++ b/fs/proc/inode.c @@ -25,7 +25,7 @@ extern void free_proc_entry(struct proc_dir_entry *); struct proc_dir_entry * de_get(struct proc_dir_entry *de) { if (de) - de->count++; + atomic_inc(&de->count); return de; } @@ -34,20 +34,21 @@ struct proc_dir_entry * de_get(struct proc_dir_entry *de) */ void de_put(struct proc_dir_entry *de) { - if (de) { - lock_kernel(); /* FIXME: count should be atomic_t */ - if (!de->count) { + if (de) { + lock_kernel(); + if (!atomic_read(&de->count)) { printk("de_put: entry %s already free!\n", de->name); + unlock_kernel(); return; } - if (!--de->count) { + if (atomic_dec_and_test(&de->count)) { if (de->deleted) { printk("de_put: deferred delete of %s\n", de->name); free_proc_entry(de); } - } + } unlock_kernel(); } } @@ -139,7 +140,7 @@ struct inode * proc_get_inode(struct super_block * sb, int ino, #if 1 /* shouldn't ever happen */ if (de && de->deleted) -printk("proc_iget: using deleted entry %s, count=%d\n", de->name, de->count); +printk("proc_iget: using deleted entry %s, count=%d\n", de->name, atomic_read(&de->count)); #endif inode = iget(sb, ino); diff --git a/fs/proc/proc_misc.c b/fs/proc/proc_misc.c index 5e94c6aa5..d24f65b50 100644 --- a/fs/proc/proc_misc.c +++ b/fs/proc/proc_misc.c @@ -9,6 +9,10 @@ * there. I took this into a separate file and switched the thing to generic * proc_file_inode_operations, leaving in array.c only per-process stuff. * Inumbers allocation made dynamic (via create_proc_entry()). AV, May 1999. + * + * Changes: + * Fulton Green : Encapsulated position metric calculations. + * <kernel@FultonGreen.com> */ #include <linux/types.h> @@ -68,6 +72,17 @@ extern int get_swaparea_info (char *); extern int get_ds1286_status(char *); #endif +static int proc_calc_metrics(char *page, char **start, off_t off, + int count, int *eof, int len) +{ + if (len <= off+count) *eof = 1; + *start = page + off; + len -= off; + if (len>count) len = count; + if (len<0) len = 0; + return len; +} + static int loadavg_read_proc(char *page, char **start, off_t off, int count, int *eof, void *data) { @@ -82,12 +97,7 @@ static int loadavg_read_proc(char *page, char **start, off_t off, LOAD_INT(b), LOAD_FRAC(b), LOAD_INT(c), LOAD_FRAC(c), nr_running, nr_threads, last_pid); - if (len <= off+count) *eof = 1; - *start = page + off; - len -= off; - if (len>count) len = count; - if (len<0) len = 0; - return len; + return proc_calc_metrics(page, start, off, count, eof, len); } static int uptime_read_proc(char *page, char **start, off_t off, @@ -122,12 +132,7 @@ static int uptime_read_proc(char *page, char **start, off_t off, idle / HZ, idle % HZ); #endif - if (len <= off+count) *eof = 1; - *start = page + off; - len -= off; - if (len>count) len = count; - if (len<0) len = 0; - return len; + return proc_calc_metrics(page, start, off, count, eof, len); } static int meminfo_read_proc(char *page, char **start, off_t off, @@ -187,12 +192,7 @@ static int meminfo_read_proc(char *page, char **start, off_t off, K(i.totalswap), K(i.freeswap)); - if (len <= off+count) *eof = 1; - *start = page + off; - len -= off; - if (len>count) len = count; - if (len<0) len = 0; - return len; + return proc_calc_metrics(page, start, off, count, eof, len); #undef B #undef K } @@ -205,20 +205,14 @@ static int version_read_proc(char *page, char **start, off_t off, strcpy(page, linux_banner); len = strlen(page); - if (len <= off+count) *eof = 1; - *start = page + off; - len -= off; - if (len>count) len = count; - if (len<0) len = 0; - return len; + return proc_calc_metrics(page, start, off, count, eof, len); } static int cpuinfo_read_proc(char *page, char **start, off_t off, int count, int *eof, void *data) { int len = get_cpuinfo(page, start, off, count); - if (len < count) *eof = 1; - return len; + return proc_calc_metrics(page, start, off, count, eof, len); } #ifdef CONFIG_PROC_HARDWARE @@ -226,12 +220,7 @@ static int hardware_read_proc(char *page, char **start, off_t off, int count, int *eof, void *data) { int len = get_hardware_list(page); - if (len <= off+count) *eof = 1; - *start = page + off; - len -= off; - if (len>count) len = count; - if (len<0) len = 0; - return len; + return proc_calc_metrics(page, start, off, count, eof, len); } #endif @@ -240,12 +229,7 @@ static int stram_read_proc(char *page, char **start, off_t off, int count, int *eof, void *data) { int len = get_stram_list(page); - if (len <= off+count) *eof = 1; - *start = page + off; - len -= off; - if (len>count) len = count; - if (len<0) len = 0; - return len; + return proc_calc_metrics(page, start, off, count, eof, len); } #endif @@ -254,12 +238,7 @@ static int malloc_read_proc(char *page, char **start, off_t off, int count, int *eof, void *data) { int len = get_malloc(page); - if (len <= off+count) *eof = 1; - *start = page + off; - len -= off; - if (len>count) len = count; - if (len<0) len = 0; - return len; + return proc_calc_metrics(page, start, off, count, eof, len); } #endif @@ -268,12 +247,7 @@ static int modules_read_proc(char *page, char **start, off_t off, int count, int *eof, void *data) { int len = get_module_list(page); - if (len <= off+count) *eof = 1; - *start = page + off; - len -= off; - if (len>count) len = count; - if (len<0) len = 0; - return len; + return proc_calc_metrics(page, start, off, count, eof, len); } static int ksyms_read_proc(char *page, char **start, off_t off, @@ -356,24 +330,14 @@ static int kstat_read_proc(char *page, char **start, off_t off, xtime.tv_sec - jif / HZ, total_forks); - if (len <= off+count) *eof = 1; - *start = page + off; - len -= off; - if (len>count) len = count; - if (len<0) len = 0; - return len; + return proc_calc_metrics(page, start, off, count, eof, len); } static int devices_read_proc(char *page, char **start, off_t off, int count, int *eof, void *data) { int len = get_device_list(page); - if (len <= off+count) *eof = 1; - *start = page + off; - len -= off; - if (len>count) len = count; - if (len<0) len = 0; - return len; + return proc_calc_metrics(page, start, off, count, eof, len); } static int partitions_read_proc(char *page, char **start, off_t off, @@ -389,12 +353,7 @@ static int interrupts_read_proc(char *page, char **start, off_t off, int count, int *eof, void *data) { int len = get_irq_list(page); - if (len <= off+count) *eof = 1; - *start = page + off; - len -= off; - if (len>count) len = count; - if (len<0) len = 0; - return len; + return proc_calc_metrics(page, start, off, count, eof, len); } #endif @@ -402,36 +361,21 @@ static int filesystems_read_proc(char *page, char **start, off_t off, int count, int *eof, void *data) { int len = get_filesystem_list(page); - if (len <= off+count) *eof = 1; - *start = page + off; - len -= off; - if (len>count) len = count; - if (len<0) len = 0; - return len; + return proc_calc_metrics(page, start, off, count, eof, len); } static int dma_read_proc(char *page, char **start, off_t off, int count, int *eof, void *data) { int len = get_dma_list(page); - if (len <= off+count) *eof = 1; - *start = page + off; - len -= off; - if (len>count) len = count; - if (len<0) len = 0; - return len; + return proc_calc_metrics(page, start, off, count, eof, len); } static int ioports_read_proc(char *page, char **start, off_t off, int count, int *eof, void *data) { int len = get_ioport_list(page); - if (len <= off+count) *eof = 1; - *start = page + off; - len -= off; - if (len>count) len = count; - if (len<0) len = 0; - return len; + return proc_calc_metrics(page, start, off, count, eof, len); } static int cmdline_read_proc(char *page, char **start, off_t off, @@ -442,12 +386,7 @@ static int cmdline_read_proc(char *page, char **start, off_t off, len = sprintf(page, "%s\n", saved_command_line); len = strlen(page); - if (len <= off+count) *eof = 1; - *start = page + off; - len -= off; - if (len>count) len = count; - if (len<0) len = 0; - return len; + return proc_calc_metrics(page, start, off, count, eof, len); } #ifdef CONFIG_SGI_DS1286 @@ -455,12 +394,7 @@ static int ds1286_read_proc(char *page, char **start, off_t off, int count, int *eof, void *data) { int len = get_ds1286_status(page); - if (len <= off+count) *eof = 1; - *start = page + off; - len -= off; - if (len>count) len = count; - if (len<0) len = 0; - return len; + return proc_calc_metrics(page, start, off, count, eof, len); } #endif @@ -479,48 +413,28 @@ static int mounts_read_proc(char *page, char **start, off_t off, int count, int *eof, void *data) { int len = get_filesystem_info(page); - if (len <= off+count) *eof = 1; - *start = page + off; - len -= off; - if (len>count) len = count; - if (len<0) len = 0; - return len; + return proc_calc_metrics(page, start, off, count, eof, len); } static int execdomains_read_proc(char *page, char **start, off_t off, int count, int *eof, void *data) { int len = get_exec_domain_list(page); - if (len <= off+count) *eof = 1; - *start = page + off; - len -= off; - if (len>count) len = count; - if (len<0) len = 0; - return len; + return proc_calc_metrics(page, start, off, count, eof, len); } static int swaps_read_proc(char *page, char **start, off_t off, int count, int *eof, void *data) { int len = get_swaparea_info(page); - if (len <= off+count) *eof = 1; - *start = page + off; - len -= off; - if (len>count) len = count; - if (len<0) len = 0; - return len; + return proc_calc_metrics(page, start, off, count, eof, len); } static int memory_read_proc(char *page, char **start, off_t off, int count, int *eof, void *data) { int len = get_mem_list(page); - if (len <= off+count) *eof = 1; - *start = page + off; - len -= off; - if (len>count) len = count; - if (len<0) len = 0; - return len; + return proc_calc_metrics(page, start, off, count, eof, len); } /* @@ -631,9 +545,9 @@ void __init proc_misc_init(void) {"swaps", swaps_read_proc}, {"iomem", memory_read_proc}, {"execdomains", execdomains_read_proc}, - {NULL,NULL} + {NULL,} }; - for(p=simple_ones;p->name;p++) + for (p = simple_ones; p->name; p++) create_proc_read_entry(p->name, 0, NULL, p->read_proc, NULL); /* And now for trickier ones */ @@ -661,12 +575,8 @@ void __init proc_misc_init(void) entry->proc_fops = &ppc_htab_operations; } #endif - { - struct proc_dir_entry *res = create_proc_entry("slabinfo", - S_IWUSR | S_IRUGO, NULL); - if (res) { - res->read_proc = slabinfo_read_proc; - res->write_proc = slabinfo_write_proc; - } - } + entry = create_proc_read_entry("slabinfo", S_IWUSR | S_IRUGO, NULL, + slabinfo_read_proc, NULL); + if (entry) + entry->write_proc = slabinfo_write_proc; } diff --git a/fs/proc/root.c b/fs/proc/root.c index 075a5843d..cae861960 100644 --- a/fs/proc/root.c +++ b/fs/proc/root.c @@ -96,10 +96,12 @@ static struct inode_operations proc_root_inode_operations = { * This is the root "inode" in the /proc tree.. */ struct proc_dir_entry proc_root = { - PROC_ROOT_INO, 5, "/proc", - S_IFDIR | S_IRUGO | S_IXUGO, 2, 0, 0, - 0, &proc_root_inode_operations, &proc_root_operations, - NULL, NULL, - NULL, - &proc_root, NULL + low_ino: PROC_ROOT_INO, + namelen: 5, + name: "/proc", + mode: S_IFDIR | S_IRUGO | S_IXUGO, + nlink: 2, + proc_iops: &proc_root_inode_operations, + proc_fops: &proc_root_operations, + parent: &proc_root, }; diff --git a/fs/ramfs/inode.c b/fs/ramfs/inode.c index f13ba4f3d..31461669c 100644 --- a/fs/ramfs/inode.c +++ b/fs/ramfs/inode.c @@ -65,7 +65,8 @@ static struct dentry * ramfs_lookup(struct inode *dir, struct dentry *dentry) static int ramfs_readpage(struct file *file, struct page * page) { if (!Page_Uptodate(page)) { - memset(page_address(page), 0, PAGE_CACHE_SIZE); + memset(kmap(page), 0, PAGE_CACHE_SIZE); + kunmap(page); flush_dcache_page(page); SetPageUptodate(page); } @@ -85,9 +86,7 @@ static int ramfs_writepage(struct file *file, struct page *page) static int ramfs_prepare_write(struct file *file, struct page *page, unsigned offset, unsigned to) { - void *addr; - - addr = (void *) kmap(page); + void *addr = kmap(page); if (!Page_Uptodate(page)) { memset(addr, 0, PAGE_CACHE_SIZE); flush_dcache_page(page); @@ -110,21 +109,15 @@ static int ramfs_commit_write(struct file *file, struct page *page, unsigned off struct inode *ramfs_get_inode(struct super_block *sb, int mode, int dev) { - struct inode * inode = get_empty_inode(); + struct inode * inode = new_inode(sb); if (inode) { - inode->i_sb = sb; - inode->i_dev = sb->s_dev; inode->i_mode = mode; inode->i_uid = current->fsuid; inode->i_gid = current->fsgid; - inode->i_size = 0; inode->i_blksize = PAGE_CACHE_SIZE; inode->i_blocks = 0; inode->i_rdev = to_kdev_t(dev); - inode->i_nlink = 1; - inode->i_op = NULL; - inode->i_fop = NULL; inode->i_mapping->a_ops = &ramfs_aops; inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME; switch (mode & S_IFMT) { diff --git a/fs/select.c b/fs/select.c index a49213ecb..975013e7f 100644 --- a/fs/select.c +++ b/fs/select.c @@ -382,13 +382,14 @@ static void do_pollfd(unsigned int num, struct pollfd * fdpage, static int do_poll(unsigned int nfds, unsigned int nchunks, unsigned int nleft, struct pollfd *fds[], poll_table *wait, long timeout) { - int count = 0; + int count; poll_table* pt = wait; for (;;) { unsigned int i; set_current_state(TASK_INTERRUPTIBLE); + count = 0; for (i=0; i < nchunks; i++) do_pollfd(POLLFD_PER_PAGE, fds[i], &pt, &count); if (nleft) @@ -396,9 +397,9 @@ static int do_poll(unsigned int nfds, unsigned int nchunks, unsigned int nleft, pt = NULL; if (count || !timeout || signal_pending(current)) break; - if(wait->error) { - return wait->error; - } + count = wait->error; + if (count) + break; timeout = schedule_timeout(timeout); } current->state = TASK_RUNNING; diff --git a/fs/smbfs/cache.c b/fs/smbfs/cache.c index 0b42c2387..aa85680ac 100644 --- a/fs/smbfs/cache.c +++ b/fs/smbfs/cache.c @@ -47,11 +47,11 @@ smb_get_dircache(struct dentry * dentry) page = grab_cache_page(mapping, 0); if (!page) goto out; - cachep = (struct cache_head *)kmap(page); + cachep = kmap(page); memset((char*)cachep, 0, PAGE_SIZE); goto out; } - cachep = (struct cache_head *)kmap(page); + cachep = kmap(page); if (cachep->valid) { /* * OK, at least the page 0 survived and seems to be promising. @@ -69,7 +69,7 @@ smb_get_dircache(struct dentry * dentry) cachep->valid = 0; goto out; } - index->block = (struct cache_block *) kmap(page); + index->block = kmap(page); } } out: @@ -188,7 +188,7 @@ get_block: page_off = PAGE_SIZE + (cachep->idx << PAGE_SHIFT); page = grab_cache_page(mapping, page_off>>PAGE_CACHE_SHIFT); if (page) { - block = (struct cache_block *)kmap(page); + block = kmap(page); index->block = block; index->space = PAGE_SIZE; goto add_entry; diff --git a/fs/smbfs/inode.c b/fs/smbfs/inode.c index 0406f72cb..bcc900626 100644 --- a/fs/smbfs/inode.c +++ b/fs/smbfs/inode.c @@ -78,11 +78,9 @@ smb_iget(struct super_block *sb, struct smb_fattr *fattr) DEBUG1("smb_iget: %p\n", fattr); - result = get_empty_inode(); + result = new_inode(sb); if (!result) return result; - result->i_sb = sb; - result->i_dev = sb->s_dev; result->i_ino = fattr->f_ino; memset(&(result->u.smbfs_i), 0, sizeof(result->u.smbfs_i)); smb_set_inode_attr(result, fattr); diff --git a/fs/sysv/ialloc.c b/fs/sysv/ialloc.c index 8469366cf..7709ade8d 100644 --- a/fs/sysv/ialloc.c +++ b/fs/sysv/ialloc.c @@ -91,10 +91,12 @@ struct inode * sysv_new_inode(const struct inode * dir) struct sysv_inode * raw_inode; int i,j,ino,block; - if (!dir || !(inode = get_empty_inode())) + if (!dir) return NULL; sb = dir->i_sb; - inode->i_sb = sb; + inode = new_inode(sb); + if (!inode) + return NULL; lock_super(sb); /* protect against task switches */ if ((*sb->sv_sb_fic_count == 0) || (*sv_sb_fic_inode(sb,(*sb->sv_sb_fic_count)-1) == 0) /* Applies only to SystemV2 FS */ @@ -131,7 +133,6 @@ struct inode * sysv_new_inode(const struct inode * dir) mark_buffer_dirty(sb->sv_bh1); /* super-block has been modified */ if (sb->sv_bh1 != sb->sv_bh2) mark_buffer_dirty(sb->sv_bh2); sb->s_dirt = 1; /* and needs time stamp */ - inode->i_dev = sb->s_dev; inode->i_uid = current->fsuid; inode->i_gid = (dir->i_mode & S_ISGID) ? dir->i_gid : current->fsgid; inode->i_ino = ino; @@ -141,7 +142,6 @@ struct inode * sysv_new_inode(const struct inode * dir) mark_inode_dirty(inode); /* Change directory entry: */ inode->i_mode = 0; /* for sysv_write_inode() */ - inode->i_size = 0; /* ditto */ sysv_write_inode(inode, 0); /* ensure inode not allocated again */ /* FIXME: caller may call this too. */ mark_inode_dirty(inode); /* cleared by sysv_write_inode() */ diff --git a/fs/udf/dir.c b/fs/udf/dir.c index 9f093c536..9ec279e47 100644 --- a/fs/udf/dir.c +++ b/fs/udf/dir.c @@ -86,12 +86,6 @@ int udf_readdir(struct file *filp, void *dirent, filldir_t filldir) struct inode *dir = filp->f_dentry->d_inode; int result; - if (!dir) - return -EBADF; - - if (!S_ISDIR(dir->i_mode)) - return -ENOTDIR; - if ( filp->f_pos == 0 ) { if (filldir(dirent, ".", 1, filp->f_pos, dir->i_ino, DT_DIR)) diff --git a/fs/udf/file.c b/fs/udf/file.c index 9ba4a6641..7e8ac9b7d 100644 --- a/fs/udf/file.c +++ b/fs/udf/file.c @@ -54,7 +54,7 @@ static int udf_adinicb_readpage(struct file *file, struct page * page) if (!PageLocked(page)) PAGE_BUG(page); - kaddr = (char *)kmap(page); + kaddr = kmap(page); memset(kaddr, 0, PAGE_CACHE_SIZE); block = udf_get_lb_pblock(inode->i_sb, UDF_I_LOCATION(inode), 0); bh = bread (inode->i_dev, block, inode->i_sb->s_blocksize); @@ -78,7 +78,7 @@ static int udf_adinicb_writepage(struct file *file, struct page *page) if (!PageLocked(page)) PAGE_BUG(page); - kaddr = (char *)kmap(page); + kaddr = kmap(page); block = udf_get_lb_pblock(inode->i_sb, UDF_I_LOCATION(inode), 0); bh = bread (inode->i_dev, block, inode->i_sb->s_blocksize); memcpy(bh->b_data + udf_ext0_offset(inode), kaddr, inode->i_size); diff --git a/fs/udf/ialloc.c b/fs/udf/ialloc.c index 5377773ce..5a2e7a1dc 100644 --- a/fs/udf/ialloc.c +++ b/fs/udf/ialloc.c @@ -77,15 +77,13 @@ struct inode * udf_new_inode (const struct inode *dir, int mode, int * err) int block; Uint32 start = UDF_I_LOCATION(dir).logicalBlockNum; - inode = get_empty_inode(); + sb = dir->i_sb; + inode = new_inode(sb); if (!inode) { *err = -ENOMEM; return NULL; } - sb = dir->i_sb; - inode->i_sb = sb; - inode->i_flags = 0; *err = -ENOSPC; block = udf_new_block(dir, UDF_I_LOCATION(dir).partitionReferenceNum, @@ -115,9 +113,6 @@ struct inode * udf_new_inode (const struct inode *dir, int mode, int * err) mark_buffer_dirty(UDF_SB_LVIDBH(sb)); } inode->i_mode = mode; - inode->i_sb = sb; - inode->i_nlink = 1; - inode->i_dev = sb->s_dev; inode->i_uid = current->fsuid; if (dir->i_mode & S_ISGID) { inode->i_gid = dir->i_gid; @@ -132,7 +127,6 @@ struct inode * udf_new_inode (const struct inode *dir, int mode, int * err) inode->i_ino = udf_get_lb_pblock(sb, UDF_I_LOCATION(inode), 0); inode->i_blksize = PAGE_SIZE; inode->i_blocks = 0; - inode->i_size = 0; UDF_I_LENEATTR(inode) = 0; UDF_I_LENALLOC(inode) = 0; if (UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_USE_EXTENDED_FE)) diff --git a/fs/udf/inode.c b/fs/udf/inode.c index 4219c505f..83a34f258 100644 --- a/fs/udf/inode.c +++ b/fs/udf/inode.c @@ -158,7 +158,6 @@ void udf_expand_file_adinicb(struct inode * inode, int newsize, int * err) { struct buffer_head *bh = NULL; struct page *page; - unsigned long kaddr = 0; int block; /* from now on we have normal address_space methods */ @@ -183,10 +182,10 @@ void udf_expand_file_adinicb(struct inode * inode, int newsize, int * err) PAGE_BUG(page); if (!Page_Uptodate(page)) { - kaddr = kmap(page); - memset((char *)kaddr + UDF_I_LENALLOC(inode), 0x00, + char *kaddr = kmap(page); + memset(kaddr + UDF_I_LENALLOC(inode), 0x00, PAGE_CACHE_SIZE - UDF_I_LENALLOC(inode)); - memcpy((char *)kaddr, bh->b_data + udf_file_entry_alloc_offset(inode), + memcpy(kaddr, bh->b_data + udf_file_entry_alloc_offset(inode), UDF_I_LENALLOC(inode)); flush_dcache_page(page); SetPageUptodate(page); diff --git a/fs/udf/symlink.c b/fs/udf/symlink.c index 8a0dde5e4..547fc784b 100644 --- a/fs/udf/symlink.c +++ b/fs/udf/symlink.c @@ -83,7 +83,7 @@ static int udf_symlink_filler(struct file *file, struct page *page) struct buffer_head *bh = NULL; char *symlink; int err = -EIO; - char *p = (char *)kmap(page); + char *p = kmap(page); lock_kernel(); if (UDF_I_ALLOCTYPE(inode) == ICB_FLAG_AD_IN_ICB) diff --git a/fs/ufs/ialloc.c b/fs/ufs/ialloc.c index 1a97daf7c..d7fef19cd 100644 --- a/fs/ufs/ialloc.c +++ b/fs/ufs/ialloc.c @@ -161,19 +161,16 @@ struct inode * ufs_new_inode (const struct inode * dir, int mode, int * err ) *err = -EPERM; return NULL; } - inode = get_empty_inode (); + sb = dir->i_sb; + inode = new_inode(sb); if (!inode) { *err = -ENOMEM; return NULL; } - sb = dir->i_sb; swab = sb->u.ufs_sb.s_swab; uspi = sb->u.ufs_sb.s_uspi; usb1 = ubh_get_usb_first(USPI_UBH); - inode->i_sb = sb; - inode->i_flags = 0; - lock_super (sb); *err = -ENOSPC; @@ -261,9 +258,6 @@ cg_found: sb->s_dirt = 1; inode->i_mode = mode; - inode->i_sb = sb; - inode->i_nlink = 1; - inode->i_dev = sb->s_dev; inode->i_uid = current->fsuid; if (dir->i_mode & S_ISGID) { inode->i_gid = dir->i_gid; diff --git a/fs/umsdos/dir.c b/fs/umsdos/dir.c index 63ee81b16..2e0b7bb14 100644 --- a/fs/umsdos/dir.c +++ b/fs/umsdos/dir.c @@ -700,7 +700,7 @@ struct dentry *umsdos_solve_hlink (struct dentry *hlink) path = (char *) kmalloc (PATH_MAX, GFP_KERNEL); if (path == NULL) goto out_release; - memcpy(path, (char*)kmap(page), hlink->d_inode->i_size); + memcpy(path, kmap(page), hlink->d_inode->i_size); kunmap(page); page_cache_release(page); diff --git a/fs/umsdos/emd.c b/fs/umsdos/emd.c index 551c9662f..93c6af317 100644 --- a/fs/umsdos/emd.c +++ b/fs/umsdos/emd.c @@ -129,7 +129,7 @@ int umsdos_emd_dir_readentry (struct dentry *demd, loff_t *pos, struct umsdos_di wait_on_page(page); if (!Page_Uptodate(page)) goto async_fail; - p = (struct umsdos_dirent*)((char*)kmap(page)+offs); + p = (struct umsdos_dirent*)(kmap(page)+offs); /* if this is an invalid entry (invalid name length), ignore it */ if( p->name_len > UMSDOS_MAXNAME ) @@ -158,7 +158,7 @@ int umsdos_emd_dir_readentry (struct dentry *demd, loff_t *pos, struct umsdos_di goto async_fail; } memcpy(entry->spare,p->spare,part); - memcpy(entry->spare+part,(char*)kmap(page2), + memcpy(entry->spare+part,kmap(page2), recsize+offs-PAGE_CACHE_SIZE); kunmap(page2); page_cache_release(page2); @@ -399,7 +399,7 @@ static int umsdos_find (struct dentry *demd, struct umsdos_info *info) wait_on_page(page); if (!Page_Uptodate(page)) goto async_fail; - p = (char*)kmap(page); + p = kmap(page); } rentry = (struct umsdos_dirent *)(p+offs); @@ -451,7 +451,7 @@ static int umsdos_find (struct dentry *demd, struct umsdos_info *info) page = next_page; goto async_fail; } - q = (char*)kmap(next_page); + q = kmap(next_page); if (memcmp(entry->name, rentry->name, len) || memcmp(entry->name+len, q, entry->name_len-len)) { kunmap(next_page); |