diff options
Diffstat (limited to 'fs')
| -rw-r--r-- | fs/autofs4/autofs_i.h | 1 | ||||
| -rw-r--r-- | fs/autofs4/inode.c | 1 | ||||
| -rw-r--r-- | fs/autofs4/waitq.c | 40 | ||||
| -rw-r--r-- | fs/block_dev.c | 10 | ||||
| -rw-r--r-- | fs/coda/cnode.c | 38 | ||||
| -rw-r--r-- | fs/coda/coda_fs_i.h | 4 | ||||
| -rw-r--r-- | fs/coda/dir.c | 29 | ||||
| -rw-r--r-- | fs/coda/inode.c | 10 | ||||
| -rw-r--r-- | fs/dcache.c | 15 | ||||
| -rw-r--r-- | fs/hfsplus/super.c | 11 | 
10 files changed, 86 insertions, 73 deletions
| diff --git a/fs/autofs4/autofs_i.h b/fs/autofs4/autofs_i.h index 5869d4e974a..d8d8e7ba6a1 100644 --- a/fs/autofs4/autofs_i.h +++ b/fs/autofs4/autofs_i.h @@ -116,6 +116,7 @@ struct autofs_sb_info {  	int needs_reghost;  	struct super_block *sb;  	struct mutex wq_mutex; +	struct mutex pipe_mutex;  	spinlock_t fs_lock;  	struct autofs_wait_queue *queues; /* Wait queue pointer */  	spinlock_t lookup_lock; diff --git a/fs/autofs4/inode.c b/fs/autofs4/inode.c index 2ba44c79d54..e16980b00b8 100644 --- a/fs/autofs4/inode.c +++ b/fs/autofs4/inode.c @@ -225,6 +225,7 @@ int autofs4_fill_super(struct super_block *s, void *data, int silent)  	sbi->min_proto = 0;  	sbi->max_proto = 0;  	mutex_init(&sbi->wq_mutex); +	mutex_init(&sbi->pipe_mutex);  	spin_lock_init(&sbi->fs_lock);  	sbi->queues = NULL;  	spin_lock_init(&sbi->lookup_lock); diff --git a/fs/autofs4/waitq.c b/fs/autofs4/waitq.c index e1fbdeef85d..9ef5b291440 100644 --- a/fs/autofs4/waitq.c +++ b/fs/autofs4/waitq.c @@ -56,26 +56,27 @@ void autofs4_catatonic_mode(struct autofs_sb_info *sbi)  	mutex_unlock(&sbi->wq_mutex);  } -static int autofs4_write(struct file *file, const void *addr, int bytes) +static int autofs4_write(struct autofs_sb_info *sbi, +			 struct file *file, const void *addr, int bytes)  {  	unsigned long sigpipe, flags;  	mm_segment_t fs;  	const char *data = (const char *)addr;  	ssize_t wr = 0; -	/** WARNING: this is not safe for writing more than PIPE_BUF bytes! **/ -  	sigpipe = sigismember(¤t->pending.signal, SIGPIPE);  	/* Save pointer to user space and point back to kernel space */  	fs = get_fs();  	set_fs(KERNEL_DS); +	mutex_lock(&sbi->pipe_mutex);  	while (bytes &&  	       (wr = file->f_op->write(file,data,bytes,&file->f_pos)) > 0) {  		data += wr;  		bytes -= wr;  	} +	mutex_lock(&sbi->pipe_mutex);  	set_fs(fs); @@ -110,6 +111,13 @@ static void autofs4_notify_daemon(struct autofs_sb_info *sbi,  	pkt.hdr.proto_version = sbi->version;  	pkt.hdr.type = type; +	mutex_lock(&sbi->wq_mutex); + +	/* Check if we have become catatonic */ +	if (sbi->catatonic) { +		mutex_unlock(&sbi->wq_mutex); +		return; +	}  	switch (type) {  	/* Kernel protocol v4 missing and expire packets */  	case autofs_ptype_missing: @@ -163,22 +171,18 @@ static void autofs4_notify_daemon(struct autofs_sb_info *sbi,  	}  	default:  		printk("autofs4_notify_daemon: bad type %d!\n", type); +		mutex_unlock(&sbi->wq_mutex);  		return;  	} -	/* Check if we have become catatonic */ -	mutex_lock(&sbi->wq_mutex); -	if (!sbi->catatonic) { -		pipe = sbi->pipe; -		get_file(pipe); -	} +	pipe = sbi->pipe; +	get_file(pipe); +  	mutex_unlock(&sbi->wq_mutex); -	if (pipe) { -		if (autofs4_write(pipe, &pkt, pktsz)) -			autofs4_catatonic_mode(sbi); -		fput(pipe); -	} +	if (autofs4_write(sbi, pipe, &pkt, pktsz)) +		autofs4_catatonic_mode(sbi); +	fput(pipe);  }  static int autofs4_getpath(struct autofs_sb_info *sbi, @@ -257,6 +261,9 @@ static int validate_request(struct autofs_wait_queue **wait,  	struct autofs_wait_queue *wq;  	struct autofs_info *ino; +	if (sbi->catatonic) +		return -ENOENT; +  	/* Wait in progress, continue; */  	wq = autofs4_find_wait(sbi, qstr);  	if (wq) { @@ -289,6 +296,9 @@ static int validate_request(struct autofs_wait_queue **wait,  			if (mutex_lock_interruptible(&sbi->wq_mutex))  				return -EINTR; +			if (sbi->catatonic) +				return -ENOENT; +  			wq = autofs4_find_wait(sbi, qstr);  			if (wq) {  				*wait = wq; @@ -389,7 +399,7 @@ int autofs4_wait(struct autofs_sb_info *sbi, struct dentry *dentry,  	ret = validate_request(&wq, sbi, &qstr, dentry, notify);  	if (ret <= 0) { -		if (ret == 0) +		if (ret != -EINTR)  			mutex_unlock(&sbi->wq_mutex);  		kfree(qstr.name);  		return ret; diff --git a/fs/block_dev.c b/fs/block_dev.c index 69a5b6fbee2..afe74dda632 100644 --- a/fs/block_dev.c +++ b/fs/block_dev.c @@ -25,7 +25,6 @@  #include <linux/uio.h>  #include <linux/namei.h>  #include <linux/log2.h> -#include <linux/kmemleak.h>  #include <linux/cleancache.h>  #include <asm/uaccess.h>  #include "internal.h" @@ -521,7 +520,7 @@ static struct super_block *blockdev_superblock __read_mostly;  void __init bdev_cache_init(void)  {  	int err; -	struct vfsmount *bd_mnt; +	static struct vfsmount *bd_mnt;  	bdev_cachep = kmem_cache_create("bdev_cache", sizeof(struct bdev_inode),  			0, (SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT| @@ -533,12 +532,7 @@ void __init bdev_cache_init(void)  	bd_mnt = kern_mount(&bd_type);  	if (IS_ERR(bd_mnt))  		panic("Cannot create bdev pseudo-fs"); -	/* -	 * This vfsmount structure is only used to obtain the -	 * blockdev_superblock, so tell kmemleak not to report it. -	 */ -	kmemleak_not_leak(bd_mnt); -	blockdev_superblock = bd_mnt->mnt_sb;	/* For writeback */ +	blockdev_superblock = bd_mnt->mnt_sb;   /* For writeback */  }  /* diff --git a/fs/coda/cnode.c b/fs/coda/cnode.c index 6475877b076..911cf30d057 100644 --- a/fs/coda/cnode.c +++ b/fs/coda/cnode.c @@ -88,24 +88,21 @@ struct inode * coda_iget(struct super_block * sb, struct CodaFid * fid,     - link the two up if this is needed     - fill in the attributes  */ -int coda_cnode_make(struct inode **inode, struct CodaFid *fid, struct super_block *sb) +struct inode *coda_cnode_make(struct CodaFid *fid, struct super_block *sb)  {          struct coda_vattr attr; +	struct inode *inode;          int error;  	/* We get inode numbers from Venus -- see venus source */  	error = venus_getattr(sb, fid, &attr); -	if ( error ) { -	    *inode = NULL; -	    return error; -	}  +	if (error) +		return ERR_PTR(error); -	*inode = coda_iget(sb, fid, &attr); -	if ( IS_ERR(*inode) ) { +	inode = coda_iget(sb, fid, &attr); +	if (IS_ERR(inode))  		printk("coda_cnode_make: coda_iget failed\n"); -                return PTR_ERR(*inode); -        } -	return 0; +	return inode;  } @@ -156,19 +153,16 @@ struct inode *coda_fid_to_inode(struct CodaFid *fid, struct super_block *sb)  }  /* the CONTROL inode is made without asking attributes from Venus */ -int coda_cnode_makectl(struct inode **inode, struct super_block *sb) +struct inode *coda_cnode_makectl(struct super_block *sb)  { -	int error = -ENOMEM; - -	*inode = new_inode(sb); -	if (*inode) { -		(*inode)->i_ino = CTL_INO; -		(*inode)->i_op = &coda_ioctl_inode_operations; -		(*inode)->i_fop = &coda_ioctl_operations; -		(*inode)->i_mode = 0444; -		error = 0; +	struct inode *inode = new_inode(sb); +	if (inode) { +		inode->i_ino = CTL_INO; +		inode->i_op = &coda_ioctl_inode_operations; +		inode->i_fop = &coda_ioctl_operations; +		inode->i_mode = 0444; +		return inode;  	} - -	return error; +	return ERR_PTR(-ENOMEM);  } diff --git a/fs/coda/coda_fs_i.h b/fs/coda/coda_fs_i.h index e35071b1de0..b24fdfd8a3f 100644 --- a/fs/coda/coda_fs_i.h +++ b/fs/coda/coda_fs_i.h @@ -49,9 +49,9 @@ struct coda_file_info {  #define C_DYING       0x4   /* from venus (which died) */  #define C_PURGE       0x8 -int coda_cnode_make(struct inode **, struct CodaFid *, struct super_block *); +struct inode *coda_cnode_make(struct CodaFid *, struct super_block *);  struct inode *coda_iget(struct super_block *sb, struct CodaFid *fid, struct coda_vattr *attr); -int coda_cnode_makectl(struct inode **inode, struct super_block *sb); +struct inode *coda_cnode_makectl(struct super_block *sb);  struct inode *coda_fid_to_inode(struct CodaFid *fid, struct super_block *sb);  void coda_replace_fid(struct inode *, struct CodaFid *, struct CodaFid *); diff --git a/fs/coda/dir.c b/fs/coda/dir.c index 83d2fd8ec24..17751582906 100644 --- a/fs/coda/dir.c +++ b/fs/coda/dir.c @@ -96,12 +96,11 @@ const struct file_operations coda_dir_operations = {  /* access routines: lookup, readlink, permission */  static struct dentry *coda_lookup(struct inode *dir, struct dentry *entry, struct nameidata *nd)  { -	struct inode *inode = NULL; -	struct CodaFid resfid = { { 0, } }; -	int type = 0; -	int error = 0; +	struct super_block *sb = dir->i_sb;  	const char *name = entry->d_name.name;  	size_t length = entry->d_name.len; +	struct inode *inode; +	int type = 0;  	if (length > CODA_MAXNAMLEN) {  		printk(KERN_ERR "name too long: lookup, %s (%*s)\n", @@ -111,23 +110,21 @@ static struct dentry *coda_lookup(struct inode *dir, struct dentry *entry, struc  	/* control object, create inode on the fly */  	if (coda_isroot(dir) && coda_iscontrol(name, length)) { -		error = coda_cnode_makectl(&inode, dir->i_sb); +		inode = coda_cnode_makectl(sb);  		type = CODA_NOCACHE; -		goto exit; +	} else { +		struct CodaFid fid = { { 0, } }; +		int error = venus_lookup(sb, coda_i2f(dir), name, length, +				     &type, &fid); +		inode = !error ? coda_cnode_make(&fid, sb) : ERR_PTR(error);  	} -	error = venus_lookup(dir->i_sb, coda_i2f(dir), name, length, -			     &type, &resfid); -	if (!error) -		error = coda_cnode_make(&inode, &resfid, dir->i_sb); - -	if (error && error != -ENOENT) -		return ERR_PTR(error); - -exit: -	if (inode && (type & CODA_NOCACHE)) +	if (!IS_ERR(inode) && (type & CODA_NOCACHE))  		coda_flag_inode(inode, C_VATTR | C_PURGE); +	if (inode == ERR_PTR(-ENOENT)) +		inode = NULL; +  	return d_splice_alias(inode, entry);  } diff --git a/fs/coda/inode.c b/fs/coda/inode.c index 1c08a8cd673..5e2e1b3f068 100644 --- a/fs/coda/inode.c +++ b/fs/coda/inode.c @@ -204,10 +204,12 @@ static int coda_fill_super(struct super_block *sb, void *data, int silent)  	printk("coda_read_super: rootfid is %s\n", coda_f2s(&fid));  	/* make root inode */ -        error = coda_cnode_make(&root, &fid, sb); -        if ( error || !root ) { -	    printk("Failure of coda_cnode_make for root: error %d\n", error); -	    goto error; +        root = coda_cnode_make(&fid, sb); +        if (IS_ERR(root)) { +		error = PTR_ERR(root); +		printk("Failure of coda_cnode_make for root: error %d\n", error); +		root = NULL; +		goto error;  	}   	printk("coda_read_super: rootinode is %ld dev %s\n",  diff --git a/fs/dcache.c b/fs/dcache.c index 3c6d3113a25..616fedff011 100644 --- a/fs/dcache.c +++ b/fs/dcache.c @@ -243,6 +243,7 @@ static void dentry_lru_add(struct dentry *dentry)  static void __dentry_lru_del(struct dentry *dentry)  {  	list_del_init(&dentry->d_lru); +	dentry->d_flags &= ~DCACHE_SHRINK_LIST;  	dentry->d_sb->s_nr_dentry_unused--;  	dentry_stat.nr_unused--;  } @@ -806,6 +807,7 @@ relock:  			spin_unlock(&dentry->d_lock);  		} else {  			list_move_tail(&dentry->d_lru, &tmp); +			dentry->d_flags |= DCACHE_SHRINK_LIST;  			spin_unlock(&dentry->d_lock);  			if (!--count)  				break; @@ -1097,14 +1099,19 @@ resume:  		/*  		 * move only zero ref count dentries to the dispose list. +		 * +		 * Those which are presently on the shrink list, being processed +		 * by shrink_dentry_list(), shouldn't be moved.  Otherwise the +		 * loop in shrink_dcache_parent() might not make any progress +		 * and loop forever.  		 */ -		if (!dentry->d_count) { +		if (dentry->d_count) { +			dentry_lru_del(dentry); +		} else if (!(dentry->d_flags & DCACHE_SHRINK_LIST)) {  			dentry_lru_move_list(dentry, dispose); +			dentry->d_flags |= DCACHE_SHRINK_LIST;  			found++; -		} else { -			dentry_lru_del(dentry);  		} -  		/*  		 * We can return to the caller if we have found some (this  		 * ensures forward progress). We'll be coming back to find diff --git a/fs/hfsplus/super.c b/fs/hfsplus/super.c index edf0a801446..427682ca9e4 100644 --- a/fs/hfsplus/super.c +++ b/fs/hfsplus/super.c @@ -499,9 +499,16 @@ static int hfsplus_fill_super(struct super_block *sb, void *data, int silent)  		if (!sbi->hidden_dir) {  			mutex_lock(&sbi->vh_mutex);  			sbi->hidden_dir = hfsplus_new_inode(sb, S_IFDIR); -			hfsplus_create_cat(sbi->hidden_dir->i_ino, root, &str, -					   sbi->hidden_dir); +			if (!sbi->hidden_dir) { +				mutex_unlock(&sbi->vh_mutex); +				err = -ENOMEM; +				goto out_put_root; +			} +			err = hfsplus_create_cat(sbi->hidden_dir->i_ino, root, +						 &str, sbi->hidden_dir);  			mutex_unlock(&sbi->vh_mutex); +			if (err) +				goto out_put_hidden_dir;  			hfsplus_mark_inode_dirty(sbi->hidden_dir,  						 HFSPLUS_I_CAT_DIRTY); | 
