summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSage Weil <sage@inktank.com>2013-10-02 10:51:29 -0700
committerSage Weil <sage@inktank.com>2013-10-02 10:51:29 -0700
commit348890232d590d656162f3d7c0a85742f3cf1760 (patch)
tree9add931ab9e630acd0917af37b10e8003cb905e5
parentb822373afdfe8064f7b9a91c426749662fe4f6ce (diff)
parent8835ef8f9833b250e8d09716f683893073db5306 (diff)
downloadceph-348890232d590d656162f3d7c0a85742f3cf1760.tar.gz
Merge pull request #649 from ceph/wip-6422
#6422 Reviewed-by: Sage Weil <sage@inktank.com>
-rw-r--r--src/common/safe_io.c80
-rw-r--r--src/common/safe_io.h9
-rw-r--r--src/os/FileStore.cc68
-rw-r--r--src/os/ObjectStore.cc9
-rw-r--r--src/osd/OSD.cc100
-rw-r--r--src/osd/OSD.h4
6 files changed, 119 insertions, 151 deletions
diff --git a/src/common/safe_io.c b/src/common/safe_io.c
index ac99db04ad3..afee82edf07 100644
--- a/src/common/safe_io.c
+++ b/src/common/safe_io.c
@@ -14,8 +14,12 @@
#define _XOPEN_SOURCE 500
+#include <stdio.h>
+#include <string.h>
#include <unistd.h>
#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
#include "common/safe_io.h"
@@ -112,3 +116,79 @@ ssize_t safe_pwrite(int fd, const void *buf, size_t count, off_t offset)
}
return 0;
}
+
+int safe_write_file(const char *base, const char *file,
+ const char *val, size_t vallen)
+{
+ int ret;
+ char fn[PATH_MAX];
+ char tmp[PATH_MAX];
+ int fd;
+
+ // does the file already have correct content?
+ char oldval[80];
+ ret = safe_read_file(base, file, oldval, sizeof(oldval));
+ if (ret == (int)vallen && memcmp(oldval, val, vallen) == 0)
+ return 0; // yes.
+
+ snprintf(fn, sizeof(fn), "%s/%s", base, file);
+ snprintf(tmp, sizeof(tmp), "%s/%s.tmp", base, file);
+ fd = open(tmp, O_WRONLY|O_CREAT|O_TRUNC, 0644);
+ if (fd < 0) {
+ ret = errno;
+ return -ret;
+ }
+ ret = safe_write(fd, val, vallen);
+ if (ret) {
+ TEMP_FAILURE_RETRY(close(fd));
+ return ret;
+ }
+
+ ret = fsync(fd);
+ if (ret < 0) ret = -errno;
+ TEMP_FAILURE_RETRY(close(fd));
+ if (ret < 0) {
+ unlink(tmp);
+ return ret;
+ }
+ ret = rename(tmp, fn);
+ if (ret < 0) {
+ ret = -errno;
+ unlink(tmp);
+ return ret;
+ }
+
+ fd = open(base, O_RDONLY);
+ if (fd < 0) {
+ ret = -errno;
+ return ret;
+ }
+ ret = fsync(fd);
+ if (ret < 0) ret = -errno;
+ TEMP_FAILURE_RETRY(close(fd));
+
+ return ret;
+}
+
+int safe_read_file(const char *base, const char *file,
+ char *val, size_t vallen)
+{
+ char fn[PATH_MAX];
+ int fd, len;
+
+ snprintf(fn, sizeof(fn), "%s/%s", base, file);
+ fd = open(fn, O_RDONLY);
+ if (fd < 0) {
+ return -errno;
+ }
+ len = safe_read(fd, val, vallen - 1);
+ if (len < 0) {
+ TEMP_FAILURE_RETRY(close(fd));
+ return len;
+ }
+ // close sometimes returns errors, but only after write()
+ TEMP_FAILURE_RETRY(close(fd));
+
+ val[len] = 0;
+ return len;
+}
diff --git a/src/common/safe_io.h b/src/common/safe_io.h
index 4c2991fe6e8..a4c9bc7a72f 100644
--- a/src/common/safe_io.h
+++ b/src/common/safe_io.h
@@ -45,6 +45,15 @@ extern "C" {
ssize_t safe_pread_exact(int fd, void *buf, size_t count, off_t offset)
WARN_UNUSED_RESULT;
+
+ /*
+ * Safe functions to read and write an entire file.
+ */
+ int safe_write_file(const char *base, const char *file,
+ const char *val, size_t vallen);
+ int safe_read_file(const char *base, const char *file,
+ char *val, size_t vallen);
+
#ifdef __cplusplus
}
#endif
diff --git a/src/os/FileStore.cc b/src/os/FileStore.cc
index a470e63dc1c..cd8a8e50658 100644
--- a/src/os/FileStore.cc
+++ b/src/os/FileStore.cc
@@ -953,43 +953,25 @@ int FileStore::_sanity_check_fs()
int FileStore::write_superblock()
{
- char fn[PATH_MAX];
- snprintf(fn, sizeof(fn), "%s/superblock", basedir.c_str());
- int fd = ::open(fn, O_WRONLY|O_CREAT|O_TRUNC, 0644);
- if (fd < 0)
- return -errno;
bufferlist bl;
::encode(superblock, bl);
-
- int ret = safe_write(fd, bl.c_str(), bl.length());
- if (ret < 0)
- goto out;
- ret = ::fsync(fd);
- if (ret < 0)
- ret = -errno;
- // XXX: fsync() man page says I need to sync containing directory
-out:
- TEMP_FAILURE_RETRY(::close(fd));
- return ret;
+ return safe_write_file(basedir.c_str(), "superblock",
+ bl.c_str(), bl.length());
}
int FileStore::read_superblock()
{
- char fn[PATH_MAX];
- snprintf(fn, sizeof(fn), "%s/superblock", basedir.c_str());
- int fd = ::open(fn, O_RDONLY, 0644);
- if (fd < 0) {
- if (errno == ENOENT) {
+ bufferptr bp(PATH_MAX);
+ int ret = safe_read_file(basedir.c_str(), "superblock",
+ bp.c_str(), bp.length());
+ if (ret < 0) {
+ if (ret == -ENOENT) {
// If the file doesn't exist write initial CompatSet
return write_superblock();
- } else
- return -errno;
- }
- bufferptr bp(PATH_MAX);
- int ret = safe_read(fd, bp.c_str(), bp.length());
- TEMP_FAILURE_RETRY(::close(fd));
- if (ret < 0)
+ }
return ret;
+ }
+
bufferlist bl;
bl.push_back(bp);
bufferlist::iterator i = bl.begin();
@@ -1019,20 +1001,14 @@ int FileStore::update_version_stamp()
int FileStore::version_stamp_is_valid(uint32_t *version)
{
- char fn[PATH_MAX];
- snprintf(fn, sizeof(fn), "%s/store_version", basedir.c_str());
- int fd = ::open(fn, O_RDONLY, 0644);
- if (fd < 0) {
- if (errno == ENOENT)
- return 0;
- else
- return -errno;
- }
bufferptr bp(PATH_MAX);
- int ret = safe_read(fd, bp.c_str(), bp.length());
- TEMP_FAILURE_RETRY(::close(fd));
- if (ret < 0)
+ int ret = safe_read_file(basedir.c_str(), "store_version",
+ bp.c_str(), bp.length());
+ if (ret < 0) {
+ if (ret == -ENOENT)
+ return 0;
return ret;
+ }
bufferlist bl;
bl.push_back(bp);
bufferlist::iterator i = bl.begin();
@@ -1045,17 +1021,11 @@ int FileStore::version_stamp_is_valid(uint32_t *version)
int FileStore::write_version_stamp()
{
- char fn[PATH_MAX];
- snprintf(fn, sizeof(fn), "%s/store_version", basedir.c_str());
- int fd = ::open(fn, O_WRONLY|O_CREAT|O_TRUNC, 0644);
- if (fd < 0)
- return -errno;
bufferlist bl;
::encode(target_version, bl);
-
- int ret = safe_write(fd, bl.c_str(), bl.length());
- TEMP_FAILURE_RETRY(::close(fd));
- return ret;
+
+ return safe_write_file(basedir.c_str(), "store_version",
+ bl.c_str(), bl.length());
}
int FileStore::read_op_seq(uint64_t *seq)
diff --git a/src/os/ObjectStore.cc b/src/os/ObjectStore.cc
index 84549821aff..1a1bbcb0b67 100644
--- a/src/os/ObjectStore.cc
+++ b/src/os/ObjectStore.cc
@@ -501,8 +501,7 @@ void ObjectStore::Transaction::generate_test_instances(list<ObjectStore::Transac
int ObjectStore::collection_list(coll_t c, vector<hobject_t>& o)
{
vector<ghobject_t> go;
- FileStore *fs = dynamic_cast<FileStore * >(this);
- int ret = fs->collection_list(c, go);
+ int ret = collection_list(c, go);
if (ret == 0) {
o.reserve(go.size());
for (vector<ghobject_t>::iterator i = go.begin(); i != go.end() ; i++)
@@ -517,8 +516,7 @@ int ObjectStore::collection_list_partial(coll_t c, hobject_t start,
{
vector<ghobject_t> go;
ghobject_t gnext, gstart(start);
- FileStore *fs = dynamic_cast<FileStore * >(this);
- int ret = fs->collection_list_partial(c, gstart, min, max, snap, &go, &gnext);
+ int ret = collection_list_partial(c, gstart, min, max, snap, &go, &gnext);
if (ret == 0) {
*next = gnext.hobj;
ls->reserve(go.size());
@@ -533,8 +531,7 @@ int ObjectStore::collection_list_range(coll_t c, hobject_t start, hobject_t end,
{
vector<ghobject_t> go;
ghobject_t gstart(start), gend(end);
- FileStore *fs = dynamic_cast<FileStore * >(this);
- int ret = fs->collection_list_range(c, gstart, gend, seq, &go);
+ int ret = collection_list_range(c, gstart, gend, seq, &go);
if (ret == 0) {
ls->reserve(go.size());
for (vector<ghobject_t>::iterator i = go.begin(); i != go.end() ; i++)
diff --git a/src/osd/OSD.cc b/src/osd/OSD.cc
index 22366b0baca..8ce11bb558c 100644
--- a/src/osd/OSD.cc
+++ b/src/osd/OSD.cc
@@ -713,7 +713,7 @@ int OSD::mkfs(CephContext *cct, const std::string &dev, const std::string &jdev,
goto umount_store;
}
- ret = write_meta(dev, "ready", "ready\n", 6);
+ ret = safe_write_file(dev.c_str(), "ready", "ready\n", 6);
if (ret) {
derr << "OSD::mkfs: failed to write ready file: error " << ret << dendl;
goto umount_store;
@@ -769,103 +769,19 @@ int OSD::dump_journal(CephContext *cct, const std::string &dev, const std::strin
return err;
}
-int OSD::write_meta(const std::string &base, const std::string &file,
- const char *val, size_t vallen)
-{
- int ret;
- char fn[PATH_MAX];
- char tmp[PATH_MAX];
- int fd;
-
- // does the file already have correct content?
- char oldval[80];
- ret = read_meta(base, file, oldval, sizeof(oldval));
- if (ret == (int)vallen && memcmp(oldval, val, vallen) == 0)
- return 0; // yes.
-
- snprintf(fn, sizeof(fn), "%s/%s", base.c_str(), file.c_str());
- snprintf(tmp, sizeof(tmp), "%s/%s.tmp", base.c_str(), file.c_str());
- fd = ::open(tmp, O_WRONLY|O_CREAT|O_TRUNC, 0644);
- if (fd < 0) {
- ret = errno;
- derr << "write_meta: error opening '" << tmp << "': "
- << cpp_strerror(ret) << dendl;
- return -ret;
- }
- ret = safe_write(fd, val, vallen);
- if (ret) {
- derr << "write_meta: failed to write to '" << tmp << "': "
- << cpp_strerror(ret) << dendl;
- TEMP_FAILURE_RETRY(::close(fd));
- return ret;
- }
-
- ret = ::fsync(fd);
- TEMP_FAILURE_RETRY(::close(fd));
- if (ret) {
- ::unlink(tmp);
- derr << "write_meta: failed to fsync to '" << tmp << "': "
- << cpp_strerror(ret) << dendl;
- return ret;
- }
- ret = ::rename(tmp, fn);
- if (ret) {
- ::unlink(tmp);
- derr << "write_meta: failed to rename '" << tmp << "' to '" << fn << "': "
- << cpp_strerror(ret) << dendl;
- return ret;
- }
-
- fd = ::open(base.c_str(), O_RDONLY);
- if (fd < 0) {
- ret = errno;
- derr << "write_meta: failed to open dir '" << base << "': "
- << cpp_strerror(ret) << dendl;
- return -ret;
- }
- ::fsync(fd);
- TEMP_FAILURE_RETRY(::close(fd));
-
- return 0;
-}
-
-int OSD::read_meta(const std::string &base, const std::string &file,
- char *val, size_t vallen)
-{
- char fn[PATH_MAX];
- int fd, len;
-
- snprintf(fn, sizeof(fn), "%s/%s", base.c_str(), file.c_str());
- fd = ::open(fn, O_RDONLY);
- if (fd < 0) {
- int err = errno;
- return -err;
- }
- len = safe_read(fd, val, vallen);
- if (len < 0) {
- TEMP_FAILURE_RETRY(::close(fd));
- return len;
- }
- // close sometimes returns errors, but only after write()
- TEMP_FAILURE_RETRY(::close(fd));
-
- val[len] = 0;
- return len;
-}
-
int OSD::write_meta(const std::string &base, uuid_d& cluster_fsid, uuid_d& osd_fsid, int whoami)
{
char val[80];
snprintf(val, sizeof(val), "%s\n", CEPH_OSD_ONDISK_MAGIC);
- write_meta(base, "magic", val, strlen(val));
+ safe_write_file(base.c_str(), "magic", val, strlen(val));
snprintf(val, sizeof(val), "%d\n", whoami);
- write_meta(base, "whoami", val, strlen(val));
+ safe_write_file(base.c_str(), "whoami", val, strlen(val));
cluster_fsid.print(val);
strcat(val, "\n");
- write_meta(base, "ceph_fsid", val, strlen(val));
+ safe_write_file(base.c_str(), "ceph_fsid", val, strlen(val));
return 0;
}
@@ -875,24 +791,24 @@ int OSD::peek_meta(const std::string &dev, std::string& magic,
{
char val[80] = { 0 };
- if (read_meta(dev, "magic", val, sizeof(val)) < 0)
+ if (safe_read_file(dev.c_str(), "magic", val, sizeof(val)) < 0)
return -errno;
int l = strlen(val);
if (l && val[l-1] == '\n')
val[l-1] = 0;
magic = val;
- if (read_meta(dev, "whoami", val, sizeof(val)) < 0)
+ if (safe_read_file(dev.c_str(), "whoami", val, sizeof(val)) < 0)
return -errno;
whoami = atoi(val);
- if (read_meta(dev, "ceph_fsid", val, sizeof(val)) < 0)
+ if (safe_read_file(dev.c_str(), "ceph_fsid", val, sizeof(val)) < 0)
return -errno;
if (strlen(val) > 36)
val[36] = 0;
cluster_fsid.parse(val);
- if (read_meta(dev, "fsid", val, sizeof(val)) < 0)
+ if (safe_read_file(dev.c_str(), "fsid", val, sizeof(val)) < 0)
osd_fsid = uuid_d();
else {
if (strlen(val) > 36)
diff --git a/src/osd/OSD.h b/src/osd/OSD.h
index 5fe667344a9..9346cee6890 100644
--- a/src/osd/OSD.h
+++ b/src/osd/OSD.h
@@ -1738,10 +1738,6 @@ protected:
}
private:
- static int write_meta(const std::string &base, const std::string &file,
- const char *val, size_t vallen);
- static int read_meta(const std::string &base, const std::string &file,
- char *val, size_t vallen);
static int write_meta(const std::string &base,
uuid_d& cluster_fsid, uuid_d& osd_fsid, int whoami);
public: