diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2011-07-11 12:48:24 -0700 | 
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2011-07-11 12:48:24 -0700 | 
| commit | 71a1b44b036457169e7974eea0b5b37f64176952 (patch) | |
| tree | f6756944ee46e2cb9225c46941a08db824094140 /fs/cifs | |
| parent | c891f2cd89c7a2b4d51d009e94c74a1e31626528 (diff) | |
| parent | f484b5d001a972a42129570e98086a2a6d216ce0 (diff) | |
| download | linux-71a1b44b036457169e7974eea0b5b37f64176952.tar.bz2 | |
Merge git://git.kernel.org/pub/scm/linux/kernel/git/sfrench/cifs-2.6
* git://git.kernel.org/pub/scm/linux/kernel/git/sfrench/cifs-2.6:
  cifs: drop spinlock before calling cifs_put_tlink
  cifs: fix expand_dfs_referral
  cifs: move bdi_setup_and_register outside of CONFIG_CIFS_DFS_UPCALL
  cifs: factor smb_vol allocation out of cifs_setup_volume_info
  cifs: have cifs_cleanup_volume_info not take a double pointer
  cifs: fix build_unc_path_to_root to account for a prefixpath
  cifs: remove bogus call to cifs_cleanup_volume_info
Diffstat (limited to 'fs/cifs')
| -rw-r--r-- | fs/cifs/cifsfs.c | 8 | ||||
| -rw-r--r-- | fs/cifs/cifsproto.h | 6 | ||||
| -rw-r--r-- | fs/cifs/connect.c | 116 | 
3 files changed, 73 insertions, 57 deletions
diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c index 35f9154615fa..3e2989976297 100644 --- a/fs/cifs/cifsfs.c +++ b/fs/cifs/cifsfs.c @@ -649,9 +649,9 @@ cifs_do_mount(struct file_system_type *fs_type,  	cFYI(1, "Devname: %s flags: %d ", dev_name, flags); -	rc = cifs_setup_volume_info(&volume_info, (char *)data, dev_name); -	if (rc) -		return ERR_PTR(rc); +	volume_info = cifs_get_volume_info((char *)data, dev_name); +	if (IS_ERR(volume_info)) +		return ERR_CAST(volume_info);  	cifs_sb = kzalloc(sizeof(struct cifs_sb_info), GFP_KERNEL);  	if (cifs_sb == NULL) { @@ -713,7 +713,7 @@ cifs_do_mount(struct file_system_type *fs_type,  out_super:  	deactivate_locked_super(sb);  out: -	cifs_cleanup_volume_info(&volume_info); +	cifs_cleanup_volume_info(volume_info);  	return root;  out_mountdata: diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h index 257f312ede42..8df28e925e5b 100644 --- a/fs/cifs/cifsproto.h +++ b/fs/cifs/cifsproto.h @@ -154,9 +154,9 @@ extern int set_cifs_acl(struct cifs_ntsd *, __u32, struct inode *,  extern void cifs_setup_cifs_sb(struct smb_vol *pvolume_info,  			       struct cifs_sb_info *cifs_sb);  extern int cifs_match_super(struct super_block *, void *); -extern void cifs_cleanup_volume_info(struct smb_vol **pvolume_info); -extern int cifs_setup_volume_info(struct smb_vol **pvolume_info, -				  char *mount_data, const char *devname); +extern void cifs_cleanup_volume_info(struct smb_vol *pvolume_info); +extern struct smb_vol *cifs_get_volume_info(char *mount_data, +					    const char *devname);  extern int cifs_mount(struct cifs_sb_info *, struct smb_vol *);  extern void cifs_umount(struct cifs_sb_info *);  extern void cifs_dfs_release_automount_timer(void); diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index c8cb83ef6f6f..dbd669cc5bc7 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c @@ -65,6 +65,8 @@ static int ip_connect(struct TCP_Server_Info *server);  static int generic_ip_connect(struct TCP_Server_Info *server);  static void tlink_rb_insert(struct rb_root *root, struct tcon_link *new_tlink);  static void cifs_prune_tlinks(struct work_struct *work); +static int cifs_setup_volume_info(struct smb_vol *volume_info, char *mount_data, +					const char *devname);  /*   * cifs tcp session reconnection @@ -2240,8 +2242,8 @@ cifs_match_super(struct super_block *sb, void *data)  	rc = compare_mount_options(sb, mnt_data);  out: -	cifs_put_tlink(tlink);  	spin_unlock(&cifs_tcp_ses_lock); +	cifs_put_tlink(tlink);  	return rc;  } @@ -2830,15 +2832,9 @@ is_path_accessible(int xid, struct cifs_tcon *tcon,  	return rc;  } -void -cifs_cleanup_volume_info(struct smb_vol **pvolume_info) +static void +cleanup_volume_info_contents(struct smb_vol *volume_info)  { -	struct smb_vol *volume_info; - -	if (!pvolume_info || !*pvolume_info) -		return; - -	volume_info = *pvolume_info;  	kfree(volume_info->username);  	kzfree(volume_info->password);  	kfree(volume_info->UNC); @@ -2846,28 +2842,44 @@ cifs_cleanup_volume_info(struct smb_vol **pvolume_info)  	kfree(volume_info->domainname);  	kfree(volume_info->iocharset);  	kfree(volume_info->prepath); +} + +void +cifs_cleanup_volume_info(struct smb_vol *volume_info) +{ +	if (!volume_info) +		return; +	cleanup_volume_info_contents(volume_info);  	kfree(volume_info); -	*pvolume_info = NULL; -	return;  } +  #ifdef CONFIG_CIFS_DFS_UPCALL  /* build_path_to_root returns full path to root when   * we do not have an exiting connection (tcon) */  static char * -build_unc_path_to_root(const struct smb_vol *volume_info, +build_unc_path_to_root(const struct smb_vol *vol,  		const struct cifs_sb_info *cifs_sb)  { -	char *full_path; +	char *full_path, *pos; +	unsigned int pplen = vol->prepath ? strlen(vol->prepath) : 0; +	unsigned int unc_len = strnlen(vol->UNC, MAX_TREE_SIZE + 1); -	int unc_len = strnlen(volume_info->UNC, MAX_TREE_SIZE + 1); -	full_path = kmalloc(unc_len + 1, GFP_KERNEL); +	full_path = kmalloc(unc_len + pplen + 1, GFP_KERNEL);  	if (full_path == NULL)  		return ERR_PTR(-ENOMEM); -	strncpy(full_path, volume_info->UNC, unc_len); -	full_path[unc_len] = 0; /* add trailing null */ +	strncpy(full_path, vol->UNC, unc_len); +	pos = full_path + unc_len; + +	if (pplen) { +		strncpy(pos, vol->prepath, pplen); +		pos += pplen; +	} + +	*pos = '\0'; /* add trailing null */  	convert_delimiter(full_path, CIFS_DIR_SEP(cifs_sb)); +	cFYI(1, "%s: full_path=%s", __func__, full_path);  	return full_path;  } @@ -2910,15 +2922,18 @@ expand_dfs_referral(int xid, struct cifs_ses *pSesInfo,  						   &fake_devname);  		free_dfs_info_array(referrals, num_referrals); -		kfree(fake_devname); - -		if (cifs_sb->mountdata != NULL) -			kfree(cifs_sb->mountdata);  		if (IS_ERR(mdata)) {  			rc = PTR_ERR(mdata);  			mdata = NULL; +		} else { +			cleanup_volume_info_contents(volume_info); +			memset(volume_info, '\0', sizeof(*volume_info)); +			rc = cifs_setup_volume_info(volume_info, mdata, +							fake_devname);  		} +		kfree(fake_devname); +		kfree(cifs_sb->mountdata);  		cifs_sb->mountdata = mdata;  	}  	kfree(full_path); @@ -2926,33 +2941,20 @@ expand_dfs_referral(int xid, struct cifs_ses *pSesInfo,  }  #endif -int cifs_setup_volume_info(struct smb_vol **pvolume_info, char *mount_data, -			   const char *devname) +static int +cifs_setup_volume_info(struct smb_vol *volume_info, char *mount_data, +			const char *devname)  { -	struct smb_vol *volume_info;  	int rc = 0; -	*pvolume_info = NULL; - -	volume_info = kzalloc(sizeof(struct smb_vol), GFP_KERNEL); -	if (!volume_info) { -		rc = -ENOMEM; -		goto out; -	} - -	if (cifs_parse_mount_options(mount_data, devname, -				     volume_info)) { -		rc = -EINVAL; -		goto out; -	} +	if (cifs_parse_mount_options(mount_data, devname, volume_info)) +		return -EINVAL;  	if (volume_info->nullauth) {  		cFYI(1, "null user");  		volume_info->username = kzalloc(1, GFP_KERNEL); -		if (volume_info->username == NULL) { -			rc = -ENOMEM; -			goto out; -		} +		if (volume_info->username == NULL) +			return -ENOMEM;  	} else if (volume_info->username) {  		/* BB fixme parse for domain name here */  		cFYI(1, "Username: %s", volume_info->username); @@ -2960,8 +2962,7 @@ int cifs_setup_volume_info(struct smb_vol **pvolume_info, char *mount_data,  		cifserror("No username specified");  	/* In userspace mount helper we can get user name from alternate  	   locations such as env variables and files on disk */ -		rc = -EINVAL; -		goto out; +		return -EINVAL;  	}  	/* this is needed for ASCII cp to Unicode converts */ @@ -2973,18 +2974,32 @@ int cifs_setup_volume_info(struct smb_vol **pvolume_info, char *mount_data,  		if (volume_info->local_nls == NULL) {  			cERROR(1, "CIFS mount error: iocharset %s not found",  				 volume_info->iocharset); -			rc = -ELIBACC; -			goto out; +			return -ELIBACC;  		}  	} -	*pvolume_info = volume_info; -	return rc; -out: -	cifs_cleanup_volume_info(&volume_info);  	return rc;  } +struct smb_vol * +cifs_get_volume_info(char *mount_data, const char *devname) +{ +	int rc; +	struct smb_vol *volume_info; + +	volume_info = kzalloc(sizeof(struct smb_vol), GFP_KERNEL); +	if (!volume_info) +		return ERR_PTR(-ENOMEM); + +	rc = cifs_setup_volume_info(volume_info, mount_data, devname); +	if (rc) { +		cifs_cleanup_volume_info(volume_info); +		volume_info = ERR_PTR(rc); +	} + +	return volume_info; +} +  int  cifs_mount(struct cifs_sb_info *cifs_sb, struct smb_vol *volume_info)  { @@ -2997,6 +3012,7 @@ cifs_mount(struct cifs_sb_info *cifs_sb, struct smb_vol *volume_info)  	struct tcon_link *tlink;  #ifdef CONFIG_CIFS_DFS_UPCALL  	int referral_walks_count = 0; +#endif  	rc = bdi_setup_and_register(&cifs_sb->bdi, "cifs", BDI_CAP_MAP_COPY);  	if (rc) @@ -3004,6 +3020,7 @@ cifs_mount(struct cifs_sb_info *cifs_sb, struct smb_vol *volume_info)  	cifs_sb->bdi.ra_pages = default_backing_dev_info.ra_pages; +#ifdef CONFIG_CIFS_DFS_UPCALL  try_mount_again:  	/* cleanup activities if we're chasing a referral */  	if (referral_walks_count) { @@ -3012,7 +3029,6 @@ try_mount_again:  		else if (pSesInfo)  			cifs_put_smb_ses(pSesInfo); -		cifs_cleanup_volume_info(&volume_info);  		FreeXid(xid);  	}  #endif  |