Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/sage/ceph...
authorLinus Torvalds <torvalds@linux-foundation.org>
Thu, 20 Dec 2012 22:00:13 +0000 (14:00 -0800)
committerLinus Torvalds <torvalds@linux-foundation.org>
Thu, 20 Dec 2012 22:00:13 +0000 (14:00 -0800)
Pull Ceph update from Sage Weil:
 "There are a few different groups of commits here.  The largest is
  Alex's ongoing work to enable the coming RBD features (cloning,
  striping).  There is some cleanup in libceph that goes along with it.

  Cyril and David have fixed some problems with NFS reexport (leaking
  dentries and page locks), and there is a batch of patches from Yan
  fixing problems with the fs client when running against a clustered
  MDS.  There are a few bug fixes mixed in for good measure, many of
  which will be going to the stable trees once they're upstream.

  My apologies for the late pull.  There is still a gremlin in the rbd
  map/unmap code and I was hoping to include the fix for that as well,
  but we haven't been able to confirm the fix is correct yet; I'll send
  that in a separate pull once it's nailed down."

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/sage/ceph-client: (68 commits)
  rbd: get rid of rbd_{get,put}_dev()
  libceph: register request before unregister linger
  libceph: don't use rb_init_node() in ceph_osdc_alloc_request()
  libceph: init event->node in ceph_osdc_create_event()
  libceph: init osd->o_node in create_osd()
  libceph: report connection fault with warning
  libceph: socket can close in any connection state
  rbd: don't use ENOTSUPP
  rbd: remove linger unconditionally
  rbd: get rid of RBD_MAX_SEG_NAME_LEN
  libceph: avoid using freed osd in __kick_osd_requests()
  ceph: don't reference req after put
  rbd: do not allow remove of mounted-on image
  libceph: Unlock unprocessed pages in start_read() error path
  ceph: call handle_cap_grant() for cap import message
  ceph: Fix __ceph_do_pending_vmtruncate
  ceph: Don't add dirty inode to dirty list if caps is in migration
  ceph: Fix infinite loop in __wake_requests
  ceph: Don't update i_max_size when handling non-auth cap
  bdi_register: add __printf verification, fix arg mismatch
  ...

1  2 
fs/ceph/addr.c
fs/ceph/file.c
fs/ceph/inode.c
fs/ceph/super.c
include/linux/ceph/libceph.h
include/linux/ceph/osdmap.h
include/linux/ceph/rados.h

diff --combined fs/ceph/addr.c
index 6690269f5dde2c5617cff3238167788f93636985,8e8a818cba07155096f4eb2019a4332e97ba3ad3..064d1a68d2c1d561cc3cd2b4bf63b511b4a76430
@@@ -267,6 -267,14 +267,14 @@@ static void finish_read(struct ceph_osd
        kfree(req->r_pages);
  }
  
+ static void ceph_unlock_page_vector(struct page **pages, int num_pages)
+ {
+       int i;
+       for (i = 0; i < num_pages; i++)
+               unlock_page(pages[i]);
+ }
  /*
   * start an async read(ahead) operation.  return nr_pages we submitted
   * a read for on success, or negative error code.
@@@ -347,6 -355,7 +355,7 @@@ static int start_read(struct inode *ino
        return nr_pages;
  
  out_pages:
+       ceph_unlock_page_vector(pages, nr_pages);
        ceph_release_page_vector(pages, nr_pages);
  out:
        ceph_osdc_put_request(req);
@@@ -1078,23 -1087,51 +1087,51 @@@ static int ceph_write_begin(struct fil
                            struct page **pagep, void **fsdata)
  {
        struct inode *inode = file->f_dentry->d_inode;
+       struct ceph_inode_info *ci = ceph_inode(inode);
+       struct ceph_file_info *fi = file->private_data;
        struct page *page;
        pgoff_t index = pos >> PAGE_CACHE_SHIFT;
-       int r;
+       int r, want, got = 0;
+       if (fi->fmode & CEPH_FILE_MODE_LAZY)
+               want = CEPH_CAP_FILE_BUFFER | CEPH_CAP_FILE_LAZYIO;
+       else
+               want = CEPH_CAP_FILE_BUFFER;
+       dout("write_begin %p %llx.%llx %llu~%u getting caps. i_size %llu\n",
+            inode, ceph_vinop(inode), pos, len, inode->i_size);
+       r = ceph_get_caps(ci, CEPH_CAP_FILE_WR, want, &got, pos+len);
+       if (r < 0)
+               return r;
+       dout("write_begin %p %llx.%llx %llu~%u  got cap refs on %s\n",
+            inode, ceph_vinop(inode), pos, len, ceph_cap_string(got));
+       if (!(got & (CEPH_CAP_FILE_BUFFER|CEPH_CAP_FILE_LAZYIO))) {
+               ceph_put_cap_refs(ci, got);
+               return -EAGAIN;
+       }
  
        do {
                /* get a page */
                page = grab_cache_page_write_begin(mapping, index, 0);
-               if (!page)
-                       return -ENOMEM;
-               *pagep = page;
+               if (!page) {
+                       r = -ENOMEM;
+                       break;
+               }
  
                dout("write_begin file %p inode %p page %p %d~%d\n", file,
                     inode, page, (int)pos, (int)len);
  
                r = ceph_update_writeable_page(file, pos, len, page);
+               if (r)
+                       page_cache_release(page);
        } while (r == -EAGAIN);
  
+       if (r) {
+               ceph_put_cap_refs(ci, got);
+       } else {
+               *pagep = page;
+               *(int *)fsdata = got;
+       }
        return r;
  }
  
@@@ -1108,10 -1145,12 +1145,12 @@@ static int ceph_write_end(struct file *
                          struct page *page, void *fsdata)
  {
        struct inode *inode = file->f_dentry->d_inode;
+       struct ceph_inode_info *ci = ceph_inode(inode);
        struct ceph_fs_client *fsc = ceph_inode_to_client(inode);
        struct ceph_mds_client *mdsc = fsc->mdsc;
        unsigned from = pos & (PAGE_CACHE_SIZE - 1);
        int check_cap = 0;
+       int got = (unsigned long)fsdata;
  
        dout("write_end file %p inode %p page %p %d~%d (%d)\n", file,
             inode, page, (int)pos, (int)copied, (int)len);
        up_read(&mdsc->snap_rwsem);
        page_cache_release(page);
  
+       if (copied > 0) {
+               int dirty;
+               spin_lock(&ci->i_ceph_lock);
+               dirty = __ceph_mark_dirty_caps(ci, CEPH_CAP_FILE_WR);
+               spin_unlock(&ci->i_ceph_lock);
+               if (dirty)
+                       __mark_inode_dirty(inode, dirty);
+       }
+       dout("write_end %p %llx.%llx %llu~%u  dropping cap refs on %s\n",
+            inode, ceph_vinop(inode), pos, len, ceph_cap_string(got));
+       ceph_put_cap_refs(ci, got);
        if (check_cap)
                ceph_check_caps(ceph_inode(inode), CHECK_CAPS_AUTHONLY, NULL);
  
@@@ -1224,7 -1276,6 +1276,7 @@@ out
  static struct vm_operations_struct ceph_vmops = {
        .fault          = filemap_fault,
        .page_mkwrite   = ceph_page_mkwrite,
 +      .remap_pages    = generic_file_remap_pages,
  };
  
  int ceph_mmap(struct file *file, struct vm_area_struct *vma)
                return -ENOEXEC;
        file_accessed(file);
        vma->vm_ops = &ceph_vmops;
 -      vma->vm_flags |= VM_CAN_NONLINEAR;
        return 0;
  }
diff --combined fs/ceph/file.c
index d4dfdcf76d7fdfbff4c318e1e4f5d9a2487d0088,d415096800a61753e0bac382dff8988176e88a09..e51558fca3a346a93797561e26e148de037d971a
@@@ -712,63 -712,53 +712,53 @@@ static ssize_t ceph_aio_write(struct ki
        struct ceph_osd_client *osdc =
                &ceph_sb_to_client(inode->i_sb)->client->osdc;
        loff_t endoff = pos + iov->iov_len;
-       int want, got = 0;
-       int ret, err;
+       int got = 0;
+       int ret, err, written;
  
        if (ceph_snap(inode) != CEPH_NOSNAP)
                return -EROFS;
  
  retry_snap:
+       written = 0;
        if (ceph_osdmap_flag(osdc->osdmap, CEPH_OSDMAP_FULL))
                return -ENOSPC;
        __ceph_do_pending_vmtruncate(inode);
-       dout("aio_write %p %llx.%llx %llu~%u getting caps. i_size %llu\n",
-            inode, ceph_vinop(inode), pos, (unsigned)iov->iov_len,
-            inode->i_size);
-       if (fi->fmode & CEPH_FILE_MODE_LAZY)
-               want = CEPH_CAP_FILE_BUFFER | CEPH_CAP_FILE_LAZYIO;
-       else
-               want = CEPH_CAP_FILE_BUFFER;
-       ret = ceph_get_caps(ci, CEPH_CAP_FILE_WR, want, &got, endoff);
-       if (ret < 0)
-               goto out_put;
-       dout("aio_write %p %llx.%llx %llu~%u  got cap refs on %s\n",
-            inode, ceph_vinop(inode), pos, (unsigned)iov->iov_len,
-            ceph_cap_string(got));
-       if ((got & (CEPH_CAP_FILE_BUFFER|CEPH_CAP_FILE_LAZYIO)) == 0 ||
-           (iocb->ki_filp->f_flags & O_DIRECT) ||
-           (inode->i_sb->s_flags & MS_SYNCHRONOUS) ||
-           (fi->flags & CEPH_F_SYNC)) {
-               ret = ceph_sync_write(file, iov->iov_base, iov->iov_len,
-                       &iocb->ki_pos);
-       } else {
-               /*
-                * buffered write; drop Fw early to avoid slow
-                * revocation if we get stuck on balance_dirty_pages
-                */
-               int dirty;
-               spin_lock(&ci->i_ceph_lock);
-               dirty = __ceph_mark_dirty_caps(ci, CEPH_CAP_FILE_WR);
-               spin_unlock(&ci->i_ceph_lock);
-               ceph_put_cap_refs(ci, got);
  
+       /*
+        * try to do a buffered write.  if we don't have sufficient
+        * caps, we'll get -EAGAIN from generic_file_aio_write, or a
+        * short write if we only get caps for some pages.
+        */
+       if (!(iocb->ki_filp->f_flags & O_DIRECT) &&
+           !(inode->i_sb->s_flags & MS_SYNCHRONOUS) &&
+           !(fi->flags & CEPH_F_SYNC)) {
                ret = generic_file_aio_write(iocb, iov, nr_segs, pos);
+               if (ret >= 0)
+                       written = ret;
                if ((ret >= 0 || ret == -EIOCBQUEUED) &&
                    ((file->f_flags & O_SYNC) || IS_SYNC(file->f_mapping->host)
                     || ceph_osdmap_flag(osdc->osdmap, CEPH_OSDMAP_NEARFULL))) {
-                       err = vfs_fsync_range(file, pos, pos + ret - 1, 1);
+                       err = vfs_fsync_range(file, pos, pos + written - 1, 1);
                        if (err < 0)
                                ret = err;
                }
+               if ((ret < 0 && ret != -EAGAIN) || pos + written >= endoff)
+                       goto out;
+       }
  
-               if (dirty)
-                       __mark_inode_dirty(inode, dirty);
+       dout("aio_write %p %llx.%llx %llu~%u getting caps. i_size %llu\n",
+            inode, ceph_vinop(inode), pos + written,
+            (unsigned)iov->iov_len - written, inode->i_size);
+       ret = ceph_get_caps(ci, CEPH_CAP_FILE_WR, 0, &got, endoff);
+       if (ret < 0)
                goto out;
-       }
  
+       dout("aio_write %p %llx.%llx %llu~%u  got cap refs on %s\n",
+            inode, ceph_vinop(inode), pos + written,
+            (unsigned)iov->iov_len - written, ceph_cap_string(got));
+       ret = ceph_sync_write(file, iov->iov_base + written,
+                             iov->iov_len - written, &iocb->ki_pos);
        if (ret >= 0) {
                int dirty;
                spin_lock(&ci->i_ceph_lock);
                if (dirty)
                        __mark_inode_dirty(inode, dirty);
        }
- out_put:
        dout("aio_write %p %llx.%llx %llu~%u  dropping cap refs on %s\n",
-            inode, ceph_vinop(inode), pos, (unsigned)iov->iov_len,
-            ceph_cap_string(got));
+            inode, ceph_vinop(inode), pos + written,
+            (unsigned)iov->iov_len - written, ceph_cap_string(got));
        ceph_put_cap_refs(ci, got);
  out:
        if (ret == -EOLDSNAPC) {
                dout("aio_write %p %llx.%llx %llu~%u got EOLDSNAPC, retrying\n",
  /*
   * llseek.  be sure to verify file size on SEEK_END.
   */
 -static loff_t ceph_llseek(struct file *file, loff_t offset, int origin)
 +static loff_t ceph_llseek(struct file *file, loff_t offset, int whence)
  {
        struct inode *inode = file->f_mapping->host;
        int ret;
        mutex_lock(&inode->i_mutex);
        __ceph_do_pending_vmtruncate(inode);
  
 -      if (origin == SEEK_END || origin == SEEK_DATA || origin == SEEK_HOLE) {
 +      if (whence == SEEK_END || whence == SEEK_DATA || whence == SEEK_HOLE) {
                ret = ceph_do_getattr(inode, CEPH_STAT_CAP_SIZE);
                if (ret < 0) {
                        offset = ret;
                }
        }
  
 -      switch (origin) {
 +      switch (whence) {
        case SEEK_END:
                offset += inode->i_size;
                break;
diff --combined fs/ceph/inode.c
index ba95eea201bf1ef8e809159d6b41019fb9169752,81613bced19f4f53f4684ef5056f87fa47673777..2971eaa65cdce9b3b31edca64ea979eeb814ab7a
@@@ -1104,7 -1104,7 +1104,7 @@@ int ceph_fill_trace(struct super_block 
                                pr_err("fill_trace bad get_inode "
                                       "%llx.%llx\n", vino.ino, vino.snap);
                                err = PTR_ERR(in);
 -                              d_delete(dn);
 +                              d_drop(dn);
                                goto done;
                        }
                        dn = splice_dentry(dn, in, &have_lease, true);
@@@ -1277,7 -1277,7 +1277,7 @@@ retry_lookup
                        in = ceph_get_inode(parent->d_sb, vino);
                        if (IS_ERR(in)) {
                                dout("new_inode badness\n");
 -                              d_delete(dn);
 +                              d_drop(dn);
                                dput(dn);
                                err = PTR_ERR(in);
                                goto out;
@@@ -1466,7 -1466,7 +1466,7 @@@ void __ceph_do_pending_vmtruncate(struc
  {
        struct ceph_inode_info *ci = ceph_inode(inode);
        u64 to;
-       int wrbuffer_refs, wake = 0;
+       int wrbuffer_refs, finish = 0;
  
  retry:
        spin_lock(&ci->i_ceph_lock);
        truncate_inode_pages(inode->i_mapping, to);
  
        spin_lock(&ci->i_ceph_lock);
-       ci->i_truncate_pending--;
-       if (ci->i_truncate_pending == 0)
-               wake = 1;
+       if (to == ci->i_truncate_size) {
+               ci->i_truncate_pending = 0;
+               finish = 1;
+       }
        spin_unlock(&ci->i_ceph_lock);
+       if (!finish)
+               goto retry;
  
        if (wrbuffer_refs == 0)
                ceph_check_caps(ci, CHECK_CAPS_AUTHONLY, NULL);
-       if (wake)
-               wake_up_all(&ci->i_cap_wq);
+       wake_up_all(&ci->i_cap_wq);
  }
  
  
diff --combined fs/ceph/super.c
index 2eb43f211325860a9d8c4eb870fa32c494568966,1a144001b2e1eab74b8cde4c00c0fedb2d9aeec9..e86aa9948124b3601e1734515e4fb629627855de
@@@ -403,8 -403,6 +403,6 @@@ static int ceph_show_options(struct seq
                seq_printf(m, ",mount_timeout=%d", opt->mount_timeout);
        if (opt->osd_idle_ttl != CEPH_OSD_IDLE_TTL_DEFAULT)
                seq_printf(m, ",osd_idle_ttl=%d", opt->osd_idle_ttl);
-       if (opt->osd_timeout != CEPH_OSD_TIMEOUT_DEFAULT)
-               seq_printf(m, ",osdtimeout=%d", opt->osd_timeout);
        if (opt->osd_keepalive_timeout != CEPH_OSD_KEEPALIVE_DEFAULT)
                seq_printf(m, ",osdkeepalivetimeout=%d",
                           opt->osd_keepalive_timeout);
@@@ -618,11 -616,6 +616,11 @@@ bad_cap
  
  static void destroy_caches(void)
  {
 +      /*
 +       * Make sure all delayed rcu free inodes are flushed before we
 +       * destroy cache.
 +       */
 +      rcu_barrier();
        kmem_cache_destroy(ceph_inode_cachep);
        kmem_cache_destroy(ceph_cap_cachep);
        kmem_cache_destroy(ceph_dentry_cachep);
@@@ -849,7 -842,7 +847,7 @@@ static int ceph_register_bdi(struct sup
                fsc->backing_dev_info.ra_pages =
                        default_backing_dev_info.ra_pages;
  
-       err = bdi_register(&fsc->backing_dev_info, NULL, "ceph-%d",
+       err = bdi_register(&fsc->backing_dev_info, NULL, "ceph-%ld",
                           atomic_long_inc_return(&bdi_seq));
        if (!err)
                sb->s_bdi = &fsc->backing_dev_info;
index 6470792b13d3c79734a9a3ae7321a9df691cec78,317aff8feb0aaab36d1fcb9f12c655fbc01d7848..084d3c622b12a8ac58ad626da2e8f325d6d3d1c9
@@@ -1,7 -1,7 +1,7 @@@
  #ifndef _FS_CEPH_LIBCEPH_H
  #define _FS_CEPH_LIBCEPH_H
  
 -#include "ceph_debug.h"
 +#include <linux/ceph/ceph_debug.h>
  
  #include <asm/unaligned.h>
  #include <linux/backing-dev.h>
  #include <linux/writeback.h>
  #include <linux/slab.h>
  
 -#include "types.h"
 -#include "messenger.h"
 -#include "msgpool.h"
 -#include "mon_client.h"
 -#include "osd_client.h"
 -#include "ceph_fs.h"
 +#include <linux/ceph/types.h>
 +#include <linux/ceph/messenger.h>
 +#include <linux/ceph/msgpool.h>
 +#include <linux/ceph/mon_client.h>
 +#include <linux/ceph/osd_client.h>
 +#include <linux/ceph/ceph_fs.h>
  
  /*
   * mount options
@@@ -43,7 -43,6 +43,6 @@@ struct ceph_options 
        struct ceph_entity_addr my_addr;
        int mount_timeout;
        int osd_idle_ttl;
-       int osd_timeout;
        int osd_keepalive_timeout;
  
        /*
@@@ -63,7 -62,6 +62,6 @@@
   * defaults
   */
  #define CEPH_MOUNT_TIMEOUT_DEFAULT  60
- #define CEPH_OSD_TIMEOUT_DEFAULT    60  /* seconds */
  #define CEPH_OSD_KEEPALIVE_DEFAULT  5
  #define CEPH_OSD_IDLE_TTL_DEFAULT    60
  
index e37acbe989a906c8cdead48c6eea2e68f53e6ed8,5ea57ba69320ad2852bd8e4bf0403c1c2c072f49..10a417f9f76fa9ccd2e2fffbc27950dbc355df59
@@@ -2,8 -2,8 +2,8 @@@
  #define _FS_CEPH_OSDMAP_H
  
  #include <linux/rbtree.h>
 -#include "types.h"
 -#include "ceph_fs.h"
 +#include <linux/ceph/types.h>
 +#include <linux/ceph/ceph_fs.h>
  #include <linux/crush/crush.h>
  
  /*
@@@ -123,6 -123,7 +123,7 @@@ extern int ceph_calc_pg_acting(struct c
  extern int ceph_calc_pg_primary(struct ceph_osdmap *osdmap,
                                struct ceph_pg pgid);
  
+ extern const char *ceph_pg_pool_name_by_id(struct ceph_osdmap *map, u64 id);
  extern int ceph_pg_poolid_by_name(struct ceph_osdmap *map, const char *name);
  
  #endif
index de91fbdf127e64b343f3fc3530d6d7fb9bd4e59e,15077db662eda473b2bef67a5590362e2afa3d51..2c04afeead1cb3d776feea90e51f93731417b1a3
@@@ -6,7 -6,7 +6,7 @@@
   * (Reliable Autonomic Distributed Object Store).
   */
  
 -#include "msgr.h"
 +#include <linux/ceph/msgr.h>
  
  /*
   * osdmap encoding versions
@@@ -87,6 -87,8 +87,8 @@@ struct ceph_pg 
   *
   *  lpgp_num -- as above.
   */
+ #define CEPH_NOPOOL  ((__u64) (-1))  /* pool id not defined */
  #define CEPH_PG_TYPE_REP     1
  #define CEPH_PG_TYPE_RAID4   2
  #define CEPH_PG_POOL_VERSION 2
This page took 0.037336 seconds and 5 git commands to generate.