]> rtime.felk.cvut.cz Git - can-eth-gw-linux.git/commitdiff
Merge tag 'for-linus-merge-3.7' of git://git.kernel.org/pub/scm/linux/kernel/git...
authorLinus Torvalds <torvalds@linux-foundation.org>
Fri, 12 Oct 2012 00:59:23 +0000 (09:59 +0900)
committerLinus Torvalds <torvalds@linux-foundation.org>
Fri, 12 Oct 2012 00:59:23 +0000 (09:59 +0900)
Pull v9fs update from Eric Van Hensbergen.

* tag 'for-linus-merge-3.7' of git://git.kernel.org/pub/scm/linux/kernel/git/ericvh/v9fs:
  9P: Fix race between p9_write_work() and p9_fd_request()
  9P: Fix race in p9_write_work()
  9P: fix test at the end of p9_write_work()
  9P: Fix race in p9_read_work()
  9p: don't use __getname/__putname for uname/aname
  net/9p: Check errno validity
  fs/9p: avoid debug OOPS when reading a long symlink

1  2 
fs/9p/v9fs.c
net/9p/trans_fd.c

diff --combined fs/9p/v9fs.c
index 392c5dac1981be79b4aff040e552b48c78c5751f,b20af74657860bd19018809bdb8e1721a5820a4d..d934f04e77368e00dc76d4a54720cff0758d3a58
@@@ -184,10 -184,20 +184,20 @@@ static int v9fs_parse_options(struct v9
                        v9ses->afid = option;
                        break;
                case Opt_uname:
-                       match_strlcpy(v9ses->uname, &args[0], PATH_MAX);
+                       kfree(v9ses->uname);
+                       v9ses->uname = match_strdup(&args[0]);
+                       if (!v9ses->uname) {
+                               ret = -ENOMEM;
+                               goto free_and_return;
+                       }
                        break;
                case Opt_remotename:
-                       match_strlcpy(v9ses->aname, &args[0], PATH_MAX);
+                       kfree(v9ses->aname);
+                       v9ses->aname = match_strdup(&args[0]);
+                       if (!v9ses->aname) {
+                               ret = -ENOMEM;
+                               goto free_and_return;
+                       }
                        break;
                case Opt_nodevmap:
                        v9ses->nodev = 1;
@@@ -287,21 -297,21 +297,21 @@@ struct p9_fid *v9fs_session_init(struc
        struct p9_fid *fid;
        int rc;
  
-       v9ses->uname = __getname();
+       v9ses->uname = kstrdup(V9FS_DEFUSER, GFP_KERNEL);
        if (!v9ses->uname)
                return ERR_PTR(-ENOMEM);
  
-       v9ses->aname = __getname();
+       v9ses->aname = kstrdup(V9FS_DEFANAME, GFP_KERNEL);
        if (!v9ses->aname) {
-               __putname(v9ses->uname);
+               kfree(v9ses->uname);
                return ERR_PTR(-ENOMEM);
        }
        init_rwsem(&v9ses->rename_sem);
  
        rc = bdi_setup_and_register(&v9ses->bdi, "9p", BDI_CAP_MAP_COPY);
        if (rc) {
-               __putname(v9ses->aname);
-               __putname(v9ses->uname);
+               kfree(v9ses->aname);
+               kfree(v9ses->uname);
                return ERR_PTR(rc);
        }
  
        list_add(&v9ses->slist, &v9fs_sessionlist);
        spin_unlock(&v9fs_sessionlist_lock);
  
-       strcpy(v9ses->uname, V9FS_DEFUSER);
-       strcpy(v9ses->aname, V9FS_DEFANAME);
        v9ses->uid = ~0;
        v9ses->dfltuid = V9FS_DEFUID;
        v9ses->dfltgid = V9FS_DEFGID;
@@@ -412,8 -420,8 +420,8 @@@ void v9fs_session_close(struct v9fs_ses
                kfree(v9ses->cachetag);
        }
  #endif
-       __putname(v9ses->uname);
-       __putname(v9ses->aname);
+       kfree(v9ses->uname);
+       kfree(v9ses->aname);
  
        bdi_destroy(&v9ses->bdi);
  
@@@ -560,11 -568,6 +568,11 @@@ static int v9fs_init_inode_cache(void
   */
  static void v9fs_destroy_inode_cache(void)
  {
 +      /*
 +       * Make sure all delayed rcu free inodes are flushed before we
 +       * destroy cache.
 +       */
 +      rcu_barrier();
        kmem_cache_destroy(v9fs_inode_cache);
  }
  
diff --combined net/9p/trans_fd.c
index 15656b8573f38b87e396998bb419f3415adb9d30,0031a8cf145d34fb1a9d2990c8f7a3ede412747a..02efb25c295705141b3c477a2712864674ae42cc
@@@ -316,8 -316,7 +316,7 @@@ static void p9_read_work(struct work_st
                                                m->rsize - m->rpos);
        p9_debug(P9_DEBUG_TRANS, "mux %p got %d bytes\n", m, err);
        if (err == -EAGAIN) {
-               clear_bit(Rworksched, &m->wsched);
-               return;
+               goto end_clear;
        }
  
        if (err <= 0)
                m->req = NULL;
        }
  
+ end_clear:
+       clear_bit(Rworksched, &m->wsched);
        if (!list_empty(&m->req_list)) {
                if (test_and_clear_bit(Rpending, &m->wsched))
                        n = POLLIN;
                else
                        n = p9_fd_poll(m->client, NULL);
  
-               if (n & POLLIN) {
+               if ((n & POLLIN) && !test_and_set_bit(Rworksched, &m->wsched)) {
                        p9_debug(P9_DEBUG_TRANS, "sched read work %p\n", m);
                        schedule_work(&m->rq);
-               } else
-                       clear_bit(Rworksched, &m->wsched);
-       } else
-               clear_bit(Rworksched, &m->wsched);
+               }
+       }
  
        return;
  error:
@@@ -453,12 -453,13 +453,13 @@@ static void p9_write_work(struct work_s
        }
  
        if (!m->wsize) {
+               spin_lock(&m->client->lock);
                if (list_empty(&m->unsent_req_list)) {
                        clear_bit(Wworksched, &m->wsched);
+                       spin_unlock(&m->client->lock);
                        return;
                }
  
-               spin_lock(&m->client->lock);
                req = list_entry(m->unsent_req_list.next, struct p9_req_t,
                               req_list);
                req->status = REQ_STATUS_SENT;
        clear_bit(Wpending, &m->wsched);
        err = p9_fd_write(m->client, m->wbuf + m->wpos, m->wsize - m->wpos);
        p9_debug(P9_DEBUG_TRANS, "mux %p sent %d bytes\n", m, err);
-       if (err == -EAGAIN) {
-               clear_bit(Wworksched, &m->wsched);
-               return;
-       }
+       if (err == -EAGAIN)
+               goto end_clear;
  
        if (err < 0)
                goto error;
        if (m->wpos == m->wsize)
                m->wpos = m->wsize = 0;
  
-       if (m->wsize == 0 && !list_empty(&m->unsent_req_list)) {
+ end_clear:
+       clear_bit(Wworksched, &m->wsched);
+       if (m->wsize || !list_empty(&m->unsent_req_list)) {
                if (test_and_clear_bit(Wpending, &m->wsched))
                        n = POLLOUT;
                else
                        n = p9_fd_poll(m->client, NULL);
  
-               if (n & POLLOUT) {
+               if ((n & POLLOUT) &&
+                  !test_and_set_bit(Wworksched, &m->wsched)) {
                        p9_debug(P9_DEBUG_TRANS, "sched write work %p\n", m);
                        schedule_work(&m->wq);
-               } else
-                       clear_bit(Wworksched, &m->wsched);
-       } else
-               clear_bit(Wworksched, &m->wsched);
+               }
+       }
  
        return;
  
@@@ -793,28 -795,30 +795,28 @@@ static int p9_fd_open(struct p9_client 
  static int p9_socket_open(struct p9_client *client, struct socket *csocket)
  {
        struct p9_trans_fd *p;
 -      int ret, fd;
 +      struct file *file;
 +      int ret;
  
        p = kmalloc(sizeof(struct p9_trans_fd), GFP_KERNEL);
        if (!p)
                return -ENOMEM;
  
        csocket->sk->sk_allocation = GFP_NOIO;
 -      fd = sock_map_fd(csocket, 0);
 -      if (fd < 0) {
 +      file = sock_alloc_file(csocket, 0, NULL);
 +      if (IS_ERR(file)) {
                pr_err("%s (%d): failed to map fd\n",
                       __func__, task_pid_nr(current));
                sock_release(csocket);
                kfree(p);
 -              return fd;
 +              return PTR_ERR(file);
        }
  
 -      get_file(csocket->file);
 -      get_file(csocket->file);
 -      p->wr = p->rd = csocket->file;
 +      get_file(file);
 +      p->wr = p->rd = file;
        client->trans = p;
        client->status = Connected;
  
 -      sys_close(fd);  /* still racy */
 -
        p->rd->f_flags |= O_NONBLOCK;
  
        p->conn = p9_conn_create(client);
@@@ -1081,7 -1085,7 +1083,7 @@@ int p9_trans_fd_init(void
  
  void p9_trans_fd_exit(void)
  {
 -      flush_work_sync(&p9_poll_work);
 +      flush_work(&p9_poll_work);
        v9fs_unregister_trans(&p9_tcp_trans);
        v9fs_unregister_trans(&p9_unix_trans);
        v9fs_unregister_trans(&p9_fd_trans);