diff -u --recursive --new-file linux-2.5.33-vfs3/fs/coda/dir.c linux-2.5.33-vfs4/fs/coda/dir.c --- linux-2.5.33-vfs3/fs/coda/dir.c Sun Sep 8 23:01:12 2002 +++ linux-2.5.33-vfs4/fs/coda/dir.c Tue Sep 10 20:01:30 2002 @@ -28,15 +28,15 @@ #include /* dir inode-ops */ -static int coda_create(struct inode *dir, struct dentry *new, int mode); -static int coda_mknod(struct inode *dir, struct dentry *new, int mode, int rdev); +static int coda_create(struct inode *dir, struct dentry *new, struct vfs_cred *vfscred, int mode); +static int coda_mknod(struct inode *dir, struct dentry *new, struct vfs_cred *vfscred, int mode, int rdev); static struct dentry *coda_lookup(struct inode *dir, struct dentry *target); static int coda_link(struct dentry *old_dentry, struct inode *dir_inode, struct dentry *entry); static int coda_unlink(struct inode *dir_inode, struct dentry *entry); -static int coda_symlink(struct inode *dir_inode, struct dentry *entry, +static int coda_symlink(struct inode *dir_inode, struct dentry *entry, struct vfs_cred *vfscred, const char *symname); -static int coda_mkdir(struct inode *dir_inode, struct dentry *entry, int mode); +static int coda_mkdir(struct inode *dir_inode, struct dentry *entry, struct vfs_cred *vfscred, int mode); static int coda_rmdir(struct inode *dir_inode, struct dentry *entry); static int coda_rename(struct inode *old_inode, struct dentry *old_dentry, struct inode *new_inode, struct dentry *new_dentry); @@ -188,7 +188,7 @@ } /* creation routines: create, mknod, mkdir, link, symlink */ -static int coda_create(struct inode *dir, struct dentry *de, int mode) +static int coda_create(struct inode *dir, struct dentry *de, struct vfs_cred *vfscred, int mode) { int error=0; const char *name=de->d_name.name; @@ -228,7 +228,7 @@ return 0; } -static int coda_mknod(struct inode *dir, struct dentry *de, int mode, int rdev) +static int coda_mknod(struct inode *dir, struct dentry *de, struct vfs_cred *vfscred, int mode, int rdev) { int error=0; const char *name=de->d_name.name; @@ -271,7 +271,7 @@ return 0; } -static int coda_mkdir(struct inode *dir, struct dentry *de, int mode) +static int coda_mkdir(struct inode *dir, struct dentry *de, struct vfs_cred *vfscred, int mode) { struct inode *inode; struct coda_vattr attrs; @@ -348,7 +348,7 @@ } -static int coda_symlink(struct inode *dir_inode, struct dentry *de, +static int coda_symlink(struct inode *dir_inode, struct dentry *de, struct vfs_cred *vfscred, const char *symname) { const char *name = de->d_name.name; diff -u --recursive --new-file linux-2.5.33-vfs3/fs/devfs/base.c linux-2.5.33-vfs4/fs/devfs/base.c --- linux-2.5.33-vfs3/fs/devfs/base.c Wed Aug 21 06:11:12 2002 +++ linux-2.5.33-vfs4/fs/devfs/base.c Tue Sep 10 20:10:38 2002 @@ -3016,7 +3016,7 @@ } /* End Function devfs_unlink */ static int devfs_symlink (struct inode *dir, struct dentry *dentry, - const char *symname) + struct vfs_cred *vfscred, const char *symname) { int err; struct fs_info *fs_info = dir->i_sb->u.generic_sbp; @@ -3048,7 +3048,7 @@ return 0; } /* End Function devfs_symlink */ -static int devfs_mkdir (struct inode *dir, struct dentry *dentry, int mode) +static int devfs_mkdir (struct inode *dir, struct dentry *dentry, struct vfs_cred *vfscred, int mode) { int err; struct fs_info *fs_info = dir->i_sb->u.generic_sbp; @@ -3110,7 +3110,7 @@ return 0; } /* End Function devfs_rmdir */ -static int devfs_mknod (struct inode *dir, struct dentry *dentry, int mode, +static int devfs_mknod (struct inode *dir, struct dentry *dentry, struct vfs_cred *vfscred, int mode, int rdev) { int err; diff -u --recursive --new-file linux-2.5.33-vfs3/fs/ext2/ialloc.c linux-2.5.33-vfs4/fs/ext2/ialloc.c --- linux-2.5.33-vfs3/fs/ext2/ialloc.c Sun Sep 8 20:05:44 2002 +++ linux-2.5.33-vfs4/fs/ext2/ialloc.c Tue Sep 10 19:44:26 2002 @@ -281,7 +281,7 @@ return group; } -struct inode * ext2_new_inode(struct inode * dir, int mode) +struct inode * ext2_new_inode(struct inode * dir, struct vfs_cred *vfscred, int mode) { struct super_block *sb; struct buffer_head *bitmap_bh = NULL; @@ -344,7 +344,7 @@ cpu_to_le32(le32_to_cpu(es->s_free_inodes_count) - 1); mark_buffer_dirty(EXT2_SB(sb)->s_sbh); sb->s_dirt = 1; - inode->i_uid = current->vfscred->uid; + inode->i_uid = vfscred->uid; if (test_opt (sb, GRPID)) inode->i_gid = dir->i_gid; else if (dir->i_mode & S_ISGID) { @@ -352,7 +352,7 @@ if (S_ISDIR(mode)) mode |= S_ISGID; } else - inode->i_gid = current->vfscred->gid; + inode->i_gid = vfscred->gid; inode->i_mode = mode; inode->i_ino = ino; diff -u --recursive --new-file linux-2.5.33-vfs3/fs/ext2/ialloc.c.orig linux-2.5.33-vfs4/fs/ext2/ialloc.c.orig --- linux-2.5.33-vfs3/fs/ext2/ialloc.c.orig Thu Jan 1 01:00:00 1970 +++ linux-2.5.33-vfs4/fs/ext2/ialloc.c.orig Sun Sep 8 20:05:44 2002 @@ -0,0 +1,512 @@ +/* + * linux/fs/ext2/ialloc.c + * + * Copyright (C) 1992, 1993, 1994, 1995 + * Remy Card (card@masi.ibp.fr) + * Laboratoire MASI - Institut Blaise Pascal + * Universite Pierre et Marie Curie (Paris VI) + * + * BSD ufs-inspired inode and directory allocation by + * Stephen Tweedie (sct@dcs.ed.ac.uk), 1993 + * Big-endian to little-endian byte-swapping/bitmaps by + * David S. Miller (davem@caip.rutgers.edu), 1995 + */ + +#include +#include "ext2.h" +#include +#include +#include + + +/* + * ialloc.c contains the inodes allocation and deallocation routines + */ + +/* + * The free inodes are managed by bitmaps. A file system contains several + * blocks groups. Each group contains 1 bitmap block for blocks, 1 bitmap + * block for inodes, N blocks for the inode table and data blocks. + * + * The file system contains group descriptors which are located after the + * super block. Each descriptor contains the number of the bitmap block and + * the free blocks count in the block. + */ + + +/* + * Read the inode allocation bitmap for a given block_group, reading + * into the specified slot in the superblock's bitmap cache. + * + * Return buffer_head of bitmap on success or NULL. + */ +static struct buffer_head * +read_inode_bitmap(struct super_block * sb, unsigned long block_group) +{ + struct ext2_group_desc *desc; + struct buffer_head *bh = NULL; + + desc = ext2_get_group_desc(sb, block_group, NULL); + if (!desc) + goto error_out; + + bh = sb_bread(sb, le32_to_cpu(desc->bg_inode_bitmap)); + if (!bh) + ext2_error(sb, "read_inode_bitmap", + "Cannot read inode bitmap - " + "block_group = %lu, inode_bitmap = %lu", + block_group, (unsigned long) desc->bg_inode_bitmap); +error_out: + return bh; +} + +/* + * NOTE! When we get the inode, we're the only people + * that have access to it, and as such there are no + * race conditions we have to worry about. The inode + * is not on the hash-lists, and it cannot be reached + * through the filesystem because the directory entry + * has been deleted earlier. + * + * HOWEVER: we must make sure that we get no aliases, + * which means that we have to call "clear_inode()" + * _before_ we mark the inode not in use in the inode + * bitmaps. Otherwise a newly created file might use + * the same inode number (not actually the same pointer + * though), and then we'd have two inodes sharing the + * same inode number and space on the harddisk. + */ +void ext2_free_inode (struct inode * inode) +{ + struct super_block * sb = inode->i_sb; + int is_directory; + unsigned long ino; + struct buffer_head *bitmap_bh = NULL; + struct buffer_head *bh2; + unsigned long block_group; + unsigned long bit; + struct ext2_group_desc * desc; + struct ext2_super_block * es; + + ino = inode->i_ino; + ext2_debug ("freeing inode %lu\n", ino); + + /* + * Note: we must free any quota before locking the superblock, + * as writing the quota to disk may need the lock as well. + */ + if (!is_bad_inode(inode)) { + /* Quota is already initialized in iput() */ + DQUOT_FREE_INODE(inode); + DQUOT_DROP(inode); + } + + lock_super (sb); + es = EXT2_SB(sb)->s_es; + is_directory = S_ISDIR(inode->i_mode); + + /* Do this BEFORE marking the inode not in use or returning an error */ + clear_inode (inode); + + if (ino < EXT2_FIRST_INO(sb) || + ino > le32_to_cpu(es->s_inodes_count)) { + ext2_error (sb, "ext2_free_inode", + "reserved or nonexistent inode %lu", ino); + goto error_return; + } + block_group = (ino - 1) / EXT2_INODES_PER_GROUP(sb); + bit = (ino - 1) % EXT2_INODES_PER_GROUP(sb); + brelse(bitmap_bh); + bitmap_bh = read_inode_bitmap(sb, block_group); + if (!bitmap_bh) + goto error_return; + + /* Ok, now we can actually update the inode bitmaps.. */ + if (!ext2_clear_bit(bit, bitmap_bh->b_data)) + ext2_error (sb, "ext2_free_inode", + "bit already cleared for inode %lu", ino); + else { + desc = ext2_get_group_desc (sb, block_group, &bh2); + if (desc) { + desc->bg_free_inodes_count = + cpu_to_le16(le16_to_cpu(desc->bg_free_inodes_count) + 1); + if (is_directory) + desc->bg_used_dirs_count = + cpu_to_le16(le16_to_cpu(desc->bg_used_dirs_count) - 1); + } + mark_buffer_dirty(bh2); + es->s_free_inodes_count = + cpu_to_le32(le32_to_cpu(es->s_free_inodes_count) + 1); + mark_buffer_dirty(EXT2_SB(sb)->s_sbh); + } + mark_buffer_dirty(bitmap_bh); + if (sb->s_flags & MS_SYNCHRONOUS) { + ll_rw_block(WRITE, 1, &bitmap_bh); + wait_on_buffer(bitmap_bh); + } + sb->s_dirt = 1; +error_return: + brelse(bitmap_bh); + unlock_super (sb); +} + +/* + * We perform asynchronous prereading of the new inode's inode block when + * we create the inode, in the expectation that the inode will be written + * back soon. There are two reasons: + * + * - When creating a large number of files, the async prereads will be + * nicely merged into large reads + * - When writing out a large number of inodes, we don't need to keep on + * stalling the writes while we read the inode block. + * + * FIXME: ext2_get_group_desc() needs to be simplified. + */ +static void ext2_preread_inode(struct inode *inode) +{ + unsigned long block_group; + unsigned long offset; + unsigned long block; + struct buffer_head *bh; + struct ext2_group_desc * gdp; + + block_group = (inode->i_ino - 1) / EXT2_INODES_PER_GROUP(inode->i_sb); + gdp = ext2_get_group_desc(inode->i_sb, block_group, &bh); + if (gdp == NULL) + return; + + /* + * Figure out the offset within the block group inode table + */ + offset = ((inode->i_ino - 1) % EXT2_INODES_PER_GROUP(inode->i_sb)) * + EXT2_INODE_SIZE(inode->i_sb); + block = le32_to_cpu(gdp->bg_inode_table) + + (offset >> EXT2_BLOCK_SIZE_BITS(inode->i_sb)); + bh = sb_getblk(inode->i_sb, block); + if (!buffer_uptodate(bh) && !buffer_locked(bh)) + ll_rw_block(READA, 1, &bh); + __brelse(bh); +} + +/* + * There are two policies for allocating an inode. If the new inode is + * a directory, then a forward search is made for a block group with both + * free space and a low directory-to-inode ratio; if that fails, then of + * the groups with above-average free space, that group with the fewest + * directories already is chosen. + * + * For other inodes, search forward from the parent directory\'s block + * group to find a free inode. + */ + +static int find_group_dir(struct super_block *sb, int parent_group) +{ + struct ext2_super_block * es = EXT2_SB(sb)->s_es; + int ngroups = EXT2_SB(sb)->s_groups_count; + int avefreei = le32_to_cpu(es->s_free_inodes_count) / ngroups; + struct ext2_group_desc *desc, *best_desc = NULL; + struct buffer_head *bh, *best_bh = NULL; + int group, best_group = -1; + + for (group = 0; group < ngroups; group++) { + desc = ext2_get_group_desc (sb, group, &bh); + if (!desc || !desc->bg_free_inodes_count) + continue; + if (le16_to_cpu(desc->bg_free_inodes_count) < avefreei) + continue; + if (!best_desc || + (le16_to_cpu(desc->bg_free_blocks_count) > + le16_to_cpu(best_desc->bg_free_blocks_count))) { + best_group = group; + best_desc = desc; + best_bh = bh; + } + } + if (!best_desc) + return -1; + best_desc->bg_free_inodes_count = + cpu_to_le16(le16_to_cpu(best_desc->bg_free_inodes_count) - 1); + best_desc->bg_used_dirs_count = + cpu_to_le16(le16_to_cpu(best_desc->bg_used_dirs_count) + 1); + mark_buffer_dirty(best_bh); + return best_group; +} + +static int find_group_other(struct super_block *sb, int parent_group) +{ + int ngroups = EXT2_SB(sb)->s_groups_count; + struct ext2_group_desc *desc; + struct buffer_head *bh; + int group, i; + + /* + * Try to place the inode in its parent directory + */ + group = parent_group; + desc = ext2_get_group_desc (sb, group, &bh); + if (desc && le16_to_cpu(desc->bg_free_inodes_count)) + goto found; + + /* + * Use a quadratic hash to find a group with a + * free inode + */ + for (i = 1; i < ngroups; i <<= 1) { + group += i; + if (group >= ngroups) + group -= ngroups; + desc = ext2_get_group_desc (sb, group, &bh); + if (desc && le16_to_cpu(desc->bg_free_inodes_count)) + goto found; + } + + /* + * That failed: try linear search for a free inode + */ + group = parent_group + 1; + for (i = 2; i < ngroups; i++) { + if (++group >= ngroups) + group = 0; + desc = ext2_get_group_desc (sb, group, &bh); + if (desc && le16_to_cpu(desc->bg_free_inodes_count)) + goto found; + } + + return -1; + +found: + desc->bg_free_inodes_count = + cpu_to_le16(le16_to_cpu(desc->bg_free_inodes_count) - 1); + mark_buffer_dirty(bh); + return group; +} + +struct inode * ext2_new_inode(struct inode * dir, int mode) +{ + struct super_block *sb; + struct buffer_head *bitmap_bh = NULL; + struct buffer_head *bh2; + int group, i; + ino_t ino; + struct inode * inode; + struct ext2_group_desc * desc; + struct ext2_super_block * es; + struct ext2_inode_info *ei; + int err; + struct inode *ret; + + sb = dir->i_sb; + inode = new_inode(sb); + if (!inode) + return ERR_PTR(-ENOMEM); + + ei = EXT2_I(inode); + lock_super (sb); + es = EXT2_SB(sb)->s_es; +repeat: + if (S_ISDIR(mode)) + group = find_group_dir(sb, EXT2_I(dir)->i_block_group); + else + group = find_group_other(sb, EXT2_I(dir)->i_block_group); + + err = -ENOSPC; + if (group == -1) + goto fail; + + err = -EIO; + brelse(bitmap_bh); + bitmap_bh = read_inode_bitmap(sb, group); + if (!bitmap_bh) + goto fail2; + + i = ext2_find_first_zero_bit((unsigned long *)bitmap_bh->b_data, + EXT2_INODES_PER_GROUP(sb)); + if (i >= EXT2_INODES_PER_GROUP(sb)) + goto bad_count; + ext2_set_bit(i, bitmap_bh->b_data); + + mark_buffer_dirty(bitmap_bh); + if (sb->s_flags & MS_SYNCHRONOUS) { + ll_rw_block(WRITE, 1, &bitmap_bh); + wait_on_buffer(bitmap_bh); + } + + ino = group * EXT2_INODES_PER_GROUP(sb) + i + 1; + if (ino < EXT2_FIRST_INO(sb) || ino > le32_to_cpu(es->s_inodes_count)) { + ext2_error (sb, "ext2_new_inode", + "reserved inode or inode > inodes count - " + "block_group = %d,inode=%ld", group, ino); + err = -EIO; + goto fail2; + } + + es->s_free_inodes_count = + cpu_to_le32(le32_to_cpu(es->s_free_inodes_count) - 1); + mark_buffer_dirty(EXT2_SB(sb)->s_sbh); + sb->s_dirt = 1; + inode->i_uid = current->vfscred->uid; + if (test_opt (sb, GRPID)) + inode->i_gid = dir->i_gid; + else if (dir->i_mode & S_ISGID) { + inode->i_gid = dir->i_gid; + if (S_ISDIR(mode)) + mode |= S_ISGID; + } else + inode->i_gid = current->vfscred->gid; + inode->i_mode = mode; + + inode->i_ino = ino; + inode->i_blksize = PAGE_SIZE; /* This is the optimal IO size (for stat), not the fs block size */ + inode->i_blocks = 0; + inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME; + memset(ei->i_data, 0, sizeof(ei->i_data)); + ei->i_flags = EXT2_I(dir)->i_flags; + if (S_ISLNK(mode)) + ei->i_flags &= ~(EXT2_IMMUTABLE_FL|EXT2_APPEND_FL); + /* dirsync is only applied to directories */ + if (!S_ISDIR(mode)) + ei->i_flags &= ~EXT2_DIRSYNC_FL; + ei->i_faddr = 0; + ei->i_frag_no = 0; + ei->i_frag_size = 0; + ei->i_file_acl = 0; + ei->i_dir_acl = 0; + ei->i_dtime = 0; + ei->i_block_group = group; + ei->i_next_alloc_block = 0; + ei->i_next_alloc_goal = 0; + ei->i_prealloc_block = 0; + ei->i_prealloc_count = 0; + ei->i_dir_start_lookup = 0; + if (ei->i_flags & EXT2_SYNC_FL) + inode->i_flags |= S_SYNC; + if (ei->i_flags & EXT2_DIRSYNC_FL) + inode->i_flags |= S_DIRSYNC; + inode->i_generation = EXT2_SB(sb)->s_next_generation++; + insert_inode_hash(inode); + mark_inode_dirty(inode); + + unlock_super(sb); + ret = inode; + if(DQUOT_ALLOC_INODE(inode)) { + DQUOT_DROP(inode); + inode->i_flags |= S_NOQUOTA; + inode->i_nlink = 0; + iput(inode); + ret = ERR_PTR(-EDQUOT); + } else { + ext2_debug("allocating inode %lu\n", inode->i_ino); + ext2_preread_inode(inode); + } + goto out; + +fail2: + desc = ext2_get_group_desc (sb, group, &bh2); + desc->bg_free_inodes_count = + cpu_to_le16(le16_to_cpu(desc->bg_free_inodes_count) + 1); + if (S_ISDIR(mode)) + desc->bg_used_dirs_count = + cpu_to_le16(le16_to_cpu(desc->bg_used_dirs_count) - 1); + mark_buffer_dirty(bh2); +fail: + unlock_super(sb); + make_bad_inode(inode); + iput(inode); + ret = ERR_PTR(err); + goto out; + +bad_count: + ext2_error (sb, "ext2_new_inode", + "Free inodes count corrupted in group %d", + group); + /* Is it really ENOSPC? */ + err = -ENOSPC; + if (sb->s_flags & MS_RDONLY) + goto fail; + + desc = ext2_get_group_desc (sb, group, &bh2); + desc->bg_free_inodes_count = 0; + mark_buffer_dirty(bh2); + goto repeat; +out: + brelse(bitmap_bh); + return ret; +} + +unsigned long ext2_count_free_inodes (struct super_block * sb) +{ +#ifdef EXT2FS_DEBUG + struct ext2_super_block * es; + unsigned long desc_count = 0, bitmap_count = 0; + struct buffer_head *bitmap_bh = NULL; + int i; + + lock_super (sb); + es = EXT2_SB(sb)->s_es; + for (i = 0; i < EXT2_SB(sb)->s_groups_count; i++) { + struct ext2_group_desc *desc; + unsigned x; + + desc = ext2_get_group_desc (sb, i, NULL); + if (!desc) + continue; + desc_count += le16_to_cpu(desc->bg_free_inodes_count); + brelse(bitmap_bh); + bitmap_bh = read_inode_bitmap(sb, i); + if (!bitmap_bh) + continue; + + x = ext2_count_free(bitmap_bh, EXT2_INODES_PER_GROUP(sb) / 8); + printk ("group %d: stored = %d, counted = %lu\n", + i, le16_to_cpu(desc->bg_free_inodes_count), x); + bitmap_count += x; + } + brelse(bitmap_bh); + printk("ext2_count_free_inodes: stored = %lu, computed = %lu, %lu\n", + le32_to_cpu(es->s_free_inodes_count), desc_count, bitmap_count); + unlock_super(sb); + return desc_count; +#else + return le32_to_cpu(EXT2_SB(sb)->s_es->s_free_inodes_count); +#endif +} + +#ifdef CONFIG_EXT2_CHECK +/* Called at mount-time, super-block is locked */ +void ext2_check_inodes_bitmap (struct super_block * sb) +{ + struct ext2_super_block * es = EXT2_SB(sb)->s_es; + unsigned long desc_count = 0, bitmap_count = 0; + struct buffer_head *bitmap_bh = NULL; + int i; + + for (i = 0; i < EXT2_SB(sb)->s_groups_count; i++) { + struct ext2_group_desc *desc; + unsigned x; + + desc = ext2_get_group_desc(sb, i, NULL); + if (!desc) + continue; + desc_count += le16_to_cpu(desc->bg_free_inodes_count); + brelse(bitmap_bh); + bitmap_bh = read_inode_bitmap(sb, i); + if (!bitmap_bh) + continue; + + x = ext2_count_free(bitmap_bh, EXT2_INODES_PER_GROUP(sb) / 8); + if (le16_to_cpu(desc->bg_free_inodes_count) != x) + ext2_error (sb, "ext2_check_inodes_bitmap", + "Wrong free inodes count in group %d, " + "stored = %d, counted = %lu", i, + le16_to_cpu(desc->bg_free_inodes_count), x); + bitmap_count += x; + } + brelse(bitmap_bh); + if (le32_to_cpu(es->s_free_inodes_count) != bitmap_count) + ext2_error(sb, "ext2_check_inodes_bitmap", + "Wrong free inodes count in super block, " + "stored = %lu, counted = %lu", + (unsigned long)le32_to_cpu(es->s_free_inodes_count), + bitmap_count); +} +#endif diff -u --recursive --new-file linux-2.5.33-vfs3/fs/ext2/namei.c linux-2.5.33-vfs4/fs/ext2/namei.c --- linux-2.5.33-vfs3/fs/ext2/namei.c Tue Aug 13 15:48:51 2002 +++ linux-2.5.33-vfs4/fs/ext2/namei.c Tue Sep 10 19:46:57 2002 @@ -118,9 +118,9 @@ * If the create succeeds, we fill in the inode information * with d_instantiate(). */ -static int ext2_create (struct inode * dir, struct dentry * dentry, int mode) +static int ext2_create (struct inode * dir, struct dentry * dentry, struct vfs_cred *vfscred, int mode) { - struct inode * inode = ext2_new_inode (dir, mode); + struct inode * inode = ext2_new_inode (dir, vfscred, mode); int err = PTR_ERR(inode); if (!IS_ERR(inode)) { inode->i_op = &ext2_file_inode_operations; @@ -132,9 +132,9 @@ return err; } -static int ext2_mknod (struct inode * dir, struct dentry *dentry, int mode, int rdev) +static int ext2_mknod (struct inode * dir, struct dentry *dentry, struct vfs_cred *vfscred, int mode, int rdev) { - struct inode * inode = ext2_new_inode (dir, mode); + struct inode * inode = ext2_new_inode (dir, vfscred, mode); int err = PTR_ERR(inode); if (!IS_ERR(inode)) { init_special_inode(inode, mode, rdev); @@ -144,7 +144,7 @@ return err; } -static int ext2_symlink (struct inode * dir, struct dentry * dentry, +static int ext2_symlink (struct inode * dir, struct dentry * dentry, struct vfs_cred *vfscred, const char * symname) { struct super_block * sb = dir->i_sb; @@ -155,7 +155,7 @@ if (l > sb->s_blocksize) goto out; - inode = ext2_new_inode (dir, S_IFLNK | S_IRWXUGO); + inode = ext2_new_inode (dir, vfscred, S_IFLNK | S_IRWXUGO); err = PTR_ERR(inode); if (IS_ERR(inode)) goto out; @@ -200,7 +200,7 @@ return ext2_add_nondir(dentry, inode); } -static int ext2_mkdir(struct inode * dir, struct dentry * dentry, int mode) +static int ext2_mkdir(struct inode * dir, struct dentry * dentry, struct vfs_cred *vfscred, int mode) { struct inode * inode; int err = -EMLINK; @@ -210,7 +210,7 @@ ext2_inc_count(dir); - inode = ext2_new_inode (dir, S_IFDIR | mode); + inode = ext2_new_inode (dir, vfscred, S_IFDIR | mode); err = PTR_ERR(inode); if (IS_ERR(inode)) goto out_dir; diff -u --recursive --new-file linux-2.5.33-vfs3/fs/ext2/namei.c.orig linux-2.5.33-vfs4/fs/ext2/namei.c.orig --- linux-2.5.33-vfs3/fs/ext2/namei.c.orig Thu Jan 1 01:00:00 1970 +++ linux-2.5.33-vfs4/fs/ext2/namei.c.orig Tue Aug 13 15:48:51 2002 @@ -0,0 +1,371 @@ +/* + * linux/fs/ext2/namei.c + * + * Rewrite to pagecache. Almost all code had been changed, so blame me + * if the things go wrong. Please, send bug reports to viro@math.psu.edu + * + * Stuff here is basically a glue between the VFS and generic UNIXish + * filesystem that keeps everything in pagecache. All knowledge of the + * directory layout is in fs/ext2/dir.c - it turned out to be easily separatable + * and it's easier to debug that way. In principle we might want to + * generalize that a bit and turn it into a library. Or not. + * + * The only non-static object here is ext2_dir_inode_operations. + * + * TODO: get rid of kmap() use, add readahead. + * + * Copyright (C) 1992, 1993, 1994, 1995 + * Remy Card (card@masi.ibp.fr) + * Laboratoire MASI - Institut Blaise Pascal + * Universite Pierre et Marie Curie (Paris VI) + * + * from + * + * linux/fs/minix/namei.c + * + * Copyright (C) 1991, 1992 Linus Torvalds + * + * Big-endian to little-endian byte-swapping/bitmaps by + * David S. Miller (davem@caip.rutgers.edu), 1995 + */ + +#include "ext2.h" +#include + +/* + * Couple of helper functions - make the code slightly cleaner. + */ + +static inline void ext2_inc_count(struct inode *inode) +{ + inode->i_nlink++; + mark_inode_dirty(inode); +} + +static inline void ext2_dec_count(struct inode *inode) +{ + inode->i_nlink--; + mark_inode_dirty(inode); +} + +static inline int ext2_add_nondir(struct dentry *dentry, struct inode *inode) +{ + int err = ext2_add_link(dentry, inode); + if (!err) { + d_instantiate(dentry, inode); + return 0; + } + ext2_dec_count(inode); + iput(inode); + return err; +} + +/* + * Methods themselves. + */ + +static struct dentry *ext2_lookup(struct inode * dir, struct dentry *dentry) +{ + struct inode * inode; + ino_t ino; + + if (dentry->d_name.len > EXT2_NAME_LEN) + return ERR_PTR(-ENAMETOOLONG); + + ino = ext2_inode_by_name(dir, dentry); + inode = NULL; + if (ino) { + inode = iget(dir->i_sb, ino); + if (!inode) + return ERR_PTR(-EACCES); + } + if (inode) + return d_splice_alias(inode, dentry); + d_add(dentry, inode); + return NULL; +} + +struct dentry *ext2_get_parent(struct dentry *child) +{ + unsigned long ino; + struct dentry *parent; + struct inode *inode; + struct dentry dotdot; + + dotdot.d_name.name = ".."; + dotdot.d_name.len = 2; + + ino = ext2_inode_by_name(child->d_inode, &dotdot); + if (!ino) + return ERR_PTR(-ENOENT); + inode = iget(child->d_inode->i_sb, ino); + + if (!inode) + return ERR_PTR(-EACCES); + parent = d_alloc_anon(inode); + if (!parent) { + iput(inode); + parent = ERR_PTR(-ENOMEM); + } + return parent; +} + +/* + * By the time this is called, we already have created + * the directory cache entry for the new file, but it + * is so far negative - it has no inode. + * + * If the create succeeds, we fill in the inode information + * with d_instantiate(). + */ +static int ext2_create (struct inode * dir, struct dentry * dentry, int mode) +{ + struct inode * inode = ext2_new_inode (dir, mode); + int err = PTR_ERR(inode); + if (!IS_ERR(inode)) { + inode->i_op = &ext2_file_inode_operations; + inode->i_fop = &ext2_file_operations; + inode->i_mapping->a_ops = &ext2_aops; + mark_inode_dirty(inode); + err = ext2_add_nondir(dentry, inode); + } + return err; +} + +static int ext2_mknod (struct inode * dir, struct dentry *dentry, int mode, int rdev) +{ + struct inode * inode = ext2_new_inode (dir, mode); + int err = PTR_ERR(inode); + if (!IS_ERR(inode)) { + init_special_inode(inode, mode, rdev); + mark_inode_dirty(inode); + err = ext2_add_nondir(dentry, inode); + } + return err; +} + +static int ext2_symlink (struct inode * dir, struct dentry * dentry, + const char * symname) +{ + struct super_block * sb = dir->i_sb; + int err = -ENAMETOOLONG; + unsigned l = strlen(symname)+1; + struct inode * inode; + + if (l > sb->s_blocksize) + goto out; + + inode = ext2_new_inode (dir, S_IFLNK | S_IRWXUGO); + err = PTR_ERR(inode); + if (IS_ERR(inode)) + goto out; + + if (l > sizeof (EXT2_I(inode)->i_data)) { + /* slow symlink */ + inode->i_op = &page_symlink_inode_operations; + inode->i_mapping->a_ops = &ext2_aops; + err = page_symlink(inode, symname, l); + if (err) + goto out_fail; + } else { + /* fast symlink */ + inode->i_op = &ext2_fast_symlink_inode_operations; + memcpy((char*)(EXT2_I(inode)->i_data),symname,l); + inode->i_size = l-1; + } + mark_inode_dirty(inode); + + err = ext2_add_nondir(dentry, inode); +out: + return err; + +out_fail: + ext2_dec_count(inode); + iput (inode); + goto out; +} + +static int ext2_link (struct dentry * old_dentry, struct inode * dir, + struct dentry *dentry) +{ + struct inode *inode = old_dentry->d_inode; + + if (inode->i_nlink >= EXT2_LINK_MAX) + return -EMLINK; + + inode->i_ctime = CURRENT_TIME; + ext2_inc_count(inode); + atomic_inc(&inode->i_count); + + return ext2_add_nondir(dentry, inode); +} + +static int ext2_mkdir(struct inode * dir, struct dentry * dentry, int mode) +{ + struct inode * inode; + int err = -EMLINK; + + if (dir->i_nlink >= EXT2_LINK_MAX) + goto out; + + ext2_inc_count(dir); + + inode = ext2_new_inode (dir, S_IFDIR | mode); + err = PTR_ERR(inode); + if (IS_ERR(inode)) + goto out_dir; + + inode->i_op = &ext2_dir_inode_operations; + inode->i_fop = &ext2_dir_operations; + inode->i_mapping->a_ops = &ext2_aops; + + ext2_inc_count(inode); + + err = ext2_make_empty(inode, dir); + if (err) + goto out_fail; + + err = ext2_add_link(dentry, inode); + if (err) + goto out_fail; + + d_instantiate(dentry, inode); +out: + return err; + +out_fail: + ext2_dec_count(inode); + ext2_dec_count(inode); + iput(inode); +out_dir: + ext2_dec_count(dir); + goto out; +} + +static int ext2_unlink(struct inode * dir, struct dentry *dentry) +{ + struct inode * inode = dentry->d_inode; + struct ext2_dir_entry_2 * de; + struct page * page; + int err = -ENOENT; + + de = ext2_find_entry (dir, dentry, &page); + if (!de) + goto out; + + err = ext2_delete_entry (de, page); + if (err) + goto out; + + inode->i_ctime = dir->i_ctime; + ext2_dec_count(inode); + err = 0; +out: + return err; +} + +static int ext2_rmdir (struct inode * dir, struct dentry *dentry) +{ + struct inode * inode = dentry->d_inode; + int err = -ENOTEMPTY; + + if (ext2_empty_dir(inode)) { + err = ext2_unlink(dir, dentry); + if (!err) { + inode->i_size = 0; + ext2_dec_count(inode); + ext2_dec_count(dir); + } + } + return err; +} + +static int ext2_rename (struct inode * old_dir, struct dentry * old_dentry, + struct inode * new_dir, struct dentry * new_dentry ) +{ + struct inode * old_inode = old_dentry->d_inode; + struct inode * new_inode = new_dentry->d_inode; + struct page * dir_page = NULL; + struct ext2_dir_entry_2 * dir_de = NULL; + struct page * old_page; + struct ext2_dir_entry_2 * old_de; + int err = -ENOENT; + + old_de = ext2_find_entry (old_dir, old_dentry, &old_page); + if (!old_de) + goto out; + + if (S_ISDIR(old_inode->i_mode)) { + err = -EIO; + dir_de = ext2_dotdot(old_inode, &dir_page); + if (!dir_de) + goto out_old; + } + + if (new_inode) { + struct page *new_page; + struct ext2_dir_entry_2 *new_de; + + err = -ENOTEMPTY; + if (dir_de && !ext2_empty_dir (new_inode)) + goto out_dir; + + err = -ENOENT; + new_de = ext2_find_entry (new_dir, new_dentry, &new_page); + if (!new_de) + goto out_dir; + ext2_inc_count(old_inode); + ext2_set_link(new_dir, new_de, new_page, old_inode); + new_inode->i_ctime = CURRENT_TIME; + if (dir_de) + new_inode->i_nlink--; + ext2_dec_count(new_inode); + } else { + if (dir_de) { + err = -EMLINK; + if (new_dir->i_nlink >= EXT2_LINK_MAX) + goto out_dir; + } + ext2_inc_count(old_inode); + err = ext2_add_link(new_dentry, old_inode); + if (err) { + ext2_dec_count(old_inode); + goto out_dir; + } + if (dir_de) + ext2_inc_count(new_dir); + } + + ext2_delete_entry (old_de, old_page); + ext2_dec_count(old_inode); + + if (dir_de) { + ext2_set_link(old_inode, dir_de, dir_page, new_dir); + ext2_dec_count(old_dir); + } + return 0; + + +out_dir: + if (dir_de) { + kunmap(dir_page); + page_cache_release(dir_page); + } +out_old: + kunmap(old_page); + page_cache_release(old_page); +out: + return err; +} + +struct inode_operations ext2_dir_inode_operations = { + .create = ext2_create, + .lookup = ext2_lookup, + .link = ext2_link, + .unlink = ext2_unlink, + .symlink = ext2_symlink, + .mkdir = ext2_mkdir, + .rmdir = ext2_rmdir, + .mknod = ext2_mknod, + .rename = ext2_rename, +}; diff -u --recursive --new-file linux-2.5.33-vfs3/fs/ext3/ialloc.c linux-2.5.33-vfs4/fs/ext3/ialloc.c --- linux-2.5.33-vfs3/fs/ext3/ialloc.c Sun Sep 8 20:05:44 2002 +++ linux-2.5.33-vfs4/fs/ext3/ialloc.c Tue Sep 10 19:48:31 2002 @@ -197,7 +197,7 @@ * For other inodes, search forward from the parent directory's block * group to find a free inode. */ -struct inode *ext3_new_inode(handle_t *handle, struct inode * dir, int mode) +struct inode *ext3_new_inode(handle_t *handle, struct inode * dir, struct vfs_cred *vfscred, int mode) { struct super_block *sb; struct buffer_head *bitmap_bh = NULL; @@ -367,7 +367,7 @@ sb->s_dirt = 1; if (err) goto fail; - inode->i_uid = current->vfscred->uid; + inode->i_uid = vfscred->uid; if (test_opt (sb, GRPID)) inode->i_gid = dir->i_gid; else if (dir->i_mode & S_ISGID) { @@ -375,7 +375,7 @@ if (S_ISDIR(mode)) mode |= S_ISGID; } else - inode->i_gid = current->vfscred->gid; + inode->i_gid = vfscred->gid; inode->i_mode = mode; inode->i_ino = j; diff -u --recursive --new-file linux-2.5.33-vfs3/fs/ext3/namei.c linux-2.5.33-vfs4/fs/ext3/namei.c --- linux-2.5.33-vfs3/fs/ext3/namei.c Sun Jul 28 01:39:12 2002 +++ linux-2.5.33-vfs4/fs/ext3/namei.c Tue Sep 10 19:55:41 2002 @@ -489,7 +489,7 @@ * If the create succeeds, we fill in the inode information * with d_instantiate(). */ -static int ext3_create (struct inode * dir, struct dentry * dentry, int mode) +static int ext3_create (struct inode * dir, struct dentry * dentry, struct vfs_cred *vfscred, int mode) { handle_t *handle; struct inode * inode; @@ -505,7 +505,7 @@ if (IS_DIRSYNC(dir)) handle->h_sync = 1; - inode = ext3_new_inode (handle, dir, mode); + inode = ext3_new_inode (handle, dir, vfscred, mode); err = PTR_ERR(inode); if (!IS_ERR(inode)) { inode->i_op = &ext3_file_inode_operations; @@ -522,7 +522,7 @@ return err; } -static int ext3_mknod (struct inode * dir, struct dentry *dentry, +static int ext3_mknod (struct inode * dir, struct dentry *dentry, struct vfs_cred *vfscred, int mode, int rdev) { handle_t *handle; @@ -539,7 +539,7 @@ if (IS_DIRSYNC(dir)) handle->h_sync = 1; - inode = ext3_new_inode (handle, dir, mode); + inode = ext3_new_inode (handle, dir, vfscred, mode); err = PTR_ERR(inode); if (!IS_ERR(inode)) { init_special_inode(inode, mode, rdev); @@ -551,7 +551,7 @@ return err; } -static int ext3_mkdir(struct inode * dir, struct dentry * dentry, int mode) +static int ext3_mkdir(struct inode * dir, struct dentry * dentry, struct vfs_cred *vfscred, int mode) { handle_t *handle; struct inode * inode; @@ -572,7 +572,7 @@ if (IS_DIRSYNC(dir)) handle->h_sync = 1; - inode = ext3_new_inode (handle, dir, S_IFDIR); + inode = ext3_new_inode (handle, dir, vfscred, S_IFDIR); err = PTR_ERR(inode); if (IS_ERR(inode)) goto out_stop; @@ -961,7 +961,7 @@ } static int ext3_symlink (struct inode * dir, - struct dentry *dentry, const char * symname) + struct dentry *dentry, struct vfs_cred *vfscred, const char * symname) { handle_t *handle; struct inode * inode; @@ -981,7 +981,7 @@ if (IS_DIRSYNC(dir)) handle->h_sync = 1; - inode = ext3_new_inode (handle, dir, S_IFLNK|S_IRWXUGO); + inode = ext3_new_inode (handle, dir, vfscred, S_IFLNK|S_IRWXUGO); err = PTR_ERR(inode); if (IS_ERR(inode)) goto out_stop; diff -u --recursive --new-file linux-2.5.33-vfs3/fs/hpfs/namei.c linux-2.5.33-vfs4/fs/hpfs/namei.c --- linux-2.5.33-vfs3/fs/hpfs/namei.c Sun Sep 8 22:56:15 2002 +++ linux-2.5.33-vfs4/fs/hpfs/namei.c Tue Sep 10 20:15:26 2002 @@ -11,7 +11,7 @@ #include #include "hpfs_fn.h" -int hpfs_mkdir(struct inode *dir, struct dentry *dentry, int mode) +int hpfs_mkdir(struct inode *dir, struct dentry *dentry, struct vfs_cred *vfscred, int mode) { const char *name = dentry->d_name.name; unsigned len = dentry->d_name.len; @@ -77,11 +77,11 @@ result->i_ctime = result->i_mtime = result->i_atime = local_to_gmt(dir->i_sb, dee.creation_date); hpfs_i(result)->i_ea_size = 0; if (dee.read_only) result->i_mode &= ~0222; - if (result->i_uid != current->vfscred->uid || - result->i_gid != current->vfscred->gid || + if (result->i_uid != vfscred->uid || + result->i_gid != vfscred->gid || result->i_mode != (mode | S_IFDIR)) { - result->i_uid = current->vfscred->uid; - result->i_gid = current->vfscred->gid; + result->i_uid = vfscred->uid; + result->i_gid = vfscred->gid; result->i_mode = mode | S_IFDIR; hpfs_write_inode_nolock(result); } @@ -103,7 +103,7 @@ return -ENOSPC; } -int hpfs_create(struct inode *dir, struct dentry *dentry, int mode) +int hpfs_create(struct inode *dir, struct dentry *dentry, struct vfs_cred *vfscred, int mode) { const char *name = dentry->d_name.name; unsigned len = dentry->d_name.len; @@ -152,11 +152,11 @@ result->i_data.a_ops = &hpfs_aops; hpfs_i(result)->mmu_private = 0; } - if (result->i_uid != current->vfscred->uid || - result->i_gid != current->vfscred->gid || + if (result->i_uid != vfscred->uid || + result->i_gid != vfscred->gid || result->i_mode != (mode | S_IFREG)) { - result->i_uid = current->vfscred->uid; - result->i_gid = current->vfscred->gid; + result->i_uid = vfscred->uid; + result->i_gid = vfscred->gid; result->i_mode = mode | S_IFREG; hpfs_write_inode_nolock(result); } @@ -175,7 +175,7 @@ return -ENOSPC; } -int hpfs_mknod(struct inode *dir, struct dentry *dentry, int mode, int rdev) +int hpfs_mknod(struct inode *dir, struct dentry *dentry, struct vfs_cred *vfscred, int mode, int rdev) { const char *name = dentry->d_name.name; unsigned len = dentry->d_name.len; @@ -217,8 +217,8 @@ hpfs_i(result)->i_ea_size = 0; /*if (result->i_blocks == -1) result->i_blocks = 1; if (result->i_size == -1) result->i_size = 0;*/ - result->i_uid = current->vfscred->uid; - result->i_gid = current->vfscred->gid; + result->i_uid = vfscred->uid; + result->i_gid = vfscred->gid; result->i_nlink = 1; result->i_size = 0; result->i_blocks = 1; @@ -242,7 +242,7 @@ extern struct address_space_operations hpfs_symlink_aops; -int hpfs_symlink(struct inode *dir, struct dentry *dentry, const char *symlink) +int hpfs_symlink(struct inode *dir, struct dentry *dentry, struct vfs_cred *vfscred, const char *symlink) { const char *name = dentry->d_name.name; unsigned len = dentry->d_name.len; @@ -288,8 +288,8 @@ /*if (result->i_blocks == -1) result->i_blocks = 1; if (result->i_size == -1) result->i_size = 0;*/ result->i_mode = S_IFLNK | 0777; - result->i_uid = current->vfscred->uid; - result->i_gid = current->vfscred->gid; + result->i_uid = vfscred->uid; + result->i_gid = vfscred->gid; result->i_blocks = 1; result->i_size = strlen(symlink); result->i_op = &page_symlink_inode_operations;