]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/commitdiff
Merge tag 'for-linus-4.1-merge-window' of git://git.kernel.org/pub/scm/linux/kernel...
authorLinus Torvalds <torvalds@linux-foundation.org>
Sat, 18 Apr 2015 21:45:30 +0000 (17:45 -0400)
committerLinus Torvalds <torvalds@linux-foundation.org>
Sat, 18 Apr 2015 21:45:30 +0000 (17:45 -0400)
Pull 9pfs updates from Eric Van Hensbergen:
 "Some accumulated cleanup patches for kerneldoc and unused variables as
  well as some lock bug fixes and adding privateport option for RDMA"

* tag 'for-linus-4.1-merge-window' of git://git.kernel.org/pub/scm/linux/kernel/git/ericvh/v9fs:
  net/9p: add a privport option for RDMA transport.
  fs/9p: Initialize status in v9fs_file_do_lock.
  net/9p: Initialize opts->privport as it should be.
  net/9p: use memcpy() instead of snprintf() in p9_mount_tag_show()
  9p: use unsigned integers for nwqid/count
  9p: do not crash on unknown lock status code
  9p: fix error handling in v9fs_file_do_lock
  9p: remove unused variable in p9_fd_create()
  9p: kerneldoc warning fixes

1  2 
fs/9p/vfs_addr.c
fs/9p/vfs_file.c
net/9p/protocol.c
net/9p/trans_fd.c
net/9p/trans_virtio.c

diff --combined fs/9p/vfs_addr.c
index be35d05a4d0efc00c5955cc047ac20bea293149a,3672b16feac65b7981d93a6b805a39781dd05295..e9e04376c52ce8ef4673d041281c1db1e2c4ac99
@@@ -33,7 -33,7 +33,7 @@@
  #include <linux/pagemap.h>
  #include <linux/idr.h>
  #include <linux/sched.h>
 -#include <linux/aio.h>
 +#include <linux/uio.h>
  #include <net/9p/9p.h>
  #include <net/9p/client.h>
  
   */
  static int v9fs_fid_readpage(struct p9_fid *fid, struct page *page)
  {
 -      int retval;
 -      loff_t offset;
 -      char *buffer;
 -      struct inode *inode;
 +      struct inode *inode = page->mapping->host;
 +      struct bio_vec bvec = {.bv_page = page, .bv_len = PAGE_SIZE};
 +      struct iov_iter to;
 +      int retval, err;
  
 -      inode = page->mapping->host;
        p9_debug(P9_DEBUG_VFS, "\n");
  
        BUG_ON(!PageLocked(page));
        if (retval == 0)
                return retval;
  
 -      buffer = kmap(page);
 -      offset = page_offset(page);
 +      iov_iter_bvec(&to, ITER_BVEC | READ, &bvec, 1, PAGE_SIZE);
  
 -      retval = v9fs_fid_readn(fid, buffer, NULL, PAGE_CACHE_SIZE, offset);
 -      if (retval < 0) {
 +      retval = p9_client_read(fid, page_offset(page), &to, &err);
 +      if (err) {
                v9fs_uncache_page(inode, page);
 +              retval = err;
                goto done;
        }
  
 -      memset(buffer + retval, 0, PAGE_CACHE_SIZE - retval);
 +      zero_user(page, retval, PAGE_SIZE - retval);
        flush_dcache_page(page);
        SetPageUptodate(page);
  
@@@ -81,6 -82,7 +81,6 @@@
        retval = 0;
  
  done:
 -      kunmap(page);
        unlock_page(page);
        return retval;
  }
@@@ -159,32 -161,41 +159,32 @@@ static void v9fs_invalidate_page(struc
  
  static int v9fs_vfs_writepage_locked(struct page *page)
  {
 -      char *buffer;
 -      int retval, len;
 -      loff_t offset, size;
 -      mm_segment_t old_fs;
 -      struct v9fs_inode *v9inode;
        struct inode *inode = page->mapping->host;
 +      struct v9fs_inode *v9inode = V9FS_I(inode);
 +      loff_t size = i_size_read(inode);
 +      struct iov_iter from;
 +      struct bio_vec bvec;
 +      int err, len;
  
 -      v9inode = V9FS_I(inode);
 -      size = i_size_read(inode);
        if (page->index == size >> PAGE_CACHE_SHIFT)
                len = size & ~PAGE_CACHE_MASK;
        else
                len = PAGE_CACHE_SIZE;
  
 -      set_page_writeback(page);
 -
 -      buffer = kmap(page);
 -      offset = page_offset(page);
 +      bvec.bv_page = page;
 +      bvec.bv_offset = 0;
 +      bvec.bv_len = len;
 +      iov_iter_bvec(&from, ITER_BVEC | WRITE, &bvec, 1, len);
  
 -      old_fs = get_fs();
 -      set_fs(get_ds());
        /* We should have writeback_fid always set */
        BUG_ON(!v9inode->writeback_fid);
  
 -      retval = v9fs_file_write_internal(inode,
 -                                        v9inode->writeback_fid,
 -                                        (__force const char __user *)buffer,
 -                                        len, &offset, 0);
 -      if (retval > 0)
 -              retval = 0;
 +      set_page_writeback(page);
 +
 +      p9_client_write(v9inode->writeback_fid, page_offset(page), &from, &err);
  
 -      set_fs(old_fs);
 -      kunmap(page);
        end_page_writeback(page);
 -      return retval;
 +      return err;
  }
  
  static int v9fs_vfs_writepage(struct page *page, struct writeback_control *wbc)
@@@ -230,10 -241,9 +230,8 @@@ static int v9fs_launder_page(struct pag
  
  /**
   * v9fs_direct_IO - 9P address space operation for direct I/O
 - * @rw: direction (read or write)
   * @iocb: target I/O control block
-  * @iov: array of vectors that define I/O buffer
   * @pos: offset in file to begin the operation
-  * @nr_segs: size of iovec array
   *
   * The presence of v9fs_direct_IO() in the address space ops vector
   * allowes open() O_DIRECT flags which would have failed otherwise.
   *
   */
  static ssize_t
 -v9fs_direct_IO(int rw, struct kiocb *iocb, struct iov_iter *iter, loff_t pos)
 +v9fs_direct_IO(struct kiocb *iocb, struct iov_iter *iter, loff_t pos)
  {
 -      /*
 -       * FIXME
 -       * Now that we do caching with cache mode enabled, We need
 -       * to support direct IO
 -       */
 -      p9_debug(P9_DEBUG_VFS, "v9fs_direct_IO: v9fs_direct_IO (%pD) off/no(%lld/%lu) EINVAL\n",
 -               iocb->ki_filp,
 -               (long long)pos, iter->nr_segs);
 -
 -      return -EINVAL;
 +      struct file *file = iocb->ki_filp;
 +      ssize_t n;
 +      int err = 0;
 +      if (iov_iter_rw(iter) == WRITE) {
 +              n = p9_client_write(file->private_data, pos, iter, &err);
 +              if (n) {
 +                      struct inode *inode = file_inode(file);
 +                      loff_t i_size = i_size_read(inode);
 +                      if (pos + n > i_size)
 +                              inode_add_bytes(inode, pos + n - i_size);
 +              }
 +      } else {
 +              n = p9_client_read(file->private_data, pos, iter, &err);
 +      }
 +      return n ? n : err;
  }
  
  static int v9fs_write_begin(struct file *filp, struct address_space *mapping,
diff --combined fs/9p/vfs_file.c
index 2a9dd37dc426d6cf38eeac64727217164c903ae6,bdb103f73e34fa0ec9ef440bc85d1984df2604fb..1ef16bd8280b595c0d261bcfa4246d5473d7015e
@@@ -36,8 -36,6 +36,8 @@@
  #include <linux/utsname.h>
  #include <asm/uaccess.h>
  #include <linux/idr.h>
 +#include <linux/uio.h>
 +#include <linux/slab.h>
  #include <net/9p/9p.h>
  #include <net/9p/client.h>
  
@@@ -151,7 -149,7 +151,7 @@@ static int v9fs_file_do_lock(struct fil
  {
        struct p9_flock flock;
        struct p9_fid *fid;
-       uint8_t status;
+       uint8_t status = P9_LOCK_ERROR;
        int res = 0;
        unsigned char fl_type;
  
        for (;;) {
                res = p9_client_lock_dotl(fid, &flock, &status);
                if (res < 0)
-                       break;
+                       goto out_unlock;
  
                if (status != P9_LOCK_BLOCKED)
                        break;
        case P9_LOCK_BLOCKED:
                res = -EAGAIN;
                break;
+       default:
+               WARN_ONCE(1, "unknown lock status code: %d\n", status);
+               /* fallthough */
        case P9_LOCK_ERROR:
        case P9_LOCK_GRACE:
                res = -ENOLCK;
                break;
-       default:
-               BUG();
        }
  
+ out_unlock:
        /*
         * incase server returned error for lock request, revert
         * it locally
@@@ -287,7 -287,6 +289,7 @@@ static int v9fs_file_getlock(struct fil
                        fl->fl_end = glock.start + glock.length - 1;
                fl->fl_pid = glock.proc_id;
        }
 +      kfree(glock.client_id);
        return res;
  }
  
@@@ -366,6 -365,63 +368,6 @@@ out_err
        return ret;
  }
  
 -/**
 - * v9fs_fid_readn - read from a fid
 - * @fid: fid to read
 - * @data: data buffer to read data into
 - * @udata: user data buffer to read data into
 - * @count: size of buffer
 - * @offset: offset at which to read data
 - *
 - */
 -ssize_t
 -v9fs_fid_readn(struct p9_fid *fid, char *data, char __user *udata, u32 count,
 -             u64 offset)
 -{
 -      int n, total, size;
 -
 -      p9_debug(P9_DEBUG_VFS, "fid %d offset %llu count %d\n",
 -               fid->fid, (long long unsigned)offset, count);
 -      n = 0;
 -      total = 0;
 -      size = fid->iounit ? fid->iounit : fid->clnt->msize - P9_IOHDRSZ;
 -      do {
 -              n = p9_client_read(fid, data, udata, offset, count);
 -              if (n <= 0)
 -                      break;
 -
 -              if (data)
 -                      data += n;
 -              if (udata)
 -                      udata += n;
 -
 -              offset += n;
 -              count -= n;
 -              total += n;
 -      } while (count > 0 && n == size);
 -
 -      if (n < 0)
 -              total = n;
 -
 -      return total;
 -}
 -
 -/**
 - * v9fs_file_readn - read from a file
 - * @filp: file pointer to read
 - * @data: data buffer to read data into
 - * @udata: user data buffer to read data into
 - * @count: size of buffer
 - * @offset: offset at which to read data
 - *
 - */
 -ssize_t
 -v9fs_file_readn(struct file *filp, char *data, char __user *udata, u32 count,
 -             u64 offset)
 -{
 -      return v9fs_fid_readn(filp->private_data, data, udata, count, offset);
 -}
 -
  /**
   * v9fs_file_read - read from a file
   * @filp: file pointer to read
   */
  
  static ssize_t
 -v9fs_file_read(struct file *filp, char __user *udata, size_t count,
 -             loff_t * offset)
 +v9fs_file_read_iter(struct kiocb *iocb, struct iov_iter *to)
  {
 -      int ret;
 -      struct p9_fid *fid;
 -      size_t size;
 +      struct p9_fid *fid = iocb->ki_filp->private_data;
 +      int ret, err;
  
 -      p9_debug(P9_DEBUG_VFS, "count %zu offset %lld\n", count, *offset);
 -      fid = filp->private_data;
 -
 -      size = fid->iounit ? fid->iounit : fid->clnt->msize - P9_IOHDRSZ;
 -      if (count > size)
 -              ret = v9fs_file_readn(filp, NULL, udata, count, *offset);
 -      else
 -              ret = p9_client_read(fid, NULL, udata, *offset, count);
 +      p9_debug(P9_DEBUG_VFS, "count %zu offset %lld\n",
 +               iov_iter_count(to), iocb->ki_pos);
  
 -      if (ret > 0)
 -              *offset += ret;
 +      ret = p9_client_read(fid, iocb->ki_pos, to, &err);
 +      if (!ret)
 +              return err;
  
 +      iocb->ki_pos += ret;
        return ret;
  }
  
 -ssize_t
 -v9fs_file_write_internal(struct inode *inode, struct p9_fid *fid,
 -                       const char __user *data, size_t count,
 -                       loff_t *offset, int invalidate)
 -{
 -      int n;
 -      loff_t i_size;
 -      size_t total = 0;
 -      loff_t origin = *offset;
 -      unsigned long pg_start, pg_end;
 -
 -      p9_debug(P9_DEBUG_VFS, "data %p count %d offset %x\n",
 -               data, (int)count, (int)*offset);
 -
 -      do {
 -              n = p9_client_write(fid, NULL, data+total, origin+total, count);
 -              if (n <= 0)
 -                      break;
 -              count -= n;
 -              total += n;
 -      } while (count > 0);
 -
 -      if (invalidate && (total > 0)) {
 -              pg_start = origin >> PAGE_CACHE_SHIFT;
 -              pg_end = (origin + total - 1) >> PAGE_CACHE_SHIFT;
 -              if (inode->i_mapping && inode->i_mapping->nrpages)
 -                      invalidate_inode_pages2_range(inode->i_mapping,
 -                                                    pg_start, pg_end);
 -              *offset += total;
 -              i_size = i_size_read(inode);
 -              if (*offset > i_size) {
 -                      inode_add_bytes(inode, *offset - i_size);
 -                      i_size_write(inode, *offset);
 -              }
 -      }
 -      if (n < 0)
 -              return n;
 -
 -      return total;
 -}
 -
  /**
   * v9fs_file_write - write to a file
   * @filp: file pointer to write
   *
   */
  static ssize_t
 -v9fs_file_write(struct file *filp, const char __user * data,
 -              size_t count, loff_t *offset)
 +v9fs_file_write_iter(struct kiocb *iocb, struct iov_iter *from)
  {
 -      ssize_t retval = 0;
 -      loff_t origin = *offset;
 -
 -
 -      retval = generic_write_checks(filp, &origin, &count, 0);
 -      if (retval)
 -              goto out;
 +      struct file *file = iocb->ki_filp;
 +      ssize_t retval;
 +      loff_t origin;
 +      int err = 0;
  
 -      retval = -EINVAL;
 -      if ((ssize_t) count < 0)
 -              goto out;
 -      retval = 0;
 -      if (!count)
 -              goto out;
 +      retval = generic_write_checks(iocb, from);
 +      if (retval <= 0)
 +              return retval;
  
 -      retval = v9fs_file_write_internal(file_inode(filp),
 -                                      filp->private_data,
 -                                      data, count, &origin, 1);
 -      /* update offset on successful write */
 -      if (retval > 0)
 -              *offset = origin;
 -out:
 -      return retval;
 +      origin = iocb->ki_pos;
 +      retval = p9_client_write(file->private_data, iocb->ki_pos, from, &err);
 +      if (retval > 0) {
 +              struct inode *inode = file_inode(file);
 +              loff_t i_size;
 +              unsigned long pg_start, pg_end;
 +              pg_start = origin >> PAGE_CACHE_SHIFT;
 +              pg_end = (origin + retval - 1) >> PAGE_CACHE_SHIFT;
 +              if (inode->i_mapping && inode->i_mapping->nrpages)
 +                      invalidate_inode_pages2_range(inode->i_mapping,
 +                                                    pg_start, pg_end);
 +              iocb->ki_pos += retval;
 +              i_size = i_size_read(inode);
 +              if (iocb->ki_pos > i_size) {
 +                      inode_add_bytes(inode, iocb->ki_pos - i_size);
 +                      i_size_write(inode, iocb->ki_pos);
 +              }
 +              return retval;
 +      }
 +      return err;
  }
  
 -
  static int v9fs_file_fsync(struct file *filp, loff_t start, loff_t end,
                           int datasync)
  {
@@@ -560,6 -659,44 +562,6 @@@ out_unlock
        return VM_FAULT_NOPAGE;
  }
  
 -static ssize_t
 -v9fs_direct_read(struct file *filp, char __user *udata, size_t count,
 -               loff_t *offsetp)
 -{
 -      loff_t size, offset;
 -      struct inode *inode;
 -      struct address_space *mapping;
 -
 -      offset = *offsetp;
 -      mapping = filp->f_mapping;
 -      inode = mapping->host;
 -      if (!count)
 -              return 0;
 -      size = i_size_read(inode);
 -      if (offset < size)
 -              filemap_write_and_wait_range(mapping, offset,
 -                                           offset + count - 1);
 -
 -      return v9fs_file_read(filp, udata, count, offsetp);
 -}
 -
 -/**
 - * v9fs_cached_file_read - read from a file
 - * @filp: file pointer to read
 - * @data: user data buffer to read data into
 - * @count: size of buffer
 - * @offset: offset at which to read data
 - *
 - */
 -static ssize_t
 -v9fs_cached_file_read(struct file *filp, char __user *data, size_t count,
 -                    loff_t *offset)
 -{
 -      if (filp->f_flags & O_DIRECT)
 -              return v9fs_direct_read(filp, data, count, offset);
 -      return new_sync_read(filp, data, count, offset);
 -}
 -
  /**
   * v9fs_mmap_file_read - read from a file
   * @filp: file pointer to read
   *
   */
  static ssize_t
 -v9fs_mmap_file_read(struct file *filp, char __user *data, size_t count,
 -                    loff_t *offset)
 +v9fs_mmap_file_read_iter(struct kiocb *iocb, struct iov_iter *to)
  {
        /* TODO: Check if there are dirty pages */
 -      return v9fs_file_read(filp, data, count, offset);
 +      return v9fs_file_read_iter(iocb, to);
  }
  
 -static ssize_t
 -v9fs_direct_write(struct file *filp, const char __user * data,
 -                size_t count, loff_t *offsetp)
 -{
 -      loff_t offset;
 -      ssize_t retval;
 -      struct inode *inode;
 -      struct address_space *mapping;
 -
 -      offset = *offsetp;
 -      mapping = filp->f_mapping;
 -      inode = mapping->host;
 -      if (!count)
 -              return 0;
 -
 -      mutex_lock(&inode->i_mutex);
 -      retval = filemap_write_and_wait_range(mapping, offset,
 -                                            offset + count - 1);
 -      if (retval)
 -              goto err_out;
 -      /*
 -       * After a write we want buffered reads to be sure to go to disk to get
 -       * the new data.  We invalidate clean cached page from the region we're
 -       * about to write.  We do this *before* the write so that if we fail
 -       * here we fall back to buffered write
 -       */
 -      if (mapping->nrpages) {
 -              pgoff_t pg_start = offset >> PAGE_CACHE_SHIFT;
 -              pgoff_t pg_end   = (offset + count - 1) >> PAGE_CACHE_SHIFT;
 -
 -              retval = invalidate_inode_pages2_range(mapping,
 -                                                      pg_start, pg_end);
 -              /*
 -               * If a page can not be invalidated, fall back
 -               * to buffered write.
 -               */
 -              if (retval) {
 -                      if (retval == -EBUSY)
 -                              goto buff_write;
 -                      goto err_out;
 -              }
 -      }
 -      retval = v9fs_file_write(filp, data, count, offsetp);
 -err_out:
 -      mutex_unlock(&inode->i_mutex);
 -      return retval;
 -
 -buff_write:
 -      mutex_unlock(&inode->i_mutex);
 -      return new_sync_write(filp, data, count, offsetp);
 -}
 -
 -/**
 - * v9fs_cached_file_write - write to a file
 - * @filp: file pointer to write
 - * @data: data buffer to write data from
 - * @count: size of buffer
 - * @offset: offset at which to write data
 - *
 - */
 -static ssize_t
 -v9fs_cached_file_write(struct file *filp, const char __user * data,
 -                     size_t count, loff_t *offset)
 -{
 -
 -      if (filp->f_flags & O_DIRECT)
 -              return v9fs_direct_write(filp, data, count, offset);
 -      return new_sync_write(filp, data, count, offset);
 -}
 -
 -
  /**
   * v9fs_mmap_file_write - write to a file
   * @filp: file pointer to write
   *
   */
  static ssize_t
 -v9fs_mmap_file_write(struct file *filp, const char __user *data,
 -                     size_t count, loff_t *offset)
 +v9fs_mmap_file_write_iter(struct kiocb *iocb, struct iov_iter *from)
  {
        /*
         * TODO: invalidate mmaps on filp's inode between
         * offset and offset+count
         */
 -      return v9fs_file_write(filp, data, count, offset);
 +      return v9fs_file_write_iter(iocb, from);
  }
  
  static void v9fs_mmap_vm_close(struct vm_area_struct *vma)
@@@ -635,6 -845,8 +637,6 @@@ static const struct vm_operations_struc
  
  const struct file_operations v9fs_cached_file_operations = {
        .llseek = generic_file_llseek,
 -      .read = v9fs_cached_file_read,
 -      .write = v9fs_cached_file_write,
        .read_iter = generic_file_read_iter,
        .write_iter = generic_file_write_iter,
        .open = v9fs_file_open,
  
  const struct file_operations v9fs_cached_file_operations_dotl = {
        .llseek = generic_file_llseek,
 -      .read = v9fs_cached_file_read,
 -      .write = v9fs_cached_file_write,
        .read_iter = generic_file_read_iter,
        .write_iter = generic_file_write_iter,
        .open = v9fs_file_open,
  
  const struct file_operations v9fs_file_operations = {
        .llseek = generic_file_llseek,
 -      .read = v9fs_file_read,
 -      .write = v9fs_file_write,
 +      .read_iter = v9fs_file_read_iter,
 +      .write_iter = v9fs_file_write_iter,
        .open = v9fs_file_open,
        .release = v9fs_dir_release,
        .lock = v9fs_file_lock,
  
  const struct file_operations v9fs_file_operations_dotl = {
        .llseek = generic_file_llseek,
 -      .read = v9fs_file_read,
 -      .write = v9fs_file_write,
 +      .read_iter = v9fs_file_read_iter,
 +      .write_iter = v9fs_file_write_iter,
        .open = v9fs_file_open,
        .release = v9fs_dir_release,
        .lock = v9fs_file_lock_dotl,
  
  const struct file_operations v9fs_mmap_file_operations = {
        .llseek = generic_file_llseek,
 -      .read = v9fs_mmap_file_read,
 -      .write = v9fs_mmap_file_write,
 +      .read_iter = v9fs_mmap_file_read_iter,
 +      .write_iter = v9fs_mmap_file_write_iter,
        .open = v9fs_file_open,
        .release = v9fs_dir_release,
        .lock = v9fs_file_lock,
  
  const struct file_operations v9fs_mmap_file_operations_dotl = {
        .llseek = generic_file_llseek,
 -      .read = v9fs_mmap_file_read,
 -      .write = v9fs_mmap_file_write,
 +      .read_iter = v9fs_mmap_file_read_iter,
 +      .write_iter = v9fs_mmap_file_write_iter,
        .open = v9fs_file_open,
        .release = v9fs_dir_release,
        .lock = v9fs_file_lock_dotl,
diff --combined net/9p/protocol.c
index e9d0f0c1a04827f0d1cc0f554f6b4dfaabb2c414,305e4789f2ccd98b60dcc67248ee573cbbdd2d44..16d28756598789504f9a30a07476256a2146b2e3
@@@ -33,7 -33,6 +33,7 @@@
  #include <linux/sched.h>
  #include <linux/stddef.h>
  #include <linux/types.h>
 +#include <linux/uio.h>
  #include <net/9p/9p.h>
  #include <net/9p/client.h>
  #include "protocol.h"
@@@ -70,11 -69,10 +70,11 @@@ static size_t pdu_write(struct p9_fcal
  }
  
  static size_t
 -pdu_write_u(struct p9_fcall *pdu, const char __user *udata, size_t size)
 +pdu_write_u(struct p9_fcall *pdu, struct iov_iter *from, size_t size)
  {
        size_t len = min(pdu->capacity - pdu->size, size);
 -      if (copy_from_user(&pdu->sdata[pdu->size], udata, len))
 +      struct iov_iter i = *from;
 +      if (copy_from_iter(&pdu->sdata[pdu->size], len, &i) != len)
                len = 0;
  
        pdu->size += len;
@@@ -275,7 -273,7 +275,7 @@@ p9pdu_vreadf(struct p9_fcall *pdu, int 
                        }
                        break;
                case 'R':{
-                               int16_t *nwqid = va_arg(ap, int16_t *);
+                               uint16_t *nwqid = va_arg(ap, uint16_t *);
                                struct p9_qid **wqids =
                                    va_arg(ap, struct p9_qid **);
  
@@@ -439,13 -437,23 +439,13 @@@ p9pdu_vwritef(struct p9_fcall *pdu, in
                                                 stbuf->extension, stbuf->n_uid,
                                                 stbuf->n_gid, stbuf->n_muid);
                        } break;
 -              case 'D':{
 -                              uint32_t count = va_arg(ap, uint32_t);
 -                              const void *data = va_arg(ap, const void *);
 -
 -                              errcode = p9pdu_writef(pdu, proto_version, "d",
 -                                                                      count);
 -                              if (!errcode && pdu_write(pdu, data, count))
 -                                      errcode = -EFAULT;
 -                      }
 -                      break;
 -              case 'U':{
 +              case 'V':{
-                               int32_t count = va_arg(ap, int32_t);
+                               uint32_t count = va_arg(ap, uint32_t);
 -                              const char __user *udata =
 -                                              va_arg(ap, const void __user *);
 +                              struct iov_iter *from =
 +                                              va_arg(ap, struct iov_iter *);
                                errcode = p9pdu_writef(pdu, proto_version, "d",
                                                                        count);
 -                              if (!errcode && pdu_write_u(pdu, udata, count))
 +                              if (!errcode && pdu_write_u(pdu, from, count))
                                        errcode = -EFAULT;
                        }
                        break;
                        }
                        break;
                case 'R':{
-                               int16_t nwqid = va_arg(ap, int);
+                               uint16_t nwqid = va_arg(ap, int);
                                struct p9_qid *wqids =
                                    va_arg(ap, struct p9_qid *);
  
diff --combined net/9p/trans_fd.c
index 3e3d82d8ff70506c2878d4b55bf44269ed26b5cb,154479d2756d8d88487c17d3f659871fcb59d828..bced8c074c1280c6ff175576cb035bf048f18ddd
@@@ -734,6 -734,7 +734,7 @@@ static int parse_opts(char *params, str
        opts->port = P9_PORT;
        opts->rfd = ~0;
        opts->wfd = ~0;
+       opts->privport = 0;
  
        if (!params)
                return 0;
@@@ -940,7 -941,7 +941,7 @@@ p9_fd_create_tcp(struct p9_client *clie
        sin_server.sin_family = AF_INET;
        sin_server.sin_addr.s_addr = in_aton(addr);
        sin_server.sin_port = htons(opts.port);
 -      err = __sock_create(read_pnet(&current->nsproxy->net_ns), PF_INET,
 +      err = __sock_create(current->nsproxy->net_ns, PF_INET,
                            SOCK_STREAM, IPPROTO_TCP, &csocket, 1);
        if (err) {
                pr_err("%s (%d): problem creating socket\n",
@@@ -988,7 -989,7 +989,7 @@@ p9_fd_create_unix(struct p9_client *cli
  
        sun_server.sun_family = PF_UNIX;
        strcpy(sun_server.sun_path, addr);
 -      err = __sock_create(read_pnet(&current->nsproxy->net_ns), PF_UNIX,
 +      err = __sock_create(current->nsproxy->net_ns, PF_UNIX,
                            SOCK_STREAM, 0, &csocket, 1);
        if (err < 0) {
                pr_err("%s (%d): problem creating socket\n",
@@@ -1013,7 -1014,6 +1014,6 @@@ p9_fd_create(struct p9_client *client, 
  {
        int err;
        struct p9_fd_opts opts;
-       struct p9_trans_fd *p;
  
        parse_opts(args, &opts);
  
        if (err < 0)
                return err;
  
-       p = (struct p9_trans_fd *) client->trans;
        p9_conn_create(client);
  
        return 0;
diff --combined net/9p/trans_virtio.c
index e62bcbbabb5e3cd43717f7980fce3e280aba3ded,486df019f8752eef6adc1aec7d5a49d656cd3301..9dd49ca67dbc22a905999de21b8355475ba40052
@@@ -217,15 -217,15 +217,15 @@@ static int p9_virtio_cancel(struct p9_c
   * @start: which segment of the sg_list to start at
   * @pdata: a list of pages to add into sg.
   * @nr_pages: number of pages to pack into the scatter/gather list
 - * @data: data to pack into scatter/gather list
 + * @offs: amount of data in the beginning of first page _not_ to pack
   * @count: amount of data to pack into the scatter/gather list
   */
  static int
  pack_sg_list_p(struct scatterlist *sg, int start, int limit,
 -             struct page **pdata, int nr_pages, char *data, int count)
 +             struct page **pdata, int nr_pages, size_t offs, int count)
  {
        int i = 0, s;
 -      int data_off;
 +      int data_off = offs;
        int index = start;
  
        BUG_ON(nr_pages > (limit - start));
         * if the first page doesn't start at
         * page boundary find the offset
         */
 -      data_off = offset_in_page(data);
        while (nr_pages) {
 -              s = rest_of_page(data);
 +              s = PAGE_SIZE - data_off;
                if (s > count)
                        s = count;
                /* Make sure we don't terminate early. */
                sg_unmark_end(&sg[index]);
                sg_set_page(&sg[index++], pdata[i++], s, data_off);
                data_off = 0;
 -              data += s;
                count -= s;
                nr_pages--;
        }
@@@ -312,20 -314,11 +312,20 @@@ req_retry
  }
  
  static int p9_get_mapped_pages(struct virtio_chan *chan,
 -                             struct page **pages, char *data,
 -                             int nr_pages, int write, int kern_buf)
 +                             struct page ***pages,
 +                             struct iov_iter *data,
 +                             int count,
 +                             size_t *offs,
 +                             int *need_drop)
  {
 +      int nr_pages;
        int err;
 -      if (!kern_buf) {
 +
 +      if (!iov_iter_count(data))
 +              return 0;
 +
 +      if (!(data->type & ITER_KVEC)) {
 +              int n;
                /*
                 * We allow only p9_max_pages pinned. We wait for the
                 * Other zc request to finish here
                        if (err == -ERESTARTSYS)
                                return err;
                }
 -              err = p9_payload_gup(data, &nr_pages, pages, write);
 -              if (err < 0)
 -                      return err;
 +              n = iov_iter_get_pages_alloc(data, pages, count, offs);
 +              if (n < 0)
 +                      return n;
 +              *need_drop = 1;
 +              nr_pages = DIV_ROUND_UP(n + *offs, PAGE_SIZE);
                atomic_add(nr_pages, &vp_pinned);
 +              return n;
        } else {
                /* kernel buffer, no need to pin pages */
 -              int s, index = 0;
 -              int count = nr_pages;
 -              while (nr_pages) {
 -                      s = rest_of_page(data);
 -                      if (is_vmalloc_addr(data))
 -                              pages[index++] = vmalloc_to_page(data);
 +              int index;
 +              size_t len;
 +              void *p;
 +
 +              /* we'd already checked that it's non-empty */
 +              while (1) {
 +                      len = iov_iter_single_seg_count(data);
 +                      if (likely(len)) {
 +                              p = data->kvec->iov_base + data->iov_offset;
 +                              break;
 +                      }
 +                      iov_iter_advance(data, 0);
 +              }
 +              if (len > count)
 +                      len = count;
 +
 +              nr_pages = DIV_ROUND_UP((unsigned long)p + len, PAGE_SIZE) -
 +                         (unsigned long)p / PAGE_SIZE;
 +
 +              *pages = kmalloc(sizeof(struct page *) * nr_pages, GFP_NOFS);
 +              if (!*pages)
 +                      return -ENOMEM;
 +
 +              *need_drop = 0;
 +              p -= (*offs = (unsigned long)p % PAGE_SIZE);
 +              for (index = 0; index < nr_pages; index++) {
 +                      if (is_vmalloc_addr(p))
 +                              (*pages)[index] = vmalloc_to_page(p);
                        else
 -                              pages[index++] = kmap_to_page(data);
 -                      data += s;
 -                      nr_pages--;
 +                              (*pages)[index] = kmap_to_page(p);
 +                      p += PAGE_SIZE;
                }
 -              nr_pages = count;
 +              return len;
        }
 -      return nr_pages;
  }
  
  /**
   */
  static int
  p9_virtio_zc_request(struct p9_client *client, struct p9_req_t *req,
 -                   char *uidata, char *uodata, int inlen,
 -                   int outlen, int in_hdr_len, int kern_buf)
 +                   struct iov_iter *uidata, struct iov_iter *uodata,
 +                   int inlen, int outlen, int in_hdr_len)
  {
        int in, out, err, out_sgs, in_sgs;
        unsigned long flags;
        struct page **in_pages = NULL, **out_pages = NULL;
        struct virtio_chan *chan = client->trans;
        struct scatterlist *sgs[4];
 +      size_t offs;
 +      int need_drop = 0;
  
        p9_debug(P9_DEBUG_TRANS, "virtio request\n");
  
        if (uodata) {
 -              out_nr_pages = p9_nr_pages(uodata, outlen);
 -              out_pages = kmalloc(sizeof(struct page *) * out_nr_pages,
 -                                  GFP_NOFS);
 -              if (!out_pages) {
 -                      err = -ENOMEM;
 -                      goto err_out;
 -              }
 -              out_nr_pages = p9_get_mapped_pages(chan, out_pages, uodata,
 -                                                 out_nr_pages, 0, kern_buf);
 -              if (out_nr_pages < 0) {
 -                      err = out_nr_pages;
 -                      kfree(out_pages);
 -                      out_pages = NULL;
 -                      goto err_out;
 +              int n = p9_get_mapped_pages(chan, &out_pages, uodata,
 +                                          outlen, &offs, &need_drop);
 +              if (n < 0)
 +                      return n;
 +              out_nr_pages = DIV_ROUND_UP(n + offs, PAGE_SIZE);
 +              if (n != outlen) {
 +                      __le32 v = cpu_to_le32(n);
 +                      memcpy(&req->tc->sdata[req->tc->size - 4], &v, 4);
 +                      outlen = n;
                }
 -      }
 -      if (uidata) {
 -              in_nr_pages = p9_nr_pages(uidata, inlen);
 -              in_pages = kmalloc(sizeof(struct page *) * in_nr_pages,
 -                                 GFP_NOFS);
 -              if (!in_pages) {
 -                      err = -ENOMEM;
 -                      goto err_out;
 -              }
 -              in_nr_pages = p9_get_mapped_pages(chan, in_pages, uidata,
 -                                                in_nr_pages, 1, kern_buf);
 -              if (in_nr_pages < 0) {
 -                      err = in_nr_pages;
 -                      kfree(in_pages);
 -                      in_pages = NULL;
 -                      goto err_out;
 +      } else if (uidata) {
 +              int n = p9_get_mapped_pages(chan, &in_pages, uidata,
 +                                          inlen, &offs, &need_drop);
 +              if (n < 0)
 +                      return n;
 +              in_nr_pages = DIV_ROUND_UP(n + offs, PAGE_SIZE);
 +              if (n != inlen) {
 +                      __le32 v = cpu_to_le32(n);
 +                      memcpy(&req->tc->sdata[req->tc->size - 4], &v, 4);
 +                      inlen = n;
                }
        }
        req->status = REQ_STATUS_SENT;
@@@ -447,7 -426,7 +447,7 @@@ req_retry_pinned
        if (out_pages) {
                sgs[out_sgs++] = chan->sg + out;
                out += pack_sg_list_p(chan->sg, out, VIRTQUEUE_NUM,
 -                                    out_pages, out_nr_pages, uodata, outlen);
 +                                    out_pages, out_nr_pages, offs, outlen);
        }
                
        /*
        if (in_pages) {
                sgs[out_sgs + in_sgs++] = chan->sg + out + in;
                in += pack_sg_list_p(chan->sg, out + in, VIRTQUEUE_NUM,
 -                                   in_pages, in_nr_pages, uidata, inlen);
 +                                   in_pages, in_nr_pages, offs, inlen);
        }
  
        BUG_ON(out_sgs + in_sgs > ARRAY_SIZE(sgs));
         * Non kernel buffers are pinned, unpin them
         */
  err_out:
 -      if (!kern_buf) {
 +      if (need_drop) {
                if (in_pages) {
                        p9_release_pages(in_pages, in_nr_pages);
                        atomic_sub(in_nr_pages, &vp_pinned);
@@@ -525,7 -504,10 +525,10 @@@ static ssize_t p9_mount_tag_show(struc
        vdev = dev_to_virtio(dev);
        chan = vdev->priv;
  
-       return snprintf(buf, chan->tag_len + 1, "%s", chan->tag);
+       memcpy(buf, chan->tag, chan->tag_len);
+       buf[chan->tag_len] = 0;
+       return chan->tag_len + 1;
  }
  
  static DEVICE_ATTR(mount_tag, 0444, p9_mount_tag_show, NULL);