2.1.55 smbfs patch-in-progress

Bill Hawes (whawes@star.net)
Wed, 10 Sep 1997 20:51:22 -0400


This is a multi-part message in MIME format.
--------------AFC04042F0A7E3C150181ED9
Content-Type: text/plain; charset=us-ascii
Content-Transfer-Encoding: 7bit

The attached patch gets smbfs working again on 2.1.55. It's very rough
still, but most operations are working. My hope is that those
interested in smbfs can play with this and help me track down the
remaining bugs.

A few notes:
(1) mv operations don't work properly; I'll be working on this
(2) Attempting to make a kernel over smbfs generates errors from getwd.
I'm not sure what's wrong here.
(3) Editing a file with vi leaves the .swp file open, and attempts to
delete it generate "text file busy". This may be a mmapping problem.

Anyway, check it out and let me know of any problems you find.

Regards,
Bill
--------------AFC04042F0A7E3C150181ED9
Content-Type: text/plain; charset=us-ascii; name="smbfs_55-patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline; filename="smbfs_55-patch"

--- linux-2.1.55/include/linux/smb_fs_i.h.old Thu Sep 4 12:33:52 1997
+++ linux-2.1.55/include/linux/smb_fs_i.h Wed Sep 10 10:03:18 1997
@@ -22,6 +22,7 @@
* (open == generation).
*/
unsigned int open;
+ void * dentry; /* The dentry we were opened with */
__u16 fileid; /* What id to handle a file with? */
__u16 attr; /* Attribute fields, DOS value */

--- linux-2.1.55/fs/smbfs/inode.c.old Thu Sep 4 12:33:51 1997
+++ linux-2.1.55/fs/smbfs/inode.c Wed Sep 10 14:07:02 1997
@@ -26,6 +26,9 @@
#include <asm/system.h>
#include <asm/uaccess.h>

+#define SB_of(server) ((struct super_block *) ((char *)(server) - \
+ (unsigned long)(&((struct super_block *)0)->u.smbfs_sb)))
+
extern int close_fp(struct file *filp);

static void smb_put_inode(struct inode *);
@@ -114,10 +117,16 @@
inode->i_op = NULL;
}

+/*
+ * This is called if the connection has gone bad ...
+ * try to kill off all the current inodes.
+ */
void
smb_invalidate_inodes(struct smb_sb_info *server)
{
printk("smb_invalidate_inodes\n");
+ shrink_dcache(); /* should shrink only this sb */
+ invalidate_inodes(SB_of(server));
}

int
@@ -134,19 +143,50 @@
return 0;
}

+/*
+ * This routine is called for every iput().
+ */
static void
smb_put_inode(struct inode *ino)
{
+ struct dentry * dentry;
pr_debug("smb_put_inode: count = %d\n", ino->i_count);

- if (smb_close(ino))
- printk("smbfs: could not close inode\n");
+ if (ino->i_count > 1) {
+ /*
+ * Check whether the dentry still holds this inode.
+ * This looks scary, but should work ... d_inode is
+ * cleared before iput() in the dcache.
+ */
+ dentry = (struct dentry *) ino->u.smbfs_i.dentry;
+ if (dentry && dentry->d_inode != ino) {
+ ino->u.smbfs_i.dentry = NULL;
+#if 0
+printk("smb_put_inode: cleared dentry for %s/%s (%ld), count=%d\n",
+dentry->d_parent->d_name.name, dentry->d_name.name, ino->i_ino, ino->i_count);
+#endif
+ }
+ } else {
+ /*
+ * Last use ... clear i_nlink to force
+ * smb_delete_inode to be called.
+ */
+ ino->i_nlink = 0;
+ }
}

+/*
+ * This routine is called when i_nlink == 0 and i_count goes to 0.
+ * All blocking cleanup operations need to go here to avoid races.
+ */
static void
-smb_delete_inode(struct inode *i)
+smb_delete_inode(struct inode *ino)
{
pr_debug("smb_delete_inode\n");
+ if (smb_close((struct dentry *) ino)) /* FIXME */
+ printk("smb_delete_inode: could not close inode %ld\n",
+ ino->i_ino);
+ clear_inode(ino);
}

static void
@@ -181,33 +221,20 @@
struct smb_fattr root;
kdev_t dev = sb->s_dev;
unsigned char *packet;
+ struct inode *root_inode;
+ struct dentry *dentry;

MOD_INC_USE_COUNT;

- if (!data) {
- printk("smb_read_super: missing data argument\n");
- sb->s_dev = 0;
- MOD_DEC_USE_COUNT;
- return NULL;
- }
+ if (!data)
+ goto out_no_data;

if (data->version != SMB_MOUNT_VERSION)
- {
- printk(KERN_ERR "smb_read_super: wrong data argument."
- " Recompile smbmount.\n");
- sb->s_dev = 0;
- MOD_DEC_USE_COUNT;
- return NULL;
- }
+ goto out_wrong_data;

packet = smb_vmalloc(SMB_INITIAL_PACKET_SIZE);
if (!packet)
- {
- pr_debug("smb_read_super: could not alloc packet\n");
- sb->s_dev = 0;
- MOD_DEC_USE_COUNT;
- return NULL;
- }
+ goto out_no_mem;

lock_super(sb);

@@ -232,18 +259,38 @@

smb_init_root_dirent(&(sb->u.smbfs_sb), &root);

+ sb->s_root = NULL;
unlock_super(sb);

- sb->s_root = d_alloc_root(smb_iget(sb, &root), NULL);
- if (!sb->s_root)
- {
- sb->s_dev = 0;
- printk(KERN_ERR "smb_read_super: get root inode failed\n");
- smb_vfree(sb->u.smbfs_sb.packet);
- MOD_DEC_USE_COUNT;
- return NULL;
- }
+ root_inode = smb_iget(sb, &root);
+ if (!root_inode)
+ goto out_no_root;
+ dentry = d_alloc_root(root_inode, NULL);
+ if (!dentry)
+ goto out_no_root;
+ root_inode->u.smbfs_i.dentry = dentry;
+ sb->s_root = dentry;
return sb;
+
+out_no_data:
+ printk("smb_read_super: missing data argument\n");
+ goto out;
+out_wrong_data:
+ printk(KERN_ERR "smb_read_super: wrong data argument."
+ " Recompile smbmount.\n");
+ goto out;
+out_no_mem:
+ pr_debug("smb_read_super: could not alloc packet\n");
+ goto out;
+out_no_root:
+ sb->s_dev = 0; /* iput() might block */
+ printk(KERN_ERR "smb_read_super: get root inode failed\n");
+ iput(root_inode);
+ smb_vfree(packet);
+out:
+ sb->s_dev = 0;
+ MOD_DEC_USE_COUNT;
+ return NULL;
}

static int
@@ -265,26 +312,32 @@
int
smb_notify_change(struct inode *inode, struct iattr *attr)
{
- int error = 0;
+ struct dentry *dentry = inode->u.smbfs_i.dentry;
+ int error;
+
+ error = -EIO;
+ if (!dentry)
+ goto out;

if ((error = inode_change_ok(inode, attr)) < 0)
- return error;
+ goto out;

+ error = -EPERM;
if (((attr->ia_valid & ATTR_UID) &&
(attr->ia_uid != SMB_SERVER(inode)->m.uid)))
- return -EPERM;
+ goto out;

if (((attr->ia_valid & ATTR_GID) &&
(attr->ia_uid != SMB_SERVER(inode)->m.gid)))
- return -EPERM;
+ goto out;

if (((attr->ia_valid & ATTR_MODE) &&
(attr->ia_mode & ~(S_IFREG | S_IFDIR | S_IRWXU | S_IRWXG | S_IRWXO))))
- return -EPERM;
+ goto out;

if ((attr->ia_valid & ATTR_SIZE) != 0)
{
- if ((error = smb_open(inode, O_WRONLY)) < 0)
+ if ((error = smb_open(dentry, O_WRONLY)) < 0)
goto fail;

if ((error = smb_proc_trunc(SMB_SERVER(inode),
@@ -316,8 +369,8 @@
else
fattr.f_atime = inode->i_atime;

- if ((error = smb_proc_setattr(SMB_SERVER(inode),
- inode, &fattr)) >= 0)
+ error = smb_proc_setattr(SMB_SERVER(inode), dentry, &fattr);
+ if (error >= 0)
{
inode->i_ctime = fattr.f_ctime;
inode->i_mtime = fattr.f_mtime;
@@ -326,10 +379,9 @@
}
fail:
/* smb_invalid_dir_cache(smb_info_ino(SMB_INOP(inode)->dir));*/
-
+out:
return error;
}
-

#ifdef DEBUG_SMB_MALLOC
int smb_malloced;
--- linux-2.1.55/fs/smbfs/proc.c.old Wed Sep 10 09:21:27 1997
+++ linux-2.1.55/fs/smbfs/proc.c Wed Sep 10 15:58:21 1997
@@ -29,6 +29,8 @@
#define SMB_DIRINFO_SIZE 43
#define SMB_STATUS_SIZE 21

+extern void prune_dcache(int);
+static int smb_open_files = 0;
static int smb_request_ok(struct smb_sb_info *s, int command, int wct, int bcc);

static inline int
@@ -79,6 +81,27 @@
return p + 4;
}

+/*
+ * For many operations we need the server for a dentry ...
+ * this should be added to the dentry structure.
+ */
+static struct smb_sb_info * server_from_dentry(struct dentry * dentry)
+{
+ struct inode *root;
+ struct smb_sb_info *server;
+
+ while (dentry->d_parent != dentry)
+ dentry = dentry->d_parent;
+ /* root dentries are guaranteed to have inodes, so ... */
+ root = dentry->d_inode;
+ server = &root->i_sb->u.smbfs_sb;
+#if 0
+ printk("sfd: inode %ld, sb %p, server %p\n",
+ root->i_ino, root->i_sb, server);
+#endif
+ return server;
+}
+
static int smb_d_path(struct dentry * entry, char * buf)
{
if (IS_ROOT(entry)) {
@@ -384,6 +407,8 @@
{
return 0;
}
+
+ /* N.B. check for races ... server isn't locked */
if (server->sock_file != NULL)
{
close_fp(server->sock_file);
@@ -420,6 +445,9 @@
return 0;
}

+/*
+ * This must be called with the server locked.
+ */
int
smb_newconn(struct smb_sb_info *server, struct smb_conn_opt *opt)
{
@@ -510,10 +538,9 @@
*/

static int
-smb_proc_open(struct dentry *dir)
+smb_proc_open(struct smb_sb_info *server, struct dentry *dir)
{
struct inode *ino = dir->d_inode;
- struct smb_sb_info *server = SMB_SERVER(ino);
int error;
char *p;

@@ -557,6 +584,7 @@
ino->u.smbfs_i.access &= 3;

ino->u.smbfs_i.open = server->generation;
+ smb_open_files++;

pr_debug("smb_proc_open: entry->access = %d\n", ino->u.smbfs_i.access);
return 0;
@@ -565,20 +593,26 @@
int
smb_open(struct dentry *dir, int wish)
{
- struct inode *i=dir->d_inode;
- struct smb_sb_info *server = SMB_SERVER(i);
- int result = -EACCES;
+ struct inode *i = dir->d_inode;
+ struct smb_sb_info *server;
+ int result;

+ if (!i) {
+ printk("smb_open: no inode for dentry %s/%s\n",
+ dir->d_parent->d_name.name, dir->d_name.name);
+ return -EIO;
+ }
+ server = SMB_SERVER(i);
smb_lock_server(server);

- if (!smb_is_open(i)) {
- int error = smb_proc_open(dir);
- if (error) {
- smb_unlock_server(server);
- return error;
- }
- }
+ result = 0;
+ if (!smb_is_open(i))
+ result = smb_proc_open(server, dir);
+ smb_unlock_server(server);
+ if (result)
+ goto out;

+ result = -EACCES;
if (((wish == O_RDONLY) && ((i->u.smbfs_i.access == O_RDONLY)
|| (i->u.smbfs_i.access == O_RDWR)))
|| ((wish == O_WRONLY) && ((i->u.smbfs_i.access == O_WRONLY)
@@ -586,7 +620,15 @@
|| ((wish == O_RDWR) && (i->u.smbfs_i.access == O_RDWR)))
result = 0;

- smb_unlock_server(server);
+ /*
+ * Check how many open files we have, and
+ * shrink the dcache if there are too many.
+ */
+ if (smb_open_files > 100) {
+ printk("smb_open: %d files, pruning dcache\n", smb_open_files);
+ prune_dcache(64);
+ }
+out:
return result;
}

@@ -600,23 +642,27 @@
DSET(server->packet, smb_vwv1, mtime);
return smb_request_ok(server, SMBclose, 0, 0);
}
-

-int smb_close(struct dentry *dir)
+/*
+ * This needs an inode, not a dentry. FIXME.
+ */
+int
+smb_close(struct dentry *dir)
{
- struct inode *ino = dir->d_inode;
+ struct inode *ino = (struct inode *) dir;
struct smb_sb_info *server = SMB_SERVER(ino);
- int result;
+ int result = 0;

smb_lock_server(server);

- if (!smb_is_open(ino)) {
- smb_unlock_server(server);
- return 0;
- }
+ if (!smb_is_open(ino))
+ goto out;

result = smb_proc_close(server, ino->u.smbfs_i.fileid, ino->i_mtime);
+ if (!result)
+ smb_open_files--;
ino->u.smbfs_i.open = 0;
+out:
smb_unlock_server(server);
return result;
}
@@ -697,13 +743,14 @@
smb_proc_create(struct dentry *dir, struct qstr *name,
__u16 attr, time_t ctime)
{
+ struct smb_sb_info *server;
int error;
char *p;
- struct inode *i=dir->d_inode;
- struct smb_sb_info *server = SMB_SERVER(i);
char *buf;

+ server = server_from_dentry(dir);
smb_lock_server(server);
+
retry:
buf = server->packet;
p = smb_setup_header(server, SMBcreate, 3, 0);
@@ -732,10 +779,11 @@
smb_proc_mv(struct dentry *odir, struct qstr *oname,
struct dentry *ndir, struct qstr *nname)
{
+ struct smb_sb_info *server;
char *p;
- struct smb_sb_info *server = SMB_SERVER(odir->d_inode);
int result;

+ server = server_from_dentry(odir);
smb_lock_server(server);

retry:
@@ -761,10 +809,11 @@
int
smb_proc_mkdir(struct dentry *dir, struct qstr *name)
{
+ struct smb_sb_info *server;
char *p;
int result;
- struct smb_sb_info *server = SMB_SERVER(dir->d_inode);

+ server = server_from_dentry(dir);
smb_lock_server(server);

retry:
@@ -787,10 +836,11 @@
int
smb_proc_rmdir(struct dentry *dir, struct qstr *name)
{
+ struct smb_sb_info *server;
char *p;
int result;
- struct smb_sb_info *server = SMB_SERVER(dir->d_inode);

+ server = server_from_dentry(dir);
smb_lock_server(server);

retry:
@@ -813,10 +863,11 @@
int
smb_proc_unlink(struct dentry *dir, struct qstr *name)
{
+ struct smb_sb_info *server;
char *p;
- struct smb_sb_info *server = SMB_SERVER(dir->d_inode);
int result;

+ server = server_from_dentry(dir);
smb_lock_server(server);

retry:
@@ -1342,8 +1393,9 @@
smb_proc_readdir(struct dentry *dir, int fpos,
int cache_size, struct smb_dirent *entry)
{
- struct smb_sb_info *server = SMB_SERVER(dir->d_inode);
+ struct smb_sb_info *server;

+ server = server_from_dentry(dir);
if (server->opt.protocol >= SMB_PROTOCOL_LANMAN2)
return smb_proc_readdir_long(server, dir, fpos, cache_size,
entry);
@@ -1353,12 +1405,11 @@
}

static int
-smb_proc_getattr_core(struct dentry *dir, struct qstr *name,
- struct smb_fattr *attr)
+smb_proc_getattr_core(struct smb_sb_info *server, struct dentry *dir,
+ struct qstr *name, struct smb_fattr *attr)
{
int result;
char *p;
- struct smb_sb_info *server = SMB_SERVER(dir->d_inode);
char *buf;

smb_lock_server(server);
@@ -1373,26 +1424,25 @@
if ((result = smb_request_ok(server, SMBgetatr, 10, 0)) < 0)
{
if (smb_retry(server))
- {
goto retry;
- }
- smb_unlock_server(server);
- return result;
+ goto out;
}
attr->attr = WVAL(buf, smb_vwv0);
attr->f_ctime = attr->f_atime =
attr->f_mtime = local2utc(DVAL(buf, smb_vwv1));

attr->f_size = DVAL(buf, smb_vwv3);
+ result = 0;
+
+out:
smb_unlock_server(server);
- return 0;
+ return result;
}

static int
-smb_proc_getattr_trans2(struct dentry *dir, struct qstr *name,
- struct smb_fattr *attr)
+smb_proc_getattr_trans2(struct smb_sb_info *server, struct dentry *dir,
+ struct qstr *name, struct smb_fattr *attr)
{
- struct smb_sb_info *server = SMB_SERVER(dir->d_inode);
char param[SMB_MAXPATHLEN + 20];
char *p;
int result;
@@ -1412,26 +1462,22 @@
0, NULL, p - param, param,
&resp_data_len, &resp_data,
&resp_param_len, &resp_param);
-
+
if (server->rcls != 0)
{
- smb_unlock_server(server);
- return -smb_errno(server->rcls, server->err);
+ result = -smb_errno(server->rcls, server->err);
+ goto out;
}
if (result < 0)
{
if (smb_retry(server))
- {
goto retry;
- }
- smb_unlock_server(server);
- return result;
+ goto out;
}
+ result = -ENOENT;
if (resp_data_len < 22)
- {
- smb_unlock_server(server);
- return -ENOENT;
- }
+ goto out;
+
attr->f_ctime = date_dos2unix(WVAL(resp_data, 2),
WVAL(resp_data, 0));
attr->f_atime = date_dos2unix(WVAL(resp_data, 6),
@@ -1440,24 +1486,28 @@
WVAL(resp_data, 8));
attr->f_size = DVAL(resp_data, 12);
attr->attr = WVAL(resp_data, 20);
- smb_unlock_server(server);
+ result = 0;

- return 0;
+out:
+ smb_unlock_server(server);
+ return result;
}

-int smb_proc_getattr(struct dentry *dir, struct qstr *name,
+int
+smb_proc_getattr(struct dentry *dir, struct qstr *name,
struct smb_fattr *fattr)
{
- struct smb_sb_info *server = SMB_SERVER(dir->d_inode);
- int result = 0;
+ struct smb_sb_info *server;
+ int result = -1;

+ server = server_from_dentry(dir);
smb_init_dirent(server, fattr);

if (server->opt.protocol >= SMB_PROTOCOL_LANMAN2)
- result = smb_proc_getattr_trans2(dir, name, fattr);
+ result = smb_proc_getattr_trans2(server, dir, name, fattr);

- if ((server->opt.protocol < SMB_PROTOCOL_LANMAN2) || (result < 0))
- result = smb_proc_getattr_core(dir, name, fattr);
+ if (result < 0)
+ result = smb_proc_getattr_core(server, dir, name, fattr);

smb_finish_dirent(server, fattr);

@@ -1546,12 +1596,12 @@
smb_proc_setattr(struct smb_sb_info *server, struct dentry *dir,
struct smb_fattr *fattr)
{
- int result;
+ int result = -1;

if (server->opt.protocol >= SMB_PROTOCOL_LANMAN2)
result = smb_proc_setattr_trans2(server, dir, fattr);

- if ((server->opt.protocol < SMB_PROTOCOL_LANMAN2) || (result < 0))
+ if (result < 0)
result = smb_proc_setattr_core(server, dir, fattr);

return result;
@@ -1560,9 +1610,9 @@
int
smb_proc_dskattr(struct super_block *sb, struct statfs *attr)
{
+ struct smb_sb_info *server = &(sb->u.smbfs_sb);
int error;
char *p;
- struct smb_sb_info *server = &(sb->u.smbfs_sb);

smb_lock_server(server);

@@ -1573,16 +1623,17 @@
{
if (smb_retry(server))
goto retry;
-
- smb_unlock_server(server);
- return error;
+ goto out;
}
p = SMB_VWV(server->packet);
attr->f_bsize = WVAL(p, 2) * WVAL(p, 4);
attr->f_blocks = WVAL(p, 0);
attr->f_bavail = attr->f_bfree = WVAL(p, 6);
+ error = 0;
+
+out:
smb_unlock_server(server);
- return 0;
+ return error;
}

int
--- linux-2.1.55/fs/smbfs/dir.c.old Wed Sep 10 09:21:27 1997
+++ linux-2.1.55/fs/smbfs/dir.c Wed Sep 10 16:43:36 1997
@@ -112,17 +112,16 @@
int i;
ino_t ino;

+ down(&sem);
do
{
- down(&sem);
result = smb_proc_readdir(dentry, f_pos,
SMB_READDIR_CACHE_SIZE, c_entry);

if (result <= 0)
{
smb_invalid_dir_cache(dir->i_ino);
- up(&sem);
- return result;
+ goto out;
}
c_seen_eof = (result < SMB_READDIR_CACHE_SIZE);
c_dev = dir->i_dev;
@@ -135,10 +134,11 @@
for (i = 0; i < c_size; i++)
c_entry[i].attr.f_ino = ino++;

- up(&sem);
}
while ((c_dev != dir->i_dev) || (c_ino != dir->i_ino));

+out:
+ up(&sem);
return result;
}

@@ -246,6 +246,7 @@
{
if (c_entry != NULL)
{
+ /* N.B. can this block?? */
smb_vfree(c_entry);
}
c_entry = NULL;
@@ -267,15 +268,16 @@
if (len > SMB_MAXNAMELEN)
return -ENAMETOOLONG;

- error = smb_proc_getattr(d_entry, &(d_entry->d_name), &finfo);
+ error = smb_proc_getattr(d_entry->d_parent, &(d_entry->d_name), &finfo);

inode = NULL;
if (!error) {
- error = -ENOENT;
finfo.f_ino = smb_invent_inos(1);
inode = smb_iget(dir->i_sb, &finfo);
if (!inode)
return -EACCES;
+ /* cache the dentry pointer */
+ inode->u.smbfs_i.dentry = d_entry;
} else if (error != -ENOENT)
return error;

@@ -283,7 +285,8 @@
return 0;
}

-static int smb_create(struct inode *dir, struct dentry *dentry, int mode)
+static int
+smb_create(struct inode *dir, struct dentry *dentry, int mode)
{
struct smb_fattr fattr;
struct inode *inode;
@@ -298,7 +301,8 @@
if (dentry->d_name.len > SMB_MAXNAMELEN)
return -ENAMETOOLONG;

- error = smb_proc_create(dentry, &(dentry->d_name), 0, CURRENT_TIME);
+ error = smb_proc_create(dentry->d_parent, &(dentry->d_name),
+ 0, CURRENT_TIME);
if (error < 0)
return error;

@@ -308,7 +312,7 @@
* state. Currently we close it directly again, although this
* is not necessary anymore. */

- error = smb_proc_getattr(dentry, &(dentry->d_name), &fattr);
+ error = smb_proc_getattr(dentry->d_parent, &(dentry->d_name), &fattr);
if (error < 0)
return error;

@@ -318,6 +322,8 @@
if (!inode)
return -EACCES;

+ /* cache the dentry pointer */
+ inode->u.smbfs_i.dentry = dentry;
d_instantiate(dentry, inode);
return 0;
}
@@ -338,13 +344,13 @@
if (dentry->d_name.len > SMB_MAXNAMELEN)
return -ENAMETOOLONG;

- error = smb_proc_mkdir(dentry, &(dentry->d_name));
+ error = smb_proc_mkdir(dentry->d_parent, &(dentry->d_name));
if (error)
return error;

smb_invalid_dir_cache(dir->i_ino);

- error = smb_proc_getattr(dentry, &(dentry->d_name), &fattr);
+ error = smb_proc_getattr(dentry->d_parent, &(dentry->d_name), &fattr);
if (error < 0)
return error;

@@ -354,6 +360,8 @@
if (!inode)
return -EACCES;

+ /* cache the dentry pointer */
+ inode->u.smbfs_i.dentry = dentry;
d_instantiate(dentry, inode);
return 0;
}
@@ -372,7 +380,7 @@
if (dentry->d_name.len > NFS_MAXNAMLEN)
return -ENAMETOOLONG;

- error = smb_proc_rmdir(dentry, &(dentry->d_name));
+ error = smb_proc_rmdir(dentry->d_parent, &(dentry->d_name));
if (error)
return error;

@@ -394,7 +402,7 @@
if (dentry->d_name.len > SMB_MAXNAMELEN)
return -ENAMETOOLONG;

- error = smb_proc_unlink(dentry, &(dentry->d_name));
+ error = smb_proc_unlink(dentry->d_parent, &(dentry->d_name));
if (error)
return error;

@@ -404,8 +412,12 @@
return 0;
}

-static int smb_rename(struct inode *old_dir, struct dentry *old_dentry,
- struct inode *new_dir, struct dentry *new_dentry)
+/*
+ * N.B. This needs to call d_move ...
+ */
+static int
+smb_rename(struct inode *old_dir, struct dentry *old_dentry,
+ struct inode *new_dir, struct dentry *new_dentry)
{
int error;

@@ -425,18 +437,19 @@
new_dentry->d_name.len > SMB_MAXNAMELEN)
return -ENAMETOOLONG;

- error = smb_proc_mv(old_dentry, &(old_dentry->d_name),
- new_dentry, &(new_dentry->d_name));
+ error = smb_proc_mv(old_dentry->d_parent, &(old_dentry->d_name),
+ new_dentry->d_parent, &(new_dentry->d_name));

if (error == -EEXIST)
{
- error = smb_proc_unlink(old_dentry, &(new_dentry->d_name));
+ error = smb_proc_unlink(old_dentry->d_parent,
+ &(new_dentry->d_name));

if (error)
return error;

- error = smb_proc_mv(old_dentry, &(old_dentry->d_name),
- new_dentry, &(new_dentry->d_name));
+ error = smb_proc_mv(old_dentry->d_parent, &(old_dentry->d_name),
+ new_dentry->d_parent, &(new_dentry->d_name));
}

if (error)
--- linux-2.1.55/fs/smbfs/file.c.old Thu Sep 4 12:33:51 1997
+++ linux-2.1.55/fs/smbfs/file.c Wed Sep 10 11:37:32 1997
@@ -39,6 +39,7 @@
{
unsigned long offset = page->offset;
char *buffer = (char *) page_address(page);
+ struct dentry * dentry = inode->u.smbfs_i.dentry;
int rsize = SMB_SERVER(inode)->opt.max_xmit - (SMB_HEADER_LEN+15);
int result, refresh = 0;
int count = PAGE_SIZE;
@@ -46,7 +47,14 @@
pr_debug("SMB: smb_readpage_sync(%p)\n", page);
clear_bit(PG_error, &page->flags);

- result = smb_open(inode, O_RDONLY);
+ result = -EIO;
+ if (!dentry) {
+ printk("smb_readpage_sync: no dentry for inode %ld\n",
+ inode->i_ino);
+ goto io_error;
+ }
+
+ result = smb_open(dentry, O_RDONLY);
if (result < 0)
goto io_error;

@@ -86,10 +94,10 @@

pr_debug("SMB: smb_readpage %08lx\n", page_address(page));
set_bit(PG_locked, &page->flags);
- address = page_address(page);
atomic_inc(&page->count);
+ address = page_address(page);
error = smb_readpage_sync(inode, page);
- free_page(address);
+ __free_page(page);
return error;
}

@@ -109,6 +117,8 @@
inode->i_dev, inode->i_ino,
count, page->offset + offset);

+ /* Why doesn't this have to call smb_open?? */
+
buffer = (u8 *) page_address(page) + offset;
offset += page->offset;

@@ -145,7 +155,15 @@
static int
smb_writepage(struct inode *inode, struct page *page)
{
- return smb_writepage_sync(inode, page, 0, PAGE_SIZE);
+ int result;
+
+ if (test_bit(PG_locked, &page->flags))
+ printk("smb_writepage: page already locked!\n");
+ set_bit(PG_locked, &page->flags);
+ atomic_inc(&page->count);
+ result = smb_writepage_sync(inode, page, 0, PAGE_SIZE);
+ __free_page(page);
+ return result;
}

static int
@@ -153,15 +171,23 @@
unsigned long offset, unsigned int count, int sync)
{
u8 *page_addr;
+ int result;

pr_debug("SMB: smb_updatepage(%x/%ld %d@%ld, sync=%d)\n",
inode->i_dev, inode->i_ino,
count, page->offset+offset, sync);

+ if (test_bit(PG_locked, &page->flags))
+ printk("smb_updatepage: page already locked!\n");
+ set_bit(PG_locked, &page->flags);
+ atomic_inc(&page->count);
+
page_addr = (u8 *) page_address(page);

copy_from_user(page_addr + offset, buffer, count);
- return smb_writepage_sync(inode, page, offset, count);
+ result = smb_writepage_sync(inode, page, offset, count);
+ __free_page(page);
+ return result;
}

static long
@@ -216,7 +242,7 @@
if (result < 0)
return result;

- result = smb_open(inode, O_WRONLY);
+ result = smb_open(file->f_dentry, O_WRONLY);
if (result < 0)
return result;

--- linux-2.1.55/fs/smbfs/sock.c.old Wed Sep 10 09:21:27 1997
+++ linux-2.1.55/fs/smbfs/sock.c Wed Sep 10 18:00:01 1997
@@ -352,6 +352,7 @@
pr_debug("smb_receive: Increase packet size from %d to %d\n",
server->packet_size, len + 4);
smb_vfree(server->packet);
+ server->packet = 0;
server->packet_size = 0;
server->packet = smb_vmalloc(len + 4);
if (server->packet == NULL)
@@ -371,11 +372,11 @@
server->rcls = *(server->packet+9);
server->err = WVAL(server->packet, 11);

+#if 0
if (server->rcls != 0)
- {
- pr_debug("smb_receive: rcls=%d, err=%d\n",
- server->rcls, server->err);
- }
+ printk("smb_receive: rcls=%d, err=%d\n",
+ server->rcls, server->err);
+#endif
return result;
}

@@ -428,8 +429,10 @@

while (1)
{
- unsigned char *inbuf = server->packet;
+ unsigned char *inbuf;

+ /* server->packet may change, so we have to update inbuf */
+ inbuf = server->packet;
if (WVAL(inbuf, smb_prdisp) + WVAL(inbuf, smb_prcnt)
> total_param)
{
@@ -477,11 +480,9 @@
{
goto fail;
}
+ result = -EIO;
if (server->rcls != 0)
- {
- result = -EIO;
goto fail;
- }
}
*ldata = data_len;
*lparam = param_len;
@@ -502,26 +503,24 @@
unsigned long old_mask;
unsigned long fs;
int len, result;
+ unsigned char *buffer;

- unsigned char *buffer = (server == NULL) ? NULL : server->packet;
+ result = -EBADF;
+ if (!server)
+ goto bad_no_server;
+
+ buffer = server->packet;
+ if (!buffer)
+ goto bad_no_packet;

- if (buffer == NULL)
- {
- pr_debug("smb_request: Bad server!\n");
- return -EBADF;
- }
+ result = -EIO;
if (server->state != CONN_VALID)
- {
- return -EIO;
- }
+ goto out;
+
if ((result = smb_dont_catch_keepalive(server)) != 0)
- {
- server->state = CONN_INVALID;
- smb_invalidate_inodes(server);
- return result;
- }
- len = smb_len(buffer) + 4;
+ goto bad_conn;

+ len = smb_len(buffer) + 4;
pr_debug("smb_request: len = %d cmd = 0x%X\n", len, buffer[8]);

old_mask = current->blocked;
@@ -548,13 +547,23 @@
}
}
if (result < 0)
- {
- server->state = CONN_INVALID;
- smb_invalidate_inodes(server);
- }
+ goto bad_conn;
pr_debug("smb_request: result = %d\n", result);

+out:
return result;
+
+bad_conn:
+ printk("smb_request: connection bad, setting invalid\n");
+ server->state = CONN_INVALID;
+ smb_invalidate_inodes(server);
+ goto out;
+bad_no_server:
+ printk("smb_request: no server!\n");
+ goto out;
+bad_no_packet:
+ printk("smb_request: no packet!\n");
+ goto out;
}

#define ROUND_UP(x) (((x)+3) & ~3)
@@ -629,11 +638,11 @@
iov[3].iov_len = ldata;

err = scm_send(sock, &msg, &scm);
- if (err < 0)
- return err;
-
- err = sock->ops->sendmsg(sock, &msg, packet_length, &scm);
- scm_destroy(&scm);
+ if (err >= 0)
+ {
+ err = sock->ops->sendmsg(sock, &msg, packet_length, &scm);
+ scm_destroy(&scm);
+ }
return err;
}

@@ -655,16 +664,19 @@
pr_debug("smb_trans2_request: com=%d, ld=%d, lp=%d\n",
trans2_command, ldata, lparam);

+ /*
+ * These are initialized in smb_request_ok, but not here??
+ */
+ server->rcls = 0;
+ server->err = 0;
+
+ result = -EIO;
if (server->state != CONN_VALID)
- {
- return -EIO;
- }
+ goto out;
+
if ((result = smb_dont_catch_keepalive(server)) != 0)
- {
- server->state = CONN_INVALID;
- smb_invalidate_inodes(server);
- return result;
- }
+ goto bad_conn;
+
old_mask = current->blocked;
current->blocked |= ~(_S(SIGKILL) | _S(SIGSTOP));
fs = get_fs();
@@ -691,11 +703,15 @@
}
}
if (result < 0)
- {
- server->state = CONN_INVALID;
- smb_invalidate_inodes(server);
- }
+ goto bad_conn;
pr_debug("smb_trans2_request: result = %d\n", result);

+out:
return result;
+
+bad_conn:
+ printk("smb_trans2_request: connection bad, setting invalid\n");
+ server->state = CONN_INVALID;
+ smb_invalidate_inodes(server);
+ goto out;
}

--------------AFC04042F0A7E3C150181ED9--