diff options
Diffstat (limited to 'fs/ocfs2/xattr.c')
| -rw-r--r-- | fs/ocfs2/xattr.c | 661 |
1 files changed, 186 insertions, 475 deletions
diff --git a/fs/ocfs2/xattr.c b/fs/ocfs2/xattr.c index fbec11610223..550a3e86c971 100644 --- a/fs/ocfs2/xattr.c +++ b/fs/ocfs2/xattr.c | |||
| @@ -573,24 +573,6 @@ static u32 ocfs2_xattr_name_hash(struct inode *inode, | |||
| 573 | return hash; | 573 | return hash; |
| 574 | } | 574 | } |
| 575 | 575 | ||
| 576 | /* | ||
| 577 | * ocfs2_xattr_hash_entry() | ||
| 578 | * | ||
| 579 | * Compute the hash of an extended attribute. | ||
| 580 | */ | ||
| 581 | static void ocfs2_xattr_hash_entry(struct inode *inode, | ||
| 582 | struct ocfs2_xattr_header *header, | ||
| 583 | struct ocfs2_xattr_entry *entry) | ||
| 584 | { | ||
| 585 | u32 hash = 0; | ||
| 586 | char *name = (char *)header + le16_to_cpu(entry->xe_name_offset); | ||
| 587 | |||
| 588 | hash = ocfs2_xattr_name_hash(inode, name, entry->xe_name_len); | ||
| 589 | entry->xe_name_hash = cpu_to_le32(hash); | ||
| 590 | |||
| 591 | return; | ||
| 592 | } | ||
| 593 | |||
| 594 | static int ocfs2_xattr_entry_real_size(int name_len, size_t value_len) | 576 | static int ocfs2_xattr_entry_real_size(int name_len, size_t value_len) |
| 595 | { | 577 | { |
| 596 | return namevalue_size(name_len, value_len) + | 578 | return namevalue_size(name_len, value_len) + |
| @@ -1423,113 +1405,6 @@ out: | |||
| 1423 | return ret; | 1405 | return ret; |
| 1424 | } | 1406 | } |
| 1425 | 1407 | ||
| 1426 | static int ocfs2_xattr_cleanup(struct inode *inode, | ||
| 1427 | handle_t *handle, | ||
| 1428 | struct ocfs2_xattr_info *xi, | ||
| 1429 | struct ocfs2_xattr_search *xs, | ||
| 1430 | struct ocfs2_xattr_value_buf *vb, | ||
| 1431 | size_t offs) | ||
| 1432 | { | ||
| 1433 | int ret = 0; | ||
| 1434 | void *val = xs->base + offs; | ||
| 1435 | size_t size = namevalue_size_xi(xi); | ||
| 1436 | |||
| 1437 | ret = vb->vb_access(handle, INODE_CACHE(inode), vb->vb_bh, | ||
| 1438 | OCFS2_JOURNAL_ACCESS_WRITE); | ||
| 1439 | if (ret) { | ||
| 1440 | mlog_errno(ret); | ||
| 1441 | goto out; | ||
| 1442 | } | ||
| 1443 | /* Decrease xattr count */ | ||
| 1444 | le16_add_cpu(&xs->header->xh_count, -1); | ||
| 1445 | /* Remove the xattr entry and tree root which has already be set*/ | ||
| 1446 | memset((void *)xs->here, 0, sizeof(struct ocfs2_xattr_entry)); | ||
| 1447 | memset(val, 0, size); | ||
| 1448 | |||
| 1449 | ret = ocfs2_journal_dirty(handle, vb->vb_bh); | ||
| 1450 | if (ret < 0) | ||
| 1451 | mlog_errno(ret); | ||
| 1452 | out: | ||
| 1453 | return ret; | ||
| 1454 | } | ||
| 1455 | |||
| 1456 | static int ocfs2_xattr_update_entry(struct inode *inode, | ||
| 1457 | handle_t *handle, | ||
| 1458 | struct ocfs2_xattr_info *xi, | ||
| 1459 | struct ocfs2_xattr_search *xs, | ||
| 1460 | struct ocfs2_xattr_value_buf *vb, | ||
| 1461 | size_t offs) | ||
| 1462 | { | ||
| 1463 | int ret; | ||
| 1464 | |||
| 1465 | ret = vb->vb_access(handle, INODE_CACHE(inode), vb->vb_bh, | ||
| 1466 | OCFS2_JOURNAL_ACCESS_WRITE); | ||
| 1467 | if (ret) { | ||
| 1468 | mlog_errno(ret); | ||
| 1469 | goto out; | ||
| 1470 | } | ||
| 1471 | |||
| 1472 | xs->here->xe_name_offset = cpu_to_le16(offs); | ||
| 1473 | xs->here->xe_value_size = cpu_to_le64(xi->xi_value_len); | ||
| 1474 | if (xi->xi_value_len <= OCFS2_XATTR_INLINE_SIZE) | ||
| 1475 | ocfs2_xattr_set_local(xs->here, 1); | ||
| 1476 | else | ||
| 1477 | ocfs2_xattr_set_local(xs->here, 0); | ||
| 1478 | ocfs2_xattr_hash_entry(inode, xs->header, xs->here); | ||
| 1479 | |||
| 1480 | ret = ocfs2_journal_dirty(handle, vb->vb_bh); | ||
| 1481 | if (ret < 0) | ||
| 1482 | mlog_errno(ret); | ||
| 1483 | out: | ||
| 1484 | return ret; | ||
| 1485 | } | ||
| 1486 | |||
| 1487 | /* | ||
| 1488 | * ocfs2_xattr_set_value_outside() | ||
| 1489 | * | ||
| 1490 | * Set large size value in B tree. | ||
| 1491 | */ | ||
| 1492 | static int ocfs2_xattr_set_value_outside(struct inode *inode, | ||
| 1493 | struct ocfs2_xattr_info *xi, | ||
| 1494 | struct ocfs2_xattr_search *xs, | ||
| 1495 | struct ocfs2_xattr_set_ctxt *ctxt, | ||
| 1496 | struct ocfs2_xattr_value_buf *vb, | ||
| 1497 | size_t offs) | ||
| 1498 | { | ||
| 1499 | void *val = xs->base + offs; | ||
| 1500 | struct ocfs2_xattr_value_root *xv = NULL; | ||
| 1501 | size_t size = namevalue_size_xi(xi); | ||
| 1502 | int ret = 0; | ||
| 1503 | |||
| 1504 | memset(val, 0, size); | ||
| 1505 | memcpy(val, xi->xi_name, xi->xi_name_len); | ||
| 1506 | xv = (struct ocfs2_xattr_value_root *) | ||
| 1507 | (val + OCFS2_XATTR_SIZE(xi->xi_name_len)); | ||
| 1508 | xv->xr_clusters = 0; | ||
| 1509 | xv->xr_last_eb_blk = 0; | ||
| 1510 | xv->xr_list.l_tree_depth = 0; | ||
| 1511 | xv->xr_list.l_count = cpu_to_le16(1); | ||
| 1512 | xv->xr_list.l_next_free_rec = 0; | ||
| 1513 | vb->vb_xv = xv; | ||
| 1514 | |||
| 1515 | ret = ocfs2_xattr_value_truncate(inode, vb, xi->xi_value_len, ctxt); | ||
| 1516 | if (ret < 0) { | ||
| 1517 | mlog_errno(ret); | ||
| 1518 | return ret; | ||
| 1519 | } | ||
| 1520 | ret = ocfs2_xattr_update_entry(inode, ctxt->handle, xi, xs, vb, offs); | ||
| 1521 | if (ret < 0) { | ||
| 1522 | mlog_errno(ret); | ||
| 1523 | return ret; | ||
| 1524 | } | ||
| 1525 | ret = __ocfs2_xattr_set_value_outside(inode, ctxt->handle, vb, | ||
| 1526 | xi->xi_value, xi->xi_value_len); | ||
| 1527 | if (ret < 0) | ||
| 1528 | mlog_errno(ret); | ||
| 1529 | |||
| 1530 | return ret; | ||
| 1531 | } | ||
| 1532 | |||
| 1533 | static int ocfs2_xa_check_space_helper(int needed_space, int free_start, | 1408 | static int ocfs2_xa_check_space_helper(int needed_space, int free_start, |
| 1534 | int num_entries) | 1409 | int num_entries) |
| 1535 | { | 1410 | { |
| @@ -1640,6 +1515,7 @@ static void ocfs2_xa_fill_value_buf(struct ocfs2_xa_loc *loc, | |||
| 1640 | int name_size = OCFS2_XATTR_SIZE(loc->xl_entry->xe_name_len); | 1515 | int name_size = OCFS2_XATTR_SIZE(loc->xl_entry->xe_name_len); |
| 1641 | 1516 | ||
| 1642 | /* Value bufs are for value trees */ | 1517 | /* Value bufs are for value trees */ |
| 1518 | BUG_ON(ocfs2_xattr_is_local(loc->xl_entry)); | ||
| 1643 | BUG_ON(namevalue_size_xe(loc->xl_entry) != | 1519 | BUG_ON(namevalue_size_xe(loc->xl_entry) != |
| 1644 | (name_size + OCFS2_XATTR_ROOT_SIZE)); | 1520 | (name_size + OCFS2_XATTR_ROOT_SIZE)); |
| 1645 | 1521 | ||
| @@ -2001,6 +1877,33 @@ static const struct ocfs2_xa_loc_operations ocfs2_xa_bucket_loc_ops = { | |||
| 2001 | .xlo_fill_value_buf = ocfs2_xa_bucket_fill_value_buf, | 1877 | .xlo_fill_value_buf = ocfs2_xa_bucket_fill_value_buf, |
| 2002 | }; | 1878 | }; |
| 2003 | 1879 | ||
| 1880 | static int ocfs2_xa_value_truncate(struct ocfs2_xa_loc *loc, u64 bytes, | ||
| 1881 | struct ocfs2_xattr_set_ctxt *ctxt) | ||
| 1882 | { | ||
| 1883 | int trunc_rc, access_rc; | ||
| 1884 | struct ocfs2_xattr_value_buf vb; | ||
| 1885 | |||
| 1886 | ocfs2_xa_fill_value_buf(loc, &vb); | ||
| 1887 | trunc_rc = ocfs2_xattr_value_truncate(loc->xl_inode, &vb, bytes, | ||
| 1888 | ctxt); | ||
| 1889 | |||
| 1890 | /* | ||
| 1891 | * The caller of ocfs2_xa_value_truncate() has already called | ||
| 1892 | * ocfs2_xa_journal_access on the loc. However, The truncate code | ||
| 1893 | * calls ocfs2_extend_trans(). This may commit the previous | ||
| 1894 | * transaction and open a new one. If this is a bucket, truncate | ||
| 1895 | * could leave only vb->vb_bh set up for journaling. Meanwhile, | ||
| 1896 | * the caller is expecting to dirty the entire bucket. So we must | ||
| 1897 | * reset the journal work. We do this even if truncate has failed, | ||
| 1898 | * as it could have failed after committing the extend. | ||
| 1899 | */ | ||
| 1900 | access_rc = ocfs2_xa_journal_access(ctxt->handle, loc, | ||
| 1901 | OCFS2_JOURNAL_ACCESS_WRITE); | ||
| 1902 | |||
| 1903 | /* Errors in truncate take precedence */ | ||
| 1904 | return trunc_rc ? trunc_rc : access_rc; | ||
| 1905 | } | ||
| 1906 | |||
| 2004 | static void ocfs2_xa_remove_entry(struct ocfs2_xa_loc *loc) | 1907 | static void ocfs2_xa_remove_entry(struct ocfs2_xa_loc *loc) |
| 2005 | { | 1908 | { |
| 2006 | int index, count; | 1909 | int index, count; |
| @@ -2028,6 +1931,88 @@ static void ocfs2_xa_remove_entry(struct ocfs2_xa_loc *loc) | |||
| 2028 | } | 1931 | } |
| 2029 | } | 1932 | } |
| 2030 | 1933 | ||
| 1934 | static int ocfs2_xa_remove(struct ocfs2_xa_loc *loc, | ||
| 1935 | struct ocfs2_xattr_set_ctxt *ctxt) | ||
| 1936 | { | ||
| 1937 | int rc = 0; | ||
| 1938 | |||
| 1939 | if (!ocfs2_xattr_is_local(loc->xl_entry)) { | ||
| 1940 | rc = ocfs2_xa_value_truncate(loc, 0, ctxt); | ||
| 1941 | if (rc) { | ||
| 1942 | mlog_errno(rc); | ||
| 1943 | goto out; | ||
| 1944 | } | ||
| 1945 | } | ||
| 1946 | |||
| 1947 | ocfs2_xa_remove_entry(loc); | ||
| 1948 | |||
| 1949 | out: | ||
| 1950 | return rc; | ||
| 1951 | } | ||
| 1952 | |||
| 1953 | static void ocfs2_xa_install_value_root(struct ocfs2_xa_loc *loc) | ||
| 1954 | { | ||
| 1955 | int name_size = OCFS2_XATTR_SIZE(loc->xl_entry->xe_name_len); | ||
| 1956 | char *nameval_buf; | ||
| 1957 | |||
| 1958 | nameval_buf = ocfs2_xa_offset_pointer(loc, | ||
| 1959 | le16_to_cpu(loc->xl_entry->xe_name_offset)); | ||
| 1960 | memcpy(nameval_buf + name_size, &def_xv, OCFS2_XATTR_ROOT_SIZE); | ||
| 1961 | } | ||
| 1962 | |||
| 1963 | /* | ||
| 1964 | * Take an existing entry and make it ready for the new value. This | ||
| 1965 | * won't allocate space, but it may free space. It should be ready for | ||
| 1966 | * ocfs2_xa_prepare_entry() to finish the work. | ||
| 1967 | */ | ||
| 1968 | static int ocfs2_xa_reuse_entry(struct ocfs2_xa_loc *loc, | ||
| 1969 | struct ocfs2_xattr_info *xi, | ||
| 1970 | struct ocfs2_xattr_set_ctxt *ctxt) | ||
| 1971 | { | ||
| 1972 | int rc = 0; | ||
| 1973 | int name_size = OCFS2_XATTR_SIZE(xi->xi_name_len); | ||
| 1974 | char *nameval_buf; | ||
| 1975 | int xe_local = ocfs2_xattr_is_local(loc->xl_entry); | ||
| 1976 | int xi_local = xi->xi_value_len <= OCFS2_XATTR_INLINE_SIZE; | ||
| 1977 | |||
| 1978 | BUG_ON(OCFS2_XATTR_SIZE(loc->xl_entry->xe_name_len) != | ||
| 1979 | name_size); | ||
| 1980 | |||
| 1981 | nameval_buf = ocfs2_xa_offset_pointer(loc, | ||
| 1982 | le16_to_cpu(loc->xl_entry->xe_name_offset)); | ||
| 1983 | if (xe_local) { | ||
| 1984 | memset(nameval_buf + name_size, 0, | ||
| 1985 | namevalue_size_xe(loc->xl_entry) - name_size); | ||
| 1986 | if (!xi_local) | ||
| 1987 | ocfs2_xa_install_value_root(loc); | ||
| 1988 | } else { | ||
| 1989 | if (xi_local) { | ||
| 1990 | rc = ocfs2_xa_value_truncate(loc, 0, ctxt); | ||
| 1991 | if (rc < 0) { | ||
| 1992 | mlog_errno(rc); | ||
| 1993 | goto out; | ||
| 1994 | } | ||
| 1995 | memset(nameval_buf + name_size, 0, | ||
| 1996 | namevalue_size_xe(loc->xl_entry) - | ||
| 1997 | name_size); | ||
| 1998 | } else if (le64_to_cpu(loc->xl_entry->xe_value_size) > | ||
| 1999 | xi->xi_value_len) { | ||
| 2000 | rc = ocfs2_xa_value_truncate(loc, xi->xi_value_len, | ||
| 2001 | ctxt); | ||
| 2002 | if (rc < 0) { | ||
| 2003 | mlog_errno(rc); | ||
| 2004 | goto out; | ||
| 2005 | } | ||
| 2006 | } | ||
| 2007 | } | ||
| 2008 | |||
| 2009 | loc->xl_entry->xe_value_size = cpu_to_le64(xi->xi_value_len); | ||
| 2010 | ocfs2_xattr_set_local(loc->xl_entry, xi_local); | ||
| 2011 | |||
| 2012 | out: | ||
| 2013 | return rc; | ||
| 2014 | } | ||
| 2015 | |||
| 2031 | /* | 2016 | /* |
| 2032 | * Prepares loc->xl_entry to receive the new xattr. This includes | 2017 | * Prepares loc->xl_entry to receive the new xattr. This includes |
| 2033 | * properly setting up the name+value pair region. If loc->xl_entry | 2018 | * properly setting up the name+value pair region. If loc->xl_entry |
| @@ -2040,14 +2025,13 @@ static void ocfs2_xa_remove_entry(struct ocfs2_xa_loc *loc) | |||
| 2040 | */ | 2025 | */ |
| 2041 | static int ocfs2_xa_prepare_entry(struct ocfs2_xa_loc *loc, | 2026 | static int ocfs2_xa_prepare_entry(struct ocfs2_xa_loc *loc, |
| 2042 | struct ocfs2_xattr_info *xi, | 2027 | struct ocfs2_xattr_info *xi, |
| 2043 | u32 name_hash) | 2028 | u32 name_hash, |
| 2029 | struct ocfs2_xattr_set_ctxt *ctxt) | ||
| 2044 | { | 2030 | { |
| 2045 | int rc = 0; | 2031 | int rc = 0; |
| 2046 | int name_size = OCFS2_XATTR_SIZE(xi->xi_name_len); | ||
| 2047 | char *nameval_buf; | ||
| 2048 | 2032 | ||
| 2049 | if (!xi->xi_value) { | 2033 | if (!xi->xi_value) { |
| 2050 | ocfs2_xa_remove_entry(loc); | 2034 | rc = ocfs2_xa_remove(loc, ctxt); |
| 2051 | goto out; | 2035 | goto out; |
| 2052 | } | 2036 | } |
| 2053 | 2037 | ||
| @@ -2057,15 +2041,19 @@ static int ocfs2_xa_prepare_entry(struct ocfs2_xa_loc *loc, | |||
| 2057 | 2041 | ||
| 2058 | if (loc->xl_entry) { | 2042 | if (loc->xl_entry) { |
| 2059 | if (ocfs2_xa_can_reuse_entry(loc, xi)) { | 2043 | if (ocfs2_xa_can_reuse_entry(loc, xi)) { |
| 2060 | nameval_buf = ocfs2_xa_offset_pointer(loc, | 2044 | rc = ocfs2_xa_reuse_entry(loc, xi, ctxt); |
| 2061 | le16_to_cpu(loc->xl_entry->xe_name_offset)); | 2045 | if (rc) |
| 2062 | memset(nameval_buf + name_size, 0, | 2046 | goto out; |
| 2063 | namevalue_size_xe(loc->xl_entry) - name_size); | 2047 | goto alloc_value; |
| 2064 | loc->xl_entry->xe_value_size = | ||
| 2065 | cpu_to_le64(xi->xi_value_len); | ||
| 2066 | goto out; | ||
| 2067 | } | 2048 | } |
| 2068 | 2049 | ||
| 2050 | if (!ocfs2_xattr_is_local(loc->xl_entry)) { | ||
| 2051 | rc = ocfs2_xa_value_truncate(loc, 0, ctxt); | ||
| 2052 | if (rc) { | ||
| 2053 | mlog_errno(rc); | ||
| 2054 | goto out; | ||
| 2055 | } | ||
| 2056 | } | ||
| 2069 | ocfs2_xa_wipe_namevalue(loc); | 2057 | ocfs2_xa_wipe_namevalue(loc); |
| 2070 | } else | 2058 | } else |
| 2071 | ocfs2_xa_add_entry(loc, name_hash); | 2059 | ocfs2_xa_add_entry(loc, name_hash); |
| @@ -2075,33 +2063,50 @@ static int ocfs2_xa_prepare_entry(struct ocfs2_xa_loc *loc, | |||
| 2075 | * name+value pair back from the end. | 2063 | * name+value pair back from the end. |
| 2076 | */ | 2064 | */ |
| 2077 | ocfs2_xa_add_namevalue(loc, xi); | 2065 | ocfs2_xa_add_namevalue(loc, xi); |
| 2066 | if (xi->xi_value_len > OCFS2_XATTR_INLINE_SIZE) | ||
| 2067 | ocfs2_xa_install_value_root(loc); | ||
| 2068 | |||
| 2069 | alloc_value: | ||
| 2070 | if (xi->xi_value_len > OCFS2_XATTR_INLINE_SIZE) { | ||
| 2071 | rc = ocfs2_xa_value_truncate(loc, xi->xi_value_len, ctxt); | ||
| 2072 | if (rc < 0) | ||
| 2073 | mlog_errno(rc); | ||
| 2074 | } | ||
| 2078 | 2075 | ||
| 2079 | out: | 2076 | out: |
| 2080 | return rc; | 2077 | return rc; |
| 2081 | } | 2078 | } |
| 2082 | 2079 | ||
| 2083 | /* | 2080 | /* |
| 2084 | * Store the value portion of the name+value pair. This is either an | 2081 | * Store the value portion of the name+value pair. This will skip |
| 2085 | * inline value or the tree root of an external value. | 2082 | * values that are stored externally. Their tree roots were set up |
| 2083 | * by ocfs2_xa_prepare_entry(). | ||
| 2086 | */ | 2084 | */ |
| 2087 | static void ocfs2_xa_store_inline_value(struct ocfs2_xa_loc *loc, | 2085 | static int ocfs2_xa_store_value(struct ocfs2_xa_loc *loc, |
| 2088 | struct ocfs2_xattr_info *xi) | 2086 | struct ocfs2_xattr_info *xi, |
| 2087 | struct ocfs2_xattr_set_ctxt *ctxt) | ||
| 2089 | { | 2088 | { |
| 2089 | int rc = 0; | ||
| 2090 | int nameval_offset = le16_to_cpu(loc->xl_entry->xe_name_offset); | 2090 | int nameval_offset = le16_to_cpu(loc->xl_entry->xe_name_offset); |
| 2091 | int name_size = OCFS2_XATTR_SIZE(xi->xi_name_len); | 2091 | int name_size = OCFS2_XATTR_SIZE(xi->xi_name_len); |
| 2092 | int inline_value_size = namevalue_size_xi(xi) - name_size; | ||
| 2093 | const void *value = xi->xi_value; | ||
| 2094 | char *nameval_buf; | 2092 | char *nameval_buf; |
| 2093 | struct ocfs2_xattr_value_buf vb; | ||
| 2095 | 2094 | ||
| 2096 | if (!xi->xi_value) | 2095 | if (!xi->xi_value) |
| 2097 | return; | 2096 | goto out; |
| 2098 | 2097 | ||
| 2099 | if (xi->xi_value_len > OCFS2_XATTR_INLINE_SIZE) { | ||
| 2100 | value = &def_xv; | ||
| 2101 | inline_value_size = OCFS2_XATTR_ROOT_SIZE; | ||
| 2102 | } | ||
| 2103 | nameval_buf = ocfs2_xa_offset_pointer(loc, nameval_offset); | 2098 | nameval_buf = ocfs2_xa_offset_pointer(loc, nameval_offset); |
| 2104 | memcpy(nameval_buf + name_size, value, inline_value_size); | 2099 | if (xi->xi_value_len > OCFS2_XATTR_INLINE_SIZE) { |
| 2100 | ocfs2_xa_fill_value_buf(loc, &vb); | ||
| 2101 | rc = __ocfs2_xattr_set_value_outside(loc->xl_inode, | ||
| 2102 | ctxt->handle, &vb, | ||
| 2103 | xi->xi_value, | ||
| 2104 | xi->xi_value_len); | ||
| 2105 | } else | ||
| 2106 | memcpy(nameval_buf + name_size, xi->xi_value, xi->xi_value_len); | ||
| 2107 | |||
| 2108 | out: | ||
| 2109 | return rc; | ||
| 2105 | } | 2110 | } |
| 2106 | 2111 | ||
| 2107 | static void ocfs2_init_dinode_xa_loc(struct ocfs2_xa_loc *loc, | 2112 | static void ocfs2_init_dinode_xa_loc(struct ocfs2_xa_loc *loc, |
| @@ -2174,117 +2179,19 @@ static int ocfs2_xattr_set_entry(struct inode *inode, | |||
| 2174 | struct ocfs2_xattr_set_ctxt *ctxt, | 2179 | struct ocfs2_xattr_set_ctxt *ctxt, |
| 2175 | int flag) | 2180 | int flag) |
| 2176 | { | 2181 | { |
| 2177 | struct ocfs2_xattr_entry *last; | ||
| 2178 | struct ocfs2_inode_info *oi = OCFS2_I(inode); | 2182 | struct ocfs2_inode_info *oi = OCFS2_I(inode); |
| 2179 | struct ocfs2_dinode *di = (struct ocfs2_dinode *)xs->inode_bh->b_data; | 2183 | struct ocfs2_dinode *di = (struct ocfs2_dinode *)xs->inode_bh->b_data; |
| 2180 | size_t min_offs = xs->end - xs->base; | ||
| 2181 | size_t size_l = 0; | ||
| 2182 | handle_t *handle = ctxt->handle; | 2184 | handle_t *handle = ctxt->handle; |
| 2183 | int free, i, ret; | 2185 | int ret; |
| 2184 | u32 name_hash = ocfs2_xattr_name_hash(inode, xi->xi_name, | 2186 | u32 name_hash = ocfs2_xattr_name_hash(inode, xi->xi_name, |
| 2185 | xi->xi_name_len); | 2187 | xi->xi_name_len); |
| 2186 | struct ocfs2_xa_loc loc; | 2188 | struct ocfs2_xa_loc loc; |
| 2187 | struct ocfs2_xattr_value_buf vb = { | ||
| 2188 | .vb_bh = xs->xattr_bh, | ||
| 2189 | .vb_access = ocfs2_journal_access_di, | ||
| 2190 | }; | ||
| 2191 | 2189 | ||
| 2192 | if (!(flag & OCFS2_INLINE_XATTR_FL)) { | 2190 | if (!(flag & OCFS2_INLINE_XATTR_FL)) |
| 2193 | BUG_ON(xs->xattr_bh == xs->inode_bh); | 2191 | BUG_ON(xs->xattr_bh == xs->inode_bh); |
| 2194 | vb.vb_access = ocfs2_journal_access_xb; | 2192 | else |
| 2195 | } else | ||
| 2196 | BUG_ON(xs->xattr_bh != xs->inode_bh); | 2193 | BUG_ON(xs->xattr_bh != xs->inode_bh); |
| 2197 | 2194 | ||
| 2198 | /* Compute min_offs, last and free space. */ | ||
| 2199 | last = xs->header->xh_entries; | ||
| 2200 | |||
| 2201 | for (i = 0 ; i < le16_to_cpu(xs->header->xh_count); i++) { | ||
| 2202 | size_t offs = le16_to_cpu(last->xe_name_offset); | ||
| 2203 | if (offs < min_offs) | ||
| 2204 | min_offs = offs; | ||
| 2205 | last += 1; | ||
| 2206 | } | ||
| 2207 | |||
| 2208 | free = min_offs - ((void *)last - xs->base) - OCFS2_XATTR_HEADER_GAP; | ||
| 2209 | if (free < 0) | ||
| 2210 | return -EIO; | ||
| 2211 | |||
| 2212 | if (!xs->not_found) | ||
| 2213 | free += ocfs2_xe_entry_usage(xs->here); | ||
| 2214 | |||
| 2215 | /* Check free space in inode or block */ | ||
| 2216 | if (xi->xi_value && (free < ocfs2_xi_entry_usage(xi))) { | ||
| 2217 | ret = -ENOSPC; | ||
| 2218 | goto out; | ||
| 2219 | } | ||
| 2220 | |||
| 2221 | if (!xs->not_found) { | ||
| 2222 | /* For existing extended attribute */ | ||
| 2223 | size_t size = namevalue_size_xe(xs->here); | ||
| 2224 | size_t offs = le16_to_cpu(xs->here->xe_name_offset); | ||
| 2225 | void *val = xs->base + offs; | ||
| 2226 | |||
| 2227 | if (ocfs2_xattr_is_local(xs->here) && size == size_l) { | ||
| 2228 | /* Replace existing local xattr with tree root */ | ||
| 2229 | ret = ocfs2_xattr_set_value_outside(inode, xi, xs, | ||
| 2230 | ctxt, &vb, offs); | ||
| 2231 | if (ret < 0) | ||
| 2232 | mlog_errno(ret); | ||
| 2233 | goto out; | ||
| 2234 | } else if (!ocfs2_xattr_is_local(xs->here)) { | ||
| 2235 | /* For existing xattr which has value outside */ | ||
| 2236 | vb.vb_xv = (struct ocfs2_xattr_value_root *) | ||
| 2237 | (val + OCFS2_XATTR_SIZE(xi->xi_name_len)); | ||
| 2238 | |||
| 2239 | if (xi->xi_value_len > OCFS2_XATTR_INLINE_SIZE) { | ||
| 2240 | /* | ||
| 2241 | * If new value need set outside also, | ||
| 2242 | * first truncate old value to new value, | ||
| 2243 | * then set new value with set_value_outside(). | ||
| 2244 | */ | ||
| 2245 | ret = ocfs2_xattr_value_truncate(inode, | ||
| 2246 | &vb, | ||
| 2247 | xi->xi_value_len, | ||
| 2248 | ctxt); | ||
| 2249 | if (ret < 0) { | ||
| 2250 | mlog_errno(ret); | ||
| 2251 | goto out; | ||
| 2252 | } | ||
| 2253 | |||
| 2254 | ret = ocfs2_xattr_update_entry(inode, | ||
| 2255 | handle, | ||
| 2256 | xi, | ||
| 2257 | xs, | ||
| 2258 | &vb, | ||
| 2259 | offs); | ||
| 2260 | if (ret < 0) { | ||
| 2261 | mlog_errno(ret); | ||
| 2262 | goto out; | ||
| 2263 | } | ||
| 2264 | |||
| 2265 | ret = __ocfs2_xattr_set_value_outside(inode, | ||
| 2266 | handle, | ||
| 2267 | &vb, | ||
| 2268 | xi->xi_value, | ||
| 2269 | xi->xi_value_len); | ||
| 2270 | if (ret < 0) | ||
| 2271 | mlog_errno(ret); | ||
| 2272 | goto out; | ||
| 2273 | } else { | ||
| 2274 | /* | ||
| 2275 | * If new value need set in local, | ||
| 2276 | * just trucate old value to zero. | ||
| 2277 | */ | ||
| 2278 | ret = ocfs2_xattr_value_truncate(inode, | ||
| 2279 | &vb, | ||
| 2280 | 0, | ||
| 2281 | ctxt); | ||
| 2282 | if (ret < 0) | ||
| 2283 | mlog_errno(ret); | ||
| 2284 | } | ||
| 2285 | } | ||
| 2286 | } | ||
| 2287 | |||
| 2288 | ret = ocfs2_journal_access_di(handle, INODE_CACHE(inode), xs->inode_bh, | 2195 | ret = ocfs2_journal_access_di(handle, INODE_CACHE(inode), xs->inode_bh, |
| 2289 | OCFS2_JOURNAL_ACCESS_WRITE); | 2196 | OCFS2_JOURNAL_ACCESS_WRITE); |
| 2290 | if (ret) { | 2197 | if (ret) { |
| @@ -2305,22 +2212,20 @@ static int ocfs2_xattr_set_entry(struct inode *inode, | |||
| 2305 | goto out; | 2212 | goto out; |
| 2306 | } | 2213 | } |
| 2307 | 2214 | ||
| 2308 | /* | 2215 | ret = ocfs2_xa_prepare_entry(&loc, xi, name_hash, ctxt); |
| 2309 | * Prepare our entry and insert the inline value. This will | ||
| 2310 | * be a value tree root for values that are larger than | ||
| 2311 | * OCFS2_XATTR_INLINE_SIZE. | ||
| 2312 | */ | ||
| 2313 | ret = ocfs2_xa_prepare_entry(&loc, xi, name_hash); | ||
| 2314 | if (ret) { | 2216 | if (ret) { |
| 2315 | if (ret != -ENOSPC) | 2217 | if (ret != -ENOSPC) |
| 2316 | mlog_errno(ret); | 2218 | mlog_errno(ret); |
| 2317 | goto out; | 2219 | goto out; |
| 2318 | } | 2220 | } |
| 2319 | /* XXX For now, until we make ocfs2_xa_prepare_entry() primary */ | ||
| 2320 | BUG_ON(ret == -ENOSPC); | ||
| 2321 | ocfs2_xa_store_inline_value(&loc, xi); | ||
| 2322 | xs->here = loc.xl_entry; | 2221 | xs->here = loc.xl_entry; |
| 2323 | 2222 | ||
| 2223 | ret = ocfs2_xa_store_value(&loc, xi, ctxt); | ||
| 2224 | if (ret) { | ||
| 2225 | mlog_errno(ret); | ||
| 2226 | goto out; | ||
| 2227 | } | ||
| 2228 | |||
| 2324 | ocfs2_xa_journal_dirty(handle, &loc); | 2229 | ocfs2_xa_journal_dirty(handle, &loc); |
| 2325 | 2230 | ||
| 2326 | if (!(oi->ip_dyn_features & OCFS2_INLINE_XATTR_FL) && | 2231 | if (!(oi->ip_dyn_features & OCFS2_INLINE_XATTR_FL) && |
| @@ -2352,28 +2257,6 @@ static int ocfs2_xattr_set_entry(struct inode *inode, | |||
| 2352 | if (ret < 0) | 2257 | if (ret < 0) |
| 2353 | mlog_errno(ret); | 2258 | mlog_errno(ret); |
| 2354 | 2259 | ||
| 2355 | if (!ret && xi->xi_value_len > OCFS2_XATTR_INLINE_SIZE) { | ||
| 2356 | /* | ||
| 2357 | * Set value outside in B tree. | ||
| 2358 | * This is the second step for value size > INLINE_SIZE. | ||
| 2359 | */ | ||
| 2360 | size_t offs = le16_to_cpu(xs->here->xe_name_offset); | ||
| 2361 | ret = ocfs2_xattr_set_value_outside(inode, xi, xs, ctxt, | ||
| 2362 | &vb, offs); | ||
| 2363 | if (ret < 0) { | ||
| 2364 | int ret2; | ||
| 2365 | |||
| 2366 | mlog_errno(ret); | ||
| 2367 | /* | ||
| 2368 | * If set value outside failed, we have to clean | ||
| 2369 | * the junk tree root we have already set in local. | ||
| 2370 | */ | ||
| 2371 | ret2 = ocfs2_xattr_cleanup(inode, ctxt->handle, | ||
| 2372 | xi, xs, &vb, offs); | ||
| 2373 | if (ret2 < 0) | ||
| 2374 | mlog_errno(ret2); | ||
| 2375 | } | ||
| 2376 | } | ||
| 2377 | out: | 2260 | out: |
| 2378 | return ret; | 2261 | return ret; |
| 2379 | } | 2262 | } |
| @@ -5354,61 +5237,6 @@ static inline char *ocfs2_xattr_bucket_get_val(struct inode *inode, | |||
| 5354 | } | 5237 | } |
| 5355 | 5238 | ||
| 5356 | /* | 5239 | /* |
| 5357 | * Set the xattr entry in the specified bucket. | ||
| 5358 | * The bucket is indicated by xs->bucket and it should have the enough | ||
| 5359 | * space for the xattr insertion. | ||
| 5360 | */ | ||
| 5361 | static int ocfs2_xattr_set_entry_in_bucket(struct inode *inode, | ||
| 5362 | handle_t *handle, | ||
| 5363 | struct ocfs2_xattr_info *xi, | ||
| 5364 | struct ocfs2_xattr_search *xs, | ||
| 5365 | u32 name_hash) | ||
| 5366 | { | ||
| 5367 | int ret; | ||
| 5368 | u64 blkno; | ||
| 5369 | struct ocfs2_xa_loc loc; | ||
| 5370 | |||
| 5371 | mlog(0, "Set xattr entry len = %lu index = %d in bucket %llu\n", | ||
| 5372 | (unsigned long)xi->xi_value_len, xi->xi_name_index, | ||
| 5373 | (unsigned long long)bucket_blkno(xs->bucket)); | ||
| 5374 | |||
| 5375 | if (!xs->bucket->bu_bhs[1]) { | ||
| 5376 | blkno = bucket_blkno(xs->bucket); | ||
| 5377 | ocfs2_xattr_bucket_relse(xs->bucket); | ||
| 5378 | ret = ocfs2_read_xattr_bucket(xs->bucket, blkno); | ||
| 5379 | if (ret) { | ||
| 5380 | mlog_errno(ret); | ||
| 5381 | goto out; | ||
| 5382 | } | ||
| 5383 | } | ||
| 5384 | |||
| 5385 | ocfs2_init_xattr_bucket_xa_loc(&loc, xs->bucket, | ||
| 5386 | xs->not_found ? NULL : xs->here); | ||
| 5387 | ret = ocfs2_xa_journal_access(handle, &loc, | ||
| 5388 | OCFS2_JOURNAL_ACCESS_WRITE); | ||
| 5389 | if (ret < 0) { | ||
| 5390 | mlog_errno(ret); | ||
| 5391 | goto out; | ||
| 5392 | } | ||
| 5393 | |||
| 5394 | ret = ocfs2_xa_prepare_entry(&loc, xi, name_hash); | ||
| 5395 | if (ret) { | ||
| 5396 | if (ret != -ENOSPC) | ||
| 5397 | mlog_errno(ret); | ||
| 5398 | goto out; | ||
| 5399 | } | ||
| 5400 | /* XXX For now, until we make ocfs2_xa_prepare_entry() primary */ | ||
| 5401 | BUG_ON(ret == -ENOSPC); | ||
| 5402 | ocfs2_xa_store_inline_value(&loc, xi); | ||
| 5403 | xs->here = loc.xl_entry; | ||
| 5404 | |||
| 5405 | ocfs2_xa_journal_dirty(handle, &loc); | ||
| 5406 | |||
| 5407 | out: | ||
| 5408 | return ret; | ||
| 5409 | } | ||
| 5410 | |||
| 5411 | /* | ||
| 5412 | * Truncate the specified xe_off entry in xattr bucket. | 5240 | * Truncate the specified xe_off entry in xattr bucket. |
| 5413 | * bucket is indicated by header_bh and len is the new length. | 5241 | * bucket is indicated by header_bh and len is the new length. |
| 5414 | * Both the ocfs2_xattr_value_root and the entry will be updated here. | 5242 | * Both the ocfs2_xattr_value_root and the entry will be updated here. |
| @@ -5478,66 +5306,6 @@ out: | |||
| 5478 | return ret; | 5306 | return ret; |
| 5479 | } | 5307 | } |
| 5480 | 5308 | ||
| 5481 | static int ocfs2_xattr_bucket_value_truncate_xs(struct inode *inode, | ||
| 5482 | struct ocfs2_xattr_search *xs, | ||
| 5483 | int len, | ||
| 5484 | struct ocfs2_xattr_set_ctxt *ctxt) | ||
| 5485 | { | ||
| 5486 | int ret, offset; | ||
| 5487 | struct ocfs2_xattr_entry *xe = xs->here; | ||
| 5488 | struct ocfs2_xattr_header *xh = (struct ocfs2_xattr_header *)xs->base; | ||
| 5489 | |||
| 5490 | BUG_ON(!xs->bucket->bu_bhs[0] || !xe || ocfs2_xattr_is_local(xe)); | ||
| 5491 | |||
| 5492 | offset = xe - xh->xh_entries; | ||
| 5493 | ret = ocfs2_xattr_bucket_value_truncate(inode, xs->bucket, | ||
| 5494 | offset, len, ctxt); | ||
| 5495 | if (ret) | ||
| 5496 | mlog_errno(ret); | ||
| 5497 | |||
| 5498 | return ret; | ||
| 5499 | } | ||
| 5500 | |||
| 5501 | static int ocfs2_xattr_bucket_set_value_outside(struct inode *inode, | ||
| 5502 | handle_t *handle, | ||
| 5503 | struct ocfs2_xattr_search *xs, | ||
| 5504 | char *val, | ||
| 5505 | int value_len) | ||
| 5506 | { | ||
| 5507 | int ret, offset, block_off; | ||
| 5508 | struct ocfs2_xattr_value_root *xv; | ||
| 5509 | struct ocfs2_xattr_entry *xe = xs->here; | ||
| 5510 | struct ocfs2_xattr_header *xh = bucket_xh(xs->bucket); | ||
| 5511 | void *base; | ||
| 5512 | struct ocfs2_xattr_value_buf vb = { | ||
| 5513 | .vb_access = ocfs2_journal_access, | ||
| 5514 | }; | ||
| 5515 | |||
| 5516 | BUG_ON(!xs->base || !xe || ocfs2_xattr_is_local(xe)); | ||
| 5517 | |||
| 5518 | ret = ocfs2_xattr_bucket_get_name_value(inode->i_sb, xh, | ||
| 5519 | xe - xh->xh_entries, | ||
| 5520 | &block_off, | ||
| 5521 | &offset); | ||
| 5522 | if (ret) { | ||
| 5523 | mlog_errno(ret); | ||
| 5524 | goto out; | ||
| 5525 | } | ||
| 5526 | |||
| 5527 | base = bucket_block(xs->bucket, block_off); | ||
| 5528 | xv = (struct ocfs2_xattr_value_root *)(base + offset + | ||
| 5529 | OCFS2_XATTR_SIZE(xe->xe_name_len)); | ||
| 5530 | |||
| 5531 | vb.vb_xv = xv; | ||
| 5532 | vb.vb_bh = xs->bucket->bu_bhs[block_off]; | ||
| 5533 | ret = __ocfs2_xattr_set_value_outside(inode, handle, | ||
| 5534 | &vb, val, value_len); | ||
| 5535 | if (ret) | ||
| 5536 | mlog_errno(ret); | ||
| 5537 | out: | ||
| 5538 | return ret; | ||
| 5539 | } | ||
| 5540 | |||
| 5541 | static int ocfs2_rm_xattr_cluster(struct inode *inode, | 5309 | static int ocfs2_rm_xattr_cluster(struct inode *inode, |
| 5542 | struct buffer_head *root_bh, | 5310 | struct buffer_head *root_bh, |
| 5543 | u64 blkno, | 5311 | u64 blkno, |
| @@ -5636,41 +5404,8 @@ out: | |||
| 5636 | return ret; | 5404 | return ret; |
| 5637 | } | 5405 | } |
| 5638 | 5406 | ||
| 5639 | static void ocfs2_xattr_bucket_remove_xs(struct inode *inode, | ||
| 5640 | handle_t *handle, | ||
| 5641 | struct ocfs2_xattr_search *xs) | ||
| 5642 | { | ||
| 5643 | struct ocfs2_xattr_header *xh = bucket_xh(xs->bucket); | ||
| 5644 | struct ocfs2_xattr_entry *last = &xh->xh_entries[ | ||
| 5645 | le16_to_cpu(xh->xh_count) - 1]; | ||
| 5646 | int ret = 0; | ||
| 5647 | |||
| 5648 | ret = ocfs2_xattr_bucket_journal_access(handle, xs->bucket, | ||
| 5649 | OCFS2_JOURNAL_ACCESS_WRITE); | ||
| 5650 | if (ret) { | ||
| 5651 | mlog_errno(ret); | ||
| 5652 | return; | ||
| 5653 | } | ||
| 5654 | |||
| 5655 | /* Remove the old entry. */ | ||
| 5656 | memmove(xs->here, xs->here + 1, | ||
| 5657 | (void *)last - (void *)xs->here); | ||
| 5658 | memset(last, 0, sizeof(struct ocfs2_xattr_entry)); | ||
| 5659 | le16_add_cpu(&xh->xh_count, -1); | ||
| 5660 | |||
| 5661 | ocfs2_xattr_bucket_journal_dirty(handle, xs->bucket); | ||
| 5662 | } | ||
| 5663 | |||
| 5664 | /* | 5407 | /* |
| 5665 | * Set the xattr name/value in the bucket specified in xs. | 5408 | * Set the xattr name/value in the bucket specified in xs. |
| 5666 | * | ||
| 5667 | * As the new value in xi may be stored in the bucket or in an outside cluster, | ||
| 5668 | * we divide the whole process into 3 steps: | ||
| 5669 | * 1. insert name/value in the bucket(ocfs2_xattr_set_entry_in_bucket) | ||
| 5670 | * 2. truncate of the outside cluster(ocfs2_xattr_bucket_value_truncate_xs) | ||
| 5671 | * 3. Set the value to the outside cluster(ocfs2_xattr_bucket_set_value_outside) | ||
| 5672 | * 4. If the clusters for the new outside value can't be allocated, we need | ||
| 5673 | * to free the xattr we allocated in set. | ||
| 5674 | */ | 5409 | */ |
| 5675 | static int ocfs2_xattr_set_in_bucket(struct inode *inode, | 5410 | static int ocfs2_xattr_set_in_bucket(struct inode *inode, |
| 5676 | struct ocfs2_xattr_info *xi, | 5411 | struct ocfs2_xattr_info *xi, |
| @@ -5678,70 +5413,46 @@ static int ocfs2_xattr_set_in_bucket(struct inode *inode, | |||
| 5678 | struct ocfs2_xattr_set_ctxt *ctxt) | 5413 | struct ocfs2_xattr_set_ctxt *ctxt) |
| 5679 | { | 5414 | { |
| 5680 | int ret; | 5415 | int ret; |
| 5681 | size_t value_len; | 5416 | u64 blkno; |
| 5682 | char *val = (char *)xi->xi_value; | 5417 | struct ocfs2_xa_loc loc; |
| 5683 | struct ocfs2_xattr_entry *xe = xs->here; | ||
| 5684 | u32 name_hash = ocfs2_xattr_name_hash(inode, xi->xi_name, | 5418 | u32 name_hash = ocfs2_xattr_name_hash(inode, xi->xi_name, |
| 5685 | xi->xi_name_len); | 5419 | xi->xi_name_len); |
| 5686 | 5420 | ||
| 5687 | value_len = xi->xi_value_len; | 5421 | if (!xs->bucket->bu_bhs[1]) { |
| 5688 | if (!xs->not_found && !ocfs2_xattr_is_local(xe)) { | 5422 | blkno = bucket_blkno(xs->bucket); |
| 5689 | /* | 5423 | ocfs2_xattr_bucket_relse(xs->bucket); |
| 5690 | * We need to truncate the xattr storage first. | 5424 | ret = ocfs2_read_xattr_bucket(xs->bucket, blkno); |
| 5691 | * | 5425 | if (ret) { |
| 5692 | * If both the old and new value are stored to | 5426 | mlog_errno(ret); |
| 5693 | * outside block, we only need to truncate | ||
| 5694 | * the storage and then set the value outside. | ||
| 5695 | * | ||
| 5696 | * If the new value should be stored within block, | ||
| 5697 | * we should free all the outside block first and | ||
| 5698 | * the modification to the xattr block will be done | ||
| 5699 | * by following steps. | ||
| 5700 | */ | ||
| 5701 | if (xi->xi_value_len <= OCFS2_XATTR_INLINE_SIZE) | ||
| 5702 | value_len = 0; | ||
| 5703 | |||
| 5704 | ret = ocfs2_xattr_bucket_value_truncate_xs(inode, xs, | ||
| 5705 | value_len, | ||
| 5706 | ctxt); | ||
| 5707 | if (ret) | ||
| 5708 | goto out; | 5427 | goto out; |
| 5709 | 5428 | } | |
| 5710 | if (value_len) | ||
| 5711 | goto set_value_outside; | ||
| 5712 | } | 5429 | } |
| 5713 | 5430 | ||
| 5714 | /* So we have to handle the inside block change now. */ | 5431 | ocfs2_init_xattr_bucket_xa_loc(&loc, xs->bucket, |
| 5715 | ret = ocfs2_xattr_set_entry_in_bucket(inode, ctxt->handle, xi, xs, | 5432 | xs->not_found ? NULL : xs->here); |
| 5716 | name_hash); | 5433 | ret = ocfs2_xa_journal_access(ctxt->handle, &loc, |
| 5717 | if (ret) { | 5434 | OCFS2_JOURNAL_ACCESS_WRITE); |
| 5435 | if (ret < 0) { | ||
| 5718 | mlog_errno(ret); | 5436 | mlog_errno(ret); |
| 5719 | goto out; | 5437 | goto out; |
| 5720 | } | 5438 | } |
| 5721 | 5439 | ||
| 5722 | if (xi->xi_value_len <= OCFS2_XATTR_INLINE_SIZE) | 5440 | ret = ocfs2_xa_prepare_entry(&loc, xi, name_hash, ctxt); |
| 5441 | if (ret) { | ||
| 5442 | if (ret != -ENOSPC) | ||
| 5443 | mlog_errno(ret); | ||
| 5723 | goto out; | 5444 | goto out; |
| 5445 | } | ||
| 5446 | xs->here = loc.xl_entry; | ||
| 5724 | 5447 | ||
| 5725 | /* allocate the space now for the outside block storage. */ | 5448 | ret = ocfs2_xa_store_value(&loc, xi, ctxt); |
| 5726 | ret = ocfs2_xattr_bucket_value_truncate_xs(inode, xs, | ||
| 5727 | value_len, ctxt); | ||
| 5728 | if (ret) { | 5449 | if (ret) { |
| 5729 | mlog_errno(ret); | 5450 | mlog_errno(ret); |
| 5730 | |||
| 5731 | if (xs->not_found) { | ||
| 5732 | /* | ||
| 5733 | * We can't allocate enough clusters for outside | ||
| 5734 | * storage and we have allocated xattr already, | ||
| 5735 | * so need to remove it. | ||
| 5736 | */ | ||
| 5737 | ocfs2_xattr_bucket_remove_xs(inode, ctxt->handle, xs); | ||
| 5738 | } | ||
| 5739 | goto out; | 5451 | goto out; |
| 5740 | } | 5452 | } |
| 5741 | 5453 | ||
| 5742 | set_value_outside: | 5454 | ocfs2_xa_journal_dirty(ctxt->handle, &loc); |
| 5743 | ret = ocfs2_xattr_bucket_set_value_outside(inode, ctxt->handle, | 5455 | |
| 5744 | xs, val, value_len); | ||
| 5745 | out: | 5456 | out: |
| 5746 | return ret; | 5457 | return ret; |
| 5747 | } | 5458 | } |
