Tim Robbins wrote:
Here's a backtrace of a smbfs panic. Looks like it does not correctly
handle the smbfs_getpages error it is encountering and leaves garbage
vnodes lying around. The panic probably comes from the VI_LOCK macro
call on smbfs_node.c line 321.
# cp blah.tar.gz ~tim
cp: /home/tim/blah.tar.gz: Bad address
Read the list archives. We discussed this to death. The correct
thing to do is to back off and retry -- that's decimal 60, which
is hex 0x3c, which, according to /sys/netsmb/smb_rq.h is:
#define SMBR_REXMIT0x0004 /* request should be retransmitted */
#define SMBR_INTR 0x0008 /* request interrupted */
#define SMBR_RESTART 0x0010 /* request should be repeated if possible */
#define SMBR_NORESTART 0x0020 /* request is not restartable */
If you don't want to try to implement this, note that the read/write
works (try 'dd' instead of 'cp', so you aren't using mmap'ed pages,
and see that 'dd' works).
I don't think it's worth writing the code to attempt the retry, until
you know that the code will work -- that it's backed up far enough
that the retry won't fail. This basically means you need to know why
it's failing in the first place, which means you need to be familiar
with how the server is implemented (not likely, unless your name is
Luke Howard, you're a Microsoft employee, or you have a Windows
source license -- otherwise it's probably about two weeks worth of
work).
The attached patch works around the problem by disabling the getpages
and putpages code in the smbfs. This basically turns paging operations
into reads and writes, which we know from using 'dd' instead of 'cp'
will work.
Note: this is only a workaround: it disables obviously incorrect code,
but doesn't provide replacement code for the bogus code.
-- Terry
Index: smbfs_io.c
===
RCS file: /cvs/src/sys/fs/smbfs/smbfs_io.c,v
retrieving revision 1.13
diff -c -r1.13 smbfs_io.c
*** smbfs_io.c 4 Aug 2002 10:29:30 - 1.13
--- smbfs_io.c 21 Nov 2002 05:53:23 -
***
*** 400,405
--- 400,406
return error;
}
+ #if BROKEN_PAGE_IO
/*
* Vnode op for VM getpages.
* Wish wish get rid from multiple IO routines
***
*** 655,660
--- 656,662
return rtvals[0];
#endif /* SMBFS_RWGENERIC */
}
+ #endif/* BROKEN_PAGE_IO */
/*
* Flush and invalidate all dirty buffers. If another process is already
Index: smbfs_node.h
===
RCS file: /cvs/src/sys/fs/smbfs/smbfs_node.h,v
retrieving revision 1.2
diff -c -r1.2 smbfs_node.h
*** smbfs_node.h18 Sep 2002 09:27:04 - 1.2
--- smbfs_node.h21 Nov 2002 05:53:47 -
***
*** 75,83
#define VTOSMB(vp)((struct smbnode *)(vp)-v_data)
#define SMBTOV(np)((struct vnode *)(np)-n_vnode)
struct vop_getpages_args;
- struct vop_inactive_args;
struct vop_putpages_args;
struct vop_reclaim_args;
struct ucred;
struct uio;
--- 75,85
#define VTOSMB(vp)((struct smbnode *)(vp)-v_data)
#define SMBTOV(np)((struct vnode *)(np)-n_vnode)
+ #if BROKEN_PAGE_IO
struct vop_getpages_args;
struct vop_putpages_args;
+ #endif/* BROKEN_PAGE_IO */
+ struct vop_inactive_args;
struct vop_reclaim_args;
struct ucred;
struct uio;
***
*** 89,96
--- 91,100
struct smbfattr *fap, struct vnode **vpp);
u_int32_t smbfs_hash(const u_char *name, int nmlen);
+ #if BROKEN_PAGE_IO
int smbfs_getpages(struct vop_getpages_args *);
int smbfs_putpages(struct vop_putpages_args *);
+ #endif/* BROKEN_PAGE_IO */
int smbfs_readvnode(struct vnode *vp, struct uio *uiop, struct ucred *cred);
int smbfs_writevnode(struct vnode *vp, struct uio *uiop, struct ucred *cred, int
ioflag);
void smbfs_attr_cacheenter(struct vnode *vp, struct smbfattr *fap);
Index: smbfs_vnops.c
===
RCS file: /cvs/src/sys/fs/smbfs/smbfs_vnops.c,v
retrieving revision 1.24
diff -c -r1.24 smbfs_vnops.c
*** smbfs_vnops.c 26 Sep 2002 14:07:43 - 1.24
--- smbfs_vnops.c 21 Nov 2002 05:52:32 -
***
*** 96,102
--- 96,104
{ vop_create_desc, (vop_t *) smbfs_create },
{ vop_fsync_desc, (vop_t *) smbfs_fsync },
{ vop_getattr_desc,(vop_t *) smbfs_getattr },
+ #if BROKEN_PAGE_IO
{ vop_getpages_desc, (vop_t *) smbfs_getpages },
+ #endif/* BROKEN_PAGE_IO */
{ vop_inactive_desc, (vop_t *) smbfs_inactive },
{ vop_ioctl_desc, (vop_t *) smbfs_ioctl },
{ vop_islocked_desc, (vop_t *) vop_stdislocked },
***
*** 108,114
--- 110,118
{ vop_open_desc, (vop_t *) smbfs_open },
{ vop_pathconf_desc