[linux-cifs-client] [PATCH] Cannot allocate memory
Pavel Shilovsky
piastry at etersoft.ru
Wed Mar 11 14:05:00 GMT 2009
Jeff Layton wrote:
> You have no guarantee that "server" is still a valid pointer when you
> go to dereference it. In most cases it probably will be, but hard to
> hit races are *worse* since they're harder to track down.
>
> We have to *know* that this pointer will be valid here before you do
> something like this. Rather than adding arbitrary delays like this, a
> better scheme would use a completion variable to indicate when the
> thread is down.
>
Yes, you are right. I fixed it.
> Finally, I'm not convinced of the need for this at all. Why should we
> guarantee that the module is able to be unplugged the instant that the
> last mount vanishes? I'd much rather my umounts return quickly rather
> than have them wait for the thread to come down.
I want to have cifs module not in use when I unmounted all share bases.
I need it, for example, when I right any script that unmouts all shares
and then deletes cifs module. In your solution, I have to wait some
unknown time before deleting module. This is uncomfortably, I think.
It's much more logical to think that all stuff connected with share
disappears as soon as unmount finishes it's work.
Here is my new patch:
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h
index 9fbf4df..0ec5a2f 100644
--- a/fs/cifs/cifsglob.h
+++ b/fs/cifs/cifsglob.h
@@ -182,6 +182,7 @@ struct TCP_Server_Info {
struct mac_key mac_signing_key;
char ntlmv2_hash[16];
unsigned long lstrp; /* when we got last response from this server */
+ int running;
};
/*
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index cd4ccc8..bc5841d 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -337,6 +337,7 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
bool isMultiRsp;
int reconnect;
+ server->running = 1;
current->flags |= PF_MEMALLOC;
cFYI(1, ("Demultiplex PID: %d", task_pid_nr(current)));
@@ -747,7 +748,6 @@ multi_t2_fnd:
kfree(server->hostname);
task_to_wake = xchg(&server->tsk, NULL);
- kfree(server);
length = atomic_dec_return(&tcpSesAllocCount);
if (length > 0)
@@ -764,6 +764,8 @@ multi_t2_fnd:
set_current_state(TASK_RUNNING);
}
+ server->running = 0;
+
module_put_and_exit(0);
}
@@ -1418,6 +1420,11 @@ cifs_put_tcp_session(struct TCP_Server_Info *server)
task = xchg(&server->tsk, NULL);
if (task)
force_sig(SIGKILL, task);
+
+ while(server->running == 1)
+ msleep(10);
+
+ kfree(server);
}
static struct TCP_Server_Info *
--
Best regards,
Pavel Shilovsky.
More information about the linux-cifs-client
mailing list