]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
filestore: use btrfs TRANS_RESV_START ioctl if present
authorSage Weil <sage@newdream.net>
Fri, 25 Sep 2009 18:19:08 +0000 (11:19 -0700)
committerSage Weil <sage@newdream.net>
Mon, 28 Sep 2009 20:51:10 +0000 (13:51 -0700)
This will detect ENOSPC when starting the transaction, instead of
failing part way through.

src/os/FileStore.cc
src/os/FileStore.h
src/os/ObjectStore.h

index 21a31b5476b07ae1ae37a935a783a36adb6ec845..69c19eed3a0aa3f630c2b3d521be548a6d9ebb0e 100644 (file)
 #ifndef DARWIN
 # include <linux/ioctl.h>
 # define BTRFS_IOCTL_MAGIC 0x94
+struct btrfs_ioctl_trans_resv_start {
+       __u64 bytes, ops;
+};
+# define BTRFS_IOC_TRANS_RESV_START _IOW(BTRFS_IOCTL_MAGIC, 5, \
+                                       struct btrfs_ioctl_trans_resv_start)
 # define BTRFS_IOC_TRANS_START  _IO(BTRFS_IOCTL_MAGIC, 6)
 # define BTRFS_IOC_TRANS_END    _IO(BTRFS_IOCTL_MAGIC, 7)
 # define BTRFS_IOC_SYNC         _IO(BTRFS_IOCTL_MAGIC, 8)
@@ -494,8 +499,16 @@ int FileStore::mount()
   // is this btrfs?
   Transaction empty;
   btrfs = 1;
+  btrfs_trans_resv_start = true;
   btrfs_trans_start_end = true;  // trans start/end interface
   r = apply_transaction(empty, 0);
+  if (r != 0) {
+    dout(0) << "mount lame, new TRANS_RESV_START ioctl is NOT supported" << dendl;
+    btrfs_trans_resv_start = false;
+    r = apply_transaction(empty, 0);
+  } else {
+    dout(0) << "mount yay, new TRANS_RESV_START ioctl is supported" << dendl;
+  }
   if (r == 0) {
     // do we have the shiny new CLONE_RANGE ioctl?
     btrfs = 2;
@@ -553,7 +566,7 @@ unsigned FileStore::apply_transaction(Transaction &t,
   op_start();
 
   // non-atomic implementation
-  int id = _transaction_start(0);// t.get_trans_len());
+  int id = _transaction_start(t.get_num_bytes(), t.get_num_ops());
   if (id < 0) {
     op_journal_start();
     op_finish();
@@ -586,7 +599,15 @@ unsigned FileStore::apply_transactions(list<Transaction*> &tls,
 {
   op_start();
 
-  int id = _transaction_start(0);// t.get_trans_len());
+  __u64 bytes = 0, ops = 0;
+  for (list<Transaction*>::iterator p = tls.begin();
+       p != tls.end();
+       p++) {
+    bytes += (*p)->get_num_bytes();
+    ops += (*p)->get_num_ops();
+  }
+
+  int id = _transaction_start(bytes, ops);
   if (id < 0) {
     op_journal_start();
     op_finish();
@@ -623,7 +644,7 @@ unsigned FileStore::apply_transactions(list<Transaction*> &tls,
 
 // btrfs transaction start/end interface
 
-int FileStore::_transaction_start(int len)
+int FileStore::_transaction_start(__u64 bytes, __u64 ops)
 {
 #ifdef DARWIN
   return 0;
@@ -639,7 +660,17 @@ int FileStore::_transaction_start(int len)
            << " from btrfs open" << dendl;
     assert(0);
   }
-  if (::ioctl(fd, BTRFS_IOC_TRANS_START) < 0) {
+
+  int r;
+  if (btrfs_trans_resv_start) {
+    btrfs_ioctl_trans_resv_start resv;
+    resv.bytes = bytes;
+    resv.ops = ops;
+    r = ::ioctl(fd, BTRFS_IOC_TRANS_RESV_START, (unsigned long)&resv);
+  } else {
+    r = ::ioctl(fd, BTRFS_IOC_TRANS_START);
+  }
+  if (r < 0) {
     derr(0) << "transaction_start got " << strerror_r(errno, buf, sizeof(buf))
            << " from btrfs ioctl" << dendl;    
     ::close(fd);
index 01c891dd63ebcbb1fe90062967f4d67f70649273..1372d9ca6976e94c2fd270fe9b3f28849742d1dd 100644 (file)
@@ -38,6 +38,7 @@ class FileStore : public JournalingObjectStore {
   __u64 fsid;
   
   int btrfs;
+  bool btrfs_trans_resv_start;
   bool btrfs_trans_start_end;
   int fsid_fd, op_fd;
 
@@ -80,7 +81,7 @@ class FileStore : public JournalingObjectStore {
  public:
   FileStore(const char *base, const char *jdev = 0) : 
     basedir(base), journalpath(jdev ? jdev:""),
-    btrfs(false), btrfs_trans_start_end(false),
+    btrfs(false), btrfs_trans_resv_start(false), btrfs_trans_start_end(false),
     fsid_fd(-1), op_fd(-1),
     attrs(this), fake_attrs(false), 
     collections(this), fake_collections(false),
@@ -95,7 +96,7 @@ class FileStore : public JournalingObjectStore {
 
   unsigned apply_transaction(Transaction& t, Context *onjournal=0, Context *ondisk=0);
   unsigned apply_transactions(list<Transaction*>& tls, Context *onjournal=0, Context *ondisk=0);
-  int _transaction_start(int len);
+  int _transaction_start(__u64 bytes, __u64 ops);
   void _transaction_finish(int id);
   unsigned _apply_transaction(Transaction& t);
 
index 725ed8da3549285eb461da3c168e1631339a8924..cb641cd5b562d027cbc2c6ea751e934b30efc7d9 100644 (file)
@@ -128,13 +128,13 @@ public:
     int get_btrfs_len() { return blen; }
     */
 
-    __u64 disk_space_required() {
+    __u64 get_num_bytes() {
       // be conservative!
       __u64 s = 16384 +
        (ops.size() + oids.size() + cids.size() + lengths.size()) * 4096;
       for (vector<bufferlist>::iterator p = bls.begin(); p != bls.end(); p++)
        s += bls.size() + 4096;
-      return s;      
+      return s;
     }
 
     bool empty() {