|
@@ -77,35 +77,42 @@ find_set_type(const char *name, u8 family, u8 revision)
|
|
}
|
|
}
|
|
|
|
|
|
/* Unlock, try to load a set type module and lock again */
|
|
/* Unlock, try to load a set type module and lock again */
|
|
-static int
|
|
|
|
-try_to_load_type(const char *name)
|
|
|
|
|
|
+static bool
|
|
|
|
+load_settype(const char *name)
|
|
{
|
|
{
|
|
nfnl_unlock();
|
|
nfnl_unlock();
|
|
pr_debug("try to load ip_set_%s\n", name);
|
|
pr_debug("try to load ip_set_%s\n", name);
|
|
if (request_module("ip_set_%s", name) < 0) {
|
|
if (request_module("ip_set_%s", name) < 0) {
|
|
pr_warning("Can't find ip_set type %s\n", name);
|
|
pr_warning("Can't find ip_set type %s\n", name);
|
|
nfnl_lock();
|
|
nfnl_lock();
|
|
- return -IPSET_ERR_FIND_TYPE;
|
|
|
|
|
|
+ return false;
|
|
}
|
|
}
|
|
nfnl_lock();
|
|
nfnl_lock();
|
|
- return -EAGAIN;
|
|
|
|
|
|
+ return true;
|
|
}
|
|
}
|
|
|
|
|
|
/* Find a set type and reference it */
|
|
/* Find a set type and reference it */
|
|
|
|
+#define find_set_type_get(name, family, revision, found) \
|
|
|
|
+ __find_set_type_get(name, family, revision, found, false)
|
|
|
|
+
|
|
static int
|
|
static int
|
|
-find_set_type_get(const char *name, u8 family, u8 revision,
|
|
|
|
- struct ip_set_type **found)
|
|
|
|
|
|
+__find_set_type_get(const char *name, u8 family, u8 revision,
|
|
|
|
+ struct ip_set_type **found, bool retry)
|
|
{
|
|
{
|
|
struct ip_set_type *type;
|
|
struct ip_set_type *type;
|
|
int err;
|
|
int err;
|
|
|
|
|
|
|
|
+ if (retry && !load_settype(name))
|
|
|
|
+ return -IPSET_ERR_FIND_TYPE;
|
|
|
|
+
|
|
rcu_read_lock();
|
|
rcu_read_lock();
|
|
*found = find_set_type(name, family, revision);
|
|
*found = find_set_type(name, family, revision);
|
|
if (*found) {
|
|
if (*found) {
|
|
err = !try_module_get((*found)->me) ? -EFAULT : 0;
|
|
err = !try_module_get((*found)->me) ? -EFAULT : 0;
|
|
goto unlock;
|
|
goto unlock;
|
|
}
|
|
}
|
|
- /* Make sure the type is loaded but we don't support the revision */
|
|
|
|
|
|
+ /* Make sure the type is already loaded
|
|
|
|
+ * but we don't support the revision */
|
|
list_for_each_entry_rcu(type, &ip_set_type_list, list)
|
|
list_for_each_entry_rcu(type, &ip_set_type_list, list)
|
|
if (STREQ(type->name, name)) {
|
|
if (STREQ(type->name, name)) {
|
|
err = -IPSET_ERR_FIND_TYPE;
|
|
err = -IPSET_ERR_FIND_TYPE;
|
|
@@ -113,7 +120,8 @@ find_set_type_get(const char *name, u8 family, u8 revision,
|
|
}
|
|
}
|
|
rcu_read_unlock();
|
|
rcu_read_unlock();
|
|
|
|
|
|
- return try_to_load_type(name);
|
|
|
|
|
|
+ return retry ? -IPSET_ERR_FIND_TYPE :
|
|
|
|
+ __find_set_type_get(name, family, revision, found, true);
|
|
|
|
|
|
unlock:
|
|
unlock:
|
|
rcu_read_unlock();
|
|
rcu_read_unlock();
|
|
@@ -124,12 +132,19 @@ unlock:
|
|
* If we succeeded, the supported minimal and maximum revisions are
|
|
* If we succeeded, the supported minimal and maximum revisions are
|
|
* filled out.
|
|
* filled out.
|
|
*/
|
|
*/
|
|
|
|
+#define find_set_type_minmax(name, family, min, max) \
|
|
|
|
+ __find_set_type_minmax(name, family, min, max, false)
|
|
|
|
+
|
|
static int
|
|
static int
|
|
-find_set_type_minmax(const char *name, u8 family, u8 *min, u8 *max)
|
|
|
|
|
|
+__find_set_type_minmax(const char *name, u8 family, u8 *min, u8 *max,
|
|
|
|
+ bool retry)
|
|
{
|
|
{
|
|
struct ip_set_type *type;
|
|
struct ip_set_type *type;
|
|
bool found = false;
|
|
bool found = false;
|
|
|
|
|
|
|
|
+ if (retry && !load_settype(name))
|
|
|
|
+ return -IPSET_ERR_FIND_TYPE;
|
|
|
|
+
|
|
*min = 255; *max = 0;
|
|
*min = 255; *max = 0;
|
|
rcu_read_lock();
|
|
rcu_read_lock();
|
|
list_for_each_entry_rcu(type, &ip_set_type_list, list)
|
|
list_for_each_entry_rcu(type, &ip_set_type_list, list)
|
|
@@ -145,7 +160,8 @@ find_set_type_minmax(const char *name, u8 family, u8 *min, u8 *max)
|
|
if (found)
|
|
if (found)
|
|
return 0;
|
|
return 0;
|
|
|
|
|
|
- return try_to_load_type(name);
|
|
|
|
|
|
+ return retry ? -IPSET_ERR_FIND_TYPE :
|
|
|
|
+ __find_set_type_minmax(name, family, min, max, true);
|
|
}
|
|
}
|
|
|
|
|
|
#define family_name(f) ((f) == AF_INET ? "inet" : \
|
|
#define family_name(f) ((f) == AF_INET ? "inet" : \
|