diff options
Diffstat (limited to 'fs')
| -rw-r--r-- | fs/buffer.c | 2 | ||||
| -rw-r--r-- | fs/devfs/base.c | 94 | ||||
| -rw-r--r-- | fs/dquot.c | 7 | ||||
| -rw-r--r-- | fs/ext2/xattr.h | 1 | ||||
| -rw-r--r-- | fs/ext3/dir.c | 20 | ||||
| -rw-r--r-- | fs/ext3/hash.c | 5 | ||||
| -rw-r--r-- | fs/ext3/namei.c | 118 | ||||
| -rw-r--r-- | fs/ext3/super.c | 6 | ||||
| -rw-r--r-- | fs/ext3/xattr.h | 1 | ||||
| -rw-r--r-- | fs/fat/inode.c | 1 | ||||
| -rw-r--r-- | fs/fat/misc.c | 17 | ||||
| -rw-r--r-- | fs/super.c | 1 |
12 files changed, 130 insertions, 143 deletions
diff --git a/fs/buffer.c b/fs/buffer.c index f380aa531352..abb476e7679e 100644 --- a/fs/buffer.c +++ b/fs/buffer.c @@ -253,6 +253,8 @@ static void do_sync(unsigned long wait) sync_filesystems(0); /* Start syncing the filesystems */ sync_filesystems(wait); /* Waitingly sync the filesystems */ sync_inodes(wait); /* Mappings, inodes and blockdevs, again. */ + if (!wait) + printk("Emergency Sync complete\n"); } asmlinkage long sys_sync(void) diff --git a/fs/devfs/base.c b/fs/devfs/base.c index fa63dc1820a5..6ca2544a5322 100644 --- a/fs/devfs/base.c +++ b/fs/devfs/base.c @@ -752,6 +752,7 @@ # define DPRINTK(flag, format, args...) #endif +typedef struct devfs_entry *devfs_handle_t; struct directory_type { @@ -1424,98 +1425,6 @@ static void devfsd_notify (struct devfs_entry *de,unsigned short type) current->egid, &fs_info); } - -/** - * devfs_register - Register a device entry. - * @dir: The handle to the parent devfs directory entry. If this is %NULL the - * new name is relative to the root of the devfs. - * @name: The name of the entry. - * @flags: Must be 0 - * @major: The major number. Not needed for regular files. - * @minor: The minor number. Not needed for regular files. - * @mode: The default file mode. - * @ops: The &file_operations or &block_device_operations structure. - * This must not be externally deallocated. - * @info: An arbitrary pointer which will be written to the @private_data - * field of the &file structure passed to the device driver. You can set - * this to whatever you like, and change it once the file is opened (the next - * file opened will not see this change). - * - * On failure %NULL is returned. - */ - -devfs_handle_t devfs_register (devfs_handle_t dir, const char *name, - unsigned int flags, - unsigned int major, unsigned int minor, - umode_t mode, void *ops, void *info) -{ - int err; - dev_t devnum = 0, dev = MKDEV(major, minor); - struct devfs_entry *de; - - /* we don't accept any flags anymore. prototype will change soon. */ - WARN_ON(flags); - WARN_ON(dir); - WARN_ON(!S_ISCHR(mode)); - - if (name == NULL) - { - PRINTK ("(): NULL name pointer\n"); - return NULL; - } - if (ops == NULL) - { - PRINTK ("(%s): NULL ops pointer\n", name); - return NULL; - } - if ( S_ISDIR (mode) ) - { - PRINTK ("(%s): creating directories is not allowed\n", name); - return NULL; - } - if ( S_ISLNK (mode) ) - { - PRINTK ("(%s): creating symlinks is not allowed\n", name); - return NULL; - } - if ( ( de = _devfs_prepare_leaf (&dir, name, mode) ) == NULL ) - { - PRINTK ("(%s): could not prepare leaf\n", name); - if (devnum) devfs_dealloc_devnum (mode, devnum); - return NULL; - } - if (S_ISCHR (mode)) { - de->u.cdev.dev = dev; - de->u.cdev.autogen = devnum != 0; - de->u.cdev.ops = ops; - } else if (S_ISBLK (mode)) { - de->u.bdev.dev = dev; - de->u.cdev.autogen = devnum != 0; - } else { - PRINTK ("(%s): illegal mode: %x\n", name, mode); - devfs_put (de); - devfs_put (dir); - return (NULL); - } - de->info = info; - de->inode.uid = 0; - de->inode.gid = 0; - err = _devfs_append_entry(dir, de, NULL); - if (err) - { - PRINTK ("(%s): could not append to parent, err: %d\n", name, err); - devfs_put (dir); - if (devnum) devfs_dealloc_devnum (mode, devnum); - return NULL; - } - DPRINTK (DEBUG_REGISTER, "(%s): de: %p dir: %p \"%s\" pp: %p\n", - name, de, dir, dir->name, dir->parent); - devfsd_notify (de, DEVFSD_NOTIFY_REGISTERED); - devfs_put (dir); - return de; -} /* End Function devfs_register */ - - int devfs_mk_bdev(dev_t dev, umode_t mode, const char *fmt, ...) { struct devfs_entry *dir = NULL, *de; @@ -1935,7 +1844,6 @@ static int __init devfs_setup (char *str) __setup("devfs=", devfs_setup); EXPORT_SYMBOL(devfs_put); -EXPORT_SYMBOL(devfs_register); EXPORT_SYMBOL(devfs_mk_symlink); EXPORT_SYMBOL(devfs_mk_dir); EXPORT_SYMBOL(devfs_remove); diff --git a/fs/dquot.c b/fs/dquot.c index f3c0f63265c3..edda8c2009d6 100644 --- a/fs/dquot.c +++ b/fs/dquot.c @@ -1011,9 +1011,12 @@ warn_put_all: spin_unlock(&dq_data_lock); flush_warnings(transfer_to, warntype); - for (cnt = 0; cnt < MAXQUOTAS; cnt++) - if (transfer_from[cnt] != NODQUOT) + for (cnt = 0; cnt < MAXQUOTAS; cnt++) { + if (ret == QUOTA_OK && transfer_from[cnt] != NODQUOT) dqput(transfer_from[cnt]); + if (ret == NO_QUOTA && transfer_to[cnt] != NODQUOT) + dqput(transfer_to[cnt]); + } up_write(&sb_dqopt(inode->i_sb)->dqptr_sem); return ret; } diff --git a/fs/ext2/xattr.h b/fs/ext2/xattr.h index a57b9da2306d..a113ead4adf9 100644 --- a/fs/ext2/xattr.h +++ b/fs/ext2/xattr.h @@ -22,6 +22,7 @@ #define EXT2_XATTR_INDEX_POSIX_ACL_ACCESS 2 #define EXT2_XATTR_INDEX_POSIX_ACL_DEFAULT 3 #define EXT2_XATTR_INDEX_TRUSTED 4 +#define EXT2_XATTR_INDEX_LUSTRE 5 #define EXT2_XATTR_INDEX_SECURITY 6 struct ext2_xattr_header { diff --git a/fs/ext3/dir.c b/fs/ext3/dir.c index 1b5fae0032f2..b00bec6fe0ce 100644 --- a/fs/ext3/dir.c +++ b/fs/ext3/dir.c @@ -103,7 +103,11 @@ static int ext3_readdir(struct file * filp, sb = inode->i_sb; - if (is_dx(inode)) { +#ifdef CONFIG_EXT3_INDEX + if (EXT3_HAS_COMPAT_FEATURE(inode->i_sb, + EXT3_FEATURE_COMPAT_DIR_INDEX) && + ((EXT3_I(inode)->i_flags & EXT3_INDEX_FL) || + ((inode->i_size >> sb->s_blocksize_bits) == 1))) { err = ext3_dx_readdir(filp, dirent, filldir); if (err != ERR_BAD_DX_DIR) { ret = err; @@ -115,6 +119,7 @@ static int ext3_readdir(struct file * filp, */ EXT3_I(filp->f_dentry->d_inode)->i_flags &= ~EXT3_INDEX_FL; } +#endif stored = 0; bh = NULL; offset = filp->f_pos & (sb->s_blocksize - 1); @@ -434,6 +439,9 @@ static int ext3_dx_readdir(struct file * filp, filp->private_data = info; } + if (filp->f_pos == EXT3_HTREE_EOF) + return 0; /* EOF */ + /* Some one has messed with f_pos; reset the world */ if (info->last_pos != filp->f_pos) { free_rb_tree_fname(&info->root); @@ -470,8 +478,10 @@ static int ext3_dx_readdir(struct file * filp, &info->next_hash); if (ret < 0) return ret; - if (ret == 0) + if (ret == 0) { + filp->f_pos = EXT3_HTREE_EOF; break; + } info->curr_node = rb_first(&info->root); } @@ -483,6 +493,10 @@ static int ext3_dx_readdir(struct file * filp, info->curr_node = rb_next(info->curr_node); if (!info->curr_node) { + if (info->next_hash == ~0) { + filp->f_pos = EXT3_HTREE_EOF; + break; + } info->curr_hash = info->next_hash; info->curr_minor_hash = 0; } @@ -495,7 +509,7 @@ finished: static int ext3_release_dir (struct inode * inode, struct file * filp) { - if (is_dx(inode) && filp->private_data) + if (filp->private_data) ext3_htree_free_dir_info(filp->private_data); return 0; diff --git a/fs/ext3/hash.c b/fs/ext3/hash.c index 2025354b85de..d00d658b1cfb 100644 --- a/fs/ext3/hash.c +++ b/fs/ext3/hash.c @@ -209,7 +209,10 @@ int ext3fs_dirhash(const char *name, int len, struct dx_hash_info *hinfo) hinfo->hash = 0; return -1; } - hinfo->hash = hash & ~1; + hash = hash & ~1; + if (hash == (EXT3_HTREE_EOF << 1)) + hash = (EXT3_HTREE_EOF-1) << 1; + hinfo->hash = hash; hinfo->minor_hash = minor_hash; return 0; } diff --git a/fs/ext3/namei.c b/fs/ext3/namei.c index 34218818c69d..ea83d3cb7bec 100644 --- a/fs/ext3/namei.c +++ b/fs/ext3/namei.c @@ -170,7 +170,7 @@ static struct ext3_dir_entry_2* dx_pack_dirents (char *base, int size); static void dx_insert_block (struct dx_frame *frame, u32 hash, u32 block); static int ext3_htree_next_block(struct inode *dir, __u32 hash, struct dx_frame *frame, - struct dx_frame *frames, int *err, + struct dx_frame *frames, __u32 *start_hash); static struct buffer_head * ext3_dx_find_entry(struct dentry *dentry, struct ext3_dir_entry_2 **res_dir, int *err); @@ -239,6 +239,17 @@ static inline unsigned dx_node_limit (struct inode *dir) * Debug */ #ifdef DX_DEBUG +static void dx_show_index (char * label, struct dx_entry *entries) +{ + int i, n = dx_get_count (entries); + printk("%s index ", label); + for (i = 0; i < n; i++) + { + printk("%x->%u ", i? dx_get_hash(entries + i): 0, dx_get_block(entries + i)); + } + printk("\n"); +} + struct stats { unsigned names; @@ -447,22 +458,21 @@ static void dx_release (struct dx_frame *frames) * * This function returns 1 if the caller should continue to search, * or 0 if it should not. If there is an error reading one of the - * index blocks, it will return -1. + * index blocks, it will a negative error code. * * If start_hash is non-null, it will be filled in with the starting * hash of the next page. */ static int ext3_htree_next_block(struct inode *dir, __u32 hash, struct dx_frame *frame, - struct dx_frame *frames, int *err, + struct dx_frame *frames, __u32 *start_hash) { struct dx_frame *p; struct buffer_head *bh; - int num_frames = 0; + int err, num_frames = 0; __u32 bhash; - *err = ENOENT; p = frame; /* * Find the next leaf page by incrementing the frame pointer. @@ -500,8 +510,8 @@ static int ext3_htree_next_block(struct inode *dir, __u32 hash, */ while (num_frames--) { if (!(bh = ext3_bread(NULL, dir, dx_get_block(p->at), - 0, err))) - return -1; /* Failure */ + 0, &err))) + return err; /* Failure */ p++; brelse (p->bh); p->bh = bh; @@ -521,6 +531,46 @@ static inline struct ext3_dir_entry_2 *ext3_next_entry(struct ext3_dir_entry_2 * /* * This function fills a red-black tree with information from a + * directory block. It returns the number directory entries loaded + * into the tree. If there is an error it is returned in err. + */ +static int htree_dirblock_to_tree(struct file *dir_file, + struct inode *dir, int block, + struct dx_hash_info *hinfo, + __u32 start_hash, __u32 start_minor_hash) +{ + struct buffer_head *bh; + struct ext3_dir_entry_2 *de, *top; + int err, count = 0; + + dxtrace(printk("In htree dirblock_to_tree: block %d\n", block)); + if (!(bh = ext3_bread (NULL, dir, block, 0, &err))) + return err; + + de = (struct ext3_dir_entry_2 *) bh->b_data; + top = (struct ext3_dir_entry_2 *) ((char *) de + + dir->i_sb->s_blocksize - + EXT3_DIR_REC_LEN(0)); + for (; de < top; de = ext3_next_entry(de)) { + ext3fs_dirhash(de->name, de->name_len, hinfo); + if ((hinfo->hash < start_hash) || + ((hinfo->hash == start_hash) && + (hinfo->minor_hash < start_minor_hash))) + continue; + if ((err = ext3_htree_store_dirent(dir_file, + hinfo->hash, hinfo->minor_hash, de)) != 0) { + brelse(bh); + return err; + } + count++; + } + brelse(bh); + return count; +} + + +/* + * This function fills a red-black tree with information from a * directory. We start scanning the directory in hash order, starting * at start_hash and start_minor_hash. * @@ -531,8 +581,7 @@ int ext3_htree_fill_tree(struct file *dir_file, __u32 start_hash, __u32 start_minor_hash, __u32 *next_hash) { struct dx_hash_info hinfo; - struct buffer_head *bh; - struct ext3_dir_entry_2 *de, *top; + struct ext3_dir_entry_2 *de; struct dx_frame frames[2], *frame; struct inode *dir; int block, err; @@ -543,6 +592,14 @@ int ext3_htree_fill_tree(struct file *dir_file, __u32 start_hash, dxtrace(printk("In htree_fill_tree, start hash: %x:%x\n", start_hash, start_minor_hash)); dir = dir_file->f_dentry->d_inode; + if (!(EXT3_I(dir)->i_flags & EXT3_INDEX_FL)) { + hinfo.hash_version = EXT3_SB(dir->i_sb)->s_def_hash_version; + hinfo.seed = EXT3_SB(dir->i_sb)->s_hash_seed; + count = htree_dirblock_to_tree(dir_file, dir, 0, &hinfo, + start_hash, start_minor_hash); + *next_hash = ~0; + return count; + } hinfo.hash = start_hash; hinfo.minor_hash = 0; frame = dx_probe(0, dir_file->f_dentry->d_inode, &hinfo, frames, &err); @@ -562,34 +619,21 @@ int ext3_htree_fill_tree(struct file *dir_file, __u32 start_hash, while (1) { block = dx_get_block(frame->at); - dxtrace(printk("Reading block %d\n", block)); - if (!(bh = ext3_bread (NULL, dir, block, 0, &err))) + ret = htree_dirblock_to_tree(dir_file, dir, block, &hinfo, + start_hash, start_minor_hash); + if (ret < 0) { + err = ret; goto errout; - - de = (struct ext3_dir_entry_2 *) bh->b_data; - top = (struct ext3_dir_entry_2 *) ((char *) de + dir->i_sb->s_blocksize - - EXT3_DIR_REC_LEN(0)); - for (; de < top; de = ext3_next_entry(de)) { - ext3fs_dirhash(de->name, de->name_len, &hinfo); - if ((hinfo.hash < start_hash) || - ((hinfo.hash == start_hash) && - (hinfo.minor_hash < start_minor_hash))) - continue; - if ((err = ext3_htree_store_dirent(dir_file, - hinfo.hash, hinfo.minor_hash, de)) != 0) { - brelse(bh); - goto errout; - } - count++; } - brelse (bh); - hashval = ~1; + count += ret; + hashval = ~0; ret = ext3_htree_next_block(dir, HASH_NB_ALWAYS, - frame, frames, &err, &hashval); - if (next_hash) - *next_hash = hashval; - if (ret == -1) + frame, frames, &hashval); + *next_hash = hashval; + if (ret < 0) { + err = ret; goto errout; + } /* * Stop if: (a) there are no more entries, or * (b) we have inserted at least one entry and the @@ -600,7 +644,8 @@ int ext3_htree_fill_tree(struct file *dir_file, __u32 start_hash, break; } dx_release(frames); - dxtrace(printk("Fill tree: returned %d entries\n", count)); + dxtrace(printk("Fill tree: returned %d entries, next hash: %x\n", + count, *next_hash)); return count; errout: dx_release(frames); @@ -909,11 +954,12 @@ static struct buffer_head * ext3_dx_find_entry(struct dentry *dentry, brelse (bh); /* Check to see if we should continue to search */ retval = ext3_htree_next_block(dir, hash, frame, - frames, err, 0); - if (retval == -1) { + frames, 0); + if (retval < 0) { ext3_warning(sb, __FUNCTION__, "error reading index page in directory #%lu", dir->i_ino); + *err = retval; goto errout; } } while (retval == 1); diff --git a/fs/ext3/super.c b/fs/ext3/super.c index 532c501e7396..8c72318360b7 100644 --- a/fs/ext3/super.c +++ b/fs/ext3/super.c @@ -1988,8 +1988,10 @@ int ext3_statfs (struct super_block * sb, struct statfs * buf) #ifdef CONFIG_QUOTA -#define EXT3_OLD_QFMT_BLOCKS 2 -#define EXT3_V0_QFMT_BLOCKS 6 +/* Blocks: (2 data blocks) * (3 indirect + 1 descriptor + 1 bitmap) + superblock */ +#define EXT3_OLD_QFMT_BLOCKS 11 +/* Blocks: quota info + (4 pointer blocks + 1 entry block) * (3 indirect + 1 descriptor + 1 bitmap) + superblock */ +#define EXT3_V0_QFMT_BLOCKS 27 static int (*old_sync_dquot)(struct dquot *dquot); diff --git a/fs/ext3/xattr.h b/fs/ext3/xattr.h index 8de7046ed175..9c71433c6a90 100644 --- a/fs/ext3/xattr.h +++ b/fs/ext3/xattr.h @@ -21,6 +21,7 @@ #define EXT3_XATTR_INDEX_POSIX_ACL_ACCESS 2 #define EXT3_XATTR_INDEX_POSIX_ACL_DEFAULT 3 #define EXT3_XATTR_INDEX_TRUSTED 4 +#define EXT3_XATTR_INDEX_LUSTRE 5 #define EXT3_XATTR_INDEX_SECURITY 6 struct ext3_xattr_header { diff --git a/fs/fat/inode.c b/fs/fat/inode.c index 866edb62fad5..282c0c22db6f 100644 --- a/fs/fat/inode.c +++ b/fs/fat/inode.c @@ -897,6 +897,7 @@ int fat_fill_super(struct super_block *sb, void *data, int silent, sbi->fsinfo_sector); } else { sbi->free_clusters = CF_LE_L(fsinfo->free_clusters); + sbi->prev_free = CF_LE_L(fsinfo->next_cluster); } brelse(fsinfo_bh); diff --git a/fs/fat/misc.c b/fs/fat/misc.c index f7043d09f086..6e3e86c8899b 100644 --- a/fs/fat/misc.c +++ b/fs/fat/misc.c @@ -74,6 +74,7 @@ void fat_clusters_flush(struct super_block *sb) MSDOS_SB(sb)->fsinfo_sector); } else { fsinfo->free_clusters = CF_LE_L(MSDOS_SB(sb)->free_clusters); + fsinfo->next_cluster = CF_LE_L(MSDOS_SB(sb)->prev_free); mark_buffer_dirty(bh); } brelse(bh); @@ -130,19 +131,23 @@ int fat_add_cluster(struct inode *inode) unlock_fat(sb); return -ENOSPC; } - limit = MSDOS_SB(sb)->clusters; - for (count = 0; count < limit; count++) { - nr = ((count + MSDOS_SB(sb)->prev_free) % limit) + 2; + + limit = MSDOS_SB(sb)->clusters + 2; + nr = MSDOS_SB(sb)->prev_free + 1; + for (count = 0; count < MSDOS_SB(sb)->clusters; count++, nr++) { + nr = nr % limit; + if (nr < 2) + nr = 2; if (fat_access(sb, nr, -1) == FAT_ENT_FREE) break; } - if (count >= limit) { + if (count >= MSDOS_SB(sb)->clusters) { MSDOS_SB(sb)->free_clusters = 0; unlock_fat(sb); return -ENOSPC; } - - MSDOS_SB(sb)->prev_free = (count + MSDOS_SB(sb)->prev_free + 1) % limit; + MSDOS_SB(sb)->prev_free = nr; + fat_access(sb, nr, FAT_ENT_EOF); if (MSDOS_SB(sb)->free_clusters != -1) MSDOS_SB(sb)->free_clusters--; diff --git a/fs/super.c b/fs/super.c index 58f90ef3a2b9..eba1a860a141 100644 --- a/fs/super.c +++ b/fs/super.c @@ -497,6 +497,7 @@ static void do_emergency_remount(unsigned long foo) spin_lock(&sb_lock); } spin_unlock(&sb_lock); + printk("Emergency Remount complete\n"); } void emergency_remount(void) |
