diff options
author | sanjeevbagewadi <[email protected]> | 2018-02-09 23:45:53 +0530 |
---|---|---|
committer | Brian Behlendorf <[email protected]> | 2018-02-09 10:15:53 -0800 |
commit | cc63068e95ee725cce03b1b7ce50179825a6cda5 (patch) | |
tree | a9f4def7be1a9f9f49f299c858113fef982b0145 /module/zfs/zap.c | |
parent | eb9c4532dda34bcf0612c2c797cb3fcab9a21b4f (diff) |
Handle zap_add() failures in mixed case mode
With "casesensitivity=mixed", zap_add() could fail when the number of
files/directories with the same name (varying in case) exceed the
capacity of the leaf node of a Fatzap. This results in a ASSERT()
failure as zfs_link_create() does not expect zap_add() to fail. The fix
is to handle these failures and rollback the transactions.
Reviewed by: Matt Ahrens <[email protected]>
Reviewed-by: Chunwei Chen <[email protected]>
Reviewed-by: Brian Behlendorf <[email protected]>
Signed-off-by: Sanjeev Bagewadi <[email protected]>
Closes #7011
Closes #7054
Diffstat (limited to 'module/zfs/zap.c')
-rw-r--r-- | module/zfs/zap.c | 25 |
1 files changed, 24 insertions, 1 deletions
diff --git a/module/zfs/zap.c b/module/zfs/zap.c index 2f6aed667..1c2030bda 100644 --- a/module/zfs/zap.c +++ b/module/zfs/zap.c @@ -818,15 +818,19 @@ fzap_lookup(zap_name_t *zn, return (err); } +#define MAX_EXPAND_RETRIES 2 + int fzap_add_cd(zap_name_t *zn, uint64_t integer_size, uint64_t num_integers, const void *val, uint32_t cd, void *tag, dmu_tx_t *tx) { zap_leaf_t *l; + zap_leaf_t *prev_l = NULL; int err; zap_entry_handle_t zeh; zap_t *zap = zn->zn_zap; + int expand_retries = 0; ASSERT(RW_LOCK_HELD(&zap->zap_rwlock)); ASSERT(!zap->zap_ismicro); @@ -850,10 +854,29 @@ retry: if (err == 0) { zap_increment_num_entries(zap, 1, tx); } else if (err == EAGAIN) { + /* + * If the last two expansions did not help, there is no point + * trying to expand again + */ + if (expand_retries > MAX_EXPAND_RETRIES && prev_l == l) { + err = SET_ERROR(ENOSPC); + goto out; + } + err = zap_expand_leaf(zn, l, tag, tx, &l); zap = zn->zn_zap; /* zap_expand_leaf() may change zap */ - if (err == 0) + if (err == 0) { + prev_l = l; + expand_retries++; goto retry; + } else if (err == ENOSPC) { + /* + * If we failed to expand the leaf, then bailout + * as there is no point trying + * zap_put_leaf_maybe_grow_ptrtbl(). + */ + return (err); + } } out: |