patch-2.4.5 linux/fs/smbfs/proc.c
Next file: linux/fs/smbfs/sock.c
Previous file: linux/fs/smbfs/ioctl.c
Back to the patch index
Back to the overall index
- Lines: 287
- Date:
Tue May 15 13:40:55 2001
- Orig file:
v2.4.4/linux/fs/smbfs/proc.c
- Orig date:
Fri Apr 13 20:26:07 2001
diff -u --recursive --new-file v2.4.4/linux/fs/smbfs/proc.c linux/fs/smbfs/proc.c
@@ -54,18 +54,6 @@
struct smb_fattr *fattr);
-static inline void
-smb_lock_server(struct smb_sb_info *server)
-{
- down(&(server->sem));
-}
-
-static inline void
-smb_unlock_server(struct smb_sb_info *server)
-{
- up(&(server->sem));
-}
-
static void
str_upper(char *name, int len)
@@ -661,7 +649,7 @@
pid_t pid = server->conn_pid;
int error, result = 0;
- if (server->state != CONN_INVALID)
+ if (server->state == CONN_VALID || server->state == CONN_RETRYING)
goto out;
smb_close_socket(server);
@@ -673,17 +661,18 @@
}
/*
- * Clear the pid to enable the ioctl.
+ * Change state so that only one retry per server will be started.
*/
- server->conn_pid = 0;
+ server->state = CONN_RETRYING;
/*
* Note: use the "priv" flag, as a user process may need to reconnect.
*/
error = kill_proc(pid, SIGUSR1, 1);
if (error) {
+ /* FIXME: this is fatal */
printk(KERN_ERR "smb_retry: signal failed, error=%d\n", error);
- goto out_restore;
+ goto out;
}
VERBOSE("signalled pid %d, waiting for new connection\n", pid);
@@ -691,7 +680,9 @@
* Wait for the new connection.
*/
#ifdef SMB_RETRY_INTR
- interruptible_sleep_on_timeout(&server->wait, 5*HZ);
+ smb_unlock_server(server);
+ interruptible_sleep_on_timeout(&server->wait, 30*HZ);
+ smb_lock_server(server);
if (signal_pending(current))
printk(KERN_INFO "smb_retry: caught signal\n");
#else
@@ -702,8 +693,13 @@
*
* smbmount should be able to reconnect later, but it can't because
* it will get an -EIO on attempts to open the mountpoint!
+ *
+ * FIXME: go back to the interruptable version now that smbmount
+ * can avoid -EIO on the mountpoint when reconnecting?
*/
- sleep_on_timeout(&server->wait, 5*HZ);
+ smb_unlock_server(server);
+ sleep_on_timeout(&server->wait, 30*HZ);
+ smb_lock_server(server);
#endif
/*
@@ -715,15 +711,11 @@
PARANOIA("successful, new pid=%d, generation=%d\n",
server->conn_pid, server->generation);
result = 1;
+ } else if (server->state == CONN_RETRYING) {
+ /* allow further attempts later */
+ server->state = CONN_RETRIED;
}
- /*
- * Restore the original pid if we didn't get a new one.
- */
-out_restore:
- if (!server->conn_pid)
- server->conn_pid = pid;
-
out:
return result;
}
@@ -742,19 +734,16 @@
s->err = 0;
/* Make sure we have a connection */
- if (s->state != CONN_VALID)
- {
+ if (s->state != CONN_VALID) {
if (!smb_retry(s))
goto out;
}
- if (smb_request(s) < 0)
- {
+ if (smb_request(s) < 0) {
DEBUG1("smb_request failed\n");
goto out;
}
- if (smb_valid_packet(s->packet) != 0)
- {
+ if (smb_valid_packet(s->packet) != 0) {
PARANOIA("invalid packet!\n");
goto out;
}
@@ -764,8 +753,7 @@
* is squashing some error codes, but I don't think this is
* correct: after a server error the packet won't be valid.
*/
- if (s->rcls != 0)
- {
+ if (s->rcls != 0) {
result = -smb_errno(s);
if (!result)
printk(KERN_DEBUG "smb_request_ok: rcls=%d, err=%d mapped to 0\n",
@@ -785,10 +773,6 @@
/*
* This implements the NEWCONN ioctl. It installs the server pid,
* sets server->state to CONN_VALID, and wakes up the waiting process.
- *
- * Note that this must be called with the server locked, except for
- * the first call made after mounting the volume. The server pid
- * will be set to zero to indicate that smbfs is awaiting a connection.
*/
int
smb_newconn(struct smb_sb_info *server, struct smb_conn_opt *opt)
@@ -798,11 +782,13 @@
VERBOSE("fd=%d, pid=%d\n", opt->fd, current->pid);
+ smb_lock_server(server);
+
/*
- * Make sure we don't already have a pid ...
+ * Make sure we don't already have a valid connection ...
*/
error = -EINVAL;
- if (server->conn_pid)
+ if (server->state == CONN_VALID)
goto out;
error = -EACCES;
@@ -836,9 +822,7 @@
(server->opt.max_xmit < 0x1000) &&
!(server->opt.capabilities & SMB_CAP_NT_SMBS)) {
server->mnt->flags |= SMB_MOUNT_WIN95;
-#ifdef SMBFS_DEBUG_VERBOSE
- printk(KERN_NOTICE "smb_newconn: detected WIN95 server\n");
-#endif
+ VERBOSE("smb_newconn: detected WIN95 server\n");
}
VERBOSE("protocol=%d, max_xmit=%d, pid=%d capabilities=0x%x\n",
@@ -851,6 +835,8 @@
int len = smb_round_length(server->opt.max_xmit);
char *buf = smb_vmalloc(len);
if (buf) {
+ if (server->packet)
+ smb_vfree(server->packet);
server->packet = buf;
server->packet_size = len;
} else {
@@ -863,6 +849,8 @@
}
out:
+ smb_unlock_server(server);
+
#ifdef SMB_RETRY_INTR
wake_up_interruptible(&server->wait);
#else
@@ -1016,7 +1004,7 @@
}
if (!smb_is_open(inode)) {
- struct smb_sb_info *server = SMB_SERVER(inode);
+ struct smb_sb_info *server = server_from_inode(inode);
smb_lock_server(server);
result = 0;
if (!smb_is_open(inode))
@@ -1102,7 +1090,6 @@
result = smb_proc_close(server, ino->u.smbfs_i.fileid,
ino->i_mtime);
- ino->u.smbfs_i.flags &= ~SMB_F_LOCALWRITE;
/*
* Force a revalidation after closing ... some servers
* don't post the size until the file has been closed.
@@ -1119,9 +1106,8 @@
{
int result = 0;
- if (smb_is_open(ino))
- {
- struct smb_sb_info *server = SMB_SERVER(ino);
+ if (smb_is_open(ino)) {
+ struct smb_sb_info *server = server_from_inode(ino);
smb_lock_server(server);
result = smb_proc_close_inode(server, ino);
smb_unlock_server(server);
@@ -1203,14 +1189,15 @@
struct smb_sb_info *server = server_from_inode(inode);
int result;
__u8 *p;
-
+ __u16 fileid = inode->u.smbfs_i.fileid;
+
VERBOSE("ino=%ld, fileid=%d, count=%d@%ld, packet_size=%d\n",
inode->i_ino, inode->u.smbfs_i.fileid, count, offset,
server->packet_size);
smb_lock_server(server);
p = smb_setup_header(server, SMBwrite, 5, count + 3);
- WSET(server->packet, smb_vwv0, inode->u.smbfs_i.fileid);
+ WSET(server->packet, smb_vwv0, fileid);
WSET(server->packet, smb_vwv1, count);
DSET(server->packet, smb_vwv2, offset);
WSET(server->packet, smb_vwv4, 0);
@@ -1223,6 +1210,11 @@
if (result >= 0)
result = WVAL(server->packet, smb_vwv0);
+ /* flush to disk, to trigger win9x to update its filesize */
+ /* FIXME: this will be rather costly, won't it? */
+ if (server->mnt->flags & SMB_MOUNT_WIN95)
+ smb_proc_flush(server, fileid);
+
smb_unlock_server(server);
return result;
}
@@ -1423,6 +1415,17 @@
return result;
}
+/*
+ * Called with the server locked
+ */
+int
+smb_proc_flush(struct smb_sb_info *server, __u16 fileid)
+{
+ smb_setup_header(server, SMBflush, 1, 0);
+ WSET(server->packet, smb_vwv0, fileid);
+ return smb_request_ok(server, SMBflush, 0, 0);
+}
+
int
smb_proc_trunc(struct smb_sb_info *server, __u16 fid, __u32 length)
{
@@ -1431,7 +1434,7 @@
smb_lock_server(server);
- retry:
+retry:
p = smb_setup_header(server, SMBwrite, 5, 3);
WSET(server->packet, smb_vwv0, fid);
WSET(server->packet, smb_vwv1, 0);
@@ -1445,7 +1448,15 @@
goto retry;
goto out;
}
- result = 0;
+
+ /*
+ * win9x doesn't appear to update the size immediately.
+ * It will return the old file size after the truncate,
+ * confusing smbfs.
+ * NT and Samba return the new value immediately.
+ */
+ if (server->mnt->flags & SMB_MOUNT_WIN95)
+ smb_proc_flush(server, fid);
out:
smb_unlock_server(server);
return result;
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)