]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
.32 patches
authorGreg Kroah-Hartman <gregkh@suse.de>
Sat, 18 Sep 2010 17:50:47 +0000 (10:50 -0700)
committerGreg Kroah-Hartman <gregkh@suse.de>
Sat, 18 Sep 2010 17:50:47 +0000 (10:50 -0700)
queue-2.6.32/apm_power-add-missing-break-statement.patch [new file with mode: 0644]
queue-2.6.32/arm-fix-really-nasty-sigreturn-bug.patch [new file with mode: 0644]
queue-2.6.32/hwmon-f75375s-do-not-overwrite-values-read-from-registers.patch [new file with mode: 0644]
queue-2.6.32/hwmon-f75375s-shift-control-mode-to-the-correct-bit-position.patch [new file with mode: 0644]
queue-2.6.32/nfs-fix-a-typo-in-nfs_sockaddr_match_ipaddr6.patch [new file with mode: 0644]
queue-2.6.32/series
queue-2.6.32/sunrpc-fix-a-race-in-rpc_info_open.patch [new file with mode: 0644]
queue-2.6.32/sunrpc-fix-race-corrupting-rpc-upcall.patch [new file with mode: 0644]

diff --git a/queue-2.6.32/apm_power-add-missing-break-statement.patch b/queue-2.6.32/apm_power-add-missing-break-statement.patch
new file mode 100644 (file)
index 0000000..0ff6f97
--- /dev/null
@@ -0,0 +1,30 @@
+From 1d220334d6a8a711149234dc5f98d34ae02226b8 Mon Sep 17 00:00:00 2001
+From: Anton Vorontsov <cbouatmailru@gmail.com>
+Date: Wed, 8 Sep 2010 00:10:26 +0400
+Subject: apm_power: Add missing break statement
+
+From: Anton Vorontsov <cbouatmailru@gmail.com>
+
+commit 1d220334d6a8a711149234dc5f98d34ae02226b8 upstream.
+
+The missing break statement causes wrong capacity calculation for
+batteries that report energy.
+
+Reported-by: d binderman <dcb314@hotmail.com>
+Signed-off-by: Anton Vorontsov <cbouatmailru@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/power/apm_power.c |    1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/drivers/power/apm_power.c
++++ b/drivers/power/apm_power.c
+@@ -233,6 +233,7 @@ static int calculate_capacity(enum apm_s
+               empty_design_prop = POWER_SUPPLY_PROP_ENERGY_EMPTY_DESIGN;
+               now_prop = POWER_SUPPLY_PROP_ENERGY_NOW;
+               avg_prop = POWER_SUPPLY_PROP_ENERGY_AVG;
++              break;
+       case SOURCE_VOLTAGE:
+               full_prop = POWER_SUPPLY_PROP_VOLTAGE_MAX;
+               empty_prop = POWER_SUPPLY_PROP_VOLTAGE_MIN;
diff --git a/queue-2.6.32/arm-fix-really-nasty-sigreturn-bug.patch b/queue-2.6.32/arm-fix-really-nasty-sigreturn-bug.patch
new file mode 100644 (file)
index 0000000..6a95ffa
--- /dev/null
@@ -0,0 +1,95 @@
+From 653d48b22166db2d8b1515ebe6f9f0f7c95dfc86 Mon Sep 17 00:00:00 2001
+From: Al Viro <viro@zeniv.linux.org.uk>
+Date: Fri, 17 Sep 2010 14:34:39 +0100
+Subject: arm: fix really nasty sigreturn bug
+
+From: Al Viro <viro@zeniv.linux.org.uk>
+
+commit 653d48b22166db2d8b1515ebe6f9f0f7c95dfc86 upstream.
+
+If a signal hits us outside of a syscall and another gets delivered
+when we are in sigreturn (e.g. because it had been in sa_mask for
+the first one and got sent to us while we'd been in the first handler),
+we have a chance of returning from the second handler to location one
+insn prior to where we ought to return.  If r0 happens to contain -513
+(-ERESTARTNOINTR), sigreturn will get confused into doing restart
+syscall song and dance.
+
+Incredible joy to debug, since it manifests as random, infrequent and
+very hard to reproduce double execution of instructions in userland
+code...
+
+The fix is simple - mark it "don't bother with restarts" in wrapper,
+i.e. set r8 to 0 in sys_sigreturn and sys_rt_sigreturn wrappers,
+suppressing the syscall restart handling on return from these guys.
+They can't legitimately return a restart-worthy error anyway.
+
+Testcase:
+       #include <unistd.h>
+       #include <signal.h>
+       #include <stdlib.h>
+       #include <sys/time.h>
+       #include <errno.h>
+
+       void f(int n)
+       {
+               __asm__ __volatile__(
+                       "ldr r0, [%0]\n"
+                       "b 1f\n"
+                       "b 2f\n"
+                       "1:b .\n"
+                       "2:\n" : : "r"(&n));
+       }
+
+       void handler1(int sig) { }
+       void handler2(int sig) { raise(1); }
+       void handler3(int sig) { exit(0); }
+
+       main()
+       {
+               struct sigaction s = {.sa_handler = handler2};
+               struct itimerval t1 = { .it_value = {1} };
+               struct itimerval t2 = { .it_value = {2} };
+
+               signal(1, handler1);
+
+               sigemptyset(&s.sa_mask);
+               sigaddset(&s.sa_mask, 1);
+               sigaction(SIGALRM, &s, NULL);
+
+               signal(SIGVTALRM, handler3);
+
+               setitimer(ITIMER_REAL, &t1, NULL);
+               setitimer(ITIMER_VIRTUAL, &t2, NULL);
+
+               f(-513); /* -ERESTARTNOINTR */
+
+               write(1, "buggered\n", 9);
+               return 1;
+       }
+
+Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
+Acked-by: Russell King <rmk+kernel@arm.linux.org.uk>
+Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ arch/arm/kernel/entry-common.S |    2 ++
+ 1 file changed, 2 insertions(+)
+
+--- a/arch/arm/kernel/entry-common.S
++++ b/arch/arm/kernel/entry-common.S
+@@ -382,11 +382,13 @@ ENDPROC(sys_clone_wrapper)
+ sys_sigreturn_wrapper:
+               add     r0, sp, #S_OFF
++              mov     why, #0         @ prevent syscall restart handling
+               b       sys_sigreturn
+ ENDPROC(sys_sigreturn_wrapper)
+ sys_rt_sigreturn_wrapper:
+               add     r0, sp, #S_OFF
++              mov     why, #0         @ prevent syscall restart handling
+               b       sys_rt_sigreturn
+ ENDPROC(sys_rt_sigreturn_wrapper)
diff --git a/queue-2.6.32/hwmon-f75375s-do-not-overwrite-values-read-from-registers.patch b/queue-2.6.32/hwmon-f75375s-do-not-overwrite-values-read-from-registers.patch
new file mode 100644 (file)
index 0000000..2161d5c
--- /dev/null
@@ -0,0 +1,42 @@
+From c3b327d60bbba3f5ff8fd87d1efc0e95eb6c121b Mon Sep 17 00:00:00 2001
+From: Guillem Jover <guillem@hadrons.org>
+Date: Fri, 17 Sep 2010 17:24:12 +0200
+Subject: hwmon: (f75375s) Do not overwrite values read from registers
+
+From: Guillem Jover <guillem@hadrons.org>
+
+commit c3b327d60bbba3f5ff8fd87d1efc0e95eb6c121b upstream.
+
+All bits in the values read from registers to be used for the next
+write were getting overwritten, avoid doing so to not mess with the
+current configuration.
+
+Signed-off-by: Guillem Jover <guillem@hadrons.org>
+Cc: Riku Voipio <riku.voipio@iki.fi>
+Signed-off-by: Jean Delvare <khali@linux-fr.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/hwmon/f75375s.c |    4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/drivers/hwmon/f75375s.c
++++ b/drivers/hwmon/f75375s.c
+@@ -298,7 +298,7 @@ static int set_pwm_enable_direct(struct
+               return -EINVAL;
+       fanmode = f75375_read8(client, F75375_REG_FAN_TIMER);
+-      fanmode = ~(3 << FAN_CTRL_MODE(nr));
++      fanmode &= ~(3 << FAN_CTRL_MODE(nr));
+       switch (val) {
+       case 0: /* Full speed */
+@@ -350,7 +350,7 @@ static ssize_t set_pwm_mode(struct devic
+       mutex_lock(&data->update_lock);
+       conf = f75375_read8(client, F75375_REG_CONFIG1);
+-      conf = ~(1 << FAN_CTRL_LINEAR(nr));
++      conf &= ~(1 << FAN_CTRL_LINEAR(nr));
+       if (val == 0)
+               conf |= (1 << FAN_CTRL_LINEAR(nr)) ;
diff --git a/queue-2.6.32/hwmon-f75375s-shift-control-mode-to-the-correct-bit-position.patch b/queue-2.6.32/hwmon-f75375s-shift-control-mode-to-the-correct-bit-position.patch
new file mode 100644 (file)
index 0000000..f8cb520
--- /dev/null
@@ -0,0 +1,33 @@
+From 96f3640894012be7dd15a384566bfdc18297bc6c Mon Sep 17 00:00:00 2001
+From: Guillem Jover <guillem@hadrons.org>
+Date: Fri, 17 Sep 2010 17:24:11 +0200
+Subject: hwmon: (f75375s) Shift control mode to the correct bit position
+
+From: Guillem Jover <guillem@hadrons.org>
+
+commit 96f3640894012be7dd15a384566bfdc18297bc6c upstream.
+
+The spec notes that fan0 and fan1 control mode bits are located in bits
+7-6 and 5-4 respectively, but the FAN_CTRL_MODE macro was making the
+bits shift by 5 instead of by 4.
+
+Signed-off-by: Guillem Jover <guillem@hadrons.org>
+Cc: Riku Voipio <riku.voipio@iki.fi>
+Signed-off-by: Jean Delvare <khali@linux-fr.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/hwmon/f75375s.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/hwmon/f75375s.c
++++ b/drivers/hwmon/f75375s.c
+@@ -79,7 +79,7 @@ I2C_CLIENT_INSMOD_2(f75373, f75375);
+ #define F75375_REG_PWM2_DROP_DUTY     0x6C
+ #define FAN_CTRL_LINEAR(nr)           (4 + nr)
+-#define FAN_CTRL_MODE(nr)             (5 + ((nr) * 2))
++#define FAN_CTRL_MODE(nr)             (4 + ((nr) * 2))
+ /*
+  * Data structures and manipulation thereof
diff --git a/queue-2.6.32/nfs-fix-a-typo-in-nfs_sockaddr_match_ipaddr6.patch b/queue-2.6.32/nfs-fix-a-typo-in-nfs_sockaddr_match_ipaddr6.patch
new file mode 100644 (file)
index 0000000..8bbdc3a
--- /dev/null
@@ -0,0 +1,28 @@
+From b20d37ca9561711c6a3c4b859c2855f49565e061 Mon Sep 17 00:00:00 2001
+From: Trond Myklebust <Trond.Myklebust@netapp.com>
+Date: Sun, 12 Sep 2010 19:55:26 -0400
+Subject: NFS: Fix a typo in nfs_sockaddr_match_ipaddr6
+
+From: Trond Myklebust <Trond.Myklebust@netapp.com>
+
+commit b20d37ca9561711c6a3c4b859c2855f49565e061 upstream.
+
+Reported-by: Ben Greear <greearb@candelatech.com>
+Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ fs/nfs/client.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/fs/nfs/client.c
++++ b/fs/nfs/client.c
+@@ -273,7 +273,7 @@ static int nfs_sockaddr_match_ipaddr6(co
+           sin1->sin6_scope_id != sin2->sin6_scope_id)
+               return 0;
+-      return ipv6_addr_equal(&sin1->sin6_addr, &sin1->sin6_addr);
++      return ipv6_addr_equal(&sin1->sin6_addr, &sin2->sin6_addr);
+ }
+ #else /* !defined(CONFIG_IPV6) && !defined(CONFIG_IPV6_MODULE) */
+ static int nfs_sockaddr_match_ipaddr6(const struct sockaddr *sa1,
index 25be1b6d192f1f84ecd5b111b2de908e5f04fb5b..55fe7dedce189d241c9f354b5fb541c74edfdc4d 100644 (file)
@@ -111,3 +111,10 @@ sched-fix-select_idle_sibling-logic-in-select_task_rq_fair.patch
 sched-cpuacct-use-bigger-percpu-counter-batch-values-for-stats-counters.patch
 alsa-hda-handle-missing-nid-0x1b-on-alc259-codec.patch
 alsa-hda-handle-pin-nid-0x1a-on-alc259-269.patch
+arm-fix-really-nasty-sigreturn-bug.patch
+hwmon-f75375s-shift-control-mode-to-the-correct-bit-position.patch
+hwmon-f75375s-do-not-overwrite-values-read-from-registers.patch
+apm_power-add-missing-break-statement.patch
+nfs-fix-a-typo-in-nfs_sockaddr_match_ipaddr6.patch
+sunrpc-fix-race-corrupting-rpc-upcall.patch
+sunrpc-fix-a-race-in-rpc_info_open.patch
diff --git a/queue-2.6.32/sunrpc-fix-a-race-in-rpc_info_open.patch b/queue-2.6.32/sunrpc-fix-a-race-in-rpc_info_open.patch
new file mode 100644 (file)
index 0000000..fdc1cb6
--- /dev/null
@@ -0,0 +1,154 @@
+From 006abe887c5e637d059c44310de6c92f36aded3b Mon Sep 17 00:00:00 2001
+From: Trond Myklebust <Trond.Myklebust@netapp.com>
+Date: Sun, 12 Sep 2010 19:55:25 -0400
+Subject: SUNRPC: Fix a race in rpc_info_open
+
+From: Trond Myklebust <Trond.Myklebust@netapp.com>
+
+commit 006abe887c5e637d059c44310de6c92f36aded3b upstream.
+
+There is a race between rpc_info_open and rpc_release_client()
+in that nothing stops a process from opening the file after
+the clnt->cl_kref goes to zero.
+
+Fix this by using atomic_inc_unless_zero()...
+
+Reported-by: J. Bruce Fields <bfields@redhat.com>
+Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+--- a/include/linux/sunrpc/clnt.h
++++ b/include/linux/sunrpc/clnt.h
+@@ -30,7 +30,7 @@ struct rpc_inode;
+  * The high-level client handle
+  */
+ struct rpc_clnt {
+-      struct kref             cl_kref;        /* Number of references */
++      atomic_t                cl_count;       /* Number of references */
+       struct list_head        cl_clients;     /* Global list of clients */
+       struct list_head        cl_tasks;       /* List of tasks */
+       spinlock_t              cl_lock;        /* spinlock */
+diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c
+index 657aac6..3a8f53e 100644
+--- a/net/sunrpc/clnt.c
++++ b/net/sunrpc/clnt.c
+@@ -226,7 +226,7 @@ static struct rpc_clnt * rpc_new_client(const struct rpc_create_args *args, stru
+                       goto out_no_principal;
+       }
+-      kref_init(&clnt->cl_kref);
++      atomic_set(&clnt->cl_count, 1);
+       err = rpc_setup_pipedir(clnt, program->pipe_dir_name);
+       if (err < 0)
+@@ -390,14 +390,14 @@ rpc_clone_client(struct rpc_clnt *clnt)
+               if (new->cl_principal == NULL)
+                       goto out_no_principal;
+       }
+-      kref_init(&new->cl_kref);
++      atomic_set(&new->cl_count, 1);
+       err = rpc_setup_pipedir(new, clnt->cl_program->pipe_dir_name);
+       if (err != 0)
+               goto out_no_path;
+       if (new->cl_auth)
+               atomic_inc(&new->cl_auth->au_count);
+       xprt_get(clnt->cl_xprt);
+-      kref_get(&clnt->cl_kref);
++      atomic_inc(&clnt->cl_count);
+       rpc_register_client(new);
+       rpciod_up();
+       return new;
+@@ -465,10 +465,8 @@ EXPORT_SYMBOL_GPL(rpc_shutdown_client);
+  * Free an RPC client
+  */
+ static void
+-rpc_free_client(struct kref *kref)
++rpc_free_client(struct rpc_clnt *clnt)
+ {
+-      struct rpc_clnt *clnt = container_of(kref, struct rpc_clnt, cl_kref);
+-
+       dprintk("RPC:       destroying %s client for %s\n",
+                       clnt->cl_protname, clnt->cl_server);
+       if (!IS_ERR(clnt->cl_path.dentry)) {
+@@ -495,12 +493,10 @@ out_free:
+  * Free an RPC client
+  */
+ static void
+-rpc_free_auth(struct kref *kref)
++rpc_free_auth(struct rpc_clnt *clnt)
+ {
+-      struct rpc_clnt *clnt = container_of(kref, struct rpc_clnt, cl_kref);
+-
+       if (clnt->cl_auth == NULL) {
+-              rpc_free_client(kref);
++              rpc_free_client(clnt);
+               return;
+       }
+@@ -509,10 +505,11 @@ rpc_free_auth(struct kref *kref)
+        *       release remaining GSS contexts. This mechanism ensures
+        *       that it can do so safely.
+        */
+-      kref_init(kref);
++      atomic_inc(&clnt->cl_count);
+       rpcauth_release(clnt->cl_auth);
+       clnt->cl_auth = NULL;
+-      kref_put(kref, rpc_free_client);
++      if (atomic_dec_and_test(&clnt->cl_count))
++              rpc_free_client(clnt);
+ }
+ /*
+@@ -525,7 +522,8 @@ rpc_release_client(struct rpc_clnt *clnt)
+       if (list_empty(&clnt->cl_tasks))
+               wake_up(&destroy_wait);
+-      kref_put(&clnt->cl_kref, rpc_free_auth);
++      if (atomic_dec_and_test(&clnt->cl_count))
++              rpc_free_auth(clnt);
+ }
+ /**
+@@ -588,7 +586,7 @@ void rpc_task_set_client(struct rpc_task *task, struct rpc_clnt *clnt)
+       if (clnt != NULL) {
+               rpc_task_release_client(task);
+               task->tk_client = clnt;
+-              kref_get(&clnt->cl_kref);
++              atomic_inc(&clnt->cl_count);
+               if (clnt->cl_softrtry)
+                       task->tk_flags |= RPC_TASK_SOFT;
+               /* Add to the client's list of all tasks */
+diff --git a/net/sunrpc/rpc_pipe.c b/net/sunrpc/rpc_pipe.c
+index 41a762f..8c8eef2 100644
+--- a/net/sunrpc/rpc_pipe.c
++++ b/net/sunrpc/rpc_pipe.c
+@@ -371,21 +371,23 @@ rpc_show_info(struct seq_file *m, void *v)
+ static int
+ rpc_info_open(struct inode *inode, struct file *file)
+ {
+-      struct rpc_clnt *clnt;
++      struct rpc_clnt *clnt = NULL;
+       int ret = single_open(file, rpc_show_info, NULL);
+       if (!ret) {
+               struct seq_file *m = file->private_data;
+-              mutex_lock(&inode->i_mutex);
+-              clnt = RPC_I(inode)->private;
+-              if (clnt) {
+-                      kref_get(&clnt->cl_kref);
++
++              spin_lock(&file->f_path.dentry->d_lock);
++              if (!d_unhashed(file->f_path.dentry))
++                      clnt = RPC_I(inode)->private;
++              if (clnt != NULL && atomic_inc_not_zero(&clnt->cl_count)) {
++                      spin_unlock(&file->f_path.dentry->d_lock);
+                       m->private = clnt;
+               } else {
++                      spin_unlock(&file->f_path.dentry->d_lock);
+                       single_release(inode, file);
+                       ret = -EINVAL;
+               }
+-              mutex_unlock(&inode->i_mutex);
+       }
+       return ret;
+ }
diff --git a/queue-2.6.32/sunrpc-fix-race-corrupting-rpc-upcall.patch b/queue-2.6.32/sunrpc-fix-race-corrupting-rpc-upcall.patch
new file mode 100644 (file)
index 0000000..f70349f
--- /dev/null
@@ -0,0 +1,81 @@
+From 5a67657a2e90c9e4a48518f95d4ba7777aa20fbb Mon Sep 17 00:00:00 2001
+From: Trond Myklebust <Trond.Myklebust@netapp.com>
+Date: Sun, 12 Sep 2010 19:55:25 -0400
+Subject: SUNRPC: Fix race corrupting rpc upcall
+
+From: Trond Myklebust <Trond.Myklebust@netapp.com>
+
+commit 5a67657a2e90c9e4a48518f95d4ba7777aa20fbb upstream.
+
+If rpc_queue_upcall() adds a new upcall to the rpci->pipe list just
+after rpc_pipe_release calls rpc_purge_list(), but before it calls
+gss_pipe_release (as rpci->ops->release_pipe(inode)), then the latter
+will free a message without deleting it from the rpci->pipe list.
+
+We will be left with a freed object on the rpc->pipe list.  Most
+frequent symptoms are kernel crashes in rpc.gssd system calls on the
+pipe in question.
+
+Reported-by: J. Bruce Fields <bfields@redhat.com>
+Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ net/sunrpc/auth_gss/auth_gss.c |    9 +++++----
+ net/sunrpc/rpc_pipe.c          |    6 +++---
+ 2 files changed, 8 insertions(+), 7 deletions(-)
+
+--- a/net/sunrpc/auth_gss/auth_gss.c
++++ b/net/sunrpc/auth_gss/auth_gss.c
+@@ -717,17 +717,18 @@ gss_pipe_release(struct inode *inode)
+       struct rpc_inode *rpci = RPC_I(inode);
+       struct gss_upcall_msg *gss_msg;
++restart:
+       spin_lock(&inode->i_lock);
+-      while (!list_empty(&rpci->in_downcall)) {
++      list_for_each_entry(gss_msg, &rpci->in_downcall, list) {
+-              gss_msg = list_entry(rpci->in_downcall.next,
+-                              struct gss_upcall_msg, list);
++              if (!list_empty(&gss_msg->msg.list))
++                      continue;
+               gss_msg->msg.errno = -EPIPE;
+               atomic_inc(&gss_msg->count);
+               __gss_unhash_msg(gss_msg);
+               spin_unlock(&inode->i_lock);
+               gss_release_msg(gss_msg);
+-              spin_lock(&inode->i_lock);
++              goto restart;
+       }
+       spin_unlock(&inode->i_lock);
+--- a/net/sunrpc/rpc_pipe.c
++++ b/net/sunrpc/rpc_pipe.c
+@@ -47,7 +47,7 @@ static void rpc_purge_list(struct rpc_in
+               return;
+       do {
+               msg = list_entry(head->next, struct rpc_pipe_msg, list);
+-              list_del(&msg->list);
++              list_del_init(&msg->list);
+               msg->errno = err;
+               destroy_msg(msg);
+       } while (!list_empty(head));
+@@ -207,7 +207,7 @@ rpc_pipe_release(struct inode *inode, st
+       if (msg != NULL) {
+               spin_lock(&inode->i_lock);
+               msg->errno = -EAGAIN;
+-              list_del(&msg->list);
++              list_del_init(&msg->list);
+               spin_unlock(&inode->i_lock);
+               rpci->ops->destroy_msg(msg);
+       }
+@@ -267,7 +267,7 @@ rpc_pipe_read(struct file *filp, char __
+       if (res < 0 || msg->len == msg->copied) {
+               filp->private_data = NULL;
+               spin_lock(&inode->i_lock);
+-              list_del(&msg->list);
++              list_del_init(&msg->list);
+               spin_unlock(&inode->i_lock);
+               rpci->ops->destroy_msg(msg);
+       }