mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-09-06 02:50:43 +00:00
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: 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
This commit is contained in:
commit
be1d29f59c
7 changed files with 98 additions and 111 deletions
|
@ -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/
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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(struct inode *inode, struct dentry *direntry, int mode,
|
|||
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);
|
||||
|
|
100
fs/cifs/file.c
100
fs/cifs/file.c
|
@ -162,44 +162,12 @@ cifs_posix_open_inode_helper(struct inode *inode, struct file *file,
|
|||
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 @@ static int cifs_reopen_file(struct file *file, bool can_flush)
|
|||
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) {
|
||||
|
|
|
@ -1401,6 +1401,10 @@ cifs_do_rename(int xid, struct dentry *from_dentry, const char *fromPath,
|
|||
if (rc == 0 || rc != -ETXTBSY)
|
||||
return rc;
|
||||
|
||||
/* open-file renames don't work across directories */
|
||||
if (to_dentry->d_parent != from_dentry->d_parent)
|
||||
return rc;
|
||||
|
||||
/* open the file to be renamed -- we need DELETE perms */
|
||||
rc = CIFSSMBOpen(xid, pTcon, fromPath, FILE_OPEN, DELETE,
|
||||
CREATE_NOT_DIR, &srcfid, &oplock, NULL,
|
||||
|
|
|
@ -730,15 +730,7 @@ CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses,
|
|||
|
||||
/* calculate session key */
|
||||
setup_ntlmv2_rsp(ses, v2_sess_key, nls_cp);
|
||||
if (first_time) /* should this be moved into common code
|
||||
with similar ntlmv2 path? */
|
||||
/* cifs_calculate_ntlmv2_mac_key(ses->server->mac_signing_key,
|
||||
response BB FIXME, v2_sess_key); */
|
||||
|
||||
/* copy session key */
|
||||
|
||||
/* memcpy(bcc_ptr, (char *)ntlm_session_key,LM2_SESS_KEY_SIZE);
|
||||
bcc_ptr += LM2_SESS_KEY_SIZE; */
|
||||
/* FIXME: calculate MAC key */
|
||||
memcpy(bcc_ptr, (char *)v2_sess_key,
|
||||
sizeof(struct ntlmv2_resp));
|
||||
bcc_ptr += sizeof(struct ntlmv2_resp);
|
||||
|
|
Loading…
Reference in a new issue