diff options
Diffstat (limited to 'fs')
| -rw-r--r-- | fs/cifs/cifs_unicode.c | 2 | ||||
| -rw-r--r-- | fs/dcache.c | 6 | ||||
| -rw-r--r-- | fs/debugfs/file.c | 74 | ||||
| -rw-r--r-- | fs/proc/proc_sysctl.c | 5 | ||||
| -rw-r--r-- | fs/xfs/xfs_buf.c | 5 | ||||
| -rw-r--r-- | fs/xfs/xfs_buf.h | 41 | ||||
| -rw-r--r-- | fs/xfs/xfs_super.c | 1 | 
7 files changed, 61 insertions, 73 deletions
diff --git a/fs/cifs/cifs_unicode.c b/fs/cifs/cifs_unicode.c index 7dab9c04ad5..53cf2aabce8 100644 --- a/fs/cifs/cifs_unicode.c +++ b/fs/cifs/cifs_unicode.c @@ -328,7 +328,7 @@ cifsConvertToUTF16(__le16 *target, const char *source, int srclen,  	}  ctoUTF16_out: -	return i; +	return j;  }  #ifdef CONFIG_CIFS_SMB2 diff --git a/fs/dcache.c b/fs/dcache.c index 8086636bf79..0364af2311f 100644 --- a/fs/dcache.c +++ b/fs/dcache.c @@ -389,7 +389,7 @@ static struct dentry *d_kill(struct dentry *dentry, struct dentry *parent)  	 * Inform try_to_ascend() that we are no longer attached to the  	 * dentry tree  	 */ -	dentry->d_flags |= DCACHE_DISCONNECTED; +	dentry->d_flags |= DCACHE_DENTRY_KILLED;  	if (parent)  		spin_unlock(&parent->d_lock);  	dentry_iput(dentry); @@ -1048,7 +1048,7 @@ static struct dentry *try_to_ascend(struct dentry *old, int locked, unsigned seq  	 * or deletion  	 */  	if (new != old->d_parent || -		 (old->d_flags & DCACHE_DISCONNECTED) || +		 (old->d_flags & DCACHE_DENTRY_KILLED) ||  		 (!locked && read_seqretry(&rename_lock, seq))) {  		spin_unlock(&new->d_lock);  		new = NULL; @@ -1141,7 +1141,7 @@ rename_retry:  EXPORT_SYMBOL(have_submounts);  /* - * Search the dentry child list for the specified parent, + * Search the dentry child list of the specified parent,   * and move any unused dentries to the end of the unused   * list for prune_dcache(). We descend to the next level   * whenever the d_subdirs list is non-empty and continue diff --git a/fs/debugfs/file.c b/fs/debugfs/file.c index 2340f6978d6..c5ca6ae5a30 100644 --- a/fs/debugfs/file.c +++ b/fs/debugfs/file.c @@ -526,73 +526,51 @@ struct array_data {  	u32 elements;  }; -static int u32_array_open(struct inode *inode, struct file *file) -{ -	file->private_data = NULL; -	return nonseekable_open(inode, file); -} - -static size_t format_array(char *buf, size_t bufsize, const char *fmt, -			   u32 *array, u32 array_size) +static size_t u32_format_array(char *buf, size_t bufsize, +			       u32 *array, int array_size)  {  	size_t ret = 0; -	u32 i; -	for (i = 0; i < array_size; i++) { +	while (--array_size >= 0) {  		size_t len; +		char term = array_size ? ' ' : '\n'; -		len = snprintf(buf, bufsize, fmt, array[i]); -		len++;	/* ' ' or '\n' */ +		len = snprintf(buf, bufsize, "%u%c", *array++, term);  		ret += len; -		if (buf) { -			buf += len; -			bufsize -= len; -			buf[-1] = (i == array_size-1) ? '\n' : ' '; -		} +		buf += len; +		bufsize -= len;  	} - -	ret++;		/* \0 */ -	if (buf) -		*buf = '\0'; -  	return ret;  } -static char *format_array_alloc(const char *fmt, u32 *array, -						u32 array_size) +static int u32_array_open(struct inode *inode, struct file *file)  { -	size_t len = format_array(NULL, 0, fmt, array, array_size); -	char *ret; +	struct array_data *data = inode->i_private; +	int size, elements = data->elements; +	char *buf; -	ret = kmalloc(len, GFP_KERNEL); -	if (ret == NULL) -		return NULL; +	/* +	 * Max size: +	 *  - 10 digits + ' '/'\n' = 11 bytes per number +	 *  - terminating NUL character +	 */ +	size = elements*11; +	buf = kmalloc(size+1, GFP_KERNEL); +	if (!buf) +		return -ENOMEM; +	buf[size] = 0; -	format_array(ret, len, fmt, array, array_size); -	return ret; +	file->private_data = buf; +	u32_format_array(buf, size, data->array, data->elements); + +	return nonseekable_open(inode, file);  }  static ssize_t u32_array_read(struct file *file, char __user *buf, size_t len,  			      loff_t *ppos)  { -	struct inode *inode = file->f_path.dentry->d_inode; -	struct array_data *data = inode->i_private; -	size_t size; - -	if (*ppos == 0) { -		if (file->private_data) { -			kfree(file->private_data); -			file->private_data = NULL; -		} - -		file->private_data = format_array_alloc("%u", data->array, -							      data->elements); -	} - -	size = 0; -	if (file->private_data) -		size = strlen(file->private_data); +	size_t size = strlen(file->private_data);  	return simple_read_from_buffer(buf, len, ppos,  					file->private_data, size); diff --git a/fs/proc/proc_sysctl.c b/fs/proc/proc_sysctl.c index dfafeb2b05a..eb7cc91b725 100644 --- a/fs/proc/proc_sysctl.c +++ b/fs/proc/proc_sysctl.c @@ -462,9 +462,6 @@ static struct dentry *proc_sys_lookup(struct inode *dir, struct dentry *dentry,  	err = ERR_PTR(-ENOMEM);  	inode = proc_sys_make_inode(dir->i_sb, h ? h : head, p); -	if (h) -		sysctl_head_finish(h); -  	if (!inode)  		goto out; @@ -473,6 +470,8 @@ static struct dentry *proc_sys_lookup(struct inode *dir, struct dentry *dentry,  	d_add(dentry, inode);  out: +	if (h) +		sysctl_head_finish(h);  	sysctl_head_finish(head);  	return err;  } diff --git a/fs/xfs/xfs_buf.c b/fs/xfs/xfs_buf.c index d7a9dd735e1..933b7930b86 100644 --- a/fs/xfs/xfs_buf.c +++ b/fs/xfs/xfs_buf.c @@ -96,6 +96,7 @@ xfs_buf_lru_add(  		atomic_inc(&bp->b_hold);  		list_add_tail(&bp->b_lru, &btp->bt_lru);  		btp->bt_lru_nr++; +		bp->b_lru_flags &= ~_XBF_LRU_DISPOSE;  	}  	spin_unlock(&btp->bt_lru_lock);  } @@ -154,7 +155,8 @@ xfs_buf_stale(  		struct xfs_buftarg *btp = bp->b_target;  		spin_lock(&btp->bt_lru_lock); -		if (!list_empty(&bp->b_lru)) { +		if (!list_empty(&bp->b_lru) && +		    !(bp->b_lru_flags & _XBF_LRU_DISPOSE)) {  			list_del_init(&bp->b_lru);  			btp->bt_lru_nr--;  			atomic_dec(&bp->b_hold); @@ -1501,6 +1503,7 @@ xfs_buftarg_shrink(  		 */  		list_move(&bp->b_lru, &dispose);  		btp->bt_lru_nr--; +		bp->b_lru_flags |= _XBF_LRU_DISPOSE;  	}  	spin_unlock(&btp->bt_lru_lock); diff --git a/fs/xfs/xfs_buf.h b/fs/xfs/xfs_buf.h index d03b73b9604..7c0b6a0a155 100644 --- a/fs/xfs/xfs_buf.h +++ b/fs/xfs/xfs_buf.h @@ -38,27 +38,28 @@ typedef enum {  	XBRW_ZERO = 3,			/* Zero target memory */  } xfs_buf_rw_t; -#define XBF_READ	(1 << 0) /* buffer intended for reading from device */ -#define XBF_WRITE	(1 << 1) /* buffer intended for writing to device */ -#define XBF_READ_AHEAD	(1 << 2) /* asynchronous read-ahead */ -#define XBF_ASYNC	(1 << 4) /* initiator will not wait for completion */ -#define XBF_DONE	(1 << 5) /* all pages in the buffer uptodate */ -#define XBF_STALE	(1 << 6) /* buffer has been staled, do not find it */ +#define XBF_READ	 (1 << 0) /* buffer intended for reading from device */ +#define XBF_WRITE	 (1 << 1) /* buffer intended for writing to device */ +#define XBF_READ_AHEAD	 (1 << 2) /* asynchronous read-ahead */ +#define XBF_ASYNC	 (1 << 4) /* initiator will not wait for completion */ +#define XBF_DONE	 (1 << 5) /* all pages in the buffer uptodate */ +#define XBF_STALE	 (1 << 6) /* buffer has been staled, do not find it */  /* I/O hints for the BIO layer */ -#define XBF_SYNCIO	(1 << 10)/* treat this buffer as synchronous I/O */ -#define XBF_FUA		(1 << 11)/* force cache write through mode */ -#define XBF_FLUSH	(1 << 12)/* flush the disk cache before a write */ +#define XBF_SYNCIO	 (1 << 10)/* treat this buffer as synchronous I/O */ +#define XBF_FUA		 (1 << 11)/* force cache write through mode */ +#define XBF_FLUSH	 (1 << 12)/* flush the disk cache before a write */  /* flags used only as arguments to access routines */ -#define XBF_TRYLOCK	(1 << 16)/* lock requested, but do not wait */ -#define XBF_UNMAPPED	(1 << 17)/* do not map the buffer */ +#define XBF_TRYLOCK	 (1 << 16)/* lock requested, but do not wait */ +#define XBF_UNMAPPED	 (1 << 17)/* do not map the buffer */  /* flags used only internally */ -#define _XBF_PAGES	(1 << 20)/* backed by refcounted pages */ -#define _XBF_KMEM	(1 << 21)/* backed by heap memory */ -#define _XBF_DELWRI_Q	(1 << 22)/* buffer on a delwri queue */ -#define _XBF_COMPOUND	(1 << 23)/* compound buffer */ +#define _XBF_PAGES	 (1 << 20)/* backed by refcounted pages */ +#define _XBF_KMEM	 (1 << 21)/* backed by heap memory */ +#define _XBF_DELWRI_Q	 (1 << 22)/* buffer on a delwri queue */ +#define _XBF_COMPOUND	 (1 << 23)/* compound buffer */ +#define _XBF_LRU_DISPOSE (1 << 24)/* buffer being discarded */  typedef unsigned int xfs_buf_flags_t; @@ -72,12 +73,13 @@ typedef unsigned int xfs_buf_flags_t;  	{ XBF_SYNCIO,		"SYNCIO" }, \  	{ XBF_FUA,		"FUA" }, \  	{ XBF_FLUSH,		"FLUSH" }, \ -	{ XBF_TRYLOCK,		"TRYLOCK" }, 	/* should never be set */\ +	{ XBF_TRYLOCK,		"TRYLOCK" },	/* should never be set */\  	{ XBF_UNMAPPED,		"UNMAPPED" },	/* ditto */\  	{ _XBF_PAGES,		"PAGES" }, \  	{ _XBF_KMEM,		"KMEM" }, \  	{ _XBF_DELWRI_Q,	"DELWRI_Q" }, \ -	{ _XBF_COMPOUND,	"COMPOUND" } +	{ _XBF_COMPOUND,	"COMPOUND" }, \ +	{ _XBF_LRU_DISPOSE,	"LRU_DISPOSE" }  typedef struct xfs_buftarg {  	dev_t			bt_dev; @@ -124,7 +126,12 @@ typedef struct xfs_buf {  	xfs_buf_flags_t		b_flags;	/* status flags */  	struct semaphore	b_sema;		/* semaphore for lockables */ +	/* +	 * concurrent access to b_lru and b_lru_flags are protected by +	 * bt_lru_lock and not by b_sema +	 */  	struct list_head	b_lru;		/* lru list */ +	xfs_buf_flags_t		b_lru_flags;	/* internal lru status flags */  	wait_queue_head_t	b_waiters;	/* unpin waiters */  	struct list_head	b_list;  	struct xfs_perag	*b_pag;		/* contains rbtree root */ diff --git a/fs/xfs/xfs_super.c b/fs/xfs/xfs_super.c index bdaf4cb9f4a..19e2380fb86 100644 --- a/fs/xfs/xfs_super.c +++ b/fs/xfs/xfs_super.c @@ -919,6 +919,7 @@ xfs_fs_put_super(  	struct xfs_mount	*mp = XFS_M(sb);  	xfs_filestream_unmount(mp); +	cancel_delayed_work_sync(&mp->m_sync_work);  	xfs_unmountfs(mp);  	xfs_syncd_stop(mp);  	xfs_freesb(mp);  |