Skip to content

Commit

Permalink
Merge master.kernel.org:/pub/scm/linux/kernel/git/sfrench/cifs-2.6-st…
Browse files Browse the repository at this point in the history
…able

* master.kernel.org:/pub/scm/linux/kernel/git/sfrench/cifs-2.6-stable:
  [CIFS] Fix typo in previous
  [CIFS] Readdir fixes to allow search to start at arbitrary position
  [CIFS] Use the kthread_ API instead of opencoding lots of hairy code for kernel
  [CIFS] Don't allow a backslash in a path component
  [CIFS] [CIFS] Do not take rename sem on most path based calls (during
  • Loading branch information
Linus Torvalds committed Apr 23, 2006
2 parents a580e5b + b66ac3e commit 41bc398
Show file tree
Hide file tree
Showing 13 changed files with 138 additions and 115 deletions.
6 changes: 5 additions & 1 deletion fs/cifs/CHANGES
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
Version 1.42
------------
Fix slow oplock break when mounted to different servers at the same time and
the tids match and we try to find matching fid on wrong server.
the tids match and we try to find matching fid on wrong server. Fix read
looping when signing required by server (2.6.16 kernel only). Fix readdir
vs. rename race which could cause each to hang. Return . and .. even
if server does not. Allow searches to skip first three entries and
begin at any location. Fix oops in find_writeable_file.

Version 1.41
------------
Expand Down
8 changes: 8 additions & 0 deletions fs/cifs/README
Original file line number Diff line number Diff line change
Expand Up @@ -511,6 +511,14 @@ LinuxExtensionsEnabled If set to one then the client will attempt to
support and want to map the uid and gid fields
to values supplied at mount (rather than the
actual values, then set this to zero. (default 1)
Experimental When set to 1 used to enable certain experimental
features (currently enables multipage writes
when signing is enabled, the multipage write
performance enhancement was disabled when
signing turned on in case buffer was modified
just before it was sent, also this flag will
be used to use the new experimental sessionsetup
code).

These experimental features and tracing can be enabled by changing flags in
/proc/fs/cifs (after the cifs module has been installed or built into the
Expand Down
99 changes: 50 additions & 49 deletions fs/cifs/cifsfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
#include <linux/vfs.h>
#include <linux/mempool.h>
#include <linux/delay.h>
#include <linux/kthread.h>
#include "cifsfs.h"
#include "cifspdu.h"
#define DECLARE_GLOBALS_HERE
Expand Down Expand Up @@ -75,9 +76,6 @@ unsigned int cifs_max_pending = CIFS_MAX_REQ;
module_param(cifs_max_pending, int, 0);
MODULE_PARM_DESC(cifs_max_pending,"Simultaneous requests to server. Default: 50 Range: 2 to 256");

static DECLARE_COMPLETION(cifs_oplock_exited);
static DECLARE_COMPLETION(cifs_dnotify_exited);

extern mempool_t *cifs_sm_req_poolp;
extern mempool_t *cifs_req_poolp;
extern mempool_t *cifs_mid_poolp;
Expand Down Expand Up @@ -841,10 +839,6 @@ static int cifs_oplock_thread(void * dummyarg)
__u16 netfid;
int rc;

daemonize("cifsoplockd");
allow_signal(SIGTERM);

oplockThread = current;
do {
if (try_to_freeze())
continue;
Expand Down Expand Up @@ -900,20 +894,16 @@ static int cifs_oplock_thread(void * dummyarg)
set_current_state(TASK_INTERRUPTIBLE);
schedule_timeout(1); /* yield in case q were corrupt */
}
} while(!signal_pending(current));
oplockThread = NULL;
complete_and_exit (&cifs_oplock_exited, 0);
} while (!kthread_should_stop());

return 0;
}

static int cifs_dnotify_thread(void * dummyarg)
{
struct list_head *tmp;
struct cifsSesInfo *ses;

daemonize("cifsdnotifyd");
allow_signal(SIGTERM);

dnotifyThread = current;
do {
if(try_to_freeze())
continue;
Expand All @@ -931,8 +921,9 @@ static int cifs_dnotify_thread(void * dummyarg)
wake_up_all(&ses->server->response_q);
}
read_unlock(&GlobalSMBSeslock);
} while(!signal_pending(current));
complete_and_exit (&cifs_dnotify_exited, 0);
} while (!kthread_should_stop());

return 0;
}

static int __init
Expand Down Expand Up @@ -982,32 +973,48 @@ init_cifs(void)
}

rc = cifs_init_inodecache();
if (!rc) {
rc = cifs_init_mids();
if (!rc) {
rc = cifs_init_request_bufs();
if (!rc) {
rc = register_filesystem(&cifs_fs_type);
if (!rc) {
rc = (int)kernel_thread(cifs_oplock_thread, NULL,
CLONE_FS | CLONE_FILES | CLONE_VM);
if(rc > 0) {
rc = (int)kernel_thread(cifs_dnotify_thread, NULL,
CLONE_FS | CLONE_FILES | CLONE_VM);
if(rc > 0)
return 0;
else
cERROR(1,("error %d create dnotify thread", rc));
} else {
cERROR(1,("error %d create oplock thread",rc));
}
}
cifs_destroy_request_bufs();
}
cifs_destroy_mids();
}
cifs_destroy_inodecache();
if (rc)
goto out_clean_proc;

rc = cifs_init_mids();
if (rc)
goto out_destroy_inodecache;

rc = cifs_init_request_bufs();
if (rc)
goto out_destroy_mids;

rc = register_filesystem(&cifs_fs_type);
if (rc)
goto out_destroy_request_bufs;

oplockThread = kthread_run(cifs_oplock_thread, NULL, "cifsoplockd");
if (IS_ERR(oplockThread)) {
rc = PTR_ERR(oplockThread);
cERROR(1,("error %d create oplock thread", rc));
goto out_unregister_filesystem;
}

dnotifyThread = kthread_run(cifs_dnotify_thread, NULL, "cifsdnotifyd");
if (IS_ERR(dnotifyThread)) {
rc = PTR_ERR(dnotifyThread);
cERROR(1,("error %d create dnotify thread", rc));
goto out_stop_oplock_thread;
}

return 0;

out_stop_oplock_thread:
kthread_stop(oplockThread);
out_unregister_filesystem:
unregister_filesystem(&cifs_fs_type);
out_destroy_request_bufs:
cifs_destroy_request_bufs();
out_destroy_mids:
cifs_destroy_mids();
out_destroy_inodecache:
cifs_destroy_inodecache();
out_clean_proc:
#ifdef CONFIG_PROC_FS
cifs_proc_clean();
#endif
Expand All @@ -1025,14 +1032,8 @@ exit_cifs(void)
cifs_destroy_inodecache();
cifs_destroy_mids();
cifs_destroy_request_bufs();
if(oplockThread) {
send_sig(SIGTERM, oplockThread, 1);
wait_for_completion(&cifs_oplock_exited);
}
if(dnotifyThread) {
send_sig(SIGTERM, dnotifyThread, 1);
wait_for_completion(&cifs_dnotify_exited);
}
kthread_stop(oplockThread);
kthread_stop(dnotifyThread);
}

MODULE_AUTHOR("Steve French <sfrench@us.ibm.com>");
Expand Down
2 changes: 1 addition & 1 deletion fs/cifs/cifssmb.c
Original file line number Diff line number Diff line change
Expand Up @@ -3119,7 +3119,7 @@ CIFSFindFirst(const int xid, struct cifsTconInfo *tcon,
psrch_inf->endOfSearch = FALSE;

psrch_inf->entries_in_buffer = le16_to_cpu(parms->SearchCount);
psrch_inf->index_of_last_entry =
psrch_inf->index_of_last_entry = 2 /* skip . and .. */ +
psrch_inf->entries_in_buffer;
*pnetfid = parms->SearchHandle;
} else {
Expand Down
5 changes: 4 additions & 1 deletion fs/cifs/connect.c
Original file line number Diff line number Diff line change
Expand Up @@ -3447,7 +3447,10 @@ int cifs_setup_session(unsigned int xid, struct cifsSesInfo *pSesInfo,
pSesInfo->server->secMode,
pSesInfo->server->capabilities,
pSesInfo->server->timeZone));
if (extended_security
if(experimEnabled > 1)
rc = CIFS_SessSetup(xid, pSesInfo, CIFS_NTLM /* type */,
&ntlmv2_flag, nls_info);
else if (extended_security
&& (pSesInfo->capabilities & CAP_EXTENDED_SECURITY)
&& (pSesInfo->server->secType == NTLMSSP)) {
cFYI(1, ("New style sesssetup"));
Expand Down
18 changes: 14 additions & 4 deletions fs/cifs/dir.c
Original file line number Diff line number Diff line change
Expand Up @@ -139,9 +139,7 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
cifs_sb = CIFS_SB(inode->i_sb);
pTcon = cifs_sb->tcon;

mutex_lock(&direntry->d_sb->s_vfs_rename_mutex);
full_path = build_path_from_dentry(direntry);
mutex_unlock(&direntry->d_sb->s_vfs_rename_mutex);
if(full_path == NULL) {
FreeXid(xid);
return -ENOMEM;
Expand Down Expand Up @@ -316,9 +314,7 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, int mode,
cifs_sb = CIFS_SB(inode->i_sb);
pTcon = cifs_sb->tcon;

mutex_lock(&direntry->d_sb->s_vfs_rename_mutex);
full_path = build_path_from_dentry(direntry);
mutex_unlock(&direntry->d_sb->s_vfs_rename_mutex);
if(full_path == NULL)
rc = -ENOMEM;
else if (pTcon->ses->capabilities & CAP_UNIX) {
Expand Down Expand Up @@ -440,6 +436,20 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry, struct name
cifs_sb = CIFS_SB(parent_dir_inode->i_sb);
pTcon = cifs_sb->tcon;

/*
* Don't allow the separator character in a path component.
* The VFS will not allow "/", but "\" is allowed by posix.
*/
if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS)) {
int i;
for (i = 0; i < direntry->d_name.len; i++)
if (direntry->d_name.name[i] == '\\') {
cFYI(1, ("Invalid file name"));
FreeXid(xid);
return ERR_PTR(-EINVAL);
}
}

/* can not grab the rename sem here since it would
deadlock in the cases (beginning of sys_rename itself)
in which we already have the sb rename sem */
Expand Down
2 changes: 0 additions & 2 deletions fs/cifs/fcntl.c
Original file line number Diff line number Diff line change
Expand Up @@ -86,9 +86,7 @@ int cifs_dir_notify(struct file * file, unsigned long arg)
cifs_sb = CIFS_SB(file->f_dentry->d_sb);
pTcon = cifs_sb->tcon;

mutex_lock(&file->f_dentry->d_sb->s_vfs_rename_mutex);
full_path = build_path_from_dentry(file->f_dentry);
mutex_unlock(&file->f_dentry->d_sb->s_vfs_rename_mutex);

if(full_path == NULL) {
rc = -ENOMEM;
Expand Down
34 changes: 20 additions & 14 deletions fs/cifs/file.c
Original file line number Diff line number Diff line change
Expand Up @@ -203,9 +203,7 @@ int cifs_open(struct inode *inode, struct file *file)
}
}

mutex_lock(&inode->i_sb->s_vfs_rename_mutex);
full_path = build_path_from_dentry(file->f_dentry);
mutex_unlock(&inode->i_sb->s_vfs_rename_mutex);
if (full_path == NULL) {
FreeXid(xid);
return -ENOMEM;
Expand Down Expand Up @@ -906,8 +904,7 @@ static ssize_t cifs_write(struct file *file, const char *write_data,
if (rc != 0)
break;
}
/* BB FIXME We can not sign across two buffers yet */
if((pTcon->ses->server->secMode &
if(experimEnabled || (pTcon->ses->server->secMode &
(SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) == 0) {
struct kvec iov[2];
unsigned int len;
Expand All @@ -923,13 +920,13 @@ static ssize_t cifs_write(struct file *file, const char *write_data,
*poffset, &bytes_written,
iov, 1, long_op);
} else
/* BB FIXME fixup indentation of line below */
rc = CIFSSMBWrite(xid, pTcon,
open_file->netfid,
min_t(const int, cifs_sb->wsize,
write_size - total_written),
*poffset, &bytes_written,
write_data + total_written, NULL, long_op);
rc = CIFSSMBWrite(xid, pTcon,
open_file->netfid,
min_t(const int, cifs_sb->wsize,
write_size - total_written),
*poffset, &bytes_written,
write_data + total_written,
NULL, long_op);
}
if (rc || (bytes_written == 0)) {
if (total_written)
Expand Down Expand Up @@ -968,6 +965,16 @@ struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *cifs_inode)
struct cifsFileInfo *open_file;
int rc;

/* Having a null inode here (because mapping->host was set to zero by
the VFS or MM) should not happen but we had reports of on oops (due to
it being zero) during stress testcases so we need to check for it */

if(cifs_inode == NULL) {
cERROR(1,("Null inode passed to cifs_writeable_file"));
dump_stack();
return NULL;
}

read_lock(&GlobalSMBSeslock);
list_for_each_entry(open_file, &cifs_inode->openFileList, flist) {
if (open_file->closePend)
Expand Down Expand Up @@ -1093,12 +1100,11 @@ static int cifs_writepages(struct address_space *mapping,
if (cifs_sb->wsize < PAGE_CACHE_SIZE)
return generic_writepages(mapping, wbc);

/* BB FIXME we do not have code to sign across multiple buffers yet,
so go to older writepage style write which we can sign if needed */
if((cifs_sb->tcon->ses) && (cifs_sb->tcon->ses->server))
if(cifs_sb->tcon->ses->server->secMode &
(SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
return generic_writepages(mapping, wbc);
if(!experimEnabled)
return generic_writepages(mapping, wbc);

/*
* BB: Is this meaningful for a non-block-device file system?
Expand Down
6 changes: 0 additions & 6 deletions fs/cifs/inode.c
Original file line number Diff line number Diff line change
Expand Up @@ -722,9 +722,7 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode)
cifs_sb = CIFS_SB(inode->i_sb);
pTcon = cifs_sb->tcon;

mutex_lock(&inode->i_sb->s_vfs_rename_mutex);
full_path = build_path_from_dentry(direntry);
mutex_unlock(&inode->i_sb->s_vfs_rename_mutex);
if (full_path == NULL) {
FreeXid(xid);
return -ENOMEM;
Expand Down Expand Up @@ -807,9 +805,7 @@ int cifs_rmdir(struct inode *inode, struct dentry *direntry)
cifs_sb = CIFS_SB(inode->i_sb);
pTcon = cifs_sb->tcon;

mutex_lock(&inode->i_sb->s_vfs_rename_mutex);
full_path = build_path_from_dentry(direntry);
mutex_unlock(&inode->i_sb->s_vfs_rename_mutex);
if (full_path == NULL) {
FreeXid(xid);
return -ENOMEM;
Expand Down Expand Up @@ -1141,9 +1137,7 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs)
rc = 0;
}

mutex_lock(&direntry->d_sb->s_vfs_rename_mutex);
full_path = build_path_from_dentry(direntry);
mutex_unlock(&direntry->d_sb->s_vfs_rename_mutex);
if (full_path == NULL) {
FreeXid(xid);
return -ENOMEM;
Expand Down
6 changes: 0 additions & 6 deletions fs/cifs/link.c
Original file line number Diff line number Diff line change
Expand Up @@ -48,10 +48,8 @@ cifs_hardlink(struct dentry *old_file, struct inode *inode,
/* No need to check for cross device links since server will do that
BB note DFS case in future though (when we may have to check) */

mutex_lock(&inode->i_sb->s_vfs_rename_mutex);
fromName = build_path_from_dentry(old_file);
toName = build_path_from_dentry(direntry);
mutex_unlock(&inode->i_sb->s_vfs_rename_mutex);
if((fromName == NULL) || (toName == NULL)) {
rc = -ENOMEM;
goto cifs_hl_exit;
Expand Down Expand Up @@ -103,9 +101,7 @@ cifs_follow_link(struct dentry *direntry, struct nameidata *nd)

xid = GetXid();

mutex_lock(&direntry->d_sb->s_vfs_rename_mutex);
full_path = build_path_from_dentry(direntry);
mutex_unlock(&direntry->d_sb->s_vfs_rename_mutex);

if (!full_path)
goto out_no_free;
Expand Down Expand Up @@ -164,9 +160,7 @@ cifs_symlink(struct inode *inode, struct dentry *direntry, const char *symname)
cifs_sb = CIFS_SB(inode->i_sb);
pTcon = cifs_sb->tcon;

mutex_lock(&inode->i_sb->s_vfs_rename_mutex);
full_path = build_path_from_dentry(direntry);
mutex_unlock(&inode->i_sb->s_vfs_rename_mutex);

if(full_path == NULL) {
FreeXid(xid);
Expand Down
Loading

0 comments on commit 41bc398

Please sign in to comment.