diff options
Diffstat (limited to 'fs/cifs/cifsfs.c')
| -rw-r--r-- | fs/cifs/cifsfs.c | 190 | 
1 files changed, 97 insertions, 93 deletions
diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c index 989442dcfb4..35f9154615f 100644 --- a/fs/cifs/cifsfs.c +++ b/fs/cifs/cifsfs.c @@ -104,8 +104,7 @@ cifs_sb_deactive(struct super_block *sb)  }  static int -cifs_read_super(struct super_block *sb, struct smb_vol *volume_info, -		const char *devname, int silent) +cifs_read_super(struct super_block *sb)  {  	struct inode *inode;  	struct cifs_sb_info *cifs_sb; @@ -113,22 +112,16 @@ cifs_read_super(struct super_block *sb, struct smb_vol *volume_info,  	cifs_sb = CIFS_SB(sb); -	spin_lock_init(&cifs_sb->tlink_tree_lock); -	cifs_sb->tlink_tree = RB_ROOT; +	if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIXACL) +		sb->s_flags |= MS_POSIXACL; -	rc = bdi_setup_and_register(&cifs_sb->bdi, "cifs", BDI_CAP_MAP_COPY); -	if (rc) -		return rc; - -	cifs_sb->bdi.ra_pages = default_backing_dev_info.ra_pages; +	if (cifs_sb_master_tcon(cifs_sb)->ses->capabilities & CAP_LARGE_FILES) +		sb->s_maxbytes = MAX_LFS_FILESIZE; +	else +		sb->s_maxbytes = MAX_NON_LFS; -	rc = cifs_mount(sb, cifs_sb, volume_info, devname); - -	if (rc) { -		if (!silent) -			cERROR(1, "cifs_mount failed w/return code = %d", rc); -		goto out_mount_failed; -	} +	/* BB FIXME fix time_gran to be larger for LANMAN sessions */ +	sb->s_time_gran = 100;  	sb->s_magic = CIFS_MAGIC_NUMBER;  	sb->s_op = &cifs_super_ops; @@ -170,37 +163,14 @@ out_no_root:  	if (inode)  		iput(inode); -	cifs_umount(sb, cifs_sb); - -out_mount_failed: -	bdi_destroy(&cifs_sb->bdi);  	return rc;  } -static void -cifs_put_super(struct super_block *sb) +static void cifs_kill_sb(struct super_block *sb)  { -	int rc = 0; -	struct cifs_sb_info *cifs_sb; - -	cFYI(1, "In cifs_put_super"); -	cifs_sb = CIFS_SB(sb); -	if (cifs_sb == NULL) { -		cFYI(1, "Empty cifs superblock info passed to unmount"); -		return; -	} - -	rc = cifs_umount(sb, cifs_sb); -	if (rc) -		cERROR(1, "cifs_umount failed with return code %d", rc); -	if (cifs_sb->mountdata) { -		kfree(cifs_sb->mountdata); -		cifs_sb->mountdata = NULL; -	} - -	unload_nls(cifs_sb->local_nls); -	bdi_destroy(&cifs_sb->bdi); -	kfree(cifs_sb); +	struct cifs_sb_info *cifs_sb = CIFS_SB(sb); +	kill_anon_super(sb); +	cifs_umount(cifs_sb);  }  static int @@ -257,9 +227,6 @@ static int cifs_permission(struct inode *inode, int mask, unsigned int flags)  {  	struct cifs_sb_info *cifs_sb; -	if (flags & IPERM_FLAG_RCU) -		return -ECHILD; -  	cifs_sb = CIFS_SB(inode->i_sb);  	if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_PERM) { @@ -352,6 +319,37 @@ cifs_show_address(struct seq_file *s, struct TCP_Server_Info *server)  	}  } +static void +cifs_show_security(struct seq_file *s, struct TCP_Server_Info *server) +{ +	seq_printf(s, ",sec="); + +	switch (server->secType) { +	case LANMAN: +		seq_printf(s, "lanman"); +		break; +	case NTLMv2: +		seq_printf(s, "ntlmv2"); +		break; +	case NTLM: +		seq_printf(s, "ntlm"); +		break; +	case Kerberos: +		seq_printf(s, "krb5"); +		break; +	case RawNTLMSSP: +		seq_printf(s, "ntlmssp"); +		break; +	default: +		/* shouldn't ever happen */ +		seq_printf(s, "unknown"); +		break; +	} + +	if (server->sec_mode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) +		seq_printf(s, "i"); +} +  /*   * cifs_show_options() is for displaying mount options in /proc/mounts.   * Not all settable options are displayed but most of the important @@ -365,6 +363,8 @@ cifs_show_options(struct seq_file *s, struct vfsmount *m)  	struct sockaddr *srcaddr;  	srcaddr = (struct sockaddr *)&tcon->ses->server->srcaddr; +	cifs_show_security(s, tcon->ses->server); +  	seq_printf(s, ",unc=%s", tcon->treeName);  	if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MULTIUSER) @@ -518,7 +518,6 @@ static int cifs_drop_inode(struct inode *inode)  }  static const struct super_operations cifs_super_ops = { -	.put_super = cifs_put_super,  	.statfs = cifs_statfs,  	.alloc_inode = cifs_alloc_inode,  	.destroy_inode = cifs_destroy_inode, @@ -555,7 +554,7 @@ cifs_get_root(struct smb_vol *vol, struct super_block *sb)  	full_path = cifs_build_path_to_root(vol, cifs_sb,  					    cifs_sb_master_tcon(cifs_sb));  	if (full_path == NULL) -		return NULL; +		return ERR_PTR(-ENOMEM);  	cFYI(1, "Get root dentry for %s", full_path); @@ -584,7 +583,7 @@ cifs_get_root(struct smb_vol *vol, struct super_block *sb)  			dchild = d_alloc(dparent, &name);  			if (dchild == NULL) {  				dput(dparent); -				dparent = NULL; +				dparent = ERR_PTR(-ENOMEM);  				goto out;  			}  		} @@ -602,7 +601,7 @@ cifs_get_root(struct smb_vol *vol, struct super_block *sb)  			if (rc) {  				dput(dchild);  				dput(dparent); -				dparent = NULL; +				dparent = ERR_PTR(rc);  				goto out;  			}  			alias = d_materialise_unique(dchild, inode); @@ -610,7 +609,7 @@ cifs_get_root(struct smb_vol *vol, struct super_block *sb)  				dput(dchild);  				if (IS_ERR(alias)) {  					dput(dparent); -					dparent = NULL; +					dparent = ERR_PTR(-EINVAL); /* XXX */  					goto out;  				}  				dchild = alias; @@ -630,6 +629,13 @@ out:  	return dparent;  } +static int cifs_set_super(struct super_block *sb, void *data) +{ +	struct cifs_mnt_data *mnt_data = data; +	sb->s_fs_info = mnt_data->cifs_sb; +	return set_anon_super(sb, NULL); +} +  static struct dentry *  cifs_do_mount(struct file_system_type *fs_type,  	      int flags, const char *dev_name, void *data) @@ -650,75 +656,73 @@ cifs_do_mount(struct file_system_type *fs_type,  	cifs_sb = kzalloc(sizeof(struct cifs_sb_info), GFP_KERNEL);  	if (cifs_sb == NULL) {  		root = ERR_PTR(-ENOMEM); -		goto out; +		goto out_nls; +	} + +	cifs_sb->mountdata = kstrndup(data, PAGE_SIZE, GFP_KERNEL); +	if (cifs_sb->mountdata == NULL) { +		root = ERR_PTR(-ENOMEM); +		goto out_cifs_sb;  	}  	cifs_setup_cifs_sb(volume_info, cifs_sb); +	rc = cifs_mount(cifs_sb, volume_info); +	if (rc) { +		if (!(flags & MS_SILENT)) +			cERROR(1, "cifs_mount failed w/return code = %d", rc); +		root = ERR_PTR(rc); +		goto out_mountdata; +	} +  	mnt_data.vol = volume_info;  	mnt_data.cifs_sb = cifs_sb;  	mnt_data.flags = flags; -	sb = sget(fs_type, cifs_match_super, set_anon_super, &mnt_data); +	sb = sget(fs_type, cifs_match_super, cifs_set_super, &mnt_data);  	if (IS_ERR(sb)) {  		root = ERR_CAST(sb); -		goto out_cifs_sb; +		cifs_umount(cifs_sb); +		goto out;  	} -	if (sb->s_fs_info) { +	if (sb->s_root) {  		cFYI(1, "Use existing superblock"); -		goto out_shared; -	} - -	/* -	 * Copy mount params for use in submounts. Better to do -	 * the copy here and deal with the error before cleanup gets -	 * complicated post-mount. -	 */ -	cifs_sb->mountdata = kstrndup(data, PAGE_SIZE, GFP_KERNEL); -	if (cifs_sb->mountdata == NULL) { -		root = ERR_PTR(-ENOMEM); -		goto out_super; -	} +		cifs_umount(cifs_sb); +	} else { +		sb->s_flags = flags; +		/* BB should we make this contingent on mount parm? */ +		sb->s_flags |= MS_NODIRATIME | MS_NOATIME; -	sb->s_flags = flags; -	/* BB should we make this contingent on mount parm? */ -	sb->s_flags |= MS_NODIRATIME | MS_NOATIME; -	sb->s_fs_info = cifs_sb; +		rc = cifs_read_super(sb); +		if (rc) { +			root = ERR_PTR(rc); +			goto out_super; +		} -	rc = cifs_read_super(sb, volume_info, dev_name, -			     flags & MS_SILENT ? 1 : 0); -	if (rc) { -		root = ERR_PTR(rc); -		goto out_super; +		sb->s_flags |= MS_ACTIVE;  	} -	sb->s_flags |= MS_ACTIVE; -  	root = cifs_get_root(volume_info, sb); -	if (root == NULL) +	if (IS_ERR(root))  		goto out_super;  	cFYI(1, "dentry root is: %p", root);  	goto out; -out_shared: -	root = cifs_get_root(volume_info, sb); -	if (root) -		cFYI(1, "dentry root is: %p", root); -	goto out; -  out_super: -	kfree(cifs_sb->mountdata);  	deactivate_locked_super(sb); - -out_cifs_sb: -	unload_nls(cifs_sb->local_nls); -	kfree(cifs_sb); -  out:  	cifs_cleanup_volume_info(&volume_info);  	return root; + +out_mountdata: +	kfree(cifs_sb->mountdata); +out_cifs_sb: +	kfree(cifs_sb); +out_nls: +	unload_nls(volume_info->local_nls); +	goto out;  }  static ssize_t cifs_file_aio_write(struct kiocb *iocb, const struct iovec *iov, @@ -807,7 +811,7 @@ struct file_system_type cifs_fs_type = {  	.owner = THIS_MODULE,  	.name = "cifs",  	.mount = cifs_do_mount, -	.kill_sb = kill_anon_super, +	.kill_sb = cifs_kill_sb,  	/*  .fs_flags */  };  const struct inode_operations cifs_dir_inode_ops = {  |