diff options
Diffstat (limited to 'fs/ntfs')
| -rw-r--r-- | fs/ntfs/Makefile | 19 | ||||
| -rw-r--r-- | fs/ntfs/aops.c | 26 | ||||
| -rw-r--r-- | fs/ntfs/attrib.c | 31 | ||||
| -rw-r--r-- | fs/ntfs/compress.c | 7 | ||||
| -rw-r--r-- | fs/ntfs/debug.c | 58 | ||||
| -rw-r--r-- | fs/ntfs/debug.h | 22 | ||||
| -rw-r--r-- | fs/ntfs/dir.c | 94 | ||||
| -rw-r--r-- | fs/ntfs/file.c | 98 | ||||
| -rw-r--r-- | fs/ntfs/inode.c | 64 | ||||
| -rw-r--r-- | fs/ntfs/inode.h | 8 | ||||
| -rw-r--r-- | fs/ntfs/layout.h | 16 | ||||
| -rw-r--r-- | fs/ntfs/logfile.c | 2 | ||||
| -rw-r--r-- | fs/ntfs/logfile.h | 2 | ||||
| -rw-r--r-- | fs/ntfs/mft.c | 23 | ||||
| -rw-r--r-- | fs/ntfs/namei.c | 2 | ||||
| -rw-r--r-- | fs/ntfs/runlist.c | 2 | ||||
| -rw-r--r-- | fs/ntfs/super.c | 144 | ||||
| -rw-r--r-- | fs/ntfs/sysctl.c | 6 | ||||
| -rw-r--r-- | fs/ntfs/volume.h | 9 | 
19 files changed, 319 insertions, 314 deletions
diff --git a/fs/ntfs/Makefile b/fs/ntfs/Makefile index 58b6be99254..30206b23843 100644 --- a/fs/ntfs/Makefile +++ b/fs/ntfs/Makefile @@ -2,18 +2,13 @@  obj-$(CONFIG_NTFS_FS) += ntfs.o -ntfs-objs := aops.o attrib.o collate.o compress.o debug.o dir.o file.o \ -	     index.o inode.o mft.o mst.o namei.o runlist.o super.o sysctl.o \ -	     unistr.o upcase.o +ntfs-y := aops.o attrib.o collate.o compress.o debug.o dir.o file.o \ +	  index.o inode.o mft.o mst.o namei.o runlist.o super.o sysctl.o \ +	  unistr.o upcase.o -EXTRA_CFLAGS = -DNTFS_VERSION=\"2.1.29\" +ntfs-$(CONFIG_NTFS_RW) += bitmap.o lcnalloc.o logfile.o quota.o usnjrnl.o -ifeq ($(CONFIG_NTFS_DEBUG),y) -EXTRA_CFLAGS += -DDEBUG -endif +ccflags-y := -DNTFS_VERSION=\"2.1.30\" +ccflags-$(CONFIG_NTFS_DEBUG)	+= -DDEBUG +ccflags-$(CONFIG_NTFS_RW)	+= -DNTFS_RW -ifeq ($(CONFIG_NTFS_RW),y) -EXTRA_CFLAGS += -DNTFS_RW - -ntfs-objs += bitmap.o lcnalloc.o logfile.o quota.o usnjrnl.o -endif diff --git a/fs/ntfs/aops.c b/fs/ntfs/aops.c index c3c2c7ac902..d267ea6aa1a 100644 --- a/fs/ntfs/aops.c +++ b/fs/ntfs/aops.c @@ -94,11 +94,11 @@ static void ntfs_end_buffer_async_read(struct buffer_head *bh, int uptodate)  			if (file_ofs < init_size)  				ofs = init_size - file_ofs;  			local_irq_save(flags); -			kaddr = kmap_atomic(page, KM_BIO_SRC_IRQ); +			kaddr = kmap_atomic(page);  			memset(kaddr + bh_offset(bh) + ofs, 0,  					bh->b_size - ofs);  			flush_dcache_page(page); -			kunmap_atomic(kaddr, KM_BIO_SRC_IRQ); +			kunmap_atomic(kaddr);  			local_irq_restore(flags);  		}  	} else { @@ -147,11 +147,11 @@ static void ntfs_end_buffer_async_read(struct buffer_head *bh, int uptodate)  		/* Should have been verified before we got here... */  		BUG_ON(!recs);  		local_irq_save(flags); -		kaddr = kmap_atomic(page, KM_BIO_SRC_IRQ); +		kaddr = kmap_atomic(page);  		for (i = 0; i < recs; i++)  			post_read_mst_fixup((NTFS_RECORD*)(kaddr +  					i * rec_size), rec_size); -		kunmap_atomic(kaddr, KM_BIO_SRC_IRQ); +		kunmap_atomic(kaddr);  		local_irq_restore(flags);  		flush_dcache_page(page);  		if (likely(page_uptodate && !PageError(page))) @@ -504,7 +504,7 @@ retry_readpage:  		/* Race with shrinking truncate. */  		attr_len = i_size;  	} -	addr = kmap_atomic(page, KM_USER0); +	addr = kmap_atomic(page);  	/* Copy the data to the page. */  	memcpy(addr, (u8*)ctx->attr +  			le16_to_cpu(ctx->attr->data.resident.value_offset), @@ -512,7 +512,7 @@ retry_readpage:  	/* Zero the remainder of the page. */  	memset(addr + attr_len, 0, PAGE_CACHE_SIZE - attr_len);  	flush_dcache_page(page); -	kunmap_atomic(addr, KM_USER0); +	kunmap_atomic(addr);  put_unm_err_out:  	ntfs_attr_put_search_ctx(ctx);  unm_err_out: @@ -746,14 +746,14 @@ lock_retry_remap:  			unsigned long *bpos, *bend;  			/* Check if the buffer is zero. */ -			kaddr = kmap_atomic(page, KM_USER0); +			kaddr = kmap_atomic(page);  			bpos = (unsigned long *)(kaddr + bh_offset(bh));  			bend = (unsigned long *)((u8*)bpos + blocksize);  			do {  				if (unlikely(*bpos))  					break;  			} while (likely(++bpos < bend)); -			kunmap_atomic(kaddr, KM_USER0); +			kunmap_atomic(kaddr);  			if (bpos == bend) {  				/*  				 * Buffer is zero and sparse, no need to write @@ -1372,7 +1372,7 @@ retry_writepage:  		 * The page may have dirty, unmapped buffers.  Make them  		 * freeable here, so the page does not leak.  		 */ -		block_invalidatepage(page, 0); +		block_invalidatepage(page, 0, PAGE_CACHE_SIZE);  		unlock_page(page);  		ntfs_debug("Write outside i_size - truncated?");  		return 0; @@ -1495,14 +1495,14 @@ retry_writepage:  		/* Shrinking cannot fail. */  		BUG_ON(err);  	} -	addr = kmap_atomic(page, KM_USER0); +	addr = kmap_atomic(page);  	/* Copy the data from the page to the mft record. */  	memcpy((u8*)ctx->attr +  			le16_to_cpu(ctx->attr->data.resident.value_offset),  			addr, attr_len);  	/* Zero out of bounds area in the page cache page. */  	memset(addr + attr_len, 0, PAGE_CACHE_SIZE - attr_len); -	kunmap_atomic(addr, KM_USER0); +	kunmap_atomic(addr);  	flush_dcache_page(page);  	flush_dcache_mft_record_page(ctx->ntfs_ino);  	/* We are done with the page. */ @@ -1543,8 +1543,6 @@ err_out:   */  const struct address_space_operations ntfs_aops = {  	.readpage	= ntfs_readpage,	/* Fill page with data. */ -	.sync_page	= block_sync_page,	/* Currently, just unplugs the -						   disk request queue. */  #ifdef NTFS_RW  	.writepage	= ntfs_writepage,	/* Write dirty page to disk. */  #endif /* NTFS_RW */ @@ -1560,8 +1558,6 @@ const struct address_space_operations ntfs_aops = {   */  const struct address_space_operations ntfs_mst_aops = {  	.readpage	= ntfs_readpage,	/* Fill page with data. */ -	.sync_page	= block_sync_page,	/* Currently, just unplugs the -						   disk request queue. */  #ifdef NTFS_RW  	.writepage	= ntfs_writepage,	/* Write dirty page to disk. */  	.set_page_dirty	= __set_page_dirty_nobuffers,	/* Set the page dirty diff --git a/fs/ntfs/attrib.c b/fs/ntfs/attrib.c index f5094ee224c..250ed5b20c8 100644 --- a/fs/ntfs/attrib.c +++ b/fs/ntfs/attrib.c @@ -1,7 +1,7 @@  /**   * attrib.c - NTFS attribute operations.  Part of the Linux-NTFS project.   * - * Copyright (c) 2001-2007 Anton Altaparmakov + * Copyright (c) 2001-2012 Anton Altaparmakov and Tuxera Inc.   * Copyright (c) 2002 Richard Russon   *   * This program/include file is free software; you can redistribute it and/or @@ -197,7 +197,7 @@ err_out:  	} else if (ctx_needs_reset) {  		/*  		 * If there is no attribute list, restoring the search context -		 * is acomplished simply by copying the saved context back over +		 * is accomplished simply by copying the saved context back over  		 * the caller supplied context.  If there is an attribute list,  		 * things are more complicated as we need to deal with mapping  		 * of mft records and resulting potential changes in pointers. @@ -345,10 +345,10 @@ LCN ntfs_attr_vcn_to_lcn_nolock(ntfs_inode *ni, const VCN vcn,  	unsigned long flags;  	bool is_retry = false; +	BUG_ON(!ni);  	ntfs_debug("Entering for i_ino 0x%lx, vcn 0x%llx, %s_locked.",  			ni->mft_no, (unsigned long long)vcn,  			write_locked ? "write" : "read"); -	BUG_ON(!ni);  	BUG_ON(!NInoNonResident(ni));  	BUG_ON(vcn < 0);  	if (!ni->runlist.rl) { @@ -469,9 +469,9 @@ runlist_element *ntfs_attr_find_vcn_nolock(ntfs_inode *ni, const VCN vcn,  	int err = 0;  	bool is_retry = false; +	BUG_ON(!ni);  	ntfs_debug("Entering for i_ino 0x%lx, vcn 0x%llx, with%s ctx.",  			ni->mft_no, (unsigned long long)vcn, ctx ? "" : "out"); -	BUG_ON(!ni);  	BUG_ON(!NInoNonResident(ni));  	BUG_ON(vcn < 0);  	if (!ni->runlist.rl) { @@ -1181,7 +1181,7 @@ not_found:   * for, i.e. if one wants to add the attribute to the mft record this is the   * correct place to insert its attribute list entry into.   * - * When -errno != -ENOENT, an error occured during the lookup.  @ctx->attr is + * When -errno != -ENOENT, an error occurred during the lookup.  @ctx->attr is   * then undefined and in particular you should not rely on it not changing.   */  int ntfs_attr_lookup(const ATTR_TYPE type, const ntfschar *name, @@ -1656,12 +1656,12 @@ int ntfs_attr_make_non_resident(ntfs_inode *ni, const u32 data_size)  	attr_size = le32_to_cpu(a->data.resident.value_length);  	BUG_ON(attr_size != data_size);  	if (page && !PageUptodate(page)) { -		kaddr = kmap_atomic(page, KM_USER0); +		kaddr = kmap_atomic(page);  		memcpy(kaddr, (u8*)a +  				le16_to_cpu(a->data.resident.value_offset),  				attr_size);  		memset(kaddr + attr_size, 0, PAGE_CACHE_SIZE - attr_size); -		kunmap_atomic(kaddr, KM_USER0); +		kunmap_atomic(kaddr);  		flush_dcache_page(page);  		SetPageUptodate(page);  	} @@ -1748,7 +1748,6 @@ int ntfs_attr_make_non_resident(ntfs_inode *ni, const u32 data_size)  	if (page) {  		set_page_dirty(page);  		unlock_page(page); -		mark_page_accessed(page);  		page_cache_release(page);  	}  	ntfs_debug("Done."); @@ -1806,9 +1805,9 @@ undo_err_out:  			sizeof(a->data.resident.reserved));  	/* Copy the data from the page back to the attribute value. */  	if (page) { -		kaddr = kmap_atomic(page, KM_USER0); +		kaddr = kmap_atomic(page);  		memcpy((u8*)a + mp_ofs, kaddr, attr_size); -		kunmap_atomic(kaddr, KM_USER0); +		kunmap_atomic(kaddr);  	}  	/* Setup the allocated size in the ntfs inode in case it changed. */  	write_lock_irqsave(&ni->size_lock, flags); @@ -2540,10 +2539,10 @@ int ntfs_attr_set(ntfs_inode *ni, const s64 ofs, const s64 cnt, const u8 val)  		size = PAGE_CACHE_SIZE;  		if (idx == end)  			size = end_ofs; -		kaddr = kmap_atomic(page, KM_USER0); +		kaddr = kmap_atomic(page);  		memset(kaddr + start_ofs, val, size - start_ofs);  		flush_dcache_page(page); -		kunmap_atomic(kaddr, KM_USER0); +		kunmap_atomic(kaddr);  		set_page_dirty(page);  		page_cache_release(page);  		balance_dirty_pages_ratelimited(mapping); @@ -2561,10 +2560,10 @@ int ntfs_attr_set(ntfs_inode *ni, const s64 ofs, const s64 cnt, const u8 val)  					"page (index 0x%lx).", idx);  			return -ENOMEM;  		} -		kaddr = kmap_atomic(page, KM_USER0); +		kaddr = kmap_atomic(page);  		memset(kaddr, val, PAGE_CACHE_SIZE);  		flush_dcache_page(page); -		kunmap_atomic(kaddr, KM_USER0); +		kunmap_atomic(kaddr);  		/*  		 * If the page has buffers, mark them uptodate since buffer  		 * state and not page state is definitive in 2.6 kernels. @@ -2598,10 +2597,10 @@ int ntfs_attr_set(ntfs_inode *ni, const s64 ofs, const s64 cnt, const u8 val)  					"(error, index 0x%lx).", idx);  			return PTR_ERR(page);  		} -		kaddr = kmap_atomic(page, KM_USER0); +		kaddr = kmap_atomic(page);  		memset(kaddr, val, end_ofs);  		flush_dcache_page(page); -		kunmap_atomic(kaddr, KM_USER0); +		kunmap_atomic(kaddr);  		set_page_dirty(page);  		page_cache_release(page);  		balance_dirty_pages_ratelimited(mapping); diff --git a/fs/ntfs/compress.c b/fs/ntfs/compress.c index 6551c7cbad9..f82498c35e7 100644 --- a/fs/ntfs/compress.c +++ b/fs/ntfs/compress.c @@ -58,7 +58,7 @@ typedef enum {  /**   * ntfs_compression_buffer - one buffer for the decompression engine   */ -static u8 *ntfs_compression_buffer = NULL; +static u8 *ntfs_compression_buffer;  /**   * ntfs_cb_lock - spinlock which protects ntfs_compression_buffer @@ -501,7 +501,7 @@ int ntfs_read_compressed_block(struct page *page)  	VCN start_vcn = (((s64)index << PAGE_CACHE_SHIFT) & ~cb_size_mask) >>  			vol->cluster_size_bits;  	/* -	 * The first vcn after the last wanted vcn (minumum alignment is again +	 * The first vcn after the last wanted vcn (minimum alignment is again  	 * PAGE_CACHE_SIZE.  	 */  	VCN end_vcn = ((((s64)(index + 1UL) << PAGE_CACHE_SHIFT) + cb_size - 1) @@ -698,8 +698,7 @@ lock_retry_remap:  					"uptodate! Unplugging the disk queue "  					"and rescheduling.");  			get_bh(tbh); -			blk_run_address_space(mapping); -			schedule(); +			io_schedule();  			put_bh(tbh);  			if (unlikely(!buffer_uptodate(tbh)))  				goto read_err; diff --git a/fs/ntfs/debug.c b/fs/ntfs/debug.c index 807150e2c2b..dd6103cc93c 100644 --- a/fs/ntfs/debug.c +++ b/fs/ntfs/debug.c @@ -18,16 +18,9 @@   * distribution in the file COPYING); if not, write to the Free Software   * Foundation,Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA   */ - +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt  #include "debug.h" -/* - * A static buffer to hold the error string being displayed and a spinlock - * to protect concurrent accesses to it. - */ -static char err_buf[1024]; -static DEFINE_SPINLOCK(err_buf_lock); -  /**   * __ntfs_warning - output a warning to the syslog   * @function:	name of function outputting the warning @@ -50,6 +43,7 @@ static DEFINE_SPINLOCK(err_buf_lock);  void __ntfs_warning(const char *function, const struct super_block *sb,  		const char *fmt, ...)  { +	struct va_format vaf;  	va_list args;  	int flen = 0; @@ -59,17 +53,15 @@ void __ntfs_warning(const char *function, const struct super_block *sb,  #endif  	if (function)  		flen = strlen(function); -	spin_lock(&err_buf_lock);  	va_start(args, fmt); -	vsnprintf(err_buf, sizeof(err_buf), fmt, args); -	va_end(args); +	vaf.fmt = fmt; +	vaf.va = &args;  	if (sb) -		printk(KERN_ERR "NTFS-fs warning (device %s): %s(): %s\n", -				sb->s_id, flen ? function : "", err_buf); +		pr_warn("(device %s): %s(): %pV\n", +			sb->s_id, flen ? function : "", &vaf);  	else -		printk(KERN_ERR "NTFS-fs warning: %s(): %s\n", -				flen ? function : "", err_buf); -	spin_unlock(&err_buf_lock); +		pr_warn("%s(): %pV\n", flen ? function : "", &vaf); +	va_end(args);  }  /** @@ -94,6 +86,7 @@ void __ntfs_warning(const char *function, const struct super_block *sb,  void __ntfs_error(const char *function, const struct super_block *sb,  		const char *fmt, ...)  { +	struct va_format vaf;  	va_list args;  	int flen = 0; @@ -103,17 +96,15 @@ void __ntfs_error(const char *function, const struct super_block *sb,  #endif  	if (function)  		flen = strlen(function); -	spin_lock(&err_buf_lock);  	va_start(args, fmt); -	vsnprintf(err_buf, sizeof(err_buf), fmt, args); -	va_end(args); +	vaf.fmt = fmt; +	vaf.va = &args;  	if (sb) -		printk(KERN_ERR "NTFS-fs error (device %s): %s(): %s\n", -				sb->s_id, flen ? function : "", err_buf); +		pr_err("(device %s): %s(): %pV\n", +		       sb->s_id, flen ? function : "", &vaf);  	else -		printk(KERN_ERR "NTFS-fs error: %s(): %s\n", -				flen ? function : "", err_buf); -	spin_unlock(&err_buf_lock); +		pr_err("%s(): %pV\n", flen ? function : "", &vaf); +	va_end(args);  }  #ifdef DEBUG @@ -124,6 +115,7 @@ int debug_msgs = 0;  void __ntfs_debug (const char *file, int line, const char *function,  		const char *fmt, ...)  { +	struct va_format vaf;  	va_list args;  	int flen = 0; @@ -131,13 +123,11 @@ void __ntfs_debug (const char *file, int line, const char *function,  		return;  	if (function)  		flen = strlen(function); -	spin_lock(&err_buf_lock);  	va_start(args, fmt); -	vsnprintf(err_buf, sizeof(err_buf), fmt, args); +	vaf.fmt = fmt; +	vaf.va = &args; +	pr_debug("(%s, %d): %s(): %pV", file, line, flen ? function : "", &vaf);  	va_end(args); -	printk(KERN_DEBUG "NTFS-fs DEBUG (%s, %d): %s(): %s\n", file, line, -			flen ? function : "", err_buf); -	spin_unlock(&err_buf_lock);  }  /* Dump a runlist. Caller has to provide synchronisation for @rl. */ @@ -149,12 +139,12 @@ void ntfs_debug_dump_runlist(const runlist_element *rl)  	if (!debug_msgs)  		return; -	printk(KERN_DEBUG "NTFS-fs DEBUG: Dumping runlist (values in hex):\n"); +	pr_debug("Dumping runlist (values in hex):\n");  	if (!rl) { -		printk(KERN_DEBUG "Run list not present.\n"); +		pr_debug("Run list not present.\n");  		return;  	} -	printk(KERN_DEBUG "VCN              LCN               Run length\n"); +	pr_debug("VCN              LCN               Run length\n");  	for (i = 0; ; i++) {  		LCN lcn = (rl + i)->lcn; @@ -163,13 +153,13 @@ void ntfs_debug_dump_runlist(const runlist_element *rl)  			if (index > -LCN_ENOENT - 1)  				index = 3; -			printk(KERN_DEBUG "%-16Lx %s %-16Lx%s\n", +			pr_debug("%-16Lx %s %-16Lx%s\n",  					(long long)(rl + i)->vcn, lcn_str[index],  					(long long)(rl + i)->length,  					(rl + i)->length ? "" :  						" (runlist end)");  		} else -			printk(KERN_DEBUG "%-16Lx %-16Lx  %-16Lx%s\n", +			pr_debug("%-16Lx %-16Lx  %-16Lx%s\n",  					(long long)(rl + i)->vcn,  					(long long)(rl + i)->lcn,  					(long long)(rl + i)->length, diff --git a/fs/ntfs/debug.h b/fs/ntfs/debug.h index 2142b1c68b6..61bf091e32a 100644 --- a/fs/ntfs/debug.h +++ b/fs/ntfs/debug.h @@ -30,8 +30,9 @@  extern int debug_msgs; -extern void __ntfs_debug(const char *file, int line, const char *function, -	const char *format, ...) __attribute__ ((format (printf, 4, 5))); +extern __printf(4, 5) +void __ntfs_debug(const char *file, int line, const char *function, +		  const char *format, ...);  /**   * ntfs_debug - write a debug level message to syslog   * @f:		a printf format string containing the message @@ -47,17 +48,24 @@ extern void ntfs_debug_dump_runlist(const runlist_element *rl);  #else	/* !DEBUG */ -#define ntfs_debug(f, a...)		do {} while (0) +#define ntfs_debug(fmt, ...)						\ +do {									\ +	if (0)								\ +		no_printk(fmt, ##__VA_ARGS__);				\ +} while (0) +  #define ntfs_debug_dump_runlist(rl)	do {} while (0)  #endif	/* !DEBUG */ -extern void __ntfs_warning(const char *function, const struct super_block *sb, -		const char *fmt, ...) __attribute__ ((format (printf, 3, 4))); +extern  __printf(3, 4) +void __ntfs_warning(const char *function, const struct super_block *sb, +		    const char *fmt, ...);  #define ntfs_warning(sb, f, a...)	__ntfs_warning(__func__, sb, f, ##a) -extern void __ntfs_error(const char *function, const struct super_block *sb, -		const char *fmt, ...) __attribute__ ((format (printf, 3, 4))); +extern  __printf(3, 4) +void __ntfs_error(const char *function, const struct super_block *sb, +		  const char *fmt, ...);  #define ntfs_error(sb, f, a...)		__ntfs_error(__func__, sb, f, ##a)  #endif /* _LINUX_NTFS_DEBUG_H */ diff --git a/fs/ntfs/dir.c b/fs/ntfs/dir.c index 0f48e7c5d9e..9e38dafa3bc 100644 --- a/fs/ntfs/dir.c +++ b/fs/ntfs/dir.c @@ -1004,13 +1004,11 @@ dir_err_out:  /**   * ntfs_filldir - ntfs specific filldir method   * @vol:	current ntfs volume - * @fpos:	position in the directory   * @ndir:	ntfs inode of current directory   * @ia_page:	page in which the index allocation buffer @ie is in resides   * @ie:		current index entry   * @name:	buffer to use for the converted name - * @dirent:	vfs filldir callback context - * @filldir:	vfs filldir callback + * @actor:	what to feed the entries to   *   * Convert the Unicode @name to the loaded NLS and pass it to the @filldir   * callback. @@ -1024,12 +1022,12 @@ dir_err_out:   * retake the lock if we are returning a non-zero value as ntfs_readdir()   * would need to drop the lock immediately anyway.   */ -static inline int ntfs_filldir(ntfs_volume *vol, loff_t fpos, +static inline int ntfs_filldir(ntfs_volume *vol,  		ntfs_inode *ndir, struct page *ia_page, INDEX_ENTRY *ie, -		u8 *name, void *dirent, filldir_t filldir) +		u8 *name, struct dir_context *actor)  {  	unsigned long mref; -	int name_len, rc; +	int name_len;  	unsigned dt_type;  	FILE_NAME_TYPE_FLAGS name_type; @@ -1068,13 +1066,14 @@ static inline int ntfs_filldir(ntfs_volume *vol, loff_t fpos,  	if (ia_page)  		unlock_page(ia_page);  	ntfs_debug("Calling filldir for %s with len %i, fpos 0x%llx, inode " -			"0x%lx, DT_%s.", name, name_len, fpos, mref, +			"0x%lx, DT_%s.", name, name_len, actor->pos, mref,  			dt_type == DT_DIR ? "DIR" : "REG"); -	rc = filldir(dirent, name, name_len, fpos, mref, dt_type); +	if (!dir_emit(actor, name, name_len, mref, dt_type)) +		return 1;  	/* Relock the page but not if we are aborting ->readdir. */ -	if (!rc && ia_page) +	if (ia_page)  		lock_page(ia_page); -	return rc; +	return 0;  }  /* @@ -1097,11 +1096,11 @@ static inline int ntfs_filldir(ntfs_volume *vol, loff_t fpos,   *	       removes them again after the write is complete after which it    *	       unlocks the page.   */ -static int ntfs_readdir(struct file *filp, void *dirent, filldir_t filldir) +static int ntfs_readdir(struct file *file, struct dir_context *actor)  {  	s64 ia_pos, ia_start, prev_ia_pos, bmp_pos; -	loff_t fpos, i_size; -	struct inode *bmp_vi, *vdir = filp->f_path.dentry->d_inode; +	loff_t i_size; +	struct inode *bmp_vi, *vdir = file_inode(file);  	struct super_block *sb = vdir->i_sb;  	ntfs_inode *ndir = NTFS_I(vdir);  	ntfs_volume *vol = NTFS_SB(sb); @@ -1116,33 +1115,16 @@ static int ntfs_readdir(struct file *filp, void *dirent, filldir_t filldir)  	u8 *kaddr, *bmp, *index_end;  	ntfs_attr_search_ctx *ctx; -	fpos = filp->f_pos;  	ntfs_debug("Entering for inode 0x%lx, fpos 0x%llx.", -			vdir->i_ino, fpos); +			vdir->i_ino, actor->pos);  	rc = err = 0;  	/* Are we at end of dir yet? */  	i_size = i_size_read(vdir); -	if (fpos >= i_size + vol->mft_record_size) -		goto done; +	if (actor->pos >= i_size + vol->mft_record_size) +		return 0;  	/* Emulate . and .. for all directories. */ -	if (!fpos) { -		ntfs_debug("Calling filldir for . with len 1, fpos 0x0, " -				"inode 0x%lx, DT_DIR.", vdir->i_ino); -		rc = filldir(dirent, ".", 1, fpos, vdir->i_ino, DT_DIR); -		if (rc) -			goto done; -		fpos++; -	} -	if (fpos == 1) { -		ntfs_debug("Calling filldir for .. with len 2, fpos 0x1, " -				"inode 0x%lx, DT_DIR.", -				(unsigned long)parent_ino(filp->f_path.dentry)); -		rc = filldir(dirent, "..", 2, fpos, -				parent_ino(filp->f_path.dentry), DT_DIR); -		if (rc) -			goto done; -		fpos++; -	} +	if (!dir_emit_dots(file, actor)) +		return 0;  	m = NULL;  	ctx = NULL;  	/* @@ -1155,7 +1137,7 @@ static int ntfs_readdir(struct file *filp, void *dirent, filldir_t filldir)  		goto err_out;  	}  	/* Are we jumping straight into the index allocation attribute? */ -	if (fpos >= vol->mft_record_size) +	if (actor->pos >= vol->mft_record_size)  		goto skip_index_root;  	/* Get hold of the mft record for the directory. */  	m = map_mft_record(ndir); @@ -1170,7 +1152,7 @@ static int ntfs_readdir(struct file *filp, void *dirent, filldir_t filldir)  		goto err_out;  	}  	/* Get the offset into the index root attribute. */ -	ir_pos = (s64)fpos; +	ir_pos = (s64)actor->pos;  	/* Find the index root attribute in the mft record. */  	err = ntfs_attr_lookup(AT_INDEX_ROOT, I30, 4, CASE_SENSITIVE, 0, NULL,  			0, ctx); @@ -1226,10 +1208,9 @@ static int ntfs_readdir(struct file *filp, void *dirent, filldir_t filldir)  		if (ir_pos > (u8*)ie - (u8*)ir)  			continue;  		/* Advance the position even if going to skip the entry. */ -		fpos = (u8*)ie - (u8*)ir; +		actor->pos = (u8*)ie - (u8*)ir;  		/* Submit the name to the filldir callback. */ -		rc = ntfs_filldir(vol, fpos, ndir, NULL, ie, name, dirent, -				filldir); +		rc = ntfs_filldir(vol, ndir, NULL, ie, name, actor);  		if (rc) {  			kfree(ir);  			goto abort; @@ -1242,12 +1223,12 @@ static int ntfs_readdir(struct file *filp, void *dirent, filldir_t filldir)  	if (!NInoIndexAllocPresent(ndir))  		goto EOD;  	/* Advance fpos to the beginning of the index allocation. */ -	fpos = vol->mft_record_size; +	actor->pos = vol->mft_record_size;  skip_index_root:  	kaddr = NULL;  	prev_ia_pos = -1LL;  	/* Get the offset into the index allocation attribute. */ -	ia_pos = (s64)fpos - vol->mft_record_size; +	ia_pos = (s64)actor->pos - vol->mft_record_size;  	ia_mapping = vdir->i_mapping;  	ntfs_debug("Inode 0x%lx, getting index bitmap.", vdir->i_ino);  	bmp_vi = ntfs_attr_iget(vdir, AT_BITMAP, I30, 4); @@ -1409,7 +1390,7 @@ find_next_index_buffer:  		if (ia_pos - ia_start > (u8*)ie - (u8*)ia)  			continue;  		/* Advance the position even if going to skip the entry. */ -		fpos = (u8*)ie - (u8*)ia + +		actor->pos = (u8*)ie - (u8*)ia +  				(sle64_to_cpu(ia->index_block_vcn) <<  				ndir->itype.index.vcn_size_bits) +  				vol->mft_record_size; @@ -1419,8 +1400,7 @@ find_next_index_buffer:  		 * before returning, unless a non-zero value is returned in  		 * which case the page is left unlocked.  		 */ -		rc = ntfs_filldir(vol, fpos, ndir, ia_page, ie, name, dirent, -				filldir); +		rc = ntfs_filldir(vol, ndir, ia_page, ie, name, actor);  		if (rc) {  			/* @ia_page is already unlocked in this case. */  			ntfs_unmap_page(ia_page); @@ -1439,18 +1419,9 @@ unm_EOD:  	iput(bmp_vi);  EOD:  	/* We are finished, set fpos to EOD. */ -	fpos = i_size + vol->mft_record_size; +	actor->pos = i_size + vol->mft_record_size;  abort:  	kfree(name); -done: -#ifdef DEBUG -	if (!rc) -		ntfs_debug("EOD, fpos 0x%llx, returning 0.", fpos); -	else -		ntfs_debug("filldir returned %i, fpos 0x%llx, returning 0.", -				rc, fpos); -#endif -	filp->f_pos = fpos;  	return 0;  err_out:  	if (bmp_page) { @@ -1471,7 +1442,6 @@ iput_err_out:  	if (!err)  		err = -EIO;  	ntfs_debug("Failed. Returning error code %i.", -err); -	filp->f_pos = fpos;  	return err;  } @@ -1527,13 +1497,20 @@ static int ntfs_dir_open(struct inode *vi, struct file *filp)   * this problem for now.  We do write the $BITMAP attribute if it is present   * which is the important one for a directory so things are not too bad.   */ -static int ntfs_dir_fsync(struct file *filp, int datasync) +static int ntfs_dir_fsync(struct file *filp, loff_t start, loff_t end, +			  int datasync)  {  	struct inode *bmp_vi, *vi = filp->f_mapping->host;  	int err, ret;  	ntfs_attr na;  	ntfs_debug("Entering for inode 0x%lx.", vi->i_ino); + +	err = filemap_write_and_wait_range(vi->i_mapping, start, end); +	if (err) +		return err; +	mutex_lock(&vi->i_mutex); +  	BUG_ON(!S_ISDIR(vi->i_mode));  	/* If the bitmap attribute inode is in memory sync it, too. */  	na.mft_no = vi->i_ino; @@ -1555,6 +1532,7 @@ static int ntfs_dir_fsync(struct file *filp, int datasync)  	else  		ntfs_warning(vi->i_sb, "Failed to f%ssync inode 0x%lx.  Error "  				"%u.", datasync ? "data" : "", vi->i_ino, -ret); +	mutex_unlock(&vi->i_mutex);  	return ret;  } @@ -1563,7 +1541,7 @@ static int ntfs_dir_fsync(struct file *filp, int datasync)  const struct file_operations ntfs_dir_ops = {  	.llseek		= generic_file_llseek,	/* Seek inside directory. */  	.read		= generic_read_dir,	/* Return -EISDIR. */ -	.readdir	= ntfs_readdir,		/* Read directory contents. */ +	.iterate	= ntfs_readdir,		/* Read directory contents. */  #ifdef NTFS_RW  	.fsync		= ntfs_dir_fsync,	/* Sync a directory to disk. */  	/*.aio_fsync	= ,*/			/* Sync all outstanding async diff --git a/fs/ntfs/file.c b/fs/ntfs/file.c index 113ebd9f25a..5c9e2c81cb1 100644 --- a/fs/ntfs/file.c +++ b/fs/ntfs/file.c @@ -1,7 +1,7 @@  /*   * file.c - NTFS kernel file operations.  Part of the Linux-NTFS project.   * - * Copyright (c) 2001-2007 Anton Altaparmakov + * Copyright (c) 2001-2011 Anton Altaparmakov and Tuxera Inc.   *   * This program/include file is free software; you can redistribute it and/or   * modify it under the terms of the GNU General Public License as published @@ -27,6 +27,7 @@  #include <linux/swap.h>  #include <linux/uio.h>  #include <linux/writeback.h> +#include <linux/aio.h>  #include <asm/page.h>  #include <asm/uaccess.h> @@ -704,7 +705,7 @@ map_buffer_cached:  				u8 *kaddr;  				unsigned pofs; -				kaddr = kmap_atomic(page, KM_USER0); +				kaddr = kmap_atomic(page);  				if (bh_pos < pos) {  					pofs = bh_pos & ~PAGE_CACHE_MASK;  					memset(kaddr + pofs, 0, pos - bh_pos); @@ -713,7 +714,7 @@ map_buffer_cached:  					pofs = end & ~PAGE_CACHE_MASK;  					memset(kaddr + pofs, 0, bh_end - end);  				} -				kunmap_atomic(kaddr, KM_USER0); +				kunmap_atomic(kaddr);  				flush_dcache_page(page);  			}  			continue; @@ -1287,9 +1288,9 @@ static inline size_t ntfs_copy_from_user(struct page **pages,  		len = PAGE_CACHE_SIZE - ofs;  		if (len > bytes)  			len = bytes; -		addr = kmap_atomic(*pages, KM_USER0); +		addr = kmap_atomic(*pages);  		left = __copy_from_user_inatomic(addr + ofs, buf, len); -		kunmap_atomic(addr, KM_USER0); +		kunmap_atomic(addr);  		if (unlikely(left)) {  			/* Do it the slow way. */  			addr = kmap(*pages); @@ -1380,15 +1381,14 @@ static inline void ntfs_set_next_iovec(const struct iovec **iovp,   * pages (out to offset + bytes), to emulate ntfs_copy_from_user()'s   * single-segment behaviour.   * - * We call the same helper (__ntfs_copy_from_user_iovec_inatomic()) both - * when atomic and when not atomic.  This is ok because - * __ntfs_copy_from_user_iovec_inatomic() calls __copy_from_user_inatomic() - * and it is ok to call this when non-atomic. - * Infact, the only difference between __copy_from_user_inatomic() and + * We call the same helper (__ntfs_copy_from_user_iovec_inatomic()) both when + * atomic and when not atomic.  This is ok because it calls + * __copy_from_user_inatomic() and it is ok to call this when non-atomic.  In + * fact, the only difference between __copy_from_user_inatomic() and   * __copy_from_user() is that the latter calls might_sleep() and the former - * should not zero the tail of the buffer on error.  And on many - * architectures __copy_from_user_inatomic() is just defined to - * __copy_from_user() so it makes no difference at all on those architectures. + * should not zero the tail of the buffer on error.  And on many architectures + * __copy_from_user_inatomic() is just defined to __copy_from_user() so it + * makes no difference at all on those architectures.   */  static inline size_t ntfs_copy_from_user_iovec(struct page **pages,  		unsigned nr_pages, unsigned ofs, const struct iovec **iov, @@ -1402,35 +1402,35 @@ static inline size_t ntfs_copy_from_user_iovec(struct page **pages,  		len = PAGE_CACHE_SIZE - ofs;  		if (len > bytes)  			len = bytes; -		addr = kmap_atomic(*pages, KM_USER0); +		addr = kmap_atomic(*pages);  		copied = __ntfs_copy_from_user_iovec_inatomic(addr + ofs,  				*iov, *iov_ofs, len); -		kunmap_atomic(addr, KM_USER0); +		kunmap_atomic(addr);  		if (unlikely(copied != len)) {  			/* Do it the slow way. */  			addr = kmap(*pages); -			copied = __ntfs_copy_from_user_iovec_inatomic(addr + ofs, -					*iov, *iov_ofs, len); -			/* -			 * Zero the rest of the target like __copy_from_user(). -			 */ -			memset(addr + ofs + copied, 0, len - copied); -			kunmap(*pages); +			copied = __ntfs_copy_from_user_iovec_inatomic(addr + +					ofs, *iov, *iov_ofs, len);  			if (unlikely(copied != len))  				goto err_out; +			kunmap(*pages);  		}  		total += len; +		ntfs_set_next_iovec(iov, iov_ofs, len);  		bytes -= len;  		if (!bytes)  			break; -		ntfs_set_next_iovec(iov, iov_ofs, len);  		ofs = 0;  	} while (++pages < last_page);  out:  	return total;  err_out: -	total += copied; +	BUG_ON(copied > len);  	/* Zero the rest of the target like __copy_from_user(). */ +	memset(addr + ofs + copied, 0, len - copied); +	kunmap(*pages); +	total += copied; +	ntfs_set_next_iovec(iov, iov_ofs, copied);  	while (++pages < last_page) {  		bytes -= len;  		if (!bytes) @@ -1692,7 +1692,7 @@ static int ntfs_commit_pages_after_write(struct page **pages,  	BUG_ON(end > le32_to_cpu(a->length) -  			le16_to_cpu(a->data.resident.value_offset));  	kattr = (u8*)a + le16_to_cpu(a->data.resident.value_offset); -	kaddr = kmap_atomic(page, KM_USER0); +	kaddr = kmap_atomic(page);  	/* Copy the received data from the page to the mft record. */  	memcpy(kattr + pos, kaddr + pos, bytes);  	/* Update the attribute length if necessary. */ @@ -1714,7 +1714,7 @@ static int ntfs_commit_pages_after_write(struct page **pages,  		flush_dcache_page(page);  		SetPageUptodate(page);  	} -	kunmap_atomic(kaddr, KM_USER0); +	kunmap_atomic(kaddr);  	/* Update initialized_size/i_size if necessary. */  	read_lock_irqsave(&ni->size_lock, flags);  	initialized_size = ni->initialized_size; @@ -1763,6 +1763,16 @@ err_out:  	return err;  } +static void ntfs_write_failed(struct address_space *mapping, loff_t to) +{ +	struct inode *inode = mapping->host; + +	if (to > inode->i_size) { +		truncate_pagecache(inode, inode->i_size); +		ntfs_truncate_vfs(inode); +	} +} +  /**   * ntfs_file_buffered_write -   * @@ -1833,9 +1843,8 @@ static ssize_t ntfs_file_buffered_write(struct kiocb *iocb,  	 * fails again.  	 */  	if (unlikely(NInoTruncateFailed(ni))) { -		down_write(&vi->i_alloc_sem); +		inode_dio_wait(vi);  		err = ntfs_truncate(vi); -		up_write(&vi->i_alloc_sem);  		if (err || NInoTruncateFailed(ni)) {  			if (!err)  				err = -EIO; @@ -2024,8 +2033,9 @@ static ssize_t ntfs_file_buffered_write(struct kiocb *iocb,  				 * allocated space, which is not a disaster.  				 */  				i_size = i_size_read(vi); -				if (pos + bytes > i_size) -					vmtruncate(vi, i_size); +				if (pos + bytes > i_size) { +					ntfs_write_failed(mapping, pos + bytes); +				}  				break;  			}  		} @@ -2050,7 +2060,6 @@ static ssize_t ntfs_file_buffered_write(struct kiocb *iocb,  		}  		do {  			unlock_page(pages[--do_pages]); -			mark_page_accessed(pages[do_pages]);  			page_cache_release(pages[do_pages]);  		} while (do_pages);  		if (unlikely(status)) @@ -2081,12 +2090,8 @@ static ssize_t ntfs_file_aio_write_nolock(struct kiocb *iocb,  	size_t count;		/* after file limit checks */  	ssize_t written, err; -	count = 0; -	err = generic_segment_checks(iov, &nr_segs, &count, VERIFY_READ); -	if (err) -		return err; +	count = iov_length(iov, nr_segs);  	pos = *ppos; -	vfs_check_frozen(inode->i_sb, SB_FREEZE_WRITE);  	/* We can write back this queue in page reclaim. */  	current->backing_dev_info = mapping->backing_dev_info;  	written = 0; @@ -2098,7 +2103,9 @@ static ssize_t ntfs_file_aio_write_nolock(struct kiocb *iocb,  	err = file_remove_suid(file);  	if (err)  		goto out; -	file_update_time(file); +	err = file_update_time(file); +	if (err) +		goto out;  	written = ntfs_file_buffered_write(iocb, iov, nr_segs, pos, ppos,  			count);  out: @@ -2123,7 +2130,7 @@ static ssize_t ntfs_file_aio_write(struct kiocb *iocb, const struct iovec *iov,  	ret = ntfs_file_aio_write_nolock(iocb, iov, nr_segs, &iocb->ki_pos);  	mutex_unlock(&inode->i_mutex);  	if (ret > 0) { -		int err = generic_write_sync(file, pos, ret); +		int err = generic_write_sync(file, iocb->ki_pos - ret, ret);  		if (err < 0)  			ret = err;  	} @@ -2154,12 +2161,19 @@ static ssize_t ntfs_file_aio_write(struct kiocb *iocb, const struct iovec *iov,   * with this inode but since we have no simple way of getting to them we ignore   * this problem for now.   */ -static int ntfs_file_fsync(struct file *filp, int datasync) +static int ntfs_file_fsync(struct file *filp, loff_t start, loff_t end, +			   int datasync)  {  	struct inode *vi = filp->f_mapping->host;  	int err, ret = 0;  	ntfs_debug("Entering for inode 0x%lx.", vi->i_ino); + +	err = filemap_write_and_wait_range(vi->i_mapping, start, end); +	if (err) +		return err; +	mutex_lock(&vi->i_mutex); +  	BUG_ON(S_ISDIR(vi->i_mode));  	if (!datasync || !NInoNonResident(NTFS_I(vi)))  		ret = __ntfs_write_inode(vi, 1); @@ -2177,6 +2191,7 @@ static int ntfs_file_fsync(struct file *filp, int datasync)  	else  		ntfs_warning(vi->i_sb, "Failed to f%ssync inode 0x%lx.  Error "  				"%u.", datasync ? "data" : "", vi->i_ino, -ret); +	mutex_unlock(&vi->i_mutex);  	return ret;  } @@ -2184,8 +2199,8 @@ static int ntfs_file_fsync(struct file *filp, int datasync)  const struct file_operations ntfs_file_ops = {  	.llseek		= generic_file_llseek,	 /* Seek inside file. */ -	.read		= do_sync_read,		 /* Read from file. */ -	.aio_read	= generic_file_aio_read, /* Async read from file. */ +	.read		= new_sync_read,	 /* Read from file. */ +	.read_iter	= generic_file_read_iter, /* Async read from file. */  #ifdef NTFS_RW  	.write		= do_sync_write,	 /* Write to file. */  	.aio_write	= ntfs_file_aio_write,	 /* Async write to file. */ @@ -2218,7 +2233,6 @@ const struct file_operations ntfs_file_ops = {  const struct inode_operations ntfs_file_inode_ops = {  #ifdef NTFS_RW -	.truncate	= ntfs_truncate_vfs,  	.setattr	= ntfs_setattr,  #endif /* NTFS_RW */  }; diff --git a/fs/ntfs/inode.c b/fs/ntfs/inode.c index 93622b175fc..f47af5e6e23 100644 --- a/fs/ntfs/inode.c +++ b/fs/ntfs/inode.c @@ -28,6 +28,7 @@  #include <linux/quotaops.h>  #include <linux/slab.h>  #include <linux/log2.h> +#include <linux/aio.h>  #include "aops.h"  #include "attrib.h" @@ -54,7 +55,7 @@   *   * Return 1 if the attributes match and 0 if not.   * - * NOTE: This function runs with the inode_lock spin lock held so it is not + * NOTE: This function runs with the inode_hash_lock spin lock held so it is not   * allowed to sleep.   */  int ntfs_test_inode(struct inode *vi, ntfs_attr *na) @@ -98,7 +99,7 @@ int ntfs_test_inode(struct inode *vi, ntfs_attr *na)   *   * Return 0 on success and -errno on error.   * - * NOTE: This function runs with the inode_lock spin lock held so it is not + * NOTE: This function runs with the inode->i_lock spin lock held so it is not   * allowed to sleep. (Hence the GFP_ATOMIC allocation.)   */  static int ntfs_init_locked_inode(struct inode *vi, ntfs_attr *na) @@ -332,6 +333,12 @@ struct inode *ntfs_alloc_big_inode(struct super_block *sb)  	return NULL;  } +static void ntfs_i_callback(struct rcu_head *head) +{ +	struct inode *inode = container_of(head, struct inode, i_rcu); +	kmem_cache_free(ntfs_big_inode_cache, NTFS_I(inode)); +} +  void ntfs_destroy_big_inode(struct inode *inode)  {  	ntfs_inode *ni = NTFS_I(inode); @@ -340,7 +347,7 @@ void ntfs_destroy_big_inode(struct inode *inode)  	BUG_ON(ni->page);  	if (!atomic_dec_and_test(&ni->count))  		BUG(); -	kmem_cache_free(ntfs_big_inode_cache, NTFS_I(inode)); +	call_rcu(&inode->i_rcu, ntfs_i_callback);  }  static inline ntfs_inode *ntfs_alloc_extent_inode(void) @@ -605,7 +612,7 @@ static int ntfs_read_locked_inode(struct inode *vi)  	 * might be tricky due to vfs interactions. Need to think about this  	 * some more when implementing the unlink command.  	 */ -	vi->i_nlink = le16_to_cpu(m->link_count); +	set_nlink(vi, le16_to_cpu(m->link_count));  	/*  	 * FIXME: Reparse points can have the directory bit set even though  	 * they would be S_IFLNK. Need to deal with this further below when we @@ -615,7 +622,7 @@ static int ntfs_read_locked_inode(struct inode *vi)  	 */  	/* Everyone gets all permissions. */  	vi->i_mode |= S_IRWXUGO; -	/* If read-only, noone gets write permissions. */ +	/* If read-only, no one gets write permissions. */  	if (IS_RDONLY(vi))  		vi->i_mode &= ~S_IWUGO;  	if (m->flags & MFT_RECORD_IS_DIRECTORY) { @@ -627,7 +634,7 @@ static int ntfs_read_locked_inode(struct inode *vi)  		vi->i_mode &= ~vol->dmask;  		/* Things break without this kludge! */  		if (vi->i_nlink > 1) -			vi->i_nlink = 1; +			set_nlink(vi, 1);  	} else {  		vi->i_mode |= S_IFREG;  		/* Apply the file permissions mask set in the mount options. */ @@ -1235,7 +1242,7 @@ static int ntfs_read_locked_attr_inode(struct inode *base_vi, struct inode *vi)  	vi->i_version	= base_vi->i_version;  	vi->i_uid	= base_vi->i_uid;  	vi->i_gid	= base_vi->i_gid; -	vi->i_nlink	= base_vi->i_nlink; +	set_nlink(vi, base_vi->i_nlink);  	vi->i_mtime	= base_vi->i_mtime;  	vi->i_ctime	= base_vi->i_ctime;  	vi->i_atime	= base_vi->i_atime; @@ -1501,7 +1508,7 @@ static int ntfs_read_locked_index_inode(struct inode *base_vi, struct inode *vi)  	vi->i_version	= base_vi->i_version;  	vi->i_uid	= base_vi->i_uid;  	vi->i_gid	= base_vi->i_gid; -	vi->i_nlink	= base_vi->i_nlink; +	set_nlink(vi, base_vi->i_nlink);  	vi->i_mtime	= base_vi->i_mtime;  	vi->i_ctime	= base_vi->i_ctime;  	vi->i_atime	= base_vi->i_atime; @@ -1697,8 +1704,6 @@ static int ntfs_read_locked_index_inode(struct inode *base_vi, struct inode *vi)  	iput(bvi);  skip_large_index_stuff:  	/* Setup the operations for this index inode. */ -	vi->i_op = NULL; -	vi->i_fop = NULL;  	vi->i_mapping->a_ops = &ntfs_mst_aops;  	vi->i_blocks = ni->allocated_size >> 9;  	/* @@ -2118,7 +2123,8 @@ int ntfs_read_inode_mount(struct inode *vi)  			 * ntfs_read_inode() will have set up the default ones.  			 */  			/* Set uid and gid to root. */ -			vi->i_uid = vi->i_gid = 0; +			vi->i_uid = GLOBAL_ROOT_UID; +			vi->i_gid = GLOBAL_ROOT_GID;  			/* Regular file. No access for anyone. */  			vi->i_mode = S_IFREG;  			/* No VFS initiated operations allowed for $MFT. */ @@ -2251,8 +2257,8 @@ void ntfs_evict_big_inode(struct inode *vi)  {  	ntfs_inode *ni = NTFS_I(vi); -	truncate_inode_pages(&vi->i_data, 0); -	end_writeback(vi); +	truncate_inode_pages_final(&vi->i_data); +	clear_inode(vi);  #ifdef NTFS_RW  	if (NInoDirty(ni)) { @@ -2294,20 +2300,20 @@ void ntfs_evict_big_inode(struct inode *vi)  /**   * ntfs_show_options - show mount options in /proc/mounts   * @sf:		seq_file in which to write our mount options - * @mnt:	vfs mount whose mount options to display + * @root:	root of the mounted tree whose mount options to display   *   * Called by the VFS once for each mounted ntfs volume when someone reads   * /proc/mounts in order to display the NTFS specific mount options of each - * mount. The mount options of the vfs mount @mnt are written to the seq file + * mount. The mount options of fs specified by @root are written to the seq file   * @sf and success is returned.   */ -int ntfs_show_options(struct seq_file *sf, struct vfsmount *mnt) +int ntfs_show_options(struct seq_file *sf, struct dentry *root)  { -	ntfs_volume *vol = NTFS_SB(mnt->mnt_sb); +	ntfs_volume *vol = NTFS_SB(root->d_sb);  	int i; -	seq_printf(sf, ",uid=%i", vol->uid); -	seq_printf(sf, ",gid=%i", vol->gid); +	seq_printf(sf, ",uid=%i", from_kuid_munged(&init_user_ns, vol->uid)); +	seq_printf(sf, ",gid=%i", from_kgid_munged(&init_user_ns, vol->gid));  	if (vol->fmask == vol->dmask)  		seq_printf(sf, ",umask=0%o", vol->fmask);  	else { @@ -2350,12 +2356,7 @@ static const char *es = "  Leaving inconsistent metadata.  Unmount and run "   *   * Returns 0 on success or -errno on error.   * - * Called with ->i_mutex held.  In all but one case ->i_alloc_sem is held for - * writing.  The only case in the kernel where ->i_alloc_sem is not held is - * mm/filemap.c::generic_file_buffered_write() where vmtruncate() is called - * with the current i_size as the offset.  The analogous place in NTFS is in - * fs/ntfs/file.c::ntfs_file_buffered_write() where we call vmtruncate() again - * without holding ->i_alloc_sem. + * Called with ->i_mutex held.   */  int ntfs_truncate(struct inode *vi)  { @@ -2522,7 +2523,7 @@ retry_truncate:  		 * specifies that the behaviour is unspecified thus we do not  		 * have to do anything.  This means that in our implementation  		 * in the rare case that the file is mmap()ped and a write -		 * occured into the mmap()ped region just beyond the file size +		 * occurred into the mmap()ped region just beyond the file size  		 * and writepage has not yet been called to write out the page  		 * (which would clear the area beyond the file size) and we now  		 * extend the file size to incorporate this dirty region @@ -2864,9 +2865,11 @@ conv_err_out:   *   * See ntfs_truncate() description above for details.   */ +#ifdef NTFS_RW  void ntfs_truncate_vfs(struct inode *vi) {  	ntfs_truncate(vi);  } +#endif  /**   * ntfs_setattr - called from notify_change() when an attribute is being changed @@ -2880,8 +2883,7 @@ void ntfs_truncate_vfs(struct inode *vi) {   * We also abort all changes of user, group, and mode as we do not implement   * the NTFS ACLs yet.   * - * Called with ->i_mutex held.  For the ATTR_SIZE (i.e. ->truncate) case, also - * called with ->i_alloc_sem held for writing. + * Called with ->i_mutex held.   */  int ntfs_setattr(struct dentry *dentry, struct iattr *attr)  { @@ -2913,8 +2915,10 @@ int ntfs_setattr(struct dentry *dentry, struct iattr *attr)  						NInoCompressed(ni) ?  						"compressed" : "encrypted");  				err = -EOPNOTSUPP; -			} else -				err = vmtruncate(vi, attr->ia_size); +			} else { +				truncate_setsize(vi, attr->ia_size); +				ntfs_truncate_vfs(vi); +			}  			if (err || ia_valid == ATTR_SIZE)  				goto out;  		} else { diff --git a/fs/ntfs/inode.h b/fs/ntfs/inode.h index 2dabf813456..76b6cfb579d 100644 --- a/fs/ntfs/inode.h +++ b/fs/ntfs/inode.h @@ -24,7 +24,7 @@  #ifndef _LINUX_NTFS_INODE_H  #define _LINUX_NTFS_INODE_H -#include <asm/atomic.h> +#include <linux/atomic.h>  #include <linux/fs.h>  #include <linux/list.h> @@ -298,7 +298,7 @@ extern void ntfs_clear_extent_inode(ntfs_inode *ni);  extern int ntfs_read_inode_mount(struct inode *vi); -extern int ntfs_show_options(struct seq_file *sf, struct vfsmount *mnt); +extern int ntfs_show_options(struct seq_file *sf, struct dentry *root);  #ifdef NTFS_RW @@ -316,6 +316,10 @@ static inline void ntfs_commit_inode(struct inode *vi)  	return;  } +#else + +static inline void ntfs_truncate_vfs(struct inode *vi) {} +  #endif /* NTFS_RW */  #endif /* _LINUX_NTFS_INODE_H */ diff --git a/fs/ntfs/layout.h b/fs/ntfs/layout.h index 8b2549f672b..809c0e6d8e0 100644 --- a/fs/ntfs/layout.h +++ b/fs/ntfs/layout.h @@ -286,7 +286,7 @@ typedef le16 MFT_RECORD_FLAGS;   * fragmented. Volume free space includes the empty part of the mft zone and   * when the volume's free 88% are used up, the mft zone is shrunk by a factor   * of 2, thus making more space available for more files/data. This process is - * repeated everytime there is no more free space except for the mft zone until + * repeated every time there is no more free space except for the mft zone until   * there really is no more free space.   */ @@ -1657,13 +1657,13 @@ typedef enum {   *	pointed to by the Owner field was provided by a defaulting mechanism   *	rather than explicitly provided by the original provider of the   *	security descriptor.  This may affect the treatment of the SID with - *	respect to inheritence of an owner. + *	respect to inheritance of an owner.   *   * SE_GROUP_DEFAULTED - This boolean flag, when set, indicates that the SID in   *	the Group field was provided by a defaulting mechanism rather than   *	explicitly provided by the original provider of the security   *	descriptor.  This may affect the treatment of the SID with respect to - *	inheritence of a primary group. + *	inheritance of a primary group.   *   * SE_DACL_PRESENT - This boolean flag, when set, indicates that the security   *	descriptor contains a discretionary ACL.  If this flag is set and the @@ -1674,7 +1674,7 @@ typedef enum {   *	pointed to by the Dacl field was provided by a defaulting mechanism   *	rather than explicitly provided by the original provider of the   *	security descriptor.  This may affect the treatment of the ACL with - *	respect to inheritence of an ACL.  This flag is ignored if the + *	respect to inheritance of an ACL.  This flag is ignored if the   *	DaclPresent flag is not set.   *   * SE_SACL_PRESENT - This boolean flag, when set,  indicates that the security @@ -1686,7 +1686,7 @@ typedef enum {   *	pointed to by the Sacl field was provided by a defaulting mechanism   *	rather than explicitly provided by the original provider of the   *	security descriptor.  This may affect the treatment of the ACL with - *	respect to inheritence of an ACL.  This flag is ignored if the + *	respect to inheritance of an ACL.  This flag is ignored if the   *	SaclPresent flag is not set.   *   * SE_SELF_RELATIVE - This boolean flag, when set, indicates that the security @@ -2008,14 +2008,14 @@ typedef struct {   *   * When a directory is small enough to fit inside the index root then this   * is the only attribute describing the directory. When the directory is too - * large to fit in the index root, on the other hand, two aditional attributes + * large to fit in the index root, on the other hand, two additional attributes   * are present: an index allocation attribute, containing sub-nodes of the B+   * directory tree (see below), and a bitmap attribute, describing which virtual   * cluster numbers (vcns) in the index allocation attribute are in use by an   * index block.   *   * NOTE: The root directory (FILE_root) contains an entry for itself. Other - * dircetories do not contain entries for themselves, though. + * directories do not contain entries for themselves, though.   */  typedef struct {  	ATTR_TYPE type;			/* Type of the indexed attribute. Is @@ -2283,7 +2283,7 @@ typedef struct {  	//		   the key_length is zero, then the vcn immediately  	//		   follows the INDEX_ENTRY_HEADER. Regardless of  	//		   key_length, the address of the 8-byte boundary -	//		   alligned vcn of INDEX_ENTRY{_HEADER} *ie is given by +	//		   aligned vcn of INDEX_ENTRY{_HEADER} *ie is given by  	//		   (char*)ie + le16_to_cpu(ie*)->length) - sizeof(VCN),  	//		   where sizeof(VCN) can be hardcoded as 8 if wanted. */  } __attribute__ ((__packed__)) INDEX_ENTRY; diff --git a/fs/ntfs/logfile.c b/fs/ntfs/logfile.c index 4dadcdf3d45..c71de292c5a 100644 --- a/fs/ntfs/logfile.c +++ b/fs/ntfs/logfile.c @@ -669,7 +669,7 @@ err_out:   * of cases where we think that a volume is dirty when in fact it is clean.   * This should only affect volumes that have not been shutdown cleanly but did   * not have any pending, non-check-pointed i/o, i.e. they were completely idle - * at least for the five seconds preceeding the unclean shutdown. + * at least for the five seconds preceding the unclean shutdown.   *   * This function assumes that the $LogFile journal has already been consistency   * checked by a call to ntfs_check_logfile() and in particular if the $LogFile diff --git a/fs/ntfs/logfile.h b/fs/ntfs/logfile.h index b5a6f08bd35..aa2b6ac3f0a 100644 --- a/fs/ntfs/logfile.h +++ b/fs/ntfs/logfile.h @@ -222,7 +222,7 @@ typedef struct {  /* 24*/	sle64 file_size;	/* Usable byte size of the log file.  If the  				   restart_area_offset + the offset of the  				   file_size are > 510 then corruption has -				   occured.  This is the very first check when +				   occurred.  This is the very first check when  				   starting with the restart_area as if it  				   fails it means that some of the above values  				   will be corrupted by the multi sector diff --git a/fs/ntfs/mft.c b/fs/ntfs/mft.c index b572b672718..3014a36a255 100644 --- a/fs/ntfs/mft.c +++ b/fs/ntfs/mft.c @@ -1,7 +1,7 @@  /**   * mft.c - NTFS kernel mft record operations. Part of the Linux-NTFS project.   * - * Copyright (c) 2001-2006 Anton Altaparmakov + * Copyright (c) 2001-2012 Anton Altaparmakov and Tuxera Inc.   * Copyright (c) 2002 Richard Russon   *   * This program/include file is free software; you can redistribute it and/or @@ -73,7 +73,7 @@ static inline MFT_RECORD *map_mft_record_page(ntfs_inode *ni)  		if (index > end_index || (i_size & ~PAGE_CACHE_MASK) < ofs +  				vol->mft_record_size) {  			page = ERR_PTR(-ENOENT); -			ntfs_error(vol->sb, "Attemt to read mft record 0x%lx, " +			ntfs_error(vol->sb, "Attempt to read mft record 0x%lx, "  					"which is beyond the end of the mft.  "  					"This is probably a bug in the ntfs "  					"driver.", ni->mft_no); @@ -1367,7 +1367,7 @@ static int ntfs_mft_bitmap_extend_allocation_nolock(ntfs_volume *vol)  			ntfs_error(vol->sb, "Failed to merge runlists for mft "  					"bitmap.");  			if (ntfs_cluster_free_from_rl(vol, rl2)) { -				ntfs_error(vol->sb, "Failed to dealocate " +				ntfs_error(vol->sb, "Failed to deallocate "  						"allocated cluster.%s", es);  				NVolSetErrors(vol);  			} @@ -1442,7 +1442,7 @@ static int ntfs_mft_bitmap_extend_allocation_nolock(ntfs_volume *vol)  		// Note: It will need to be a special mft record and if none of  		// those are available it gets rather complicated...  		ntfs_error(vol->sb, "Not enough space in this mft record to " -				"accomodate extended mft bitmap attribute " +				"accommodate extended mft bitmap attribute "  				"extent.  Cannot handle this yet.");  		ret = -EOPNOTSUPP;  		goto undo_alloc; @@ -1805,7 +1805,7 @@ static int ntfs_mft_data_extend_allocation_nolock(ntfs_volume *vol)  		ntfs_error(vol->sb, "Failed to merge runlists for mft data "  				"attribute.");  		if (ntfs_cluster_free_from_rl(vol, rl2)) { -			ntfs_error(vol->sb, "Failed to dealocate clusters " +			ntfs_error(vol->sb, "Failed to deallocate clusters "  					"from the mft data attribute.%s", es);  			NVolSetErrors(vol);  		} @@ -1879,7 +1879,7 @@ static int ntfs_mft_data_extend_allocation_nolock(ntfs_volume *vol)  		// and we would then need to update all references to this mft  		// record appropriately.  This is rather complicated...  		ntfs_error(vol->sb, "Not enough space in this mft record to " -				"accomodate extended mft data attribute " +				"accommodate extended mft data attribute "  				"extent.  Cannot handle this yet.");  		ret = -EOPNOTSUPP;  		goto undo_alloc; @@ -2357,7 +2357,7 @@ ntfs_inode *ntfs_mft_record_alloc(ntfs_volume *vol, const int mode,  	}  #ifdef DEBUG  	read_lock_irqsave(&mftbmp_ni->size_lock, flags); -	ntfs_debug("Status of mftbmp after initialized extention: " +	ntfs_debug("Status of mftbmp after initialized extension: "  			"allocated_size 0x%llx, data_size 0x%llx, "  			"initialized_size 0x%llx.",  			(long long)mftbmp_ni->allocated_size, @@ -2576,6 +2576,8 @@ mft_rec_already_initialized:  	flush_dcache_page(page);  	SetPageUptodate(page);  	if (base_ni) { +		MFT_RECORD *m_tmp; +  		/*  		 * Setup the base mft record in the extent mft record.  This  		 * completes initialization of the allocated extent mft record @@ -2588,11 +2590,11 @@ mft_rec_already_initialized:  		 * attach it to the base inode @base_ni and map, pin, and lock  		 * its, i.e. the allocated, mft record.  		 */ -		m = map_extent_mft_record(base_ni, bit, &ni); -		if (IS_ERR(m)) { +		m_tmp = map_extent_mft_record(base_ni, bit, &ni); +		if (IS_ERR(m_tmp)) {  			ntfs_error(vol->sb, "Failed to map allocated extent "  					"mft record 0x%llx.", (long long)bit); -			err = PTR_ERR(m); +			err = PTR_ERR(m_tmp);  			/* Set the mft record itself not in use. */  			m->flags &= cpu_to_le16(  					~le16_to_cpu(MFT_RECORD_IN_USE)); @@ -2603,6 +2605,7 @@ mft_rec_already_initialized:  			ntfs_unmap_page(page);  			goto undo_mftbmp_alloc;  		} +		BUG_ON(m != m_tmp);  		/*  		 * Make sure the allocated mft record is written out to disk.  		 * No need to set the inode dirty because the caller is going diff --git a/fs/ntfs/namei.c b/fs/ntfs/namei.c index 358273e59ad..436f36037e0 100644 --- a/fs/ntfs/namei.c +++ b/fs/ntfs/namei.c @@ -101,7 +101,7 @@   * Locking: Caller must hold i_mutex on the directory.   */  static struct dentry *ntfs_lookup(struct inode *dir_ino, struct dentry *dent, -		struct nameidata *nd) +		unsigned int flags)  {  	ntfs_volume *vol = NTFS_SB(dir_ino->i_sb);  	struct inode *dent_inode; diff --git a/fs/ntfs/runlist.c b/fs/ntfs/runlist.c index 56a9a6d25a2..eac7d6788a1 100644 --- a/fs/ntfs/runlist.c +++ b/fs/ntfs/runlist.c @@ -1243,7 +1243,7 @@ err_out:   * write.   *   * This is used when building the mapping pairs array of a runlist to compress - * a given logical cluster number (lcn) or a specific run length to the minumum + * a given logical cluster number (lcn) or a specific run length to the minimum   * size possible.   *   * Return the number of bytes written on success.  On error, i.e. the diff --git a/fs/ntfs/super.c b/fs/ntfs/super.c index a30ecacc01f..6c3296e546c 100644 --- a/fs/ntfs/super.c +++ b/fs/ntfs/super.c @@ -1,7 +1,7 @@  /*   * super.c - NTFS kernel super block handling. Part of the Linux-NTFS project.   * - * Copyright (c) 2001-2007 Anton Altaparmakov + * Copyright (c) 2001-2012 Anton Altaparmakov and Tuxera Inc.   * Copyright (c) 2001,2002 Richard Russon   *   * This program/include file is free software; you can redistribute it and/or @@ -19,6 +19,7 @@   * distribution in the file COPYING); if not, write to the Free Software   * Foundation,Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA   */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt  #include <linux/stddef.h>  #include <linux/init.h> @@ -49,8 +50,8 @@  static unsigned long ntfs_nr_compression_users;  /* A global default upcase table and a corresponding reference count. */ -static ntfschar *default_upcase = NULL; -static unsigned long ntfs_nr_upcase_users = 0; +static ntfschar *default_upcase; +static unsigned long ntfs_nr_upcase_users;  /* Error constants/strings used in inode.c::ntfs_show_options(). */  typedef enum { @@ -102,9 +103,9 @@ static bool parse_options(ntfs_volume *vol, char *opt)  	char *p, *v, *ov;  	static char *utf8 = "utf8";  	int errors = 0, sloppy = 0; -	uid_t uid = (uid_t)-1; -	gid_t gid = (gid_t)-1; -	mode_t fmask = (mode_t)-1, dmask = (mode_t)-1; +	kuid_t uid = INVALID_UID; +	kgid_t gid = INVALID_GID; +	umode_t fmask = (umode_t)-1, dmask = (umode_t)-1;  	int mft_zone_multiplier = -1, on_errors = -1;  	int show_sys_files = -1, case_sensitive = -1, disable_sparse = -1;  	struct nls_table *nls_map = NULL, *old_nls; @@ -128,6 +129,30 @@ static bool parse_options(ntfs_volume *vol, char *opt)  		if (*v)							\  			goto needs_val;					\  	} +#define NTFS_GETOPT_UID(option, variable)				\ +	if (!strcmp(p, option)) {					\ +		uid_t uid_value;					\ +		if (!v || !*v)						\ +			goto needs_arg;					\ +		uid_value = simple_strtoul(ov = v, &v, 0);		\ +		if (*v)							\ +			goto needs_val;					\ +		variable = make_kuid(current_user_ns(), uid_value);	\ +		if (!uid_valid(variable))				\ +			goto needs_val;					\ +	} +#define NTFS_GETOPT_GID(option, variable)				\ +	if (!strcmp(p, option)) {					\ +		gid_t gid_value;					\ +		if (!v || !*v)						\ +			goto needs_arg;					\ +		gid_value = simple_strtoul(ov = v, &v, 0);		\ +		if (*v)							\ +			goto needs_val;					\ +		variable = make_kgid(current_user_ns(), gid_value);	\ +		if (!gid_valid(variable))				\ +			goto needs_val;					\ +	}  #define NTFS_GETOPT_OCTAL(option, variable)				\  	if (!strcmp(p, option)) {					\  		if (!v || !*v)						\ @@ -165,8 +190,8 @@ static bool parse_options(ntfs_volume *vol, char *opt)  	while ((p = strsep(&opt, ","))) {  		if ((v = strchr(p, '=')))  			*v++ = 0; -		NTFS_GETOPT("uid", uid) -		else NTFS_GETOPT("gid", gid) +		NTFS_GETOPT_UID("uid", uid) +		else NTFS_GETOPT_GID("gid", gid)  		else NTFS_GETOPT_OCTAL("umask", fmask = dmask)  		else NTFS_GETOPT_OCTAL("fmask", fmask)  		else NTFS_GETOPT_OCTAL("dmask", dmask) @@ -283,13 +308,13 @@ no_mount_options:  		vol->on_errors = on_errors;  	if (!vol->on_errors || vol->on_errors == ON_ERRORS_RECOVER)  		vol->on_errors |= ON_ERRORS_CONTINUE; -	if (uid != (uid_t)-1) +	if (uid_valid(uid))  		vol->uid = uid; -	if (gid != (gid_t)-1) +	if (gid_valid(gid))  		vol->gid = gid; -	if (fmask != (mode_t)-1) +	if (fmask != (umode_t)-1)  		vol->fmask = fmask; -	if (dmask != (mode_t)-1) +	if (dmask != (umode_t)-1)  		vol->dmask = dmask;  	if (show_sys_files != -1) {  		if (show_sys_files) @@ -444,6 +469,8 @@ static int ntfs_remount(struct super_block *sb, int *flags, char *opt)  	ntfs_debug("Entering with remount options string: %s", opt); +	sync_filesystem(sb); +  #ifndef NTFS_RW  	/* For read-only compiled driver, enforce read-only flag. */  	*flags |= MS_RDONLY; @@ -458,7 +485,7 @@ static int ntfs_remount(struct super_block *sb, int *flags, char *opt)  	 * the volume on boot and updates them.  	 *  	 * When remounting read-only, mark the volume clean if no volume errors -	 * have occured. +	 * have occurred.  	 */  	if ((sb->s_flags & MS_RDONLY) && !(*flags & MS_RDONLY)) {  		static const char *es = ".  Cannot remount read-write."; @@ -1023,7 +1050,8 @@ static bool load_and_init_mft_mirror(ntfs_volume *vol)  	 * ntfs_read_inode() will have set up the default ones.  	 */  	/* Set uid and gid to root. */ -	tmp_ino->i_uid = tmp_ino->i_gid = 0; +	tmp_ino->i_uid = GLOBAL_ROOT_UID; +	tmp_ino->i_gid = GLOBAL_ROOT_GID;  	/* Regular file.  No access for anyone. */  	tmp_ino->i_mode = S_IFREG;  	/* No VFS initiated operations allowed for $MFTMirr. */ @@ -1239,7 +1267,6 @@ static int check_windows_hibernation_status(ntfs_volume *vol)  {  	MFT_REF mref;  	struct inode *vi; -	ntfs_inode *ni;  	struct page *page;  	u32 *kaddr, *kend;  	ntfs_name *name = NULL; @@ -1269,7 +1296,7 @@ static int check_windows_hibernation_status(ntfs_volume *vol)  					"hibernated on the volume.");  			return 0;  		} -		/* A real error occured. */ +		/* A real error occurred. */  		ntfs_error(vol->sb, "Failed to find inode number for "  				"hiberfil.sys.");  		return ret; @@ -1290,7 +1317,6 @@ static int check_windows_hibernation_status(ntfs_volume *vol)  				"is not the system volume.", i_size_read(vi));  		goto iput_out;  	} -	ni = NTFS_I(vi);  	page = ntfs_map_page(vi->i_mapping, 0);  	if (IS_ERR(page)) {  		ntfs_error(vol->sb, "Failed to read from hiberfil.sys."); @@ -1370,7 +1396,7 @@ static bool load_and_init_quota(ntfs_volume *vol)  			NVolSetQuotaOutOfDate(vol);  			return true;  		} -		/* A real error occured. */ +		/* A real error occurred. */  		ntfs_error(vol->sb, "Failed to find inode number for $Quota.");  		return false;  	} @@ -1454,7 +1480,7 @@ not_enabled:  			NVolSetUsnJrnlStamped(vol);  			return true;  		} -		/* A real error occured. */ +		/* A real error occurred. */  		ntfs_error(vol->sb, "Failed to find inode number for "  				"$UsnJrnl.");  		return false; @@ -1871,7 +1897,7 @@ get_ctx_vol_failed:  	vol->minor_ver = vi->minor_ver;  	ntfs_attr_put_search_ctx(ctx);  	unmap_mft_record(NTFS_I(vol->vol_ino)); -	printk(KERN_INFO "NTFS volume version %i.%i.\n", vol->major_ver, +	pr_info("volume version %i.%i.\n", vol->major_ver,  			vol->minor_ver);  	if (vol->major_ver < 3 && NVolSparseEnabled(vol)) {  		ntfs_warning(vol->sb, "Disabling sparse support due to NTFS " @@ -2292,7 +2318,7 @@ static void ntfs_put_super(struct super_block *sb)  	ntfs_commit_inode(vol->mft_ino);  	/* -	 * If a read-write mount and no volume errors have occured, mark the +	 * If a read-write mount and no volume errors have occurred, mark the  	 * volume clean.  Also, re-commit all affected inodes.  	 */  	if (!(sb->s_flags & MS_RDONLY)) { @@ -2475,7 +2501,7 @@ static s64 get_nr_free_clusters(ntfs_volume *vol)  			nr_free -= PAGE_CACHE_SIZE * 8;  			continue;  		} -		kaddr = kmap_atomic(page, KM_USER0); +		kaddr = kmap_atomic(page);  		/*  		 * Subtract the number of set bits. If this  		 * is the last page and it is partial we don't really care as @@ -2485,7 +2511,7 @@ static s64 get_nr_free_clusters(ntfs_volume *vol)  		 */  		nr_free -= bitmap_weight(kaddr,  					PAGE_CACHE_SIZE * BITS_PER_BYTE); -		kunmap_atomic(kaddr, KM_USER0); +		kunmap_atomic(kaddr);  		page_cache_release(page);  	}  	ntfs_debug("Finished reading $Bitmap, last index = 0x%lx.", index - 1); @@ -2496,7 +2522,7 @@ static s64 get_nr_free_clusters(ntfs_volume *vol)  	if (vol->nr_clusters & 63)  		nr_free += 64 - (vol->nr_clusters & 63);  	up_read(&vol->lcnbmp_lock); -	/* If errors occured we may well have gone below zero, fix this. */ +	/* If errors occurred we may well have gone below zero, fix this. */  	if (nr_free < 0)  		nr_free = 0;  	ntfs_debug("Exiting."); @@ -2546,7 +2572,7 @@ static unsigned long __get_nr_free_mft_records(ntfs_volume *vol,  			nr_free -= PAGE_CACHE_SIZE * 8;  			continue;  		} -		kaddr = kmap_atomic(page, KM_USER0); +		kaddr = kmap_atomic(page);  		/*  		 * Subtract the number of set bits. If this  		 * is the last page and it is partial we don't really care as @@ -2556,12 +2582,12 @@ static unsigned long __get_nr_free_mft_records(ntfs_volume *vol,  		 */  		nr_free -= bitmap_weight(kaddr,  					PAGE_CACHE_SIZE * BITS_PER_BYTE); -		kunmap_atomic(kaddr, KM_USER0); +		kunmap_atomic(kaddr);  		page_cache_release(page);  	}  	ntfs_debug("Finished reading $MFT/$BITMAP, last index = 0x%lx.",  			index - 1); -	/* If errors occured we may well have gone below zero, fix this. */ +	/* If errors occurred we may well have gone below zero, fix this. */  	if (nr_free < 0)  		nr_free = 0;  	ntfs_debug("Exiting."); @@ -2662,31 +2688,14 @@ static const struct super_operations ntfs_sops = {  	.alloc_inode	= ntfs_alloc_big_inode,	  /* VFS: Allocate new inode. */  	.destroy_inode	= ntfs_destroy_big_inode, /* VFS: Deallocate inode. */  #ifdef NTFS_RW -	//.dirty_inode	= NULL,			/* VFS: Called from -	//					   __mark_inode_dirty(). */  	.write_inode	= ntfs_write_inode,	/* VFS: Write dirty inode to  						   disk. */ -	//.drop_inode	= NULL,			/* VFS: Called just after the -	//					   inode reference count has -	//					   been decreased to zero. -	//					   NOTE: The inode lock is -	//					   held. See fs/inode.c:: -	//					   generic_drop_inode(). */ -	//.delete_inode	= NULL,			/* VFS: Delete inode from disk. -	//					   Called when i_count becomes -	//					   0 and i_nlink is also 0. */ -	//.write_super	= NULL,			/* Flush dirty super block to -	//					   disk. */ -	//.sync_fs	= NULL,			/* ? */ -	//.write_super_lockfs	= NULL,		/* ? */ -	//.unlockfs	= NULL,			/* ? */  #endif /* NTFS_RW */  	.put_super	= ntfs_put_super,	/* Syscall: umount. */  	.statfs		= ntfs_statfs,		/* Syscall: statfs */  	.remount_fs	= ntfs_remount,		/* Syscall: mount -o remount. */  	.evict_inode	= ntfs_evict_big_inode,	/* VFS: Called when an inode is  						   removed from memory. */ -	//.umount_begin	= NULL,			/* Forced umount. */  	.show_options	= ntfs_show_options,	/* Show mount options in  						   proc. */  }; @@ -2910,9 +2919,10 @@ static int ntfs_fill_super(struct super_block *sb, void *opt, const int silent)  		ntfs_error(sb, "Failed to load system files.");  		goto unl_upcase_iput_tmp_ino_err_out_now;  	} -	if ((sb->s_root = d_alloc_root(vol->root_ino))) { -		/* We grab a reference, simulating an ntfs_iget(). */ -		ihold(vol->root_ino); + +	/* We grab a reference, simulating an ntfs_iget(). */ +	ihold(vol->root_ino); +	if ((sb->s_root = d_make_root(vol->root_ino))) {  		ntfs_debug("Exiting, status successful.");  		/* Release the default upcase if it has no users. */  		mutex_lock(&ntfs_lock); @@ -3072,6 +3082,7 @@ static struct file_system_type ntfs_fs_type = {  	.kill_sb	= kill_block_super,  	.fs_flags	= FS_REQUIRES_DEV,  }; +MODULE_ALIAS_FS("ntfs");  /* Stable names for the slab caches. */  static const char ntfs_index_ctx_cache_name[] = "ntfs_index_ctx_cache"; @@ -3085,7 +3096,7 @@ static int __init init_ntfs_fs(void)  	int err = 0;  	/* This may be ugly but it results in pretty output so who cares. (-8 */ -	printk(KERN_INFO "NTFS driver " NTFS_VERSION " [Flags: R/" +	pr_info("driver " NTFS_VERSION " [Flags: R/"  #ifdef NTFS_RW  			"W"  #else @@ -3105,16 +3116,15 @@ static int __init init_ntfs_fs(void)  			sizeof(ntfs_index_context), 0 /* offset */,  			SLAB_HWCACHE_ALIGN, NULL /* ctor */);  	if (!ntfs_index_ctx_cache) { -		printk(KERN_CRIT "NTFS: Failed to create %s!\n", -				ntfs_index_ctx_cache_name); +		pr_crit("Failed to create %s!\n", ntfs_index_ctx_cache_name);  		goto ictx_err_out;  	}  	ntfs_attr_ctx_cache = kmem_cache_create(ntfs_attr_ctx_cache_name,  			sizeof(ntfs_attr_search_ctx), 0 /* offset */,  			SLAB_HWCACHE_ALIGN, NULL /* ctor */);  	if (!ntfs_attr_ctx_cache) { -		printk(KERN_CRIT "NTFS: Failed to create %s!\n", -				ntfs_attr_ctx_cache_name); +		pr_crit("NTFS: Failed to create %s!\n", +			ntfs_attr_ctx_cache_name);  		goto actx_err_out;  	} @@ -3122,8 +3132,7 @@ static int __init init_ntfs_fs(void)  			(NTFS_MAX_NAME_LEN+1) * sizeof(ntfschar), 0,  			SLAB_HWCACHE_ALIGN, NULL);  	if (!ntfs_name_cache) { -		printk(KERN_CRIT "NTFS: Failed to create %s!\n", -				ntfs_name_cache_name); +		pr_crit("Failed to create %s!\n", ntfs_name_cache_name);  		goto name_err_out;  	} @@ -3131,8 +3140,7 @@ static int __init init_ntfs_fs(void)  			sizeof(ntfs_inode), 0,  			SLAB_RECLAIM_ACCOUNT|SLAB_MEM_SPREAD, NULL);  	if (!ntfs_inode_cache) { -		printk(KERN_CRIT "NTFS: Failed to create %s!\n", -				ntfs_inode_cache_name); +		pr_crit("Failed to create %s!\n", ntfs_inode_cache_name);  		goto inode_err_out;  	} @@ -3141,15 +3149,14 @@ static int __init init_ntfs_fs(void)  			SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT|SLAB_MEM_SPREAD,  			ntfs_big_inode_init_once);  	if (!ntfs_big_inode_cache) { -		printk(KERN_CRIT "NTFS: Failed to create %s!\n", -				ntfs_big_inode_cache_name); +		pr_crit("Failed to create %s!\n", ntfs_big_inode_cache_name);  		goto big_inode_err_out;  	}  	/* Register the ntfs sysctls. */  	err = ntfs_sysctl(1);  	if (err) { -		printk(KERN_CRIT "NTFS: Failed to register NTFS sysctls!\n"); +		pr_crit("Failed to register NTFS sysctls!\n");  		goto sysctl_err_out;  	} @@ -3158,8 +3165,10 @@ static int __init init_ntfs_fs(void)  		ntfs_debug("NTFS driver registered successfully.");  		return 0; /* Success! */  	} -	printk(KERN_CRIT "NTFS: Failed to register NTFS filesystem driver!\n"); +	pr_crit("Failed to register NTFS filesystem driver!\n"); +	/* Unregister the ntfs sysctls. */ +	ntfs_sysctl(0);  sysctl_err_out:  	kmem_cache_destroy(ntfs_big_inode_cache);  big_inode_err_out: @@ -3172,8 +3181,7 @@ actx_err_out:  	kmem_cache_destroy(ntfs_index_ctx_cache);  ictx_err_out:  	if (!err) { -		printk(KERN_CRIT "NTFS: Aborting NTFS filesystem driver " -				"registration...\n"); +		pr_crit("Aborting NTFS filesystem driver registration...\n");  		err = -ENOMEM;  	}  	return err; @@ -3184,6 +3192,12 @@ static void __exit exit_ntfs_fs(void)  	ntfs_debug("Unregistering NTFS driver.");  	unregister_filesystem(&ntfs_fs_type); + +	/* +	 * Make sure all delayed rcu free inodes are flushed before we +	 * destroy cache. +	 */ +	rcu_barrier();  	kmem_cache_destroy(ntfs_big_inode_cache);  	kmem_cache_destroy(ntfs_inode_cache);  	kmem_cache_destroy(ntfs_name_cache); @@ -3193,12 +3207,12 @@ static void __exit exit_ntfs_fs(void)  	ntfs_sysctl(0);  } -MODULE_AUTHOR("Anton Altaparmakov <aia21@cantab.net>"); -MODULE_DESCRIPTION("NTFS 1.2/3.x driver - Copyright (c) 2001-2007 Anton Altaparmakov"); +MODULE_AUTHOR("Anton Altaparmakov <anton@tuxera.com>"); +MODULE_DESCRIPTION("NTFS 1.2/3.x driver - Copyright (c) 2001-2011 Anton Altaparmakov and Tuxera Inc.");  MODULE_VERSION(NTFS_VERSION);  MODULE_LICENSE("GPL");  #ifdef DEBUG -module_param(debug_msgs, bool, 0); +module_param(debug_msgs, bint, 0);  MODULE_PARM_DESC(debug_msgs, "Enable debug messages.");  #endif diff --git a/fs/ntfs/sysctl.c b/fs/ntfs/sysctl.c index 79a89184cb5..a503156ec15 100644 --- a/fs/ntfs/sysctl.c +++ b/fs/ntfs/sysctl.c @@ -34,7 +34,7 @@  #include "debug.h"  /* Definition of the ntfs sysctl. */ -static ctl_table ntfs_sysctls[] = { +static struct ctl_table ntfs_sysctls[] = {  	{  		.procname	= "ntfs-debug",  		.data		= &debug_msgs,		/* Data pointer and size. */ @@ -46,7 +46,7 @@ static ctl_table ntfs_sysctls[] = {  };  /* Define the parent directory /proc/sys/fs. */ -static ctl_table sysctls_root[] = { +static struct ctl_table sysctls_root[] = {  	{  		.procname	= "fs",  		.mode		= 0555, @@ -56,7 +56,7 @@ static ctl_table sysctls_root[] = {  };  /* Storage for the sysctls header. */ -static struct ctl_table_header *sysctls_root_table = NULL; +static struct ctl_table_header *sysctls_root_table;  /**   * ntfs_sysctl - add or remove the debug sysctl diff --git a/fs/ntfs/volume.h b/fs/ntfs/volume.h index 406ab55dfb3..4f579b02bc7 100644 --- a/fs/ntfs/volume.h +++ b/fs/ntfs/volume.h @@ -25,6 +25,7 @@  #define _LINUX_NTFS_VOLUME_H  #include <linux/rwsem.h> +#include <linux/uidgid.h>  #include "types.h"  #include "layout.h" @@ -46,10 +47,10 @@ typedef struct {  					   sized blocks on the device. */  	/* Configuration provided by user at mount time. */  	unsigned long flags;		/* Miscellaneous flags, see below. */ -	uid_t uid;			/* uid that files will be mounted as. */ -	gid_t gid;			/* gid that files will be mounted as. */ -	mode_t fmask;			/* The mask for file permissions. */ -	mode_t dmask;			/* The mask for directory +	kuid_t uid;			/* uid that files will be mounted as. */ +	kgid_t gid;			/* gid that files will be mounted as. */ +	umode_t fmask;			/* The mask for file permissions. */ +	umode_t dmask;			/* The mask for directory  					   permissions. */  	u8 mft_zone_multiplier;		/* Initial mft zone multiplier. */  	u8 on_errors;			/* What to do on filesystem errors. */  | 
