From ef2a701d444a4ea9790146e92756b0dde5070a15 Mon Sep 17 00:00:00 2001 From: Nigel Cunningham Date: Wed, 27 Jul 2005 11:43:36 -0700 Subject: [PATCH] Fix missing refrigerator invocation in jffs2 Here's a patch to fix a missing refrigerator call in jffs2. Signed-off-by: Nigel Cunningham Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/jffs/intrep.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'fs') diff --git a/fs/jffs/intrep.c b/fs/jffs/intrep.c index fc589ddd076..456d7e6e29c 100644 --- a/fs/jffs/intrep.c +++ b/fs/jffs/intrep.c @@ -3397,6 +3397,9 @@ jffs_garbage_collect_thread(void *ptr) siginfo_t info; unsigned long signr = 0; + if (try_to_freeze()) + continue; + spin_lock_irq(¤t->sighand->siglock); signr = dequeue_signal(current, ¤t->blocked, &info); spin_unlock_irq(¤t->sighand->siglock); -- cgit v1.2.3 From b3bb8afd965159f155d4f629cbea158cbcc69275 Mon Sep 17 00:00:00 2001 From: Jeff Mahoney Date: Wed, 27 Jul 2005 11:43:38 -0700 Subject: [PATCH] reiserfs: fix deadlock in inode creation failure path w/ default ACL reiserfs_new_inode() can call iput() with the xattr lock held. This will cause a deadlock to occur when reiserfs_delete_xattrs() is called to clean up. The following patch releases the lock and reacquires it after the iput. This is safe because interaction with xattrs is complete, and the relock is just to balance out the release in the caller. The locking needs some reworking to be more sane, but that's more intrusive and I was just looking to fix this bug. Signed-off-by: Jeff Mahoney Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/reiserfs/inode.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) (limited to 'fs') diff --git a/fs/reiserfs/inode.c b/fs/reiserfs/inode.c index 1aaf2c7d44e..d9f614a5773 100644 --- a/fs/reiserfs/inode.c +++ b/fs/reiserfs/inode.c @@ -1980,7 +1980,17 @@ int reiserfs_new_inode(struct reiserfs_transaction_handle *th, out_inserted_sd: inode->i_nlink = 0; th->t_trans_id = 0; /* so the caller can't use this handle later */ - iput(inode); + + /* If we were inheriting an ACL, we need to release the lock so that + * iput doesn't deadlock in reiserfs_delete_xattrs. The locking + * code really needs to be reworked, but this will take care of it + * for now. -jeffm */ + if (REISERFS_I(dir)->i_acl_default) { + reiserfs_write_unlock_xattrs(dir->i_sb); + iput(inode); + reiserfs_write_lock_xattrs(dir->i_sb); + } else + iput(inode); return err; } -- cgit v1.2.3 From c7e9a52ef0089492bba457dfb8eba1a54e19f24a Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Wed, 27 Jul 2005 11:43:39 -0700 Subject: [PATCH] ext2: drop quota reference before releasing inode We must drop references to quota structures before releasing the inode. Signed-off-by: Jan Kara Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/ext2/ialloc.c | 1 + 1 file changed, 1 insertion(+) (limited to 'fs') diff --git a/fs/ext2/ialloc.c b/fs/ext2/ialloc.c index 77e05914921..161f156d98c 100644 --- a/fs/ext2/ialloc.c +++ b/fs/ext2/ialloc.c @@ -612,6 +612,7 @@ got: err = ext2_init_acl(inode, dir); if (err) { DQUOT_FREE_INODE(inode); + DQUOT_DROP(inode); goto fail2; } mark_inode_dirty(inode); -- cgit v1.2.3 From ab6862e6dab813ecde9ae7da506188dc1e9f11bb Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Wed, 27 Jul 2005 11:43:40 -0700 Subject: [PATCH] ext3: drop quota references before releasing inode We must drop references to quota structures before releasing the inode. Signed-off-by: Jan Kara Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/ext3/ialloc.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'fs') diff --git a/fs/ext3/ialloc.c b/fs/ext3/ialloc.c index 1e6f3ea2871..6981bd014ed 100644 --- a/fs/ext3/ialloc.c +++ b/fs/ext3/ialloc.c @@ -604,12 +604,14 @@ got: err = ext3_init_acl(handle, inode, dir); if (err) { DQUOT_FREE_INODE(inode); + DQUOT_DROP(inode); goto fail2; } err = ext3_mark_inode_dirty(handle, inode); if (err) { ext3_std_error(sb, err); DQUOT_FREE_INODE(inode); + DQUOT_DROP(inode); goto fail2; } -- cgit v1.2.3 From 104e49fc1e1656142869fab0e75d7df52b72eed9 Mon Sep 17 00:00:00 2001 From: Ian Kent Date: Wed, 27 Jul 2005 11:43:45 -0700 Subject: [PATCH] autofs4: fix infamous "Busy inodes after umount ..." message If the automount daemon receives a signal which causes it to sumarily terminate the autofs4 module leaks dentries. The same problem exists with detached mount requests without the warning. This patch cleans these dentries at umount. Signed-off-by: Ian Kent Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/autofs4/autofs_i.h | 1 + fs/autofs4/inode.c | 73 +++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 74 insertions(+) (limited to 'fs') diff --git a/fs/autofs4/autofs_i.h b/fs/autofs4/autofs_i.h index 9c09641ce90..fca83e28edc 100644 --- a/fs/autofs4/autofs_i.h +++ b/fs/autofs4/autofs_i.h @@ -92,6 +92,7 @@ struct autofs_wait_queue { struct autofs_sb_info { u32 magic; + struct dentry *root; struct file *pipe; pid_t oz_pgrp; int catatonic; diff --git a/fs/autofs4/inode.c b/fs/autofs4/inode.c index 4bb14cc6804..0a3c05d1016 100644 --- a/fs/autofs4/inode.c +++ b/fs/autofs4/inode.c @@ -16,6 +16,7 @@ #include #include #include +#include #include "autofs_i.h" #include @@ -76,6 +77,66 @@ void autofs4_free_ino(struct autofs_info *ino) kfree(ino); } +/* + * Deal with the infamous "Busy inodes after umount ..." message. + * + * Clean up the dentry tree. This happens with autofs if the user + * space program goes away due to a SIGKILL, SIGSEGV etc. + */ +static void autofs4_force_release(struct autofs_sb_info *sbi) +{ + struct dentry *this_parent = sbi->root; + struct list_head *next; + + spin_lock(&dcache_lock); +repeat: + next = this_parent->d_subdirs.next; +resume: + while (next != &this_parent->d_subdirs) { + struct dentry *dentry = list_entry(next, struct dentry, d_child); + + /* Negative dentry - don`t care */ + if (!simple_positive(dentry)) { + next = next->next; + continue; + } + + if (!list_empty(&dentry->d_subdirs)) { + this_parent = dentry; + goto repeat; + } + + next = next->next; + spin_unlock(&dcache_lock); + + DPRINTK("dentry %p %.*s", + dentry, (int)dentry->d_name.len, dentry->d_name.name); + + dput(dentry); + spin_lock(&dcache_lock); + } + + if (this_parent != sbi->root) { + struct dentry *dentry = this_parent; + + next = this_parent->d_child.next; + this_parent = this_parent->d_parent; + spin_unlock(&dcache_lock); + DPRINTK("parent dentry %p %.*s", + dentry, (int)dentry->d_name.len, dentry->d_name.name); + dput(dentry); + spin_lock(&dcache_lock); + goto resume; + } + spin_unlock(&dcache_lock); + + dput(sbi->root); + sbi->root = NULL; + shrink_dcache_sb(sbi->sb); + + return; +} + static void autofs4_put_super(struct super_block *sb) { struct autofs_sb_info *sbi = autofs4_sbi(sb); @@ -85,6 +146,10 @@ static void autofs4_put_super(struct super_block *sb) if ( !sbi->catatonic ) autofs4_catatonic_mode(sbi); /* Free wait queues, close pipe */ + /* Clean up and release dangling references */ + if (sbi) + autofs4_force_release(sbi); + kfree(sbi); DPRINTK("shutting down"); @@ -199,6 +264,7 @@ int autofs4_fill_super(struct super_block *s, void *data, int silent) s->s_fs_info = sbi; sbi->magic = AUTOFS_SBI_MAGIC; + sbi->root = NULL; sbi->catatonic = 0; sbi->exp_timeout = 0; sbi->oz_pgrp = process_group(current); @@ -266,6 +332,13 @@ int autofs4_fill_super(struct super_block *s, void *data, int silent) goto fail_fput; sbi->pipe = pipe; + /* + * Take a reference to the root dentry so we get a chance to + * clean up the dentry tree on umount. + * See autofs4_force_release. + */ + sbi->root = dget(root); + /* * Success! Install the root dentry now to indicate completion. */ -- cgit v1.2.3 From 0cfc11ed45e4c00750039e5a18c0fc0d681e19db Mon Sep 17 00:00:00 2001 From: Carsten Otte Date: Wed, 27 Jul 2005 11:43:52 -0700 Subject: [PATCH] fix xip sparse file handling in ext2 Oliver Paukstadt from our test department is testing the xip patches in Linus' git-tree. He found a problem that shows when reading a file that contains sparse blocks (holes) on a -o xip mounted ext2 filesystem: the BUG_ON() in fs/ext2/xip.c:40 triggers where it should not. The problem was introduced by a cleanup in my previous patch, this patch fixes it. Signed-off-by: Carsten Otte Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/ext2/xip.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'fs') diff --git a/fs/ext2/xip.c b/fs/ext2/xip.c index 0aa5ac159c0..ca7f0031238 100644 --- a/fs/ext2/xip.c +++ b/fs/ext2/xip.c @@ -36,7 +36,7 @@ __ext2_get_sector(struct inode *inode, sector_t offset, int create, *result = tmp.b_blocknr; /* did we get a sparse block (hole in the file)? */ - if (!(*result)) { + if (!tmp.b_blocknr && !rc) { BUG_ON(create); rc = -ENODATA; } -- cgit v1.2.3 From c293621bbf678a3d85e3ed721c3921c8a670610d Mon Sep 17 00:00:00 2001 From: Peter Staubach Date: Wed, 27 Jul 2005 11:45:09 -0700 Subject: [PATCH] stale POSIX lock handling I believe that there is a problem with the handling of POSIX locks, which the attached patch should address. The problem appears to be a race between fcntl(2) and close(2). A multithreaded application could close a file descriptor at the same time as it is trying to acquire a lock using the same file descriptor. I would suggest that that multithreaded application is not providing the proper synchronization for itself, but the OS should still behave correctly. SUS3 (Single UNIX Specification Version 3, read: POSIX) indicates that when a file descriptor is closed, that all POSIX locks on the file, owned by the process which closed the file descriptor, should be released. The trick here is when those locks are released. The current code releases all locks which exist when close is processing, but any locks in progress are handled when the last reference to the open file is released. There are three cases to consider. One is the simple case, a multithreaded (mt) process has a file open and races to close it and acquire a lock on it. In this case, the close will release one reference to the open file and when the fcntl is done, it will release the other reference. For this situation, no locks should exist on the file when both the close and fcntl operations are done. The current system will handle this case because the last reference to the open file is being released. The second case is when the mt process has dup(2)'d the file descriptor. The close will release one reference to the file and the fcntl, when done, will release another, but there will still be at least one more reference to the open file. One could argue that the existence of a lock on the file after the close has completed is okay, because it was acquired after the close operation and there is still a way for the application to release the lock on the file, using an existing file descriptor. The third case is when the mt process has forked, after opening the file and either before or after becoming an mt process. In this case, each process would hold a reference to the open file. For each process, this degenerates to first case above. However, the lock continues to exist until both processes have released their references to the open file. This lock could block other lock requests. The changes to release the lock when the last reference to the open file aren't quite right because they would allow the lock to exist as long as there was a reference to the open file. This is too long. The new proposed solution is to add support in the fcntl code path to detect a race with close and then to release the lock which was just acquired when such as race is detected. This causes locks to be released in a timely fashion and for the system to conform to the POSIX semantic specification. This was tested by instrumenting a kernel to detect the handling locks and then running a program which generates case #3 above. A dangling lock could be reliably generated. When the changes to detect the close/fcntl race were added, a dangling lock could no longer be generated. Cc: Matthew Wilcox Cc: Trond Myklebust Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/fcntl.c | 5 ++-- fs/locks.c | 81 +++++++++++++++++++++++++++++++++++++------------------------- 2 files changed, 51 insertions(+), 35 deletions(-) (limited to 'fs') diff --git a/fs/fcntl.c b/fs/fcntl.c index 286a9f8f3d4..6fbc9d8fcc3 100644 --- a/fs/fcntl.c +++ b/fs/fcntl.c @@ -288,7 +288,7 @@ static long do_fcntl(int fd, unsigned int cmd, unsigned long arg, break; case F_SETLK: case F_SETLKW: - err = fcntl_setlk(filp, cmd, (struct flock __user *) arg); + err = fcntl_setlk(fd, filp, cmd, (struct flock __user *) arg); break; case F_GETOWN: /* @@ -376,7 +376,8 @@ asmlinkage long sys_fcntl64(unsigned int fd, unsigned int cmd, unsigned long arg break; case F_SETLK64: case F_SETLKW64: - err = fcntl_setlk64(filp, cmd, (struct flock64 __user *) arg); + err = fcntl_setlk64(fd, filp, cmd, + (struct flock64 __user *) arg); break; default: err = do_fcntl(fd, cmd, arg, filp); diff --git a/fs/locks.c b/fs/locks.c index 29fa5da6c11..11956b6179f 100644 --- a/fs/locks.c +++ b/fs/locks.c @@ -1591,7 +1591,8 @@ out: /* Apply the lock described by l to an open file descriptor. * This implements both the F_SETLK and F_SETLKW commands of fcntl(). */ -int fcntl_setlk(struct file *filp, unsigned int cmd, struct flock __user *l) +int fcntl_setlk(unsigned int fd, struct file *filp, unsigned int cmd, + struct flock __user *l) { struct file_lock *file_lock = locks_alloc_lock(); struct flock flock; @@ -1620,6 +1621,7 @@ int fcntl_setlk(struct file *filp, unsigned int cmd, struct flock __user *l) goto out; } +again: error = flock_to_posix_lock(filp, file_lock, &flock); if (error) goto out; @@ -1648,25 +1650,33 @@ int fcntl_setlk(struct file *filp, unsigned int cmd, struct flock __user *l) if (error) goto out; - if (filp->f_op && filp->f_op->lock != NULL) { + if (filp->f_op && filp->f_op->lock != NULL) error = filp->f_op->lock(filp, cmd, file_lock); - goto out; - } + else { + for (;;) { + error = __posix_lock_file(inode, file_lock); + if ((error != -EAGAIN) || (cmd == F_SETLK)) + break; + error = wait_event_interruptible(file_lock->fl_wait, + !file_lock->fl_next); + if (!error) + continue; - for (;;) { - error = __posix_lock_file(inode, file_lock); - if ((error != -EAGAIN) || (cmd == F_SETLK)) + locks_delete_block(file_lock); break; - error = wait_event_interruptible(file_lock->fl_wait, - !file_lock->fl_next); - if (!error) - continue; + } + } - locks_delete_block(file_lock); - break; + /* + * Attempt to detect a close/fcntl race and recover by + * releasing the lock that was just acquired. + */ + if (!error && fcheck(fd) != filp && flock.l_type != F_UNLCK) { + flock.l_type = F_UNLCK; + goto again; } - out: +out: locks_free_lock(file_lock); return error; } @@ -1724,7 +1734,8 @@ out: /* Apply the lock described by l to an open file descriptor. * This implements both the F_SETLK and F_SETLKW commands of fcntl(). */ -int fcntl_setlk64(struct file *filp, unsigned int cmd, struct flock64 __user *l) +int fcntl_setlk64(unsigned int fd, struct file *filp, unsigned int cmd, + struct flock64 __user *l) { struct file_lock *file_lock = locks_alloc_lock(); struct flock64 flock; @@ -1753,6 +1764,7 @@ int fcntl_setlk64(struct file *filp, unsigned int cmd, struct flock64 __user *l) goto out; } +again: error = flock64_to_posix_lock(filp, file_lock, &flock); if (error) goto out; @@ -1781,22 +1793,30 @@ int fcntl_setlk64(struct file *filp, unsigned int cmd, struct flock64 __user *l) if (error) goto out; - if (filp->f_op && filp->f_op->lock != NULL) { + if (filp->f_op && filp->f_op->lock != NULL) error = filp->f_op->lock(filp, cmd, file_lock); - goto out; - } + else { + for (;;) { + error = __posix_lock_file(inode, file_lock); + if ((error != -EAGAIN) || (cmd == F_SETLK64)) + break; + error = wait_event_interruptible(file_lock->fl_wait, + !file_lock->fl_next); + if (!error) + continue; - for (;;) { - error = __posix_lock_file(inode, file_lock); - if ((error != -EAGAIN) || (cmd == F_SETLK64)) + locks_delete_block(file_lock); break; - error = wait_event_interruptible(file_lock->fl_wait, - !file_lock->fl_next); - if (!error) - continue; + } + } - locks_delete_block(file_lock); - break; + /* + * Attempt to detect a close/fcntl race and recover by + * releasing the lock that was just acquired. + */ + if (!error && fcheck(fd) != filp && flock.l_type != F_UNLCK) { + flock.l_type = F_UNLCK; + goto again; } out: @@ -1888,12 +1908,7 @@ void locks_remove_flock(struct file *filp) while ((fl = *before) != NULL) { if (fl->fl_file == filp) { - /* - * We might have a POSIX lock that was created at the same time - * the filp was closed for the last time. Just remove that too, - * regardless of ownership, since nobody can own it. - */ - if (IS_FLOCK(fl) || IS_POSIX(fl)) { + if (IS_FLOCK(fl)) { locks_delete_lock(before); continue; } -- cgit v1.2.3 From 8c52ab42c11b5a7fb44bb84c954d09968e90e9e7 Mon Sep 17 00:00:00 2001 From: Andreas Gruenbacher Date: Wed, 27 Jul 2005 11:45:15 -0700 Subject: [PATCH] mbcache: Remove unused mb_cache_shrink parameter The cache parameter to mb_cache_shrink isn't used. We may as well remove it. Signed-off-by: Andreas Gruenbacher Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/ext2/xattr.c | 2 +- fs/ext3/xattr.c | 2 +- fs/mbcache.c | 3 +-- 3 files changed, 3 insertions(+), 4 deletions(-) (limited to 'fs') diff --git a/fs/ext2/xattr.c b/fs/ext2/xattr.c index 27982b500e8..0099462d427 100644 --- a/fs/ext2/xattr.c +++ b/fs/ext2/xattr.c @@ -823,7 +823,7 @@ cleanup: void ext2_xattr_put_super(struct super_block *sb) { - mb_cache_shrink(ext2_xattr_cache, sb->s_bdev); + mb_cache_shrink(sb->s_bdev); } diff --git a/fs/ext3/xattr.c b/fs/ext3/xattr.c index 3f9dfa643b1..269c7b92db9 100644 --- a/fs/ext3/xattr.c +++ b/fs/ext3/xattr.c @@ -1106,7 +1106,7 @@ cleanup: void ext3_xattr_put_super(struct super_block *sb) { - mb_cache_shrink(ext3_xattr_cache, sb->s_bdev); + mb_cache_shrink(sb->s_bdev); } /* diff --git a/fs/mbcache.c b/fs/mbcache.c index c7170b9221a..b002a088857 100644 --- a/fs/mbcache.c +++ b/fs/mbcache.c @@ -316,11 +316,10 @@ fail: * currently in use cannot be freed, and thus remain in the cache. All others * are freed. * - * @cache: which cache to shrink * @bdev: which device's cache entries to shrink */ void -mb_cache_shrink(struct mb_cache *cache, struct block_device *bdev) +mb_cache_shrink(struct block_device *bdev) { LIST_HEAD(free_list); struct list_head *l, *ltmp; -- cgit v1.2.3 From 02b775696fee75a04041d8d94db26a9462216d24 Mon Sep 17 00:00:00 2001 From: Andreas Gruenbacher Date: Wed, 27 Jul 2005 11:45:16 -0700 Subject: [PATCH] reiserfs doesn't use mbcache reiserfs doesn't use the mbcache, so this can go. Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/reiserfs/xattr.c | 1 - 1 file changed, 1 deletion(-) (limited to 'fs') diff --git a/fs/reiserfs/xattr.c b/fs/reiserfs/xattr.c index e386d3db305..87ac9dc8b38 100644 --- a/fs/reiserfs/xattr.c +++ b/fs/reiserfs/xattr.c @@ -39,7 +39,6 @@ #include #include #include -#include #include #include #include -- cgit v1.2.3 From 44456d37b59d8e541936ed26d8b6e08d27e88ac1 Mon Sep 17 00:00:00 2001 From: Olaf Hering Date: Wed, 27 Jul 2005 11:45:17 -0700 Subject: [PATCH] turn many #if $undefined_string into #ifdef $undefined_string turn many #if $undefined_string into #ifdef $undefined_string to fix some warnings after -Wno-def was added to global CFLAGS Signed-off-by: Olaf Hering Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/ntfs/sysctl.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'fs') diff --git a/fs/ntfs/sysctl.h b/fs/ntfs/sysctl.h index df749cc0aac..c8064cae8f1 100644 --- a/fs/ntfs/sysctl.h +++ b/fs/ntfs/sysctl.h @@ -26,7 +26,7 @@ #include -#if (DEBUG && CONFIG_SYSCTL) +#if defined(DEBUG) && defined(CONFIG_SYSCTL) extern int ntfs_sysctl(int add); -- cgit v1.2.3 From 77933d7276ee8fa0e2947641941a6f7a100a327b Mon Sep 17 00:00:00 2001 From: Jesper Juhl Date: Wed, 27 Jul 2005 11:46:09 -0700 Subject: [PATCH] clean up inline static vs static inline `gcc -W' likes to complain if the static keyword is not at the beginning of the declaration. This patch fixes all remaining occurrences of "inline static" up with "static inline" in the entire kernel tree (140 occurrences in 47 files). While making this change I came across a few lines with trailing whitespace that I also fixed up, I have also added or removed a blank line or two here and there, but there are no functional changes in the patch. Signed-off-by: Jesper Juhl Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/reiserfs/journal.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'fs') diff --git a/fs/reiserfs/journal.c b/fs/reiserfs/journal.c index c66c27ec410..ca7989b04be 100644 --- a/fs/reiserfs/journal.c +++ b/fs/reiserfs/journal.c @@ -556,14 +556,14 @@ static inline void insert_journal_hash(struct reiserfs_journal_cnode **table, } /* lock the current transaction */ -inline static void lock_journal(struct super_block *p_s_sb) +static inline void lock_journal(struct super_block *p_s_sb) { PROC_INFO_INC(p_s_sb, journal.lock_journal); down(&SB_JOURNAL(p_s_sb)->j_lock); } /* unlock the current transaction */ -inline static void unlock_journal(struct super_block *p_s_sb) +static inline void unlock_journal(struct super_block *p_s_sb) { up(&SB_JOURNAL(p_s_sb)->j_lock); } -- cgit v1.2.3