diff options
Diffstat (limited to 'fs/ntfs/super.c')
| -rw-r--r-- | fs/ntfs/super.c | 144 | 
1 files changed, 79 insertions, 65 deletions
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  | 
