Re: smbfs Oops with Linux 2.6.3

From: Zwane Mwaikambo
Date: Thu Mar 11 2004 - 01:31:05 EST


Two patches applied in this order;

patch-smbfs-readdir-oops
fs/smbfs/inode.c | 1 +
fs/smbfs/proc.c | 45 ++++++++++++++++++++++++++++++++++++++++++---
include/linux/smb_fs_sb.h | 2 +-
3 files changed, 44 insertions(+), 4 deletions(-)

patch-smbfs-rcls-cleanup
fs/smbfs/proc.c | 12 ++++++------
include/linux/smb_fs_sb.h | 3 ---
2 files changed, 6 insertions(+), 9 deletions(-)

I avoided adding the BUG() placeholders, since we will PF# when we hit the
NULL pointer and the call trace should give us a decent idea of where it
is.

Thanks,
ZwaneIndex: linux-2.6.4-rc3/fs/smbfs/inode.c
===================================================================
RCS file: /home/cvsroot/linux-2.6.4-rc3/fs/smbfs/inode.c,v
retrieving revision 1.1.1.1
diff -u -p -B -r1.1.1.1 inode.c
--- linux-2.6.4-rc3/fs/smbfs/inode.c 10 Mar 2004 01:05:32 -0000 1.1.1.1
+++ linux-2.6.4-rc3/fs/smbfs/inode.c 11 Mar 2004 05:08:40 -0000
@@ -513,6 +513,7 @@ int smb_fill_super(struct super_block *s
server->super_block = sb;
server->mnt = NULL;
server->sock_file = NULL;
+ init_waitqueue_head(&server->conn_wq);
init_MUTEX(&server->sem);
INIT_LIST_HEAD(&server->entry);
INIT_LIST_HEAD(&server->xmitq);
Index: linux-2.6.4-rc3/fs/smbfs/proc.c
===================================================================
RCS file: /home/cvsroot/linux-2.6.4-rc3/fs/smbfs/proc.c,v
retrieving revision 1.1.1.1
diff -u -p -B -r1.1.1.1 proc.c
--- linux-2.6.4-rc3/fs/smbfs/proc.c 10 Mar 2004 01:05:32 -0000 1.1.1.1
+++ linux-2.6.4-rc3/fs/smbfs/proc.c 11 Mar 2004 05:07:48 -0000
@@ -56,6 +56,7 @@ static struct smb_ops smb_ops_os2;
static struct smb_ops smb_ops_win95;
static struct smb_ops smb_ops_winNT;
static struct smb_ops smb_ops_unix;
+static struct smb_ops smb_ops_null;

static void
smb_init_dirent(struct smb_sb_info *server, struct smb_fattr *fattr);
@@ -878,7 +879,6 @@ smb_newconn(struct smb_sb_info *server,
server->conn_pid = current->pid;
server->opt = *opt;
server->generation += 1;
- server->state = CONN_VALID;
error = 0;

if (server->conn_error) {
@@ -981,6 +981,9 @@ smb_newconn(struct smb_sb_info *server,
smbiod_wake_up();
if (server->opt.capabilities & SMB_CAP_UNIX)
smb_proc_query_cifsunix(server);
+
+ server->state = CONN_VALID;
+ wake_up_interruptible_all(&server->conn_wq);
return error;

out:
@@ -2794,10 +2797,45 @@ out:
}

static int
+smb_proc_ops_wait(struct smb_sb_info *server)
+{
+ int result;
+
+ result = wait_event_interruptible_timeout(server->conn_wq,
+ server->state == CONN_VALID, 30*HZ);
+
+ if (!result || signal_pending(current))
+ return -EIO;
+
+ return 0;
+}
+
+static int
smb_proc_getattr_null(struct smb_sb_info *server, struct dentry *dir,
- struct smb_fattr *attr)
+ struct smb_fattr *fattr)
{
- return -EIO;
+ int result;
+
+ if (smb_proc_ops_wait(server) < 0)
+ return -EIO;
+
+ smb_init_dirent(server, fattr);
+ result = server->ops->getattr(server, dir, fattr);
+ smb_finish_dirent(server, fattr);
+
+ return result;
+}
+
+static int
+smb_proc_readdir_null(struct file *filp, void *dirent, filldir_t filldir,
+ struct smb_cache_control *ctl)
+{
+ struct smb_sb_info *server = server_from_dentry(filp->f_dentry);
+
+ if (smb_proc_ops_wait(server) < 0)
+ return -EIO;
+
+ return server->ops->readdir(filp, dirent, filldir, ctl);
}

int
@@ -3431,6 +3468,7 @@ static struct smb_ops smb_ops_unix =
/* Place holder until real ops are in place */
static struct smb_ops smb_ops_null =
{
+ .readdir = smb_proc_readdir_null,
.getattr = smb_proc_getattr_null,
};

Index: linux-2.6.4-rc3/include/linux/smb_fs_sb.h
===================================================================
RCS file: /home/cvsroot/linux-2.6.4-rc3/include/linux/smb_fs_sb.h,v
retrieving revision 1.1.1.1
diff -u -p -B -r1.1.1.1 smb_fs_sb.h
--- linux-2.6.4-rc3/include/linux/smb_fs_sb.h 10 Mar 2004 01:05:23 -0000 1.1.1.1
+++ linux-2.6.4-rc3/include/linux/smb_fs_sb.h 11 Mar 2004 05:37:14 -0000
@@ -57,7 +57,7 @@ struct smb_sb_info {
unsigned int generation;
pid_t conn_pid;
struct smb_conn_opt opt;
-
+ wait_queue_head_t conn_wq;
struct semaphore sem;

unsigned short rcls; /* The error codes we received */
Index: linux-2.6.4-rc3/fs/smbfs/proc.c
===================================================================
RCS file: /home/cvsroot/linux-2.6.4-rc3/fs/smbfs/proc.c,v
retrieving revision 1.2
diff -u -p -B -r1.2 proc.c
--- linux-2.6.4-rc3/fs/smbfs/proc.c 11 Mar 2004 05:26:07 -0000 1.2
+++ linux-2.6.4-rc3/fs/smbfs/proc.c 11 Mar 2004 05:26:31 -0000
@@ -2373,7 +2373,7 @@ smb_proc_readdir_long(struct file *filp,
if (req->rq_rcls != 0) {
result = smb_errno(req);
PARANOIA("name=%s, result=%d, rcls=%d, err=%d\n",
- mask, result, server->rcls, server->err);
+ mask, result, req->rq_rcls, req->rq_err);
break;
}

@@ -2529,7 +2529,7 @@ smb_proc_getattr_ff(struct smb_sb_info *
result = smb_add_request(req);
if (result < 0)
goto out_free;
- if (server->rcls != 0) {
+ if (req->rq_rcls != 0) {
result = smb_errno(req);
#ifdef SMBFS_PARANOIA
if (result != -ENOENT)
@@ -2642,7 +2642,7 @@ smb_proc_getattr_trans2(struct smb_sb_in
result = smb_add_request(req);
if (result < 0)
goto out;
- if (server->rcls != 0) {
+ if (req->rq_rcls != 0) {
VERBOSE("for %s: result=%d, rcls=%d, err=%d\n",
&param[6], result, req->rq_rcls, req->rq_err);
result = smb_errno(req);
@@ -3255,7 +3255,7 @@ smb_proc_read_link(struct smb_sb_info *s
if (result < 0)
goto out_free;
DEBUG1("for %s: result=%d, rcls=%d, err=%d\n",
- &param[6], result, server->rcls, server->err);
+ &param[6], result, req->rq_rcls, req->rq_err);

/* copy data up to the \0 or buffer length */
result = len;
@@ -3305,7 +3305,7 @@ smb_proc_symlink(struct smb_sb_info *ser
goto out_free;

DEBUG1("for %s: result=%d, rcls=%d, err=%d\n",
- &param[6], result, server->rcls, server->err);
+ &param[6], result, req->rq_rcls, req->rq_err);
result = 0;

out_free:
@@ -3352,7 +3352,7 @@ smb_proc_link(struct smb_sb_info *server
goto out_free;

DEBUG1("for %s: result=%d, rcls=%d, err=%d\n",
- &param[6], result, server->rcls, server->err);
+ &param[6], result, req->rq_rcls, req->rq_err);
result = 0;

out_free:
Index: linux-2.6.4-rc3/include/linux/smb_fs_sb.h
===================================================================
RCS file: /home/cvsroot/linux-2.6.4-rc3/include/linux/smb_fs_sb.h,v
retrieving revision 1.2
diff -u -p -B -r1.2 smb_fs_sb.h
--- linux-2.6.4-rc3/include/linux/smb_fs_sb.h 11 Mar 2004 05:38:11 -0000 1.2
+++ linux-2.6.4-rc3/include/linux/smb_fs_sb.h 11 Mar 2004 05:38:17 -0000
@@ -60,9 +60,6 @@ struct smb_sb_info {
wait_queue_head_t conn_wq;
struct semaphore sem;

- unsigned short rcls; /* The error codes we received */
- unsigned short err;
-
unsigned char header[SMB_HEADER_LEN + 20*2 + 2];
u32 header_len;
u32 smb_len;