Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit be1d29f5 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
* git://git.kernel.org/pub/scm/linux/kernel/git/sfrench/cifs-2.6:
  MAINTAINERS: change mailing list address for CIFS
  cifs: remove bogus first_time check in NTLMv2 session setup code
  cifs: don't call cifs_new_fileinfo unless cifs_open succeeds
  cifs: don't ignore cifs_posix_open_inode_helper return value
  cifs: clean up arguments to cifs_open_inode_helper
  cifs: pass instantiated filp back after open call
  cifs: move cifs_new_fileinfo call out of cifs_posix_open
  cifs: implement drop_inode superblock op
  cifs: don't attempt busy-file rename unless it's in same directory
parents 24eb90ab 51223df6
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -1581,7 +1581,7 @@ F: include/linux/coda*.h

COMMON INTERNET FILE SYSTEM (CIFS)
M:	Steve French <sfrench@samba.org>
L:	linux-cifs-client@lists.samba.org (moderated for non-subscribers)
L:	linux-cifs@vger.kernel.org
L:	samba-technical@lists.samba.org (moderated for non-subscribers)
W:	http://linux-cifs.samba.org/
Q:	http://patchwork.ozlabs.org/project/linux-cifs-client/list/
+13 −3
Original line number Diff line number Diff line
@@ -473,14 +473,24 @@ static int cifs_remount(struct super_block *sb, int *flags, char *data)
	return 0;
}

void cifs_drop_inode(struct inode *inode)
{
	struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);

	if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM)
		return generic_drop_inode(inode);

	return generic_delete_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,
/*	.drop_inode	    = generic_delete_inode,
	.delete_inode	= cifs_delete_inode,  */  /* Do not need above two
	functions unless later we add lazy close of inodes or unless the
	.drop_inode	= cifs_drop_inode,
/*	.delete_inode	= cifs_delete_inode,  */  /* Do not need above
	function unless later we add lazy close of inodes or unless the
	kernel forgets to call us with the same number of releases (closes)
	as opens */
	.show_options = cifs_show_options,
+0 −1
Original line number Diff line number Diff line
@@ -106,7 +106,6 @@ extern struct cifsFileInfo *cifs_new_fileinfo(struct inode *newinode,
				__u16 fileHandle, struct file *file,
				struct vfsmount *mnt, unsigned int oflags);
extern int cifs_posix_open(char *full_path, struct inode **pinode,
				struct vfsmount *mnt,
				struct super_block *sb,
				int mode, int oflags,
				__u32 *poplock, __u16 *pnetfid, int xid);
+44 −32
Original line number Diff line number Diff line
@@ -25,6 +25,7 @@
#include <linux/slab.h>
#include <linux/namei.h>
#include <linux/mount.h>
#include <linux/file.h>
#include "cifsfs.h"
#include "cifspdu.h"
#include "cifsglob.h"
@@ -184,12 +185,13 @@ cifs_new_fileinfo(struct inode *newinode, __u16 fileHandle,
	}
	write_unlock(&GlobalSMBSeslock);

	file->private_data = pCifsFile;

	return pCifsFile;
}

int cifs_posix_open(char *full_path, struct inode **pinode,
			struct vfsmount *mnt, struct super_block *sb,
			int mode, int oflags,
			struct super_block *sb, int mode, int oflags,
			__u32 *poplock, __u16 *pnetfid, int xid)
{
	int rc;
@@ -258,19 +260,6 @@ int cifs_posix_open(char *full_path, struct inode **pinode,
		cifs_fattr_to_inode(*pinode, &fattr);
	}

	/*
	 * cifs_fill_filedata() takes care of setting cifsFileInfo pointer to
	 * file->private_data.
	 */
	if (mnt) {
		struct cifsFileInfo *pfile_info;

		pfile_info = cifs_new_fileinfo(*pinode, *pnetfid, NULL, mnt,
					       oflags);
		if (pfile_info == NULL)
			rc = -ENOMEM;
	}

posix_open_ret:
	kfree(presp_data);
	return rc;
@@ -298,7 +287,6 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
	int create_options = CREATE_NOT_DIR;
	__u32 oplock = 0;
	int oflags;
	bool posix_create = false;
	/*
	 * BB below access is probably too much for mknod to request
	 *    but we have to do query and setpathinfo so requesting
@@ -339,7 +327,6 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
	    (CIFS_UNIX_POSIX_PATH_OPS_CAP &
			le64_to_cpu(tcon->fsUnixInfo.Capability))) {
		rc = cifs_posix_open(full_path, &newinode,
			nd ? nd->path.mnt : NULL,
			inode->i_sb, mode, oflags, &oplock, &fileHandle, xid);
		/* EIO could indicate that (posix open) operation is not
		   supported, despite what server claimed in capability
@@ -347,7 +334,6 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
		   handled in posix open */

		if (rc == 0) {
			posix_create = true;
			if (newinode == NULL) /* query inode info */
				goto cifs_create_get_file_info;
			else /* success, no need to query */
@@ -478,21 +464,28 @@ cifs_create_set_dentry:
	else
		cFYI(1, "Create worked, get_inode_info failed rc = %d", rc);

	/* nfsd case - nfs srv does not set nd */
	if ((nd == NULL) || (!(nd->flags & LOOKUP_OPEN))) {
		/* mknod case - do not leave file open */
		CIFSSMBClose(xid, tcon, fileHandle);
	} else if (!(posix_create) && (newinode)) {
	if (newinode && nd && (nd->flags & LOOKUP_OPEN)) {
		struct cifsFileInfo *pfile_info;
		/*
		 * cifs_fill_filedata() takes care of setting cifsFileInfo
		 * pointer to file->private_data.
		 */
		pfile_info = cifs_new_fileinfo(newinode, fileHandle, NULL,
		struct file *filp;

		filp = lookup_instantiate_filp(nd, direntry, generic_file_open);
		if (IS_ERR(filp)) {
			rc = PTR_ERR(filp);
			CIFSSMBClose(xid, tcon, fileHandle);
			goto cifs_create_out;
		}

		pfile_info = cifs_new_fileinfo(newinode, fileHandle, filp,
					       nd->path.mnt, oflags);
		if (pfile_info == NULL)
		if (pfile_info == NULL) {
			fput(filp);
			CIFSSMBClose(xid, tcon, fileHandle);
			rc = -ENOMEM;
		}
	} else {
		CIFSSMBClose(xid, tcon, fileHandle);
	}

cifs_create_out:
	kfree(buf);
	kfree(full_path);
@@ -636,6 +629,7 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry,
	bool posix_open = false;
	struct cifs_sb_info *cifs_sb;
	struct cifsTconInfo *pTcon;
	struct cifsFileInfo *cfile;
	struct inode *newInode = NULL;
	char *full_path = NULL;
	struct file *filp;
@@ -703,7 +697,7 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry,
		if (nd && !(nd->flags & (LOOKUP_PARENT | LOOKUP_DIRECTORY)) &&
		     (nd->flags & LOOKUP_OPEN) && !pTcon->broken_posix_open &&
		     (nd->intent.open.flags & O_CREAT)) {
			rc = cifs_posix_open(full_path, &newInode, nd->path.mnt,
			rc = cifs_posix_open(full_path, &newInode,
					parent_dir_inode->i_sb,
					nd->intent.open.create_mode,
					nd->intent.open.flags, &oplock,
@@ -733,8 +727,25 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry,
		else
			direntry->d_op = &cifs_dentry_ops;
		d_add(direntry, newInode);
		if (posix_open)
			filp = lookup_instantiate_filp(nd, direntry, NULL);
		if (posix_open) {
			filp = lookup_instantiate_filp(nd, direntry,
						       generic_file_open);
			if (IS_ERR(filp)) {
				rc = PTR_ERR(filp);
				CIFSSMBClose(xid, pTcon, fileHandle);
				goto lookup_out;
			}

			cfile = cifs_new_fileinfo(newInode, fileHandle, filp,
						  nd->path.mnt,
						  nd->intent.open.flags);
			if (cfile == NULL) {
				fput(filp);
				CIFSSMBClose(xid, pTcon, fileHandle);
				rc = -ENOMEM;
				goto lookup_out;
			}
		}
		/* since paths are not looked up by component - the parent
		   directories are presumed to be good here */
		renew_parental_timestamps(direntry);
@@ -755,6 +766,7 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry,
		is a common return code */
	}

lookup_out:
	kfree(full_path);
	FreeXid(xid);
	return ERR_PTR(rc);
+35 −65
Original line number Diff line number Diff line
@@ -162,44 +162,12 @@ psx_client_can_cache:
	return 0;
}

static struct cifsFileInfo *
cifs_fill_filedata(struct file *file)
{
	struct list_head *tmp;
	struct cifsFileInfo *pCifsFile = NULL;
	struct cifsInodeInfo *pCifsInode = NULL;

	/* search inode for this file and fill in file->private_data */
	pCifsInode = CIFS_I(file->f_path.dentry->d_inode);
	read_lock(&GlobalSMBSeslock);
	list_for_each(tmp, &pCifsInode->openFileList) {
		pCifsFile = list_entry(tmp, struct cifsFileInfo, flist);
		if ((pCifsFile->pfile == NULL) &&
		    (pCifsFile->pid == current->tgid)) {
			/* mode set in cifs_create */

			/* needed for writepage */
			pCifsFile->pfile = file;
			file->private_data = pCifsFile;
			break;
		}
	}
	read_unlock(&GlobalSMBSeslock);

	if (file->private_data != NULL) {
		return pCifsFile;
	} else if ((file->f_flags & O_CREAT) && (file->f_flags & O_EXCL))
			cERROR(1, "could not find file instance for "
				   "new file %p", file);
	return NULL;
}

/* all arguments to this function must be checked for validity in caller */
static inline int cifs_open_inode_helper(struct inode *inode, struct file *file,
	struct cifsInodeInfo *pCifsInode, struct cifsFileInfo *pCifsFile,
static inline int cifs_open_inode_helper(struct inode *inode,
	struct cifsTconInfo *pTcon, int *oplock, FILE_ALL_INFO *buf,
	char *full_path, int xid)
{
	struct cifsInodeInfo *pCifsInode = CIFS_I(inode);
	struct timespec temp;
	int rc;

@@ -213,36 +181,35 @@ static inline int cifs_open_inode_helper(struct inode *inode, struct file *file,
	/* if not oplocked, invalidate inode pages if mtime or file
	   size changed */
	temp = cifs_NTtimeToUnix(buf->LastWriteTime);
	if (timespec_equal(&file->f_path.dentry->d_inode->i_mtime, &temp) &&
			   (file->f_path.dentry->d_inode->i_size ==
	if (timespec_equal(&inode->i_mtime, &temp) &&
			   (inode->i_size ==
			    (loff_t)le64_to_cpu(buf->EndOfFile))) {
		cFYI(1, "inode unchanged on server");
	} else {
		if (file->f_path.dentry->d_inode->i_mapping) {
		if (inode->i_mapping) {
			/* BB no need to lock inode until after invalidate
			since namei code should already have it locked? */
			rc = filemap_write_and_wait(file->f_path.dentry->d_inode->i_mapping);
			rc = filemap_write_and_wait(inode->i_mapping);
			if (rc != 0)
				CIFS_I(file->f_path.dentry->d_inode)->write_behind_rc = rc;
				pCifsInode->write_behind_rc = rc;
		}
		cFYI(1, "invalidating remote inode since open detected it "
			 "changed");
		invalidate_remote_inode(file->f_path.dentry->d_inode);
		invalidate_remote_inode(inode);
	}

client_can_cache:
	if (pTcon->unix_ext)
		rc = cifs_get_inode_info_unix(&file->f_path.dentry->d_inode,
			full_path, inode->i_sb, xid);
		rc = cifs_get_inode_info_unix(&inode, full_path, inode->i_sb,
					      xid);
	else
		rc = cifs_get_inode_info(&file->f_path.dentry->d_inode,
			full_path, buf, inode->i_sb, xid, NULL);
		rc = cifs_get_inode_info(&inode, full_path, buf, inode->i_sb,
					 xid, NULL);

	if ((*oplock & 0xF) == OPLOCK_EXCLUSIVE) {
		pCifsInode->clientCanCacheAll = true;
		pCifsInode->clientCanCacheRead = true;
		cFYI(1, "Exclusive Oplock granted on inode %p",
			 file->f_path.dentry->d_inode);
		cFYI(1, "Exclusive Oplock granted on inode %p", inode);
	} else if ((*oplock & 0xF) == OPLOCK_READ)
		pCifsInode->clientCanCacheRead = true;

@@ -256,7 +223,7 @@ int cifs_open(struct inode *inode, struct file *file)
	__u32 oplock;
	struct cifs_sb_info *cifs_sb;
	struct cifsTconInfo *tcon;
	struct cifsFileInfo *pCifsFile;
	struct cifsFileInfo *pCifsFile = NULL;
	struct cifsInodeInfo *pCifsInode;
	char *full_path = NULL;
	int desiredAccess;
@@ -270,12 +237,6 @@ int cifs_open(struct inode *inode, struct file *file)
	tcon = cifs_sb->tcon;

	pCifsInode = CIFS_I(file->f_path.dentry->d_inode);
	pCifsFile = cifs_fill_filedata(file);
	if (pCifsFile) {
		rc = 0;
		FreeXid(xid);
		return rc;
	}

	full_path = build_path_from_dentry(file->f_path.dentry);
	if (full_path == NULL) {
@@ -299,8 +260,7 @@ int cifs_open(struct inode *inode, struct file *file)
		int oflags = (int) cifs_posix_convert_flags(file->f_flags);
		oflags |= SMB_O_CREAT;
		/* can not refresh inode info since size could be stale */
		rc = cifs_posix_open(full_path, &inode, file->f_path.mnt,
				inode->i_sb,
		rc = cifs_posix_open(full_path, &inode, inode->i_sb,
				cifs_sb->mnt_file_mode /* ignored */,
				oflags, &oplock, &netfid, xid);
		if (rc == 0) {
@@ -308,9 +268,20 @@ int cifs_open(struct inode *inode, struct file *file)
			/* no need for special case handling of setting mode
			   on read only files needed here */

			pCifsFile = cifs_fill_filedata(file);
			cifs_posix_open_inode_helper(inode, file, pCifsInode,
						     oplock, netfid);
			rc = cifs_posix_open_inode_helper(inode, file,
					pCifsInode, oplock, netfid);
			if (rc != 0) {
				CIFSSMBClose(xid, tcon, netfid);
				goto out;
			}

			pCifsFile = cifs_new_fileinfo(inode, netfid, file,
							file->f_path.mnt,
							oflags);
			if (pCifsFile == NULL) {
				CIFSSMBClose(xid, tcon, netfid);
				rc = -ENOMEM;
			}
			goto out;
		} else if ((rc == -EINVAL) || (rc == -EOPNOTSUPP)) {
			if (tcon->ses->serverNOS)
@@ -391,17 +362,17 @@ int cifs_open(struct inode *inode, struct file *file)
		goto out;
	}

	rc = cifs_open_inode_helper(inode, tcon, &oplock, buf, full_path, xid);
	if (rc != 0)
		goto out;

	pCifsFile = cifs_new_fileinfo(inode, netfid, file, file->f_path.mnt,
					file->f_flags);
	file->private_data = pCifsFile;
	if (file->private_data == NULL) {
	if (pCifsFile == NULL) {
		rc = -ENOMEM;
		goto out;
	}

	rc = cifs_open_inode_helper(inode, file, pCifsInode, pCifsFile, tcon,
				    &oplock, buf, full_path, xid);

	if (oplock & CIFS_CREATE_ACTION) {
		/* time to set mode which we can not set earlier due to
		   problems creating new read-only files */
@@ -513,8 +484,7 @@ reopen_error_exit:
			le64_to_cpu(tcon->fsUnixInfo.Capability))) {
		int oflags = (int) cifs_posix_convert_flags(file->f_flags);
		/* can not refresh inode info since size could be stale */
		rc = cifs_posix_open(full_path, NULL, file->f_path.mnt,
				inode->i_sb,
		rc = cifs_posix_open(full_path, NULL, inode->i_sb,
				cifs_sb->mnt_file_mode /* ignored */,
				oflags, &oplock, &netfid, xid);
		if (rc == 0) {
Loading