summaryrefslogtreecommitdiff
path: root/fs
diff options
context:
space:
mode:
Diffstat (limited to 'fs')
-rw-r--r--fs/buffer.c2
-rw-r--r--fs/devfs/base.c94
-rw-r--r--fs/dquot.c7
-rw-r--r--fs/ext2/xattr.h1
-rw-r--r--fs/ext3/dir.c20
-rw-r--r--fs/ext3/hash.c5
-rw-r--r--fs/ext3/namei.c118
-rw-r--r--fs/ext3/super.c6
-rw-r--r--fs/ext3/xattr.h1
-rw-r--r--fs/fat/inode.c1
-rw-r--r--fs/fat/misc.c17
-rw-r--r--fs/super.c1
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)