aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ocfs2
diff options
context:
space:
mode:
authorJoel Becker <joel.becker@oracle.com>2009-09-01 21:38:27 -0400
committerJoel Becker <joel.becker@oracle.com>2010-02-26 18:41:13 -0500
commit399ff3a748cf4c8c853e96dd477153202636527b (patch)
tree3efa6c08015a3cc0348b821b39573c7a66ef3c9f /fs/ocfs2
parent139ffacebf5fe2cd9e2ae40d325a9661a679ad4f (diff)
ocfs2: Handle errors while setting external xattr values.
ocfs2 can store extended attribute values as large as a single file. It does this using a standard ocfs2 btree for the large value. However, the previous code did not handle all error cases cleanly. There are multiple problems to have. 1) We have trouble allocating space for a new xattr. This leaves us with an empty xattr. 2) We overwrote an existing local xattr with a value root, and now we have an error allocating the storage. This leaves us an empty xattr. where there used to be a value. The value is lost. 3) We have trouble truncating a reused value. This leaves us with the original entry pointing to the truncated original value. The value is lost. 4) We have trouble extending the storage on a reused value. This leaves us with the original value safely in place, but with more storage allocated when needed. This doesn't consider storing local xattrs (values that don't require a btree). Those only fail when the journal fails. Case (1) is easy. We just remove the xattr we added. We leak the storage because we can't safely remove it, but otherwise everything is happy. We'll print a warning about the leak. Case (4) is easy. We still have the original value in place. We can just leave the extra storage attached to this xattr. We return the error, but the old value is untouched. We print a warning about the storage. Case (2) and (3) are hard because we've lost the original values. In the old code, we ended up with values that could be partially read. That's not good. Instead, we just wipe the xattr entry and leak the storage. It stinks that the original value is lost, but now there isn't a partial value to be read. We'll print a big fat warning. Signed-off-by: Joel Becker <joel.becker@oracle.com>
Diffstat (limited to 'fs/ocfs2')
-rw-r--r--fs/ocfs2/xattr.c140
1 files changed, 124 insertions, 16 deletions
diff --git a/fs/ocfs2/xattr.c b/fs/ocfs2/xattr.c
index a2d912a92dd7..d1b0d386f6d1 100644
--- a/fs/ocfs2/xattr.c
+++ b/fs/ocfs2/xattr.c
@@ -1869,6 +1869,17 @@ static const struct ocfs2_xa_loc_operations ocfs2_xa_bucket_loc_ops = {
1869 .xlo_fill_value_buf = ocfs2_xa_bucket_fill_value_buf, 1869 .xlo_fill_value_buf = ocfs2_xa_bucket_fill_value_buf,
1870}; 1870};
1871 1871
1872static unsigned int ocfs2_xa_value_clusters(struct ocfs2_xa_loc *loc)
1873{
1874 struct ocfs2_xattr_value_buf vb;
1875
1876 if (ocfs2_xattr_is_local(loc->xl_entry))
1877 return 0;
1878
1879 ocfs2_xa_fill_value_buf(loc, &vb);
1880 return le32_to_cpu(vb.vb_xv->xr_clusters);
1881}
1882
1872static int ocfs2_xa_value_truncate(struct ocfs2_xa_loc *loc, u64 bytes, 1883static int ocfs2_xa_value_truncate(struct ocfs2_xa_loc *loc, u64 bytes,
1873 struct ocfs2_xattr_set_ctxt *ctxt) 1884 struct ocfs2_xattr_set_ctxt *ctxt)
1874{ 1885{
@@ -1923,16 +1934,85 @@ static void ocfs2_xa_remove_entry(struct ocfs2_xa_loc *loc)
1923 } 1934 }
1924} 1935}
1925 1936
1937/*
1938 * If we have a problem adjusting the size of an external value during
1939 * ocfs2_xa_prepare_entry() or ocfs2_xa_remove(), we may have an xattr
1940 * in an intermediate state. For example, the value may be partially
1941 * truncated.
1942 *
1943 * If the value tree hasn't changed, the extend/truncate went nowhere.
1944 * We have nothing to do. The caller can treat it as a straight error.
1945 *
1946 * If the value tree got partially truncated, we now have a corrupted
1947 * extended attribute. We're going to wipe its entry and leak the
1948 * clusters. Better to leak some storage than leave a corrupt entry.
1949 *
1950 * If the value tree grew, it obviously didn't grow enough for the
1951 * new entry. We're not going to try and reclaim those clusters either.
1952 * If there was already an external value there (orig_clusters != 0),
1953 * the new clusters are attached safely and we can just leave the old
1954 * value in place. If there was no external value there, we remove
1955 * the entry.
1956 *
1957 * This way, the xattr block we store in the journal will be consistent.
1958 * If the size change broke because of the journal, no changes will hit
1959 * disk anyway.
1960 */
1961static void ocfs2_xa_cleanup_value_truncate(struct ocfs2_xa_loc *loc,
1962 const char *what,
1963 unsigned int orig_clusters)
1964{
1965 unsigned int new_clusters = ocfs2_xa_value_clusters(loc);
1966 char *nameval_buf = ocfs2_xa_offset_pointer(loc,
1967 le16_to_cpu(loc->xl_entry->xe_name_offset));
1968
1969 if (new_clusters < orig_clusters) {
1970 mlog(ML_ERROR,
1971 "Partial truncate while %s xattr %.*s. Leaking "
1972 "%u clusters and removing the entry\n",
1973 what, loc->xl_entry->xe_name_len, nameval_buf,
1974 orig_clusters - new_clusters);
1975 ocfs2_xa_remove_entry(loc);
1976 } else if (!orig_clusters) {
1977 mlog(ML_ERROR,
1978 "Unable to allocate an external value for xattr "
1979 "%.*s safely. Leaking %u clusters and removing the "
1980 "entry\n",
1981 loc->xl_entry->xe_name_len, nameval_buf,
1982 new_clusters - orig_clusters);
1983 ocfs2_xa_remove_entry(loc);
1984 } else if (new_clusters > orig_clusters)
1985 mlog(ML_ERROR,
1986 "Unable to grow xattr %.*s safely. %u new clusters "
1987 "have been added, but the value will not be "
1988 "modified\n",
1989 loc->xl_entry->xe_name_len, nameval_buf,
1990 new_clusters - orig_clusters);
1991}
1992
1926static int ocfs2_xa_remove(struct ocfs2_xa_loc *loc, 1993static int ocfs2_xa_remove(struct ocfs2_xa_loc *loc,
1927 struct ocfs2_xattr_set_ctxt *ctxt) 1994 struct ocfs2_xattr_set_ctxt *ctxt)
1928{ 1995{
1929 int rc = 0; 1996 int rc = 0;
1997 unsigned int orig_clusters;
1930 1998
1931 if (!ocfs2_xattr_is_local(loc->xl_entry)) { 1999 if (!ocfs2_xattr_is_local(loc->xl_entry)) {
2000 orig_clusters = ocfs2_xa_value_clusters(loc);
1932 rc = ocfs2_xa_value_truncate(loc, 0, ctxt); 2001 rc = ocfs2_xa_value_truncate(loc, 0, ctxt);
1933 if (rc) { 2002 if (rc) {
1934 mlog_errno(rc); 2003 mlog_errno(rc);
1935 goto out; 2004 /*
2005 * Since this is remove, we can return 0 if
2006 * ocfs2_xa_cleanup_value_truncate() is going to
2007 * wipe the entry anyway. So we check the
2008 * cluster count as well.
2009 */
2010 if (orig_clusters != ocfs2_xa_value_clusters(loc))
2011 rc = 0;
2012 ocfs2_xa_cleanup_value_truncate(loc, "removing",
2013 orig_clusters);
2014 if (rc)
2015 goto out;
1936 } 2016 }
1937 } 2017 }
1938 2018
@@ -1963,6 +2043,7 @@ static int ocfs2_xa_reuse_entry(struct ocfs2_xa_loc *loc,
1963{ 2043{
1964 int rc = 0; 2044 int rc = 0;
1965 int name_size = OCFS2_XATTR_SIZE(xi->xi_name_len); 2045 int name_size = OCFS2_XATTR_SIZE(xi->xi_name_len);
2046 unsigned int orig_clusters;
1966 char *nameval_buf; 2047 char *nameval_buf;
1967 int xe_local = ocfs2_xattr_is_local(loc->xl_entry); 2048 int xe_local = ocfs2_xattr_is_local(loc->xl_entry);
1968 int xi_local = xi->xi_value_len <= OCFS2_XATTR_INLINE_SIZE; 2049 int xi_local = xi->xi_value_len <= OCFS2_XATTR_INLINE_SIZE;
@@ -1978,23 +2059,27 @@ static int ocfs2_xa_reuse_entry(struct ocfs2_xa_loc *loc,
1978 if (!xi_local) 2059 if (!xi_local)
1979 ocfs2_xa_install_value_root(loc); 2060 ocfs2_xa_install_value_root(loc);
1980 } else { 2061 } else {
2062 orig_clusters = ocfs2_xa_value_clusters(loc);
1981 if (xi_local) { 2063 if (xi_local) {
1982 rc = ocfs2_xa_value_truncate(loc, 0, ctxt); 2064 rc = ocfs2_xa_value_truncate(loc, 0, ctxt);
1983 if (rc < 0) { 2065 if (rc < 0)
1984 mlog_errno(rc); 2066 mlog_errno(rc);
1985 goto out; 2067 else
1986 } 2068 memset(nameval_buf + name_size, 0,
1987 memset(nameval_buf + name_size, 0, 2069 namevalue_size_xe(loc->xl_entry) -
1988 namevalue_size_xe(loc->xl_entry) - 2070 name_size);
1989 name_size);
1990 } else if (le64_to_cpu(loc->xl_entry->xe_value_size) > 2071 } else if (le64_to_cpu(loc->xl_entry->xe_value_size) >
1991 xi->xi_value_len) { 2072 xi->xi_value_len) {
1992 rc = ocfs2_xa_value_truncate(loc, xi->xi_value_len, 2073 rc = ocfs2_xa_value_truncate(loc, xi->xi_value_len,
1993 ctxt); 2074 ctxt);
1994 if (rc < 0) { 2075 if (rc < 0)
1995 mlog_errno(rc); 2076 mlog_errno(rc);
1996 goto out; 2077 }
1997 } 2078
2079 if (rc) {
2080 ocfs2_xa_cleanup_value_truncate(loc, "reusing",
2081 orig_clusters);
2082 goto out;
1998 } 2083 }
1999 } 2084 }
2000 2085
@@ -2019,6 +2104,8 @@ static int ocfs2_xa_prepare_entry(struct ocfs2_xa_loc *loc,
2019 struct ocfs2_xattr_set_ctxt *ctxt) 2104 struct ocfs2_xattr_set_ctxt *ctxt)
2020{ 2105{
2021 int rc = 0; 2106 int rc = 0;
2107 unsigned int orig_clusters;
2108 __le64 orig_value_size = 0;
2022 2109
2023 rc = ocfs2_xa_check_space(loc, xi); 2110 rc = ocfs2_xa_check_space(loc, xi);
2024 if (rc) 2111 if (rc)
@@ -2026,6 +2113,7 @@ static int ocfs2_xa_prepare_entry(struct ocfs2_xa_loc *loc,
2026 2113
2027 if (loc->xl_entry) { 2114 if (loc->xl_entry) {
2028 if (ocfs2_xa_can_reuse_entry(loc, xi)) { 2115 if (ocfs2_xa_can_reuse_entry(loc, xi)) {
2116 orig_value_size = loc->xl_entry->xe_value_size;
2029 rc = ocfs2_xa_reuse_entry(loc, xi, ctxt); 2117 rc = ocfs2_xa_reuse_entry(loc, xi, ctxt);
2030 if (rc) 2118 if (rc)
2031 goto out; 2119 goto out;
@@ -2033,9 +2121,13 @@ static int ocfs2_xa_prepare_entry(struct ocfs2_xa_loc *loc,
2033 } 2121 }
2034 2122
2035 if (!ocfs2_xattr_is_local(loc->xl_entry)) { 2123 if (!ocfs2_xattr_is_local(loc->xl_entry)) {
2124 orig_clusters = ocfs2_xa_value_clusters(loc);
2036 rc = ocfs2_xa_value_truncate(loc, 0, ctxt); 2125 rc = ocfs2_xa_value_truncate(loc, 0, ctxt);
2037 if (rc) { 2126 if (rc) {
2038 mlog_errno(rc); 2127 mlog_errno(rc);
2128 ocfs2_xa_cleanup_value_truncate(loc,
2129 "overwriting",
2130 orig_clusters);
2039 goto out; 2131 goto out;
2040 } 2132 }
2041 } 2133 }
@@ -2053,9 +2145,20 @@ static int ocfs2_xa_prepare_entry(struct ocfs2_xa_loc *loc,
2053 2145
2054alloc_value: 2146alloc_value:
2055 if (xi->xi_value_len > OCFS2_XATTR_INLINE_SIZE) { 2147 if (xi->xi_value_len > OCFS2_XATTR_INLINE_SIZE) {
2148 orig_clusters = ocfs2_xa_value_clusters(loc);
2056 rc = ocfs2_xa_value_truncate(loc, xi->xi_value_len, ctxt); 2149 rc = ocfs2_xa_value_truncate(loc, xi->xi_value_len, ctxt);
2057 if (rc < 0) 2150 if (rc < 0) {
2151 /*
2152 * If we tried to grow an existing external value,
2153 * ocfs2_xa_cleanuP-value_truncate() is going to
2154 * let it stand. We have to restore its original
2155 * value size.
2156 */
2157 loc->xl_entry->xe_value_size = orig_value_size;
2158 ocfs2_xa_cleanup_value_truncate(loc, "growing",
2159 orig_clusters);
2058 mlog_errno(rc); 2160 mlog_errno(rc);
2161 }
2059 } 2162 }
2060 2163
2061out: 2164out:
@@ -2105,25 +2208,30 @@ static int ocfs2_xa_set(struct ocfs2_xa_loc *loc,
2105 goto out; 2208 goto out;
2106 } 2209 }
2107 2210
2211 /*
2212 * From here on out, everything is going to modify the buffer a
2213 * little. Errors are going to leave the xattr header in a
2214 * sane state. Thus, even with errors we dirty the sucker.
2215 */
2216
2108 /* Don't worry, we are never called with !xi_value and !xl_entry */ 2217 /* Don't worry, we are never called with !xi_value and !xl_entry */
2109 if (!xi->xi_value) { 2218 if (!xi->xi_value) {
2110 ret = ocfs2_xa_remove(loc, ctxt); 2219 ret = ocfs2_xa_remove(loc, ctxt);
2111 goto out; 2220 goto out_dirty;
2112 } 2221 }
2113 2222
2114 ret = ocfs2_xa_prepare_entry(loc, xi, name_hash, ctxt); 2223 ret = ocfs2_xa_prepare_entry(loc, xi, name_hash, ctxt);
2115 if (ret) { 2224 if (ret) {
2116 if (ret != -ENOSPC) 2225 if (ret != -ENOSPC)
2117 mlog_errno(ret); 2226 mlog_errno(ret);
2118 goto out; 2227 goto out_dirty;
2119 } 2228 }
2120 2229
2121 ret = ocfs2_xa_store_value(loc, xi, ctxt); 2230 ret = ocfs2_xa_store_value(loc, xi, ctxt);
2122 if (ret) { 2231 if (ret)
2123 mlog_errno(ret); 2232 mlog_errno(ret);
2124 goto out;
2125 }
2126 2233
2234out_dirty:
2127 ocfs2_xa_journal_dirty(ctxt->handle, loc); 2235 ocfs2_xa_journal_dirty(ctxt->handle, loc);
2128 2236
2129out: 2237out: