diff options
author | Brian Behlendorf <[email protected]> | 2017-03-23 18:26:50 -0700 |
---|---|---|
committer | GitHub <[email protected]> | 2017-03-23 18:26:50 -0700 |
commit | 8d703987407acfcbd992ba4a7926f2d76ca3779c (patch) | |
tree | c6f5f253f82729138ee0d8b26f7fd564ce7155d6 /module/zfs/zfs_znode.c | |
parent | b25c5b0639e0d2281ccbd3b5766762dc3bebfc02 (diff) |
Retry zfs_znode_alloc() in zfs_mknode()
For historical reasons zfs_mknode() was written such that it could
never fail. This poses a problem for Linux since zfs_znode_alloc()
could potentually failure due to low memory. Handle this gracefully
by retrying zfs_znode_alloc() until it succeeds, direct reclaim
will eventually be able to allocate memory.
Reviewed-by: George Melikov <[email protected]>
Reviewed-by: loli10K <[email protected]>
Signed-off-by: Brian Behlendorf <[email protected]>
Closes #5535
Closes #5908
Diffstat (limited to 'module/zfs/zfs_znode.c')
-rw-r--r-- | module/zfs/zfs_znode.c | 13 |
1 files changed, 12 insertions, 1 deletions
diff --git a/module/zfs/zfs_znode.c b/module/zfs/zfs_znode.c index 1597940e6..93437afb3 100644 --- a/module/zfs/zfs_znode.c +++ b/module/zfs/zfs_znode.c @@ -915,7 +915,18 @@ zfs_mknode(znode_t *dzp, vattr_t *vap, dmu_tx_t *tx, cred_t *cr, VERIFY(sa_replace_all_by_template(sa_hdl, sa_attrs, cnt, tx) == 0); if (!(flag & IS_ROOT_NODE)) { - *zpp = zfs_znode_alloc(zfsvfs, db, 0, obj_type, obj, sa_hdl); + /* + * The call to zfs_znode_alloc() may fail if memory is low + * via the call path: alloc_inode() -> inode_init_always() -> + * security_inode_alloc() -> inode_alloc_security(). Since + * the existing code is written such that zfs_mknode() can + * not fail retry until sufficient memory has been reclaimed. + */ + do { + *zpp = zfs_znode_alloc(zfsvfs, db, 0, obj_type, obj, + sa_hdl); + } while (*zpp == NULL); + VERIFY(*zpp != NULL); VERIFY(dzp != NULL); } else { |