Prompt:
Given the following original C code:
err = hci_get_random_address(hdev, !connectable,
				     adv_use_rpa(hdev, flags), adv,
				     &own_addr_type, &random_addr);
	if (err < 0)
		return err;

	memset(&cp, 0, sizeof(cp));

	if (adv) {
		hci_cpu_to_le24(adv->min_interval, cp.min_interval);
		hci_cpu_to_le24(adv->max_interval, cp.max_interval);
		cp.tx_power = adv->tx_power;
	} else {
		hci_cpu_to_le24(hdev->le_adv_min_interval, cp.min_interval);
		hci_cpu_to_le24(hdev->le_adv_max_interval, cp.max_interval);
		cp.tx_power = HCI_ADV_TX_POWER_NO_PREFERENCE;
	}

	secondary_adv = (flags & MGMT_ADV_FLAG_SEC_MASK);

Instruction:
Bluetooth: ISO: Fix not using bc_sid as advertisement SID

Return the diff that fixes it:

Response:
@@ -1261,10 +1261,12 @@ int hci_setup_ext_adv_instance_sync(struct hci_dev *hdev, u8 instance)
 		hci_cpu_to_le24(adv->min_interval, cp.min_interval);
 		hci_cpu_to_le24(adv->max_interval, cp.max_interval);
 		cp.tx_power = adv->tx_power;
+		cp.sid = adv->sid;
 	} else {
 		hci_cpu_to_le24(hdev->le_adv_min_interval, cp.min_interval);
 		hci_cpu_to_le24(hdev->le_adv_max_interval, cp.max_interval);
 		cp.tx_power = HCI_ADV_TX_POWER_NO_PREFERENCE;
+		cp.sid = 0x00;
 	}

 	secondary_adv = (flags & MGMT_ADV_FLAG_SEC_MASK);
@@ -1594,8 +1596,8 @@ static int hci_adv_bcast_annoucement(struct hci_dev *hdev, struct adv_info *adv)
 	return hci_update_adv_data_sync(hdev, adv->instance);
 }

-int hci_start_per_adv_sync(struct hci_dev *hdev, u8 instance, u8 data_len,
-			   u8 *data, u32 flags, u16 min_interval,
+int hci_start_per_adv_sync(struct hci_dev *hdev, u8 instance, u8 sid,
+			   u8 data_len, u8 *data, u32 flags, u16 min_interval,
 			   u16 max_interval, u16 sync_interval)
 {
 	struct adv_info *adv = NULL;
@@ -1607,6 +1609,18 @@ int hci_start_per_adv_sync(struct hci_dev *hdev, u8 instance, u8 data_len,
 	if (instance) {
 		adv = hci_find_adv_instance(hdev, instance);
 		if (adv) {
+			if (sid != HCI_SID_INVALID && adv->sid != sid) {
+				/* If the SID don't match attempt to find by
+				 * SID.
+				 */
+				adv = hci_find_adv_sid(hdev, sid);
+				if (!adv) {
+					bt_dev_err(hdev,
+						   "Unable to find adv_info");
+					return -EINVAL;
+				}
+			}
+
 			/* Turn it into periodic advertising */
 			adv->periodic = true;
 			adv->per_adv_data_len = data_len;
@@ -1615,7 +1629,7 @@ int hci_start_per_adv_sync(struct hci_dev *hdev, u8 instance, u8 data_len,
 			adv->flags = flags;
 		} else if (!adv) {
 			/* Create an instance if that could not be found */
-			adv = hci_add_per_instance(hdev, instance, flags,
+			adv = hci_add_per_instance(hdev, instance, sid, flags,
 						   data_len, data,
 						   sync_interval,
 						   sync_interval);


Prompt:
Given the following original C code:
return ADDR_LE_DEV_PUBLIC;
	else
		return ADDR_LE_DEV_RANDOM;
}

static int iso_connect_bis(struct sock *sk)
{
	struct iso_conn *conn;
	struct hci_conn *hcon;
	struct hci_dev  *hdev;
	int err;

	BT_DBG("%pMR", &iso_pi(sk)->src);

	hdev = hci_get_route(&iso_pi(sk)->dst, &iso_pi(sk)->src,
			     iso_pi(sk)->src_type);
	if (!hdev)
		return -EHOSTUNREACH;

	hci_dev_lock(hdev);

Instruction:
Bluetooth: ISO: Fix not using bc_sid as advertisement SID

Return the diff that fixes it:

Response:
@@ -336,7 +336,7 @@ static int iso_connect_bis(struct sock *sk)
 	struct hci_dev  *hdev;
 	int err;

-	BT_DBG("%pMR", &iso_pi(sk)->src);
+	BT_DBG("%pMR (SID 0x%2.2x)", &iso_pi(sk)->src, iso_pi(sk)->bc_sid);

 	hdev = hci_get_route(&iso_pi(sk)->dst, &iso_pi(sk)->src,
 			     iso_pi(sk)->src_type);
@@ -365,7 +365,7 @@ static int iso_connect_bis(struct sock *sk)

 	/* Just bind if DEFER_SETUP has been set */
 	if (test_bit(BT_SK_DEFER_SETUP, &bt_sk(sk)->flags)) {
-		hcon = hci_bind_bis(hdev, &iso_pi(sk)->dst,
+		hcon = hci_bind_bis(hdev, &iso_pi(sk)->dst, iso_pi(sk)->bc_sid,
 				    &iso_pi(sk)->qos, iso_pi(sk)->base_len,
 				    iso_pi(sk)->base);
 		if (IS_ERR(hcon)) {
@@ -375,12 +375,16 @@ static int iso_connect_bis(struct sock *sk)
 	} else {
 		hcon = hci_connect_bis(hdev, &iso_pi(sk)->dst,
 				       le_addr_type(iso_pi(sk)->dst_type),
-				       &iso_pi(sk)->qos, iso_pi(sk)->base_len,
-				       iso_pi(sk)->base);
+				       iso_pi(sk)->bc_sid, &iso_pi(sk)->qos,
+				       iso_pi(sk)->base_len, iso_pi(sk)->base);
 		if (IS_ERR(hcon)) {
 			err = PTR_ERR(hcon);
 			goto unlock;
 		}
+
+		/* Update SID if it was not set */
+		if (iso_pi(sk)->bc_sid == HCI_SID_INVALID)
+			iso_pi(sk)->bc_sid = hcon->sid;
 	}

 	conn = iso_conn_add(hcon);


Prompt:
Given the following original C code:
static void mgmt_adv_monitor_added(struct sock *sk, struct hci_dev *hdev,
				   u16 handle)
{
	struct mgmt_ev_adv_monitor_added ev;

	ev.monitor_handle = cpu_to_le16(handle);

	mgmt_event(MGMT_EV_ADV_MONITOR_ADDED, hdev, &ev, sizeof(ev), sk);
}

static void mgmt_adv_monitor_removed(struct sock *sk, struct hci_dev *hdev,
				     u16 handle)
{
	struct mgmt_ev_adv_monitor_removed ev;

	ev.monitor_handle = cpu_to_le16(handle);

	mgmt_event(MGMT_EV_ADV_MONITOR_REMOVED, hdev, &ev, sizeof(ev), sk);
}

Instruction:
Bluetooth: MGMT: Fix sparse errors

Return the diff that fixes it:

Response:
@@ -5102,11 +5102,11 @@ static void mgmt_adv_monitor_added(struct sock *sk, struct hci_dev *hdev,
 }

 static void mgmt_adv_monitor_removed(struct sock *sk, struct hci_dev *hdev,
-				     u16 handle)
+				     __le16 handle)
 {
 	struct mgmt_ev_adv_monitor_removed ev;

-	ev.monitor_handle = cpu_to_le16(handle);
+	ev.monitor_handle = handle;

 	mgmt_event(MGMT_EV_ADV_MONITOR_REMOVED, hdev, &ev, sizeof(ev), sk);
 }


Prompt:
Given the following original C code:
n = (addr & ~MLX5_U64_4K_PAGE_MASK) >> MLX5_ADAPTER_PAGE_SHIFT;
	fwp->free_count++;
	set_bit(n, &fwp->bitmask);
	if (fwp->free_count == MLX5_NUM_4K_IN_PAGE)
		free_fwp(dev, fwp, fwp->free_count != 1);
	else if (fwp->free_count == 1)
		list_add(&fwp->list, &dev->priv.free_list);
}

static int alloc_system_page(struct mlx5_core_dev *dev, u32 function)
{
	struct device *device = mlx5_core_dma_dev(dev);
	int nid = dev_to_node(device);
	struct page *page;
	u64 zero_addr = 1;
	u64 addr;
	int err;

	page = alloc_pages_node(nid, GFP_HIGHUSER, 0);
	if (!page) {

Instruction:
net/mlx5: Ensure fw pages are always allocated on same NUMA

Return the diff that fixes it:

Response:
@@ -291,7 +291,7 @@ static void free_4k(struct mlx5_core_dev *dev, u64 addr, u32 function)
 static int alloc_system_page(struct mlx5_core_dev *dev, u32 function)
 {
 	struct device *device = mlx5_core_dma_dev(dev);
-	int nid = dev_to_node(device);
+	int nid = dev->priv.numa_node;
 	struct page *page;
 	u64 zero_addr = 1;
 	u64 addr;


Prompt:
Given the following original C code:
}

	/* Enable external host PF HCA */
	ret = host_pf_enable_hca(esw->dev);
	if (ret)
		goto pf_hca_err;

	/* Enable ECPF vport */
	if (mlx5_ecpf_vport_exists(esw->dev)) {
		ret = mlx5_eswitch_load_pf_vf_vport(esw, MLX5_VPORT_ECPF, enabled_events);
		if (ret)
			goto ecpf_err;
		if (mlx5_core_ec_sriov_enabled(esw->dev)) {
			ret = mlx5_eswitch_load_ec_vf_vports(esw, esw->esw_funcs.num_ec_vfs,
							     enabled_events);
			if (ret)
				goto ec_vf_err;
		}
	}

Instruction:
net/mlx5: Fix ECVF vports unload on shutdown flow

Return the diff that fixes it:

Response:
@@ -1295,12 +1295,15 @@ mlx5_eswitch_enable_pf_vf_vports(struct mlx5_eswitch *esw,
 		ret = mlx5_eswitch_load_pf_vf_vport(esw, MLX5_VPORT_ECPF, enabled_events);
 		if (ret)
 			goto ecpf_err;
-		if (mlx5_core_ec_sriov_enabled(esw->dev)) {
-			ret = mlx5_eswitch_load_ec_vf_vports(esw, esw->esw_funcs.num_ec_vfs,
-							     enabled_events);
-			if (ret)
-				goto ec_vf_err;
-		}
+	}
+
+	/* Enable ECVF vports */
+	if (mlx5_core_ec_sriov_enabled(esw->dev)) {
+		ret = mlx5_eswitch_load_ec_vf_vports(esw,
+						     esw->esw_funcs.num_ec_vfs,
+						     enabled_events);
+		if (ret)
+			goto ec_vf_err;
 	}

 	/* Enable VF vports */
@@ -1331,9 +1334,11 @@ void mlx5_eswitch_disable_pf_vf_vports(struct mlx5_eswitch *esw)
 {
 	mlx5_eswitch_unload_vf_vports(esw, esw->esw_funcs.num_vfs);

+	if (mlx5_core_ec_sriov_enabled(esw->dev))
+		mlx5_eswitch_unload_ec_vf_vports(esw,
+						 esw->esw_funcs.num_ec_vfs);
+
 	if (mlx5_ecpf_vport_exists(esw->dev)) {
-		if (mlx5_core_ec_sriov_enabled(esw->dev))
-			mlx5_eswitch_unload_ec_vf_vports(esw, esw->esw_funcs.num_vfs);
 		mlx5_eswitch_unload_pf_vf_vport(esw, MLX5_VPORT_ECPF);
 	}


Prompt:
Given the following original C code:
const struct mlx5_flow_spec *spec,
		       struct mlx5_flow_act *flow_act,
		       struct mlx5_flow_destination *dest,
		       int dest_num,
		       int ft_version)
{
	struct mlx5_flow_steering *steering = get_steering(&ft->node);
	struct mlx5_flow_root_namespace *root = find_root(&ft->node);
	struct mlx5_flow_group *g;
	struct mlx5_flow_handle *rule;
	struct match_list *iter;
	bool take_write = false;
	struct fs_fte *fte;
	u64  version = 0;
	int err;

	fte = alloc_fte(ft, spec, flow_act);
	if (IS_ERR(fte))
		return  ERR_PTR(-ENOMEM);

Instruction:
net/mlx5: Fix return value when searching for existing flow group

Return the diff that fixes it:

Response:
@@ -2228,6 +2228,7 @@ try_add_to_existing_fg(struct mlx5_flow_table *ft,
 	struct mlx5_flow_handle *rule;
 	struct match_list *iter;
 	bool take_write = false;
+	bool try_again = false;
 	struct fs_fte *fte;
 	u64  version = 0;
 	int err;
@@ -2292,6 +2293,7 @@ try_add_to_existing_fg(struct mlx5_flow_table *ft,
 		nested_down_write_ref_node(&g->node, FS_LOCK_PARENT);

 		if (!g->node.active) {
+			try_again = true;
 			up_write_ref_node(&g->node, false);
 			continue;
 		}
@@ -2313,7 +2315,8 @@ try_add_to_existing_fg(struct mlx5_flow_table *ft,
 			tree_put_node(&fte->node, false);
 		return rule;
 	}
-	rule = ERR_PTR(-ENOENT);
+	err = try_again ? -EAGAIN : -ENOENT;
+	rule = ERR_PTR(err);
 out:
 	kmem_cache_free(steering->ftes_cache, fte);
 	return rule;


Prompt:
Given the following original C code:
goto release_pr;
		}
		pr_data->data = kmemdup(params->data, params->size, GFP_KERNEL);
		if (!pr_data->data) {
			err = -ENOMEM;
			goto release_pr;
		}
		pr_data->hdr_idx = hdr_idx;
		pr_data->data_size = params->size;
		pkt_reformat->fs_hws_action.pr_data = pr_data;
	}

	pkt_reformat->owner = MLX5_FLOW_RESOURCE_OWNER_HWS;
	pkt_reformat->fs_hws_action.hws_action = hws_action;
	return 0;

release_pr:
	if (pr_pool && pr_data)
		mlx5_fs_hws_pr_pool_release_pr(pr_pool, pr_data);
	return err;

Instruction:
net/mlx5: HWS, Init mutex on the correct path

Return the diff that fixes it:

Response:
@@ -1357,6 +1357,7 @@ mlx5_cmd_hws_packet_reformat_alloc(struct mlx5_flow_root_namespace *ns,
 		pkt_reformat->fs_hws_action.pr_data = pr_data;
 	}

+	mutex_init(&pkt_reformat->fs_hws_action.lock);
 	pkt_reformat->owner = MLX5_FLOW_RESOURCE_OWNER_HWS;
 	pkt_reformat->fs_hws_action.hws_action = hws_action;
 	return 0;
@@ -1503,7 +1504,6 @@ static int mlx5_cmd_hws_modify_header_alloc(struct mlx5_flow_root_namespace *ns,
 		err = -ENOMEM;
 		goto release_mh;
 	}
-	mutex_init(&modify_hdr->fs_hws_action.lock);
 	modify_hdr->fs_hws_action.mh_data = mh_data;
 	modify_hdr->fs_hws_action.fs_pool = pool;
 	modify_hdr->owner = MLX5_FLOW_RESOURCE_OWNER_SW;


Prompt:
Given the following original C code:
if (HWS_GET_MATCH_PARAM(match_param, outer_headers.cvlan_tag) ||
	    HWS_GET_MATCH_PARAM(match_param, outer_headers.svlan_tag)) {
		curr_fc = &fc[MLX5HWS_DEFINER_FNAME_VLAN_TYPE_O];
		HWS_CALC_HDR_DST(curr_fc, eth_l2_outer.first_vlan_qualifier);
		curr_fc->tag_set = &hws_definer_outer_vlan_type_set;
		curr_fc->tag_mask_set = &hws_definer_ones_set;
	}

	/* L3 Check IP header */
	HWS_SET_HDR(fc, match_param, IP_PROTOCOL_O,
		    outer_headers.ip_protocol,
		    eth_l3_outer.protocol_next_header);
	HWS_SET_HDR(fc, match_param, IP_TTL_O,
		    outer_headers.ttl_hoplimit,
		    eth_l3_outer.time_to_live_hop_limit);

	/* L3 Check IPv4/IPv6 addresses */
	s_ipv6 = MLX5_ADDR_OF(fte_match_param, match_param,
			      outer_headers.src_ipv4_src_ipv6.ipv6_layout);
	d_ipv6 = MLX5_ADDR_OF(fte_match_param, match_param,

Instruction:
net/mlx5: HWS, fix missing ip_version handling in definer

Return the diff that fixes it:

Response:
@@ -785,6 +785,9 @@ hws_definer_conv_outer(struct mlx5hws_definer_conv_data *cd,
 	HWS_SET_HDR(fc, match_param, IP_PROTOCOL_O,
 		    outer_headers.ip_protocol,
 		    eth_l3_outer.protocol_next_header);
+	HWS_SET_HDR(fc, match_param, IP_VERSION_O,
+		    outer_headers.ip_version,
+		    eth_l3_outer.ip_version);
 	HWS_SET_HDR(fc, match_param, IP_TTL_O,
 		    outer_headers.ttl_hoplimit,
 		    eth_l3_outer.time_to_live_hop_limit);


Prompt:
Given the following original C code:
mlx5hws_action_create_dest_array(struct mlx5hws_context *ctx,
				 size_t num_dest,
				 struct mlx5hws_action_dest_attr *dests,
				 bool ignore_flow_level,
				 u32 flow_source,
				 u32 flags)
{
	struct mlx5hws_cmd_set_fte_dest *dest_list = NULL;
	struct mlx5hws_cmd_ft_create_attr ft_attr = {0};
	struct mlx5hws_cmd_set_fte_attr fte_attr = {0};
	struct mlx5hws_cmd_forward_tbl *fw_island;
	struct mlx5hws_action *action;
	u32 i /*, packet_reformat_id*/;
	int ret;

	if (num_dest <= 1) {
		mlx5hws_err(ctx, "Action must have multiple dests\n");
		return NULL;
	}

Instruction:
net/mlx5: HWS, make sure the uplink is the last destination

Return the diff that fixes it:

Response:
@@ -1370,8 +1370,8 @@ mlx5hws_action_create_dest_array(struct mlx5hws_context *ctx,
 	struct mlx5hws_cmd_set_fte_attr fte_attr = {0};
 	struct mlx5hws_cmd_forward_tbl *fw_island;
 	struct mlx5hws_action *action;
-	u32 i /*, packet_reformat_id*/;
-	int ret;
+	int ret, last_dest_idx = -1;
+	u32 i;

 	if (num_dest <= 1) {
 		mlx5hws_err(ctx, "Action must have multiple dests\n");
@@ -1401,11 +1401,8 @@ mlx5hws_action_create_dest_array(struct mlx5hws_context *ctx,
 			dest_list[i].destination_id = dests[i].dest->dest_obj.obj_id;
 			fte_attr.action_flags |= MLX5_FLOW_CONTEXT_ACTION_FWD_DEST;
 			fte_attr.ignore_flow_level = ignore_flow_level;
-			/* ToDo: In SW steering we have a handling of 'go to WIRE'
-			 * destination here by upper layer setting 'is_wire_ft' flag
-			 * if the destination is wire.
-			 * This is because uplink should be last dest in the list.
-			 */
+			if (dests[i].is_wire_ft)
+				last_dest_idx = i;
 			break;
 		case MLX5HWS_ACTION_TYP_VPORT:
 			dest_list[i].destination_type = MLX5_FLOW_DESTINATION_TYPE_VPORT;
@@ -1429,6 +1426,9 @@ mlx5hws_action_create_dest_array(struct mlx5hws_context *ctx,
 		}
 	}

+	if (last_dest_idx != -1)
+		swap(dest_list[last_dest_idx], dest_list[num_dest - 1]);
+
 	fte_attr.dests_num = num_dest;
 	fte_attr.dests = dest_list;


Prompt:
Given the following original C code:
if (num_fs_actions == MLX5_FLOW_CONTEXT_ACTION_MAX ||
			    num_dest_actions == MLX5_FLOW_CONTEXT_ACTION_MAX) {
				err = -EOPNOTSUPP;
				goto free_actions;
			}
			if (attr->type == MLX5_FLOW_DESTINATION_TYPE_COUNTER)
				continue;

			switch (attr->type) {
			case MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE:
				dest_action = mlx5_fs_get_dest_action_ft(fs_ctx, dst);
				break;
			case MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE_NUM:
				dest_action = mlx5_fs_get_dest_action_table_num(fs_ctx,
										dst);
				if (dest_action)
					break;
				dest_action = mlx5_fs_create_dest_action_table_num(fs_ctx,
										   dst);

Instruction:
net/mlx5: HWS, make sure the uplink is the last destination

Return the diff that fixes it:

Response:
@@ -966,6 +966,9 @@ static int mlx5_fs_fte_get_hws_actions(struct mlx5_flow_root_namespace *ns,
 			switch (attr->type) {
 			case MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE:
 				dest_action = mlx5_fs_get_dest_action_ft(fs_ctx, dst);
+				if (dst->dest_attr.ft->flags &
+				    MLX5_FLOW_TABLE_UPLINK_VPORT)
+					dest_actions[num_dest_actions].is_wire_ft = true;
 				break;
 			case MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE_NUM:
 				dest_action = mlx5_fs_get_dest_action_table_num(fs_ctx,


Prompt:
Given the following original C code:
struct mlx5hws_action_mh_pattern {
	/* Byte size of modify actions provided by "data" */
	size_t sz;
	/* PRM format modify actions pattern */
	__be64 *data;
};

struct mlx5hws_action_dest_attr {
	/* Required destination action to forward the packet */
	struct mlx5hws_action *dest;
	/* Optional reformat action */
	struct mlx5hws_action *reformat;
};

/**
 * mlx5hws_is_supported - Check whether HWS is supported
 *
 * @mdev: The device to check.
 *
 * Return: true if supported, false otherwise.

Instruction:
net/mlx5: HWS, make sure the uplink is the last destination

Return the diff that fixes it:

Response:
@@ -213,6 +213,7 @@ struct mlx5hws_action_dest_attr {
 	struct mlx5hws_action *dest;
 	/* Optional reformat action */
 	struct mlx5hws_action *reformat;
+	bool is_wire_ft;
 };

 /**


Prompt:
Given the following original C code:
err = PTR_ERR(flow->rule[0]);
		goto err_out;
	}
	flow_flag_set(flow, OFFLOADED);

	return 0;

err_out:
	flow_flag_set(flow, FAILED);
	return err;
}

static bool mlx5_flow_has_geneve_opt(struct mlx5e_tc_flow *flow)
{
	struct mlx5_flow_spec *spec = &flow->attr->parse_attr->spec;
	void *headers_v = MLX5_ADDR_OF(fte_match_param,
				       spec->match_value,
				       misc_parameters_3);
	u32 geneve_tlv_opt_0_data = MLX5_GET(fte_match_set_misc3,
					     headers_v,

Instruction:
net/mlx5e: Fix leak of Geneve TLV option object

Return the diff that fixes it:

Response:
@@ -2028,9 +2028,8 @@ mlx5e_tc_add_fdb_flow(struct mlx5e_priv *priv,
 	return err;
 }

-static bool mlx5_flow_has_geneve_opt(struct mlx5e_tc_flow *flow)
+static bool mlx5_flow_has_geneve_opt(struct mlx5_flow_spec *spec)
 {
-	struct mlx5_flow_spec *spec = &flow->attr->parse_attr->spec;
 	void *headers_v = MLX5_ADDR_OF(fte_match_param,
 				       spec->match_value,
 				       misc_parameters_3);
@@ -2069,7 +2068,7 @@ static void mlx5e_tc_del_fdb_flow(struct mlx5e_priv *priv,
 	}
 	complete_all(&flow->del_hw_done);

-	if (mlx5_flow_has_geneve_opt(flow))
+	if (mlx5_flow_has_geneve_opt(&attr->parse_attr->spec))
 		mlx5_geneve_tlv_option_del(priv->mdev->geneve);

 	if (flow->decap_route)
@@ -2574,12 +2573,13 @@ static int parse_tunnel_attr(struct mlx5e_priv *priv,

 		err = mlx5e_tc_tun_parse(filter_dev, priv, tmp_spec, f, match_level);
 		if (err) {
-			kvfree(tmp_spec);
 			NL_SET_ERR_MSG_MOD(extack, "Failed to parse tunnel attributes");
 			netdev_warn(priv->netdev, "Failed to parse tunnel attributes");
-			return err;
+		} else {
+			err = mlx5e_tc_set_attr_rx_tun(flow, tmp_spec);
 		}
-		err = mlx5e_tc_set_attr_rx_tun(flow, tmp_spec);
+		if (mlx5_flow_has_geneve_opt(tmp_spec))
+			mlx5_geneve_tlv_option_del(priv->mdev->geneve);
 		kvfree(tmp_spec);
 		if (err)
 			return err;


Prompt:
Given the following original C code:
#include <linux/ethtool_netlink.h>

#include "en.h"
#include "en/channels.h"
#include "en/dim.h"
#include "en/port.h"
#include "en/params.h"
#include "en/ptp.h"
#include "lib/clock.h"
#include "en/fs_ethtool.h"

#define LANES_UNKNOWN		 0
#define MAX_LANES		 8

void mlx5e_ethtool_get_drvinfo(struct mlx5e_priv *priv,
			       struct ethtool_drvinfo *drvinfo)
{
	struct mlx5_core_dev *mdev = priv->mdev;
	int count;

Instruction:
net/mlx5e: Fix number of lanes to UNKNOWN when using data_rate_oper

Return the diff that fixes it:

Response:
@@ -43,7 +43,6 @@
 #include "en/fs_ethtool.h"

 #define LANES_UNKNOWN		 0
-#define MAX_LANES		 8

 void mlx5e_ethtool_get_drvinfo(struct mlx5e_priv *priv,
 			       struct ethtool_drvinfo *drvinfo)
@@ -1098,10 +1097,8 @@ static void get_link_properties(struct net_device *netdev,
 		speed = info->speed;
 		lanes = info->lanes;
 		duplex = DUPLEX_FULL;
-	} else if (data_rate_oper) {
+	} else if (data_rate_oper)
 		speed = 100 * data_rate_oper;
-		lanes = MAX_LANES;
-	}

 out:
 	link_ksettings->base.duplex = duplex;


Prompt:
Given the following original C code:
*
 *   E is the exclusive marker that is not stored in swap entries.
 */
extern inline pte_t mk_swap_pte(unsigned long type, unsigned long offset)
{ pte_t pte; pte_val(pte) = ((type & 0x7f) << 32) | (offset << 40); return pte; }

#define __swp_type(x)		(((x).val >> 32) & 0x7f)
#define __swp_offset(x)		((x).val >> 40)
#define __swp_entry(type, off)	((swp_entry_t) { pte_val(mk_swap_pte((type), (off))) })
#define __pte_to_swp_entry(pte)	((swp_entry_t) { pte_val(pte) })
#define __swp_entry_to_pte(x)	((pte_t) { (x).val })

static inline int pte_swp_exclusive(pte_t pte)
{
	return pte_val(pte) & _PAGE_SWP_EXCLUSIVE;
}

static inline pte_t pte_swp_mkexclusive(pte_t pte)
{
	pte_val(pte) |= _PAGE_SWP_EXCLUSIVE;

Instruction:
mm: pgtable: fix pte_swp_exclusive

Return the diff that fixes it:

Response:
@@ -327,7 +327,7 @@ extern inline pte_t mk_swap_pte(unsigned long type, unsigned long offset)
 #define __pte_to_swp_entry(pte)	((swp_entry_t) { pte_val(pte) })
 #define __swp_entry_to_pte(x)	((pte_t) { (x).val })

-static inline int pte_swp_exclusive(pte_t pte)
+static inline bool pte_swp_exclusive(pte_t pte)
 {
 	return pte_val(pte) & _PAGE_SWP_EXCLUSIVE;
 }


Prompt:
Given the following original C code:
*   The zero'ed bits include _PAGE_PRESENT.
 */
#define __swp_entry(type, off)		((swp_entry_t) \
					{ ((type) & 0x1f) | ((off) << 13) })

/* Decode a PTE containing swap "identifier "into constituents */
#define __swp_type(pte_lookalike)	(((pte_lookalike).val) & 0x1f)
#define __swp_offset(pte_lookalike)	((pte_lookalike).val >> 13)

#define __pte_to_swp_entry(pte)		((swp_entry_t) { pte_val(pte) })
#define __swp_entry_to_pte(x)		((pte_t) { (x).val })

static inline int pte_swp_exclusive(pte_t pte)
{
	return pte_val(pte) & _PAGE_SWP_EXCLUSIVE;
}

PTE_BIT_FUNC(swp_mkexclusive, |= (_PAGE_SWP_EXCLUSIVE));
PTE_BIT_FUNC(swp_clear_exclusive, &= ~(_PAGE_SWP_EXCLUSIVE));

Instruction:
mm: pgtable: fix pte_swp_exclusive

Return the diff that fixes it:

Response:
@@ -130,7 +130,7 @@ void update_mmu_cache_range(struct vm_fault *vmf, struct vm_area_struct *vma,
 #define __pte_to_swp_entry(pte)		((swp_entry_t) { pte_val(pte) })
 #define __swp_entry_to_pte(x)		((pte_t) { (x).val })

-static inline int pte_swp_exclusive(pte_t pte)
+static inline bool pte_swp_exclusive(pte_t pte)
 {
 	return pte_val(pte) & _PAGE_SWP_EXCLUSIVE;
 }


Prompt:
Given the following original C code:
#define __SWP_TYPE_BITS		5
#define __SWP_TYPE_MASK		((1 << __SWP_TYPE_BITS) - 1)
#define __SWP_OFFSET_SHIFT	(__SWP_TYPE_BITS + __SWP_TYPE_SHIFT + 1)

#define __swp_type(x)		(((x).val >> __SWP_TYPE_SHIFT) & __SWP_TYPE_MASK)
#define __swp_offset(x)		((x).val >> __SWP_OFFSET_SHIFT)
#define __swp_entry(type, offset) ((swp_entry_t) { (((type) & __SWP_TYPE_MASK) << __SWP_TYPE_SHIFT) | \
						   ((offset) << __SWP_OFFSET_SHIFT) })

#define __pte_to_swp_entry(pte)	((swp_entry_t) { pte_val(pte) })
#define __swp_entry_to_pte(swp)	__pte((swp).val)

static inline int pte_swp_exclusive(pte_t pte)
{
	return pte_isset(pte, L_PTE_SWP_EXCLUSIVE);
}

static inline pte_t pte_swp_mkexclusive(pte_t pte)
{
	return set_pte_bit(pte, __pgprot(L_PTE_SWP_EXCLUSIVE));

Instruction:
mm: pgtable: fix pte_swp_exclusive

Return the diff that fixes it:

Response:
@@ -301,7 +301,7 @@ static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
 #define __pte_to_swp_entry(pte)	((swp_entry_t) { pte_val(pte) })
 #define __swp_entry_to_pte(swp)	__pte((swp).val)

-static inline int pte_swp_exclusive(pte_t pte)
+static inline bool pte_swp_exclusive(pte_t pte)
 {
 	return pte_isset(pte, L_PTE_SWP_EXCLUSIVE);
 }


Prompt:
Given the following original C code:
}

static inline pgprot_t mk_pmd_sect_prot(pgprot_t prot)
{
	return __pgprot((pgprot_val(prot) & ~PMD_TYPE_MASK) | PMD_TYPE_SECT);
}

static inline pte_t pte_swp_mkexclusive(pte_t pte)
{
	return set_pte_bit(pte, __pgprot(PTE_SWP_EXCLUSIVE));
}

static inline int pte_swp_exclusive(pte_t pte)
{
	return pte_val(pte) & PTE_SWP_EXCLUSIVE;
}

static inline pte_t pte_swp_clear_exclusive(pte_t pte)
{
	return clear_pte_bit(pte, __pgprot(PTE_SWP_EXCLUSIVE));

Instruction:
mm: pgtable: fix pte_swp_exclusive

Return the diff that fixes it:

Response:
@@ -563,7 +563,7 @@ static inline pte_t pte_swp_mkexclusive(pte_t pte)
 	return set_pte_bit(pte, __pgprot(PTE_SWP_EXCLUSIVE));
 }

-static inline int pte_swp_exclusive(pte_t pte)
+static inline bool pte_swp_exclusive(pte_t pte)
 {
 	return pte_val(pte) & PTE_SWP_EXCLUSIVE;
 }


Prompt:
Given the following original C code:
pte_val(pte) |= _PAGE_DIRTY;
	return pte;
}

static inline pte_t pte_mkyoung(pte_t pte)
{
	pte_val(pte) |= _PAGE_ACCESSED;
	if (pte_val(pte) & _PAGE_READ)
		pte_val(pte) |= _PAGE_VALID;
	return pte;
}

static inline int pte_swp_exclusive(pte_t pte)
{
	return pte_val(pte) & _PAGE_SWP_EXCLUSIVE;
}

static inline pte_t pte_swp_mkexclusive(pte_t pte)
{
	pte_val(pte) |= _PAGE_SWP_EXCLUSIVE;

Instruction:
mm: pgtable: fix pte_swp_exclusive

Return the diff that fixes it:

Response:
@@ -200,7 +200,7 @@ static inline pte_t pte_mkyoung(pte_t pte)
 	return pte;
 }

-static inline int pte_swp_exclusive(pte_t pte)
+static inline bool pte_swp_exclusive(pte_t pte)
 {
 	return pte_val(pte) & _PAGE_SWP_EXCLUSIVE;
 }


Prompt:
Given the following original C code:
/* Used for swap PTEs */
#define __swp_type(swp_pte)		(((swp_pte).val >> 1) & 0x1f)

#define __swp_offset(swp_pte) \
	((((swp_pte).val >> 7) & 0x7) | (((swp_pte).val >> 10) & 0x3ffff8))

#define __swp_entry(type, offset) \
	((swp_entry_t)	{ \
		(((type & 0x1f) << 1) | \
		 ((offset & 0x3ffff8) << 10) | ((offset & 0x7) << 7)) })

static inline int pte_swp_exclusive(pte_t pte)
{
	return pte_val(pte) & _PAGE_SWP_EXCLUSIVE;
}

static inline pte_t pte_swp_mkexclusive(pte_t pte)
{
	pte_val(pte) |= _PAGE_SWP_EXCLUSIVE;

Instruction:
mm: pgtable: fix pte_swp_exclusive

Return the diff that fixes it:

Response:
@@ -387,7 +387,7 @@ static inline unsigned long pmd_page_vaddr(pmd_t pmd)
 		(((type & 0x1f) << 1) | \
 		 ((offset & 0x3ffff8) << 10) | ((offset & 0x7) << 7)) })

-static inline int pte_swp_exclusive(pte_t pte)
+static inline bool pte_swp_exclusive(pte_t pte)
 {
 	return pte_val(pte) & _PAGE_SWP_EXCLUSIVE;
 }


Prompt:
Given the following original C code:
*/
static inline pte_t mk_swap_pte(unsigned long type, unsigned long offset)
{ pte_t pte; pte_val(pte) = ((type & 0x7f) << 16) | (offset << 24); return pte; }

#define __swp_type(x)		(((x).val >> 16) & 0x7f)
#define __swp_offset(x)		((x).val >> 24)
#define __swp_entry(type, offset) ((swp_entry_t) { pte_val(mk_swap_pte((type), (offset))) })
#define __pte_to_swp_entry(pte) ((swp_entry_t) { pte_val(pte) })
#define __swp_entry_to_pte(x)	((pte_t) { (x).val })
#define __pmd_to_swp_entry(pmd) ((swp_entry_t) { pmd_val(pmd) })
#define __swp_entry_to_pmd(x)	((pmd_t) { (x).val | _PAGE_HUGE })

static inline int pte_swp_exclusive(pte_t pte)
{
	return pte_val(pte) & _PAGE_SWP_EXCLUSIVE;
}

static inline pte_t pte_swp_mkexclusive(pte_t pte)
{
	pte_val(pte) |= _PAGE_SWP_EXCLUSIVE;

Instruction:
mm: pgtable: fix pte_swp_exclusive

Return the diff that fixes it:

Response:
@@ -301,7 +301,7 @@ static inline pte_t mk_swap_pte(unsigned long type, unsigned long offset)
 #define __pmd_to_swp_entry(pmd) ((swp_entry_t) { pmd_val(pmd) })
 #define __swp_entry_to_pmd(x)	((pmd_t) { (x).val | _PAGE_HUGE })

-static inline int pte_swp_exclusive(pte_t pte)
+static inline bool pte_swp_exclusive(pte_t pte)
 {
 	return pte_val(pte) & _PAGE_SWP_EXCLUSIVE;
 }


Prompt:
Given the following original C code:
*   1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
 *   <------------------ offset -------------> 0 0 0 E <-- type --->
 *
 *   E is the exclusive marker that is not stored in swap entries.
 */
#define __swp_type(x)		((x).val & 0x7f)
#define __swp_offset(x)		((x).val >> 11)
#define __swp_entry(typ, off)	((swp_entry_t) { ((typ) & 0x7f) | \
					(off << 11) })
#define __pte_to_swp_entry(pte)	((swp_entry_t) { pte_val(pte) })
#define __swp_entry_to_pte(x)	(__pte((x).val))

static inline int pte_swp_exclusive(pte_t pte)
{
	return pte_val(pte) & _PAGE_SWP_EXCLUSIVE;
}

static inline pte_t pte_swp_mkexclusive(pte_t pte)
{
	pte_val(pte) |= _PAGE_SWP_EXCLUSIVE;

Instruction:
mm: pgtable: fix pte_swp_exclusive

Return the diff that fixes it:

Response:
@@ -268,7 +268,7 @@ extern pgd_t kernel_pg_dir[PTRS_PER_PGD];
 #define __pte_to_swp_entry(pte)	((swp_entry_t) { pte_val(pte) })
 #define __swp_entry_to_pte(x)	(__pte((x).val))

-static inline int pte_swp_exclusive(pte_t pte)
+static inline bool pte_swp_exclusive(pte_t pte)
 {
 	return pte_val(pte) & _PAGE_SWP_EXCLUSIVE;
 }


Prompt:
Given the following original C code:
*   3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1
 *   1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
 *   <----------------- offset ------------> E <-- type ---> 0 0 0 0
 *
 *   E is the exclusive marker that is not stored in swap entries.
 */
#define __swp_type(x)		(((x).val >> 4) & 0x7f)
#define __swp_offset(x)		((x).val >> 12)
#define __swp_entry(type, offset) ((swp_entry_t) { (((type) & 0x7f) << 4) | ((offset) << 12) })
#define __pte_to_swp_entry(pte)	((swp_entry_t) { pte_val(pte) })
#define __swp_entry_to_pte(x)	((pte_t) { (x).val })

static inline int pte_swp_exclusive(pte_t pte)
{
	return pte_val(pte) & _PAGE_SWP_EXCLUSIVE;
}

static inline pte_t pte_swp_mkexclusive(pte_t pte)
{
	pte_val(pte) |= _PAGE_SWP_EXCLUSIVE;

Instruction:
mm: pgtable: fix pte_swp_exclusive

Return the diff that fixes it:

Response:
@@ -185,7 +185,7 @@ extern pgd_t kernel_pg_dir[128];
 #define __pte_to_swp_entry(pte)	((swp_entry_t) { pte_val(pte) })
 #define __swp_entry_to_pte(x)	((pte_t) { (x).val })

-static inline int pte_swp_exclusive(pte_t pte)
+static inline bool pte_swp_exclusive(pte_t pte)
 {
 	return pte_val(pte) & _PAGE_SWP_EXCLUSIVE;
 }


Prompt:
Given the following original C code:
*   1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
 *   0 <--------------------- offset ----------------> E <- type -->
 *
 *   E is the exclusive marker that is not stored in swap entries.
 */
#define __swp_type(x)		((x).val & 0x3f)
#define __swp_offset(x)		(((x).val) >> 7)
#define __swp_entry(type, offset) ((swp_entry_t) { (((type) & 0x3f) | \
						   (((offset) << 7) & ~SUN3_PAGE_VALID)) })
#define __pte_to_swp_entry(pte)	((swp_entry_t) { pte_val(pte) })
#define __swp_entry_to_pte(x)	((pte_t) { (x).val })

static inline int pte_swp_exclusive(pte_t pte)
{
	return pte_val(pte) & _PAGE_SWP_EXCLUSIVE;
}

static inline pte_t pte_swp_mkexclusive(pte_t pte)
{
	pte_val(pte) |= _PAGE_SWP_EXCLUSIVE;

Instruction:
mm: pgtable: fix pte_swp_exclusive

Return the diff that fixes it:

Response:
@@ -169,7 +169,7 @@ extern pgd_t kernel_pg_dir[PTRS_PER_PGD];
 #define __pte_to_swp_entry(pte)	((swp_entry_t) { pte_val(pte) })
 #define __swp_entry_to_pte(x)	((pte_t) { (x).val })

-static inline int pte_swp_exclusive(pte_t pte)
+static inline bool pte_swp_exclusive(pte_t pte)
 {
 	return pte_val(pte) & _PAGE_SWP_EXCLUSIVE;
 }


Prompt:
Given the following original C code:
*   0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
 *   <------------------ offset -------------------> E < type -> 0 0
 *
 *   E is the exclusive marker that is not stored in swap entries.
 */
#define __swp_type(entry)	((entry).val & 0x1f)
#define __swp_offset(entry)	((entry).val >> 6)
#define __swp_entry(type, offset) \
		((swp_entry_t) { ((type) & 0x1f) | ((offset) << 6) })
#define __pte_to_swp_entry(pte)	((swp_entry_t) { pte_val(pte) >> 2 })
#define __swp_entry_to_pte(x)	((pte_t) { (x).val << 2 })

static inline int pte_swp_exclusive(pte_t pte)
{
	return pte_val(pte) & _PAGE_SWP_EXCLUSIVE;
}

static inline pte_t pte_swp_mkexclusive(pte_t pte)
{
	pte_val(pte) |= _PAGE_SWP_EXCLUSIVE;

Instruction:
mm: pgtable: fix pte_swp_exclusive

Return the diff that fixes it:

Response:
@@ -398,7 +398,7 @@ extern pgd_t swapper_pg_dir[PTRS_PER_PGD];
 #define __pte_to_swp_entry(pte)	((swp_entry_t) { pte_val(pte) >> 2 })
 #define __swp_entry_to_pte(x)	((pte_t) { (x).val << 2 })

-static inline int pte_swp_exclusive(pte_t pte)
+static inline bool pte_swp_exclusive(pte_t pte)
 {
 	return pte_val(pte) & _PAGE_SWP_EXCLUSIVE;
 }


Prompt:
Given the following original C code:
#else
static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
{
	pte_val(pte) &= _PAGE_CHG_MASK;
	pte_val(pte) |= pgprot_val(newprot) & ~_PAGE_CHG_MASK;
	if ((pte_val(pte) & _PAGE_ACCESSED) && !(pte_val(pte) & _PAGE_NO_READ))
		pte_val(pte) |= _PAGE_SILENT_READ;
	return pte;
}
#endif

#if defined(CONFIG_PHYS_ADDR_T_64BIT) && defined(CONFIG_CPU_MIPS32)
static inline int pte_swp_exclusive(pte_t pte)
{
	return pte.pte_low & _PAGE_SWP_EXCLUSIVE;
}

static inline pte_t pte_swp_mkexclusive(pte_t pte)
{
	pte.pte_low |= _PAGE_SWP_EXCLUSIVE;

Instruction:
mm: pgtable: fix pte_swp_exclusive

Return the diff that fixes it:

Response:
@@ -534,7 +534,7 @@ static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
 #endif

 #if defined(CONFIG_PHYS_ADDR_T_64BIT) && defined(CONFIG_CPU_MIPS32)
-static inline int pte_swp_exclusive(pte_t pte)
+static inline bool pte_swp_exclusive(pte_t pte)
 {
 	return pte.pte_low & _PAGE_SWP_EXCLUSIVE;
 }
@@ -551,7 +551,7 @@ static inline pte_t pte_swp_clear_exclusive(pte_t pte)
 	return pte;
 }
 #else
-static inline int pte_swp_exclusive(pte_t pte)
+static inline bool pte_swp_exclusive(pte_t pte)
 {
 	return pte_val(pte) & _PAGE_SWP_EXCLUSIVE;
 }


Prompt:
Given the following original C code:
*   E is the exclusive marker that is not stored in swap entries.
 *
 * Note that the offset field is always non-zero if the swap type is 0, thus
 * !pte_none() is always true.
 */
#define __swp_type(swp)		(((swp).val >> 26) & 0x1f)
#define __swp_offset(swp)	((swp).val & 0xfffff)
#define __swp_entry(type, off)	((swp_entry_t) { (((type) & 0x1f) << 26) \
						 | ((off) & 0xfffff) })
#define __swp_entry_to_pte(swp)	((pte_t) { (swp).val })
#define __pte_to_swp_entry(pte)	((swp_entry_t) { pte_val(pte) })

static inline int pte_swp_exclusive(pte_t pte)
{
	return pte_val(pte) & _PAGE_SWP_EXCLUSIVE;
}

static inline pte_t pte_swp_mkexclusive(pte_t pte)
{
	pte_val(pte) |= _PAGE_SWP_EXCLUSIVE;

Instruction:
mm: pgtable: fix pte_swp_exclusive

Return the diff that fixes it:

Response:
@@ -259,7 +259,7 @@ static inline unsigned long pmd_page_vaddr(pmd_t pmd)
 #define __swp_entry_to_pte(swp)	((pte_t) { (swp).val })
 #define __pte_to_swp_entry(pte)	((swp_entry_t) { pte_val(pte) })

-static inline int pte_swp_exclusive(pte_t pte)
+static inline bool pte_swp_exclusive(pte_t pte)
 {
 	return pte_val(pte) & _PAGE_SWP_EXCLUSIVE;
 }


Prompt:
Given the following original C code:
*   <-------------- offset ---------------> E <- type --> 0 0 0 0 0
 *
 *   E is the exclusive marker that is not stored in swap entries.
 *   The zero'ed bits include _PAGE_PRESENT.
 */
#define __swp_type(x)			(((x).val >> 5) & 0x3f)
#define __swp_offset(x)			((x).val >> 12)
#define __swp_entry(type, offset) \
	((swp_entry_t) { (((type) & 0x3f) << 5) | ((offset) << 12) })
#define __pte_to_swp_entry(pte)		((swp_entry_t) { pte_val(pte) })
#define __swp_entry_to_pte(x)		((pte_t) { (x).val })

static inline int pte_swp_exclusive(pte_t pte)
{
	return pte_val(pte) & _PAGE_SWP_EXCLUSIVE;
}

static inline pte_t pte_swp_mkexclusive(pte_t pte)
{
	pte_val(pte) |= _PAGE_SWP_EXCLUSIVE;

Instruction:
mm: pgtable: fix pte_swp_exclusive

Return the diff that fixes it:

Response:
@@ -411,7 +411,7 @@ static inline void update_mmu_cache_range(struct vm_fault *vmf,
 #define __pte_to_swp_entry(pte)		((swp_entry_t) { pte_val(pte) })
 #define __swp_entry_to_pte(x)		((pte_t) { (x).val })

-static inline int pte_swp_exclusive(pte_t pte)
+static inline bool pte_swp_exclusive(pte_t pte)
 {
 	return pte_val(pte) & _PAGE_SWP_EXCLUSIVE;
 }


Prompt:
Given the following original C code:
*   For the 64bit version, the offset is extended by 32bit.
 */
#define __swp_type(x)                     ((x).val & 0x1f)
#define __swp_offset(x)                   ( (((x).val >> 5) & 0x7) | \
					  (((x).val >> 10) << 3) )
#define __swp_entry(type, offset)         ((swp_entry_t) { \
					    ((type) & 0x1f) | \
					    ((offset & 0x7) << 5) | \
					    ((offset >> 3) << 10) })
#define __pte_to_swp_entry(pte)		((swp_entry_t) { pte_val(pte) })
#define __swp_entry_to_pte(x)		((pte_t) { (x).val })

static inline int pte_swp_exclusive(pte_t pte)
{
	return pte_val(pte) & _PAGE_SWP_EXCLUSIVE;
}

static inline pte_t pte_swp_mkexclusive(pte_t pte)
{
	pte_val(pte) |= _PAGE_SWP_EXCLUSIVE;

Instruction:
mm: pgtable: fix pte_swp_exclusive

Return the diff that fixes it:

Response:
@@ -425,7 +425,7 @@ static inline void set_ptes(struct mm_struct *mm, unsigned long addr,
 #define __pte_to_swp_entry(pte)		((swp_entry_t) { pte_val(pte) })
 #define __swp_entry_to_pte(x)		((pte_t) { (x).val })

-static inline int pte_swp_exclusive(pte_t pte)
+static inline bool pte_swp_exclusive(pte_t pte)
 {
 	return pte_val(pte) & _PAGE_SWP_EXCLUSIVE;
 }


Prompt:
Given the following original C code:
*
 *   E is the exclusive marker that is not stored in swap entries.
 *   _PAGE_PRESENT (P) and __PAGE_HASHPTE (H) must be 0.
 *
 * For 64bit PTEs, the offset is extended by 32bit.
 */
#define __swp_type(entry)		((entry).val & 0x1f)
#define __swp_offset(entry)		((entry).val >> 5)
#define __swp_entry(type, offset)	((swp_entry_t) { ((type) & 0x1f) | ((offset) << 5) })
#define __pte_to_swp_entry(pte)		((swp_entry_t) { pte_val(pte) >> 3 })
#define __swp_entry_to_pte(x)		((pte_t) { (x).val << 3 })

static inline int pte_swp_exclusive(pte_t pte)
{
	return pte_val(pte) & _PAGE_SWP_EXCLUSIVE;
}

static inline pte_t pte_swp_mkexclusive(pte_t pte)
{
	return __pte(pte_val(pte) | _PAGE_SWP_EXCLUSIVE);

Instruction:
mm: pgtable: fix pte_swp_exclusive

Return the diff that fixes it:

Response:
@@ -365,7 +365,7 @@ static inline void __ptep_set_access_flags(struct vm_area_struct *vma,
 #define __pte_to_swp_entry(pte)		((swp_entry_t) { pte_val(pte) >> 3 })
 #define __swp_entry_to_pte(x)		((pte_t) { (x).val << 3 })

-static inline int pte_swp_exclusive(pte_t pte)
+static inline bool pte_swp_exclusive(pte_t pte)
 {
 	return pte_val(pte) & _PAGE_SWP_EXCLUSIVE;
 }


Prompt:
Given the following original C code:
static inline pte_t pte_swp_clear_soft_dirty(pte_t pte)
{
	return __pte_raw(pte_raw(pte) & cpu_to_be64(~_PAGE_SWP_SOFT_DIRTY));
}
#endif /* CONFIG_HAVE_ARCH_SOFT_DIRTY */

static inline pte_t pte_swp_mkexclusive(pte_t pte)
{
	return __pte_raw(pte_raw(pte) | cpu_to_be64(_PAGE_SWP_EXCLUSIVE));
}

static inline int pte_swp_exclusive(pte_t pte)
{
	return !!(pte_raw(pte) & cpu_to_be64(_PAGE_SWP_EXCLUSIVE));
}

static inline pte_t pte_swp_clear_exclusive(pte_t pte)
{
	return __pte_raw(pte_raw(pte) & cpu_to_be64(~_PAGE_SWP_EXCLUSIVE));

Instruction:
mm: pgtable: fix pte_swp_exclusive

Return the diff that fixes it:

Response:
@@ -693,7 +693,7 @@ static inline pte_t pte_swp_mkexclusive(pte_t pte)
 	return __pte_raw(pte_raw(pte) | cpu_to_be64(_PAGE_SWP_EXCLUSIVE));
 }

-static inline int pte_swp_exclusive(pte_t pte)
+static inline bool pte_swp_exclusive(pte_t pte)
 {
 	return !!(pte_raw(pte) & cpu_to_be64(_PAGE_SWP_EXCLUSIVE));
 }


Prompt:
Given the following original C code:
#ifndef pte_mkhuge
static inline pte_t pte_mkhuge(pte_t pte)
{
	return __pte(pte_val(pte));
}
#endif

static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
{
	return __pte((pte_val(pte) & _PAGE_CHG_MASK) | pgprot_val(newprot));
}

static inline int pte_swp_exclusive(pte_t pte)
{
	return pte_val(pte) & _PAGE_SWP_EXCLUSIVE;
}

static inline pte_t pte_swp_mkexclusive(pte_t pte)
{
	return __pte(pte_val(pte) | _PAGE_SWP_EXCLUSIVE);

Instruction:
mm: pgtable: fix pte_swp_exclusive

Return the diff that fixes it:

Response:
@@ -286,7 +286,7 @@ static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
 	return __pte((pte_val(pte) & _PAGE_CHG_MASK) | pgprot_val(newprot));
 }

-static inline int pte_swp_exclusive(pte_t pte)
+static inline bool pte_swp_exclusive(pte_t pte)
 {
 	return pte_val(pte) & _PAGE_SWP_EXCLUSIVE;
 }


Prompt:
Given the following original C code:
#define MAX_SWAPFILES_CHECK()	\
	BUILD_BUG_ON(MAX_SWAPFILES_SHIFT > __SWP_TYPE_BITS)

#define __swp_type(x)	(((x).val >> __SWP_TYPE_SHIFT) & __SWP_TYPE_MASK)
#define __swp_offset(x)	((x).val >> __SWP_OFFSET_SHIFT)
#define __swp_entry(type, offset) ((swp_entry_t) \
	{ (((type) & __SWP_TYPE_MASK) << __SWP_TYPE_SHIFT) | \
	  ((offset) << __SWP_OFFSET_SHIFT) })

#define __pte_to_swp_entry(pte)	((swp_entry_t) { pte_val(pte) })
#define __swp_entry_to_pte(x)	((pte_t) { (x).val })

static inline int pte_swp_exclusive(pte_t pte)
{
	return pte_val(pte) & _PAGE_SWP_EXCLUSIVE;
}

static inline pte_t pte_swp_mkexclusive(pte_t pte)
{
	return __pte(pte_val(pte) | _PAGE_SWP_EXCLUSIVE);

Instruction:
mm: pgtable: fix pte_swp_exclusive

Return the diff that fixes it:

Response:
@@ -1028,7 +1028,7 @@ static inline pud_t pud_modify(pud_t pud, pgprot_t newprot)
 #define __pte_to_swp_entry(pte)	((swp_entry_t) { pte_val(pte) })
 #define __swp_entry_to_pte(x)	((pte_t) { (x).val })

-static inline int pte_swp_exclusive(pte_t pte)
+static inline bool pte_swp_exclusive(pte_t pte)
 {
 	return pte_val(pte) & _PAGE_SWP_EXCLUSIVE;
 }


Prompt:
Given the following original C code:
static inline int pte_protnone(pte_t pte)
{
	return pte_present(pte) && !(pte_val(pte) & _PAGE_READ);
}

static inline int pmd_protnone(pmd_t pmd)
{
	/* pmd_leaf(pmd) implies pmd_present(pmd) */
	return pmd_leaf(pmd) && !(pmd_val(pmd) & _SEGMENT_ENTRY_READ);
}
#endif

static inline int pte_swp_exclusive(pte_t pte)
{
	return pte_val(pte) & _PAGE_SWP_EXCLUSIVE;
}

static inline pte_t pte_swp_mkexclusive(pte_t pte)
{
	return set_pte_bit(pte, __pgprot(_PAGE_SWP_EXCLUSIVE));

Instruction:
mm: pgtable: fix pte_swp_exclusive

Return the diff that fixes it:

Response:
@@ -915,7 +915,7 @@ static inline int pmd_protnone(pmd_t pmd)
 }
 #endif

-static inline int pte_swp_exclusive(pte_t pte)
+static inline bool pte_swp_exclusive(pte_t pte)
 {
 	return pte_val(pte) & _PAGE_SWP_EXCLUSIVE;
 }


Prompt:
Given the following original C code:
*/
#define __swp_type(x)			((x).val & 0x1f)
#define __swp_offset(x)			((x).val >> 10)
#define __swp_entry(type, offset)	((swp_entry_t){((type) & 0x1f) | (offset) << 10})

#define __pte_to_swp_entry(pte)		((swp_entry_t) { pte_val(pte) >> 1 })
#define __swp_entry_to_pte(x)		((pte_t) { (x).val << 1 })
#endif

/* In both cases, we borrow bit 6 to store the exclusive marker in swap PTEs. */
#define _PAGE_SWP_EXCLUSIVE	_PAGE_USER

static inline int pte_swp_exclusive(pte_t pte)
{
	return pte.pte_low & _PAGE_SWP_EXCLUSIVE;
}

PTE_BIT_FUNC(low, swp_mkexclusive, |= _PAGE_SWP_EXCLUSIVE);
PTE_BIT_FUNC(low, swp_clear_exclusive, &= ~_PAGE_SWP_EXCLUSIVE);

Instruction:
mm: pgtable: fix pte_swp_exclusive

Return the diff that fixes it:

Response:
@@ -470,7 +470,7 @@ static inline unsigned long pmd_page_vaddr(pmd_t pmd)
 /* In both cases, we borrow bit 6 to store the exclusive marker in swap PTEs. */
 #define _PAGE_SWP_EXCLUSIVE	_PAGE_USER

-static inline int pte_swp_exclusive(pte_t pte)
+static inline bool pte_swp_exclusive(pte_t pte)
 {
 	return pte.pte_low & _PAGE_SWP_EXCLUSIVE;
 }


Prompt:
Given the following original C code:
}

static inline swp_entry_t __swp_entry(unsigned long type, unsigned long offset)
{
	return (swp_entry_t) {
		(type & SRMMU_SWP_TYPE_MASK) << SRMMU_SWP_TYPE_SHIFT
		| (offset & SRMMU_SWP_OFF_MASK) << SRMMU_SWP_OFF_SHIFT };
}

#define __pte_to_swp_entry(pte)		((swp_entry_t) { pte_val(pte) })
#define __swp_entry_to_pte(x)		((pte_t) { (x).val })

static inline int pte_swp_exclusive(pte_t pte)
{
	return pte_val(pte) & SRMMU_SWP_EXCLUSIVE;
}

static inline pte_t pte_swp_mkexclusive(pte_t pte)
{
	return __pte(pte_val(pte) | SRMMU_SWP_EXCLUSIVE);

Instruction:
mm: pgtable: fix pte_swp_exclusive

Return the diff that fixes it:

Response:
@@ -348,7 +348,7 @@ static inline swp_entry_t __swp_entry(unsigned long type, unsigned long offset)
 #define __pte_to_swp_entry(pte)		((swp_entry_t) { pte_val(pte) })
 #define __swp_entry_to_pte(x)		((pte_t) { (x).val })

-static inline int pte_swp_exclusive(pte_t pte)
+static inline bool pte_swp_exclusive(pte_t pte)
 {
 	return pte_val(pte) & SRMMU_SWP_EXCLUSIVE;
 }


Prompt:
Given the following original C code:
*/
#define __swp_type(entry)	(((entry).val >> PAGE_SHIFT) & 0x7fUL)
#define __swp_offset(entry)	((entry).val >> (PAGE_SHIFT + 8UL))
#define __swp_entry(type, offset)	\
	( (swp_entry_t) \
	  { \
		((((long)(type) & 0x7fUL) << PAGE_SHIFT) | \
                 ((long)(offset) << (PAGE_SHIFT + 8UL))) \
	  } )
#define __pte_to_swp_entry(pte)		((swp_entry_t) { pte_val(pte) })
#define __swp_entry_to_pte(x)		((pte_t) { (x).val })

static inline int pte_swp_exclusive(pte_t pte)
{
	return pte_val(pte) & _PAGE_SWP_EXCLUSIVE;
}

static inline pte_t pte_swp_mkexclusive(pte_t pte)
{
	return __pte(pte_val(pte) | _PAGE_SWP_EXCLUSIVE);

Instruction:
mm: pgtable: fix pte_swp_exclusive

Return the diff that fixes it:

Response:
@@ -1023,7 +1023,7 @@ pgtable_t pgtable_trans_huge_withdraw(struct mm_struct *mm, pmd_t *pmdp);
 #define __pte_to_swp_entry(pte)		((swp_entry_t) { pte_val(pte) })
 #define __swp_entry_to_pte(x)		((pte_t) { (x).val })

-static inline int pte_swp_exclusive(pte_t pte)
+static inline bool pte_swp_exclusive(pte_t pte)
 {
 	return pte_val(pte) & _PAGE_SWP_EXCLUSIVE;
 }


Prompt:
Given the following original C code:
*   E is the exclusive marker that is not stored in swap entries.
 *   _PAGE_NEEDSYNC (bit 1) is always set to 1 in set_pte().
 */
#define __swp_type(x)			(((x).val >> 5) & 0x1f)
#define __swp_offset(x)			((x).val >> 11)

#define __swp_entry(type, offset) \
	((swp_entry_t) { (((type) & 0x1f) << 5) | ((offset) << 11) })
#define __pte_to_swp_entry(pte) \
	((swp_entry_t) { pte_val(pte_mkuptodate(pte)) })
#define __swp_entry_to_pte(x)		((pte_t) { (x).val })

static inline int pte_swp_exclusive(pte_t pte)
{
	return pte_get_bits(pte, _PAGE_SWP_EXCLUSIVE);
}

static inline pte_t pte_swp_mkexclusive(pte_t pte)
{
	pte_set_bits(pte, _PAGE_SWP_EXCLUSIVE);

Instruction:
mm: pgtable: fix pte_swp_exclusive

Return the diff that fixes it:

Response:
@@ -314,7 +314,7 @@ extern pte_t *virt_to_pte(struct mm_struct *mm, unsigned long addr);
 	((swp_entry_t) { pte_val(pte_mkuptodate(pte)) })
 #define __swp_entry_to_pte(x)		((pte_t) { (x).val })

-static inline int pte_swp_exclusive(pte_t pte)
+static inline bool pte_swp_exclusive(pte_t pte)
 {
 	return pte_get_bits(pte, _PAGE_SWP_EXCLUSIVE);
 }


Prompt:
Given the following original C code:
unsigned long addr, pmd_t *pmd)
{
}
static inline void update_mmu_cache_pud(struct vm_area_struct *vma,
		unsigned long addr, pud_t *pud)
{
}
static inline pte_t pte_swp_mkexclusive(pte_t pte)
{
	return pte_set_flags(pte, _PAGE_SWP_EXCLUSIVE);
}

static inline int pte_swp_exclusive(pte_t pte)
{
	return pte_flags(pte) & _PAGE_SWP_EXCLUSIVE;
}

static inline pte_t pte_swp_clear_exclusive(pte_t pte)
{
	return pte_clear_flags(pte, _PAGE_SWP_EXCLUSIVE);

Instruction:
mm: pgtable: fix pte_swp_exclusive

Return the diff that fixes it:

Response:
@@ -1561,7 +1561,7 @@ static inline pte_t pte_swp_mkexclusive(pte_t pte)
 	return pte_set_flags(pte, _PAGE_SWP_EXCLUSIVE);
 }

-static inline int pte_swp_exclusive(pte_t pte)
+static inline bool pte_swp_exclusive(pte_t pte)
 {
 	return pte_flags(pte) & _PAGE_SWP_EXCLUSIVE;
 }


Prompt:
Given the following original C code:
* are !pte_none() && !pte_present().
 */
#define MAX_SWAPFILES_CHECK() BUILD_BUG_ON(MAX_SWAPFILES_SHIFT > 5)

#define __swp_type(entry)	(((entry).val >> 6) & 0x1f)
#define __swp_offset(entry)	((entry).val >> 11)
#define __swp_entry(type,offs)	\
	((swp_entry_t){(((type) & 0x1f) << 6) | ((offs) << 11) | \
	 _PAGE_CA_INVALID | _PAGE_USER})
#define __pte_to_swp_entry(pte)	((swp_entry_t) { pte_val(pte) })
#define __swp_entry_to_pte(x)	((pte_t) { (x).val })

static inline int pte_swp_exclusive(pte_t pte)
{
	return pte_val(pte) & _PAGE_SWP_EXCLUSIVE;
}

static inline pte_t pte_swp_mkexclusive(pte_t pte)
{
	pte_val(pte) |= _PAGE_SWP_EXCLUSIVE;

Instruction:
mm: pgtable: fix pte_swp_exclusive

Return the diff that fixes it:

Response:
@@ -349,7 +349,7 @@ ptep_set_wrprotect(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
 #define __pte_to_swp_entry(pte)	((swp_entry_t) { pte_val(pte) })
 #define __swp_entry_to_pte(x)	((pte_t) { (x).val })

-static inline int pte_swp_exclusive(pte_t pte)
+static inline bool pte_swp_exclusive(pte_t pte)
 {
 	return pte_val(pte) & _PAGE_SWP_EXCLUSIVE;
 }


Prompt:
Given the following original C code:
bpf_compute_data_pointers(skb);
	return ret;
}

static const struct bpf_func_proto bpf_skb_vlan_pop_proto = {
	.func           = bpf_skb_vlan_pop,
	.gpl_only       = false,
	.ret_type       = RET_INTEGER,
	.arg1_type      = ARG_PTR_TO_CTX,
};

static int bpf_skb_generic_push(struct sk_buff *skb, u32 off, u32 len)
{
	/* Caller already did skb_cow() with len as headroom,
	 * so no need to do it here.
	 */
	skb_push(skb, len);
	memmove(skb->data, skb->data + len, off);
	memset(skb->data + off, 0, len);

Instruction:
net: clear the dst when changing skb protocol

Return the diff that fixes it:

Response:
@@ -3233,6 +3233,13 @@ static const struct bpf_func_proto bpf_skb_vlan_pop_proto = {
 	.arg1_type      = ARG_PTR_TO_CTX,
 };

+static void bpf_skb_change_protocol(struct sk_buff *skb, u16 proto)
+{
+	skb->protocol = htons(proto);
+	if (skb_valid_dst(skb))
+		skb_dst_drop(skb);
+}
+
 static int bpf_skb_generic_push(struct sk_buff *skb, u32 off, u32 len)
 {
 	/* Caller already did skb_cow() with len as headroom,
@@ -3329,7 +3336,7 @@ static int bpf_skb_proto_4_to_6(struct sk_buff *skb)
 		}
 	}

-	skb->protocol = htons(ETH_P_IPV6);
+	bpf_skb_change_protocol(skb, ETH_P_IPV6);
 	skb_clear_hash(skb);

 	return 0;
@@ -3359,7 +3366,7 @@ static int bpf_skb_proto_6_to_4(struct sk_buff *skb)
 		}
 	}

-	skb->protocol = htons(ETH_P_IP);
+	bpf_skb_change_protocol(skb, ETH_P_IP);
 	skb_clear_hash(skb);

 	return 0;
@@ -3550,10 +3557,10 @@ static int bpf_skb_net_grow(struct sk_buff *skb, u32 off, u32 len_diff,
 		/* Match skb->protocol to new outer l3 protocol */
 		if (skb->protocol == htons(ETH_P_IP) &&
 		    flags & BPF_F_ADJ_ROOM_ENCAP_L3_IPV6)
-			skb->protocol = htons(ETH_P_IPV6);
+			bpf_skb_change_protocol(skb, ETH_P_IPV6);
 		else if (skb->protocol == htons(ETH_P_IPV6) &&
 			 flags & BPF_F_ADJ_ROOM_ENCAP_L3_IPV4)
-			skb->protocol = htons(ETH_P_IP);
+			bpf_skb_change_protocol(skb, ETH_P_IP);
 	}

 	if (skb_is_gso(skb)) {
@@ -3606,10 +3613,10 @@ static int bpf_skb_net_shrink(struct sk_buff *skb, u32 off, u32 len_diff,
 	/* Match skb->protocol to new outer l3 protocol */
 	if (skb->protocol == htons(ETH_P_IP) &&
 	    flags & BPF_F_ADJ_ROOM_DECAP_L3_IPV6)
-		skb->protocol = htons(ETH_P_IPV6);
+		bpf_skb_change_protocol(skb, ETH_P_IPV6);
 	else if (skb->protocol == htons(ETH_P_IPV6) &&
 		 flags & BPF_F_ADJ_ROOM_DECAP_L3_IPV4)
-		skb->protocol = htons(ETH_P_IP);
+		bpf_skb_change_protocol(skb, ETH_P_IP);

 	if (skb_is_gso(skb)) {
 		struct skb_shared_info *shinfo = skb_shinfo(skb);


Prompt:
Given the following original C code:
if (bch2_btree_node_is_stale(c, cur)) {
			bch_info(c, "btree node older than nodes found by scanning\n  %s", buf.buf);
			six_unlock_read(&cur->c.lock);
			bch2_btree_node_evict(trans, cur_k.k);
			ret = bch2_journal_key_delete(c, b->c.btree_id,
						      b->c.level, cur_k.k->k.p);
			cur = NULL;
			if (ret)
				break;
			continue;
		}

		ret = btree_check_node_boundaries(trans, b, prev, cur, pulled_from_scan);
		if (ret == DID_FILL_FROM_SCAN) {
			new_pass = true;
			ret = 0;
		}

		if (ret == DROP_THIS_NODE) {
			six_unlock_read(&cur->c.lock);

Instruction:
bcachefs: Add missing restart handling to check_topology()

Return the diff that fixes it:

Response:
@@ -397,7 +397,11 @@ static int bch2_btree_repair_topology_recurse(struct btree_trans *trans, struct
 			continue;
 		}

-		ret = btree_check_node_boundaries(trans, b, prev, cur, pulled_from_scan);
+		ret = lockrestart_do(trans,
+			btree_check_node_boundaries(trans, b, prev, cur, pulled_from_scan));
+		if (ret < 0)
+			goto err;
+
 		if (ret == DID_FILL_FROM_SCAN) {
 			new_pass = true;
 			ret = 0;
@@ -438,7 +442,8 @@ static int bch2_btree_repair_topology_recurse(struct btree_trans *trans, struct

 	if (!ret && !IS_ERR_OR_NULL(prev)) {
 		BUG_ON(cur);
-		ret = btree_repair_node_end(trans, b, prev, pulled_from_scan);
+		ret = lockrestart_do(trans,
+			btree_repair_node_end(trans, b, prev, pulled_from_scan));
 		if (ret == DID_FILL_FROM_SCAN) {
 			new_pass = true;
 			ret = 0;
@@ -519,6 +524,46 @@ static int bch2_btree_repair_topology_recurse(struct btree_trans *trans, struct
 	bch2_bkey_buf_exit(&prev_k, c);
 	bch2_bkey_buf_exit(&cur_k, c);
 	printbuf_exit(&buf);
+	bch_err_fn(c, ret);
+	return ret;
+}
+
+static int bch2_check_root(struct btree_trans *trans, enum btree_id i,
+			   bool *reconstructed_root)
+{
+	struct bch_fs *c = trans->c;
+	struct btree_root *r = bch2_btree_id_root(c, i);
+	struct printbuf buf = PRINTBUF;
+	int ret = 0;
+
+	bch2_btree_id_to_text(&buf, i);
+
+	if (r->error) {
+		bch_info(c, "btree root %s unreadable, must recover from scan", buf.buf);
+
+		r->alive = false;
+		r->error = 0;
+
+		if (!bch2_btree_has_scanned_nodes(c, i)) {
+			__fsck_err(trans,
+				   FSCK_CAN_FIX|(!btree_id_important(i) ? FSCK_AUTOFIX : 0),
+				   btree_root_unreadable_and_scan_found_nothing,
+				   "no nodes found for btree %s, continue?", buf.buf);
+			bch2_btree_root_alloc_fake_trans(trans, i, 0);
+		} else {
+			bch2_btree_root_alloc_fake_trans(trans, i, 1);
+			bch2_shoot_down_journal_keys(c, i, 1, BTREE_MAX_DEPTH, POS_MIN, SPOS_MAX);
+			ret = bch2_get_scanned_nodes(c, i, 0, POS_MIN, SPOS_MAX);
+			if (ret)
+				goto err;
+		}
+
+		*reconstructed_root = true;
+	}
+err:
+fsck_err:
+	printbuf_exit(&buf);
+	bch_err_fn(c, ret);
 	return ret;
 }

@@ -526,42 +571,18 @@ int bch2_check_topology(struct bch_fs *c)
 {
 	struct btree_trans *trans = bch2_trans_get(c);
 	struct bpos pulled_from_scan = POS_MIN;
-	struct printbuf buf = PRINTBUF;
 	int ret = 0;

 	bch2_trans_srcu_unlock(trans);

 	for (unsigned i = 0; i < btree_id_nr_alive(c) && !ret; i++) {
-		struct btree_root *r = bch2_btree_id_root(c, i);
 		bool reconstructed_root = false;
+recover:
+		ret = lockrestart_do(trans, bch2_check_root(trans, i, &reconstructed_root));
+		if (ret)
+			break;

-		printbuf_reset(&buf);
-		bch2_btree_id_to_text(&buf, i);
-
-		if (r->error) {
-reconstruct_root:
-			bch_info(c, "btree root %s unreadable, must recover from scan", buf.buf);
-
-			r->alive = false;
-			r->error = 0;
-
-			if (!bch2_btree_has_scanned_nodes(c, i)) {
-				__fsck_err(trans,
-					   FSCK_CAN_FIX|(!btree_id_important(i) ? FSCK_AUTOFIX : 0),
-					   btree_root_unreadable_and_scan_found_nothing,
-					   "no nodes found for btree %s, continue?", buf.buf);
-				bch2_btree_root_alloc_fake_trans(trans, i, 0);
-			} else {
-				bch2_btree_root_alloc_fake_trans(trans, i, 1);
-				bch2_shoot_down_journal_keys(c, i, 1, BTREE_MAX_DEPTH, POS_MIN, SPOS_MAX);
-				ret = bch2_get_scanned_nodes(c, i, 0, POS_MIN, SPOS_MAX);
-				if (ret)
-					break;
-			}
-
-			reconstructed_root = true;
-		}
-
+		struct btree_root *r = bch2_btree_id_root(c, i);
 		struct btree *b = r->b;

 		btree_node_lock_nopath_nofail(trans, &b->c, SIX_LOCK_read);
@@ -575,17 +596,21 @@ int bch2_check_topology(struct bch_fs *c)

 			r->b = NULL;

-			if (!reconstructed_root)
-				goto reconstruct_root;
+			if (!reconstructed_root) {
+				r->error = -EIO;
+				goto recover;
+			}

+			struct printbuf buf = PRINTBUF;
+			bch2_btree_id_to_text(&buf, i);
 			bch_err(c, "empty btree root %s", buf.buf);
+			printbuf_exit(&buf);
 			bch2_btree_root_alloc_fake_trans(trans, i, 0);
 			r->alive = false;
 			ret = 0;
 		}
 	}
-fsck_err:
-	printbuf_exit(&buf);
+
 	bch2_trans_put(trans);
 	return ret;
 }


Prompt:
Given the following original C code:
while (out->pos && out->buf[out->pos - 1] == ' ')
			--out->pos;
		printbuf_nul_terminate(out);

		if (bch2_fs_stdio_redirect(c))
			bch2_print(c, "%s", out->buf);
		else
			bch2_print_str(c, KERN_ERR, out->buf);
	}

	if (s)
		s->ret = ret;
err_unlock:
	mutex_unlock(&c->fsck_error_msgs_lock);
err:
	/*
	 * We don't yet track whether the filesystem currently has errors, for
	 * log_fsck_err()s: that would require us to track for every error type
	 * which recovery pass corrects it, to get the fsck exit status correct:
	 */

Instruction:
bcachefs: Log fsck errors in the journal

Return the diff that fixes it:

Response:
@@ -620,6 +620,9 @@ int __bch2_fsck_err(struct bch_fs *c,

 	if (s)
 		s->ret = ret;
+
+	if (trans)
+		ret = bch2_trans_log_str(trans, bch2_sb_error_strs[err]) ?: ret;
 err_unlock:
 	mutex_unlock(&c->fsck_error_msgs_lock);
 err:


Prompt:
Given the following original C code:
as->update_level_end	= level_end;
	INIT_LIST_HEAD(&as->list);
	INIT_LIST_HEAD(&as->unwritten_list);
	INIT_LIST_HEAD(&as->write_blocked_list);
	bch2_keylist_init(&as->old_keys, as->_old_keys);
	bch2_keylist_init(&as->new_keys, as->_new_keys);
	bch2_keylist_init(&as->parent_keys, as->inline_keys);

	mutex_lock(&c->btree_interior_update_lock);
	list_add_tail(&as->list, &c->btree_interior_update_list);
	mutex_unlock(&c->btree_interior_update_lock);

	/*
	 * We don't want to allocate if we're in an error state, that can cause
	 * deadlock on emergency shutdown due to open buckets getting stuck in
	 * the btree_reserve_cache after allocator shutdown has cleared it out.
	 * This check needs to come after adding us to the btree_interior_update
	 * list but before calling bch2_btree_reserve_get, to synchronize with
	 * __bch2_fs_read_only().
	 */

Instruction:
bcachefs: Add range being updated to btree_update_to_text()

Return the diff that fixes it:

Response:
@@ -1232,6 +1232,15 @@ bch2_btree_update_start(struct btree_trans *trans, struct btree_path *path,
 	list_add_tail(&as->list, &c->btree_interior_update_list);
 	mutex_unlock(&c->btree_interior_update_lock);

+	struct btree *b = btree_path_node(path, path->level);
+	as->node_start	= b->data->min_key;
+	as->node_end	= b->data->max_key;
+	as->node_needed_rewrite = btree_node_need_rewrite(b);
+	as->node_written = b->written;
+	as->node_sectors = btree_buf_bytes(b) >> 9;
+	as->node_remaining = __bch2_btree_u64s_remaining(b,
+				btree_bkey_last(b, bset_tree_last(b)));
+
 	/*
 	 * We don't want to allocate if we're in an error state, that can cause
 	 * deadlock on emergency shutdown due to open buckets getting stuck in
@@ -2108,6 +2117,9 @@ int __bch2_foreground_maybe_merge(struct btree_trans *trans,
 	if (ret)
 		goto err;

+	as->node_start	= prev->data->min_key;
+	as->node_end	= next->data->max_key;
+
 	trace_and_count(c, btree_node_merge, trans, b);

 	n = bch2_btree_node_alloc(as, trans, b->c.level);
@@ -2681,9 +2693,19 @@ static void bch2_btree_update_to_text(struct printbuf *out, struct btree_update

 	prt_str(out, " ");
 	bch2_btree_id_to_text(out, as->btree_id);
-	prt_printf(out, " l=%u-%u mode=%s nodes_written=%u cl.remaining=%u journal_seq=%llu\n",
+	prt_printf(out, " l=%u-%u ",
 		   as->update_level_start,
-		   as->update_level_end,
+		   as->update_level_end);
+	bch2_bpos_to_text(out, as->node_start);
+	prt_char(out, ' ');
+	bch2_bpos_to_text(out, as->node_end);
+	prt_printf(out, "\nwritten %u/%u u64s_remaining %u need_rewrite %u",
+		   as->node_written,
+		   as->node_sectors,
+		   as->node_remaining,
+		   as->node_needed_rewrite);
+
+	prt_printf(out, "\nmode=%s nodes_written=%u cl.remaining=%u journal_seq=%llu\n",
 		   bch2_btree_update_modes[as->mode],
 		   as->nodes_written,
 		   closure_nr_remaining(&as->cl),


Prompt:
Given the following original C code:
u64				start_time;
	unsigned long			ip_started;

	struct list_head		list;
	struct list_head		unwritten_list;

	enum btree_update_mode		mode;
	enum bch_trans_commit_flags	flags;
	unsigned			nodes_written:1;
	unsigned			took_gc_lock:1;

	enum btree_id			btree_id;
	unsigned			update_level_start;
	unsigned			update_level_end;

	struct disk_reservation		disk_res;

	/*
	 * BTREE_UPDATE_node:
	 * The update that made the new nodes visible was a regular update to an

Instruction:
bcachefs: Add range being updated to btree_update_to_text()

Return the diff that fixes it:

Response:
@@ -57,6 +57,13 @@ struct btree_update {
 	unsigned			took_gc_lock:1;

 	enum btree_id			btree_id;
+	struct bpos			node_start;
+	struct bpos			node_end;
+	bool				node_needed_rewrite;
+	u16				node_written;
+	u16				node_sectors;
+	u16				node_remaining;
+
 	unsigned			update_level_start;
 	unsigned			update_level_end;


Prompt:
Given the following original C code:
}

			/*
			 * didn't find a good key, have to truncate the rest of
			 * the bset
			 */
			next_good_key = (u64 *) vstruct_last(i) - (u64 *) k;
		}
got_good_key:
		le16_add_cpu(&i->u64s, -next_good_key);
		memmove_u64s_down(k, (u64 *) k + next_good_key, (u64 *) vstruct_end(i) - (u64 *) k);
		set_btree_node_need_rewrite(b);
	}
fsck_err:
	printbuf_exit(&buf);
	return ret;
}

int bch2_btree_node_read_done(struct bch_fs *c, struct bch_dev *ca,
			      struct btree *b,

Instruction:
bcachefs: Add more flags to btree nodes for rewrite reason

Return the diff that fixes it:

Response:
@@ -1045,6 +1045,7 @@ static int validate_bset_keys(struct bch_fs *c, struct btree *b,
 		le16_add_cpu(&i->u64s, -next_good_key);
 		memmove_u64s_down(k, (u64 *) k + next_good_key, (u64 *) vstruct_end(i) - (u64 *) k);
 		set_btree_node_need_rewrite(b);
+		set_btree_node_need_rewrite_error(b);
 	}
 fsck_err:
 	printbuf_exit(&buf);
@@ -1305,6 +1306,7 @@ int bch2_btree_node_read_done(struct bch_fs *c, struct bch_dev *ca,
 					  (u64 *) vstruct_end(i) - (u64 *) k);
 			set_btree_bset_end(b, b->set);
 			set_btree_node_need_rewrite(b);
+			set_btree_node_need_rewrite_error(b);
 			continue;
 		}
 		if (ret)
@@ -1329,12 +1331,16 @@ int bch2_btree_node_read_done(struct bch_fs *c, struct bch_dev *ca,
 		bkey_for_each_ptr(bch2_bkey_ptrs(bkey_i_to_s(&b->key)), ptr) {
 			struct bch_dev *ca2 = bch2_dev_rcu(c, ptr->dev);

-			if (!ca2 || ca2->mi.state != BCH_MEMBER_STATE_rw)
+			if (!ca2 || ca2->mi.state != BCH_MEMBER_STATE_rw) {
 				set_btree_node_need_rewrite(b);
+				set_btree_node_need_rewrite_degraded(b);
+			}
 		}

-	if (!ptr_written)
+	if (!ptr_written) {
 		set_btree_node_need_rewrite(b);
+		set_btree_node_need_rewrite_ptr_written_zero(b);
+	}
 fsck_err:
 	mempool_free(iter, &c->fill_iter);
 	printbuf_exit(&buf);


Prompt:
Given the following original C code:
x(need_write)							\
	x(write_blocked)						\
	x(will_make_reachable)						\
	x(noevict)							\
	x(write_idx)							\
	x(accessed)							\
	x(write_in_flight)						\
	x(write_in_flight_inner)					\
	x(just_written)							\
	x(dying)							\
	x(fake)								\
	x(need_rewrite)							\
	x(never_write)							\
	x(pinned)

enum btree_flags {
	/* First bits for btree node write type */
	BTREE_NODE_FLAGS_START = BTREE_WRITE_TYPE_BITS - 1,
#define x(flag)	BTREE_NODE_##flag,
	BTREE_FLAGS()

Instruction:
bcachefs: Add more flags to btree nodes for rewrite reason

Return the diff that fixes it:

Response:
@@ -617,6 +617,9 @@ enum btree_write_type {
 	x(dying)							\
 	x(fake)								\
 	x(need_rewrite)							\
+	x(need_rewrite_error)						\
+	x(need_rewrite_degraded)					\
+	x(need_rewrite_ptr_written_zero)				\
 	x(never_write)							\
 	x(pinned)

@@ -641,6 +644,32 @@ static inline void clear_btree_node_ ## flag(struct btree *b)		\
 BTREE_FLAGS()
 #undef x

+#define BTREE_NODE_REWRITE_REASON()					\
+	x(none)								\
+	x(unknown)							\
+	x(error)							\
+	x(degraded)							\
+	x(ptr_written_zero)
+
+enum btree_node_rewrite_reason {
+#define x(n)	BTREE_NODE_REWRITE_##n,
+	BTREE_NODE_REWRITE_REASON()
+#undef x
+};
+
+static inline enum btree_node_rewrite_reason btree_node_rewrite_reason(struct btree *b)
+{
+	if (btree_node_need_rewrite_ptr_written_zero(b))
+		return BTREE_NODE_REWRITE_ptr_written_zero;
+	if (btree_node_need_rewrite_degraded(b))
+		return BTREE_NODE_REWRITE_degraded;
+	if (btree_node_need_rewrite_error(b))
+		return BTREE_NODE_REWRITE_error;
+	if (btree_node_need_rewrite(b))
+		return BTREE_NODE_REWRITE_unknown;
+	return BTREE_NODE_REWRITE_none;
+}
+
 static inline struct btree_write *btree_current_write(struct btree *b)
 {
 	return b->writes + btree_node_write_idx(b);


Prompt:
Given the following original C code:
up_read(&as->c->gc_lock);
	as->took_gc_lock = false;

	bch2_btree_reserve_put(as, trans);

	continue_at(&as->cl, btree_update_set_nodes_written,
		    as->c->btree_interior_update_worker);

	bch2_time_stats_update(&c->times[BCH_TIME_btree_interior_update_foreground],
			       start_time);
}

static struct btree_update *
bch2_btree_update_start(struct btree_trans *trans, struct btree_path *path,
			unsigned level_start, bool split,
			unsigned target, unsigned flags)
{
	struct bch_fs *c = trans->c;
	struct btree_update *as;
	u64 start_time = local_clock();

Instruction:
bcachefs: Add more flags to btree nodes for rewrite reason

Return the diff that fixes it:

Response:
@@ -1138,6 +1138,13 @@ static void bch2_btree_update_done(struct btree_update *as, struct btree_trans *
 			       start_time);
 }

+static const char * const btree_node_reawrite_reason_strs[] = {
+#define x(n)	#n,
+	BTREE_NODE_REWRITE_REASON()
+#undef x
+	NULL,
+};
+
 static struct btree_update *
 bch2_btree_update_start(struct btree_trans *trans, struct btree_path *path,
 			unsigned level_start, bool split,
@@ -1235,7 +1242,7 @@ bch2_btree_update_start(struct btree_trans *trans, struct btree_path *path,
 	struct btree *b = btree_path_node(path, path->level);
 	as->node_start	= b->data->min_key;
 	as->node_end	= b->data->max_key;
-	as->node_needed_rewrite = btree_node_need_rewrite(b);
+	as->node_needed_rewrite = btree_node_rewrite_reason(b);
 	as->node_written = b->written;
 	as->node_sectors = btree_buf_bytes(b) >> 9;
 	as->node_remaining = __bch2_btree_u64s_remaining(b,
@@ -2699,11 +2706,11 @@ static void bch2_btree_update_to_text(struct printbuf *out, struct btree_update
 	bch2_bpos_to_text(out, as->node_start);
 	prt_char(out, ' ');
 	bch2_bpos_to_text(out, as->node_end);
-	prt_printf(out, "\nwritten %u/%u u64s_remaining %u need_rewrite %u",
+	prt_printf(out, "\nwritten %u/%u u64s_remaining %u need_rewrite %s",
 		   as->node_written,
 		   as->node_sectors,
 		   as->node_remaining,
-		   as->node_needed_rewrite);
+		   btree_node_reawrite_reason_strs[as->node_needed_rewrite]);

 	prt_printf(out, "\nmode=%s nodes_written=%u cl.remaining=%u journal_seq=%llu\n",
 		   bch2_btree_update_modes[as->mode],


Prompt:
Given the following original C code:
struct list_head		list;
	struct list_head		unwritten_list;

	enum btree_update_mode		mode;
	enum bch_trans_commit_flags	flags;
	unsigned			nodes_written:1;
	unsigned			took_gc_lock:1;

	enum btree_id			btree_id;
	struct bpos			node_start;
	struct bpos			node_end;
	bool				node_needed_rewrite;
	u16				node_written;
	u16				node_sectors;
	u16				node_remaining;

	unsigned			update_level_start;
	unsigned			update_level_end;

Instruction:
bcachefs: Add more flags to btree nodes for rewrite reason

Return the diff that fixes it:

Response:
@@ -59,7 +59,7 @@ struct btree_update {
 	enum btree_id			btree_id;
 	struct bpos			node_start;
 	struct bpos			node_end;
-	bool				node_needed_rewrite;
+	enum btree_node_rewrite_reason	node_needed_rewrite;
 	u16				node_written;
 	u16				node_sectors;
 	u16				node_remaining;


Prompt:
Given the following original C code:
x(bucket_sector_count_overflow,				112,	0)		\
	x(bucket_metadata_type_mismatch,			113,	0)		\
	x(need_discard_key_wrong,				114,	FSCK_AUTOFIX)	\
	x(freespace_key_wrong,					115,	FSCK_AUTOFIX)	\
	x(freespace_hole_missing,				116,	FSCK_AUTOFIX)	\
	x(bucket_gens_val_size_bad,				117,	0)		\
	x(bucket_gens_key_wrong,				118,	FSCK_AUTOFIX)	\
	x(bucket_gens_hole_wrong,				119,	FSCK_AUTOFIX)	\
	x(bucket_gens_to_invalid_dev,				120,	FSCK_AUTOFIX)	\
	x(bucket_gens_to_invalid_buckets,			121,	FSCK_AUTOFIX)	\
	x(bucket_gens_nonzero_for_invalid_buckets,		122,	FSCK_AUTOFIX)	\
	x(need_discard_freespace_key_to_invalid_dev_bucket,	123,	0)		\
	x(need_discard_freespace_key_bad,			124,	0)		\
	x(discarding_bucket_not_in_need_discard_btree,		291,	0)		\
	x(backpointer_bucket_offset_wrong,			125,	0)		\
	x(backpointer_level_bad,				294,	0)		\
	x(backpointer_dev_bad,					297,	0)		\
	x(backpointer_to_missing_device,			126,	FSCK_AUTOFIX)	\
	x(backpointer_to_missing_alloc,				127,	FSCK_AUTOFIX)	\
	x(backpointer_to_missing_ptr,				128,	FSCK_AUTOFIX)	\

Instruction:
bcachefs: Mark need_discard_freespace_key_bad autofix

Return the diff that fixes it:

Response:
@@ -134,7 +134,7 @@ enum bch_fsck_flags {
 	x(bucket_gens_to_invalid_buckets,			121,	FSCK_AUTOFIX)	\
 	x(bucket_gens_nonzero_for_invalid_buckets,		122,	FSCK_AUTOFIX)	\
 	x(need_discard_freespace_key_to_invalid_dev_bucket,	123,	0)		\
-	x(need_discard_freespace_key_bad,			124,	0)		\
+	x(need_discard_freespace_key_bad,			124,	FSCK_AUTOFIX)	\
 	x(discarding_bucket_not_in_need_discard_btree,		291,	0)		\
 	x(backpointer_bucket_offset_wrong,			125,	0)		\
 	x(backpointer_level_bad,				294,	0)		\


Prompt:
Given the following original C code:
? BTREE_ID_reflink
				: BTREE_ID_extents,
				k, pos, pick, sectors, orig, failed);
	if (!promote)
		return NULL;

	ret = PTR_ERR_OR_ZERO(promote);
	if (ret)
		goto nopromote;

	*bounce		= true;
	*read_full	= promote_full;
	return promote;
nopromote:
	trace_io_read_nopromote(c, ret);
	return NULL;
}

void bch2_promote_op_to_text(struct printbuf *out, struct promote_op *op)
{

Instruction:
bcachefs: Read error message now prints if self healing

Return the diff that fixes it:

Response:
@@ -343,6 +343,10 @@ static struct bch_read_bio *promote_alloc(struct btree_trans *trans,

 	*bounce		= true;
 	*read_full	= promote_full;
+
+	if (have_io_error(failed))
+		orig->self_healing = true;
+
 	return promote;
 nopromote:
 	trace_io_read_nopromote(c, ret);
@@ -635,12 +639,15 @@ static void bch2_rbio_retry(struct work_struct *work)
 			prt_str(&buf, "(internal move) ");

 		prt_str(&buf, "data read error, ");
-		if (!ret)
+		if (!ret) {
 			prt_str(&buf, "successful retry");
-		else
+			if (rbio->self_healing)
+				prt_str(&buf, ", self healing");
+		} else
 			prt_str(&buf, bch2_err_str(ret));
 		prt_newline(&buf);

+
 		if (!bkey_deleted(&sk.k->k)) {
 			bch2_bkey_val_to_text(&buf, c, bkey_i_to_s_c(sk.k));
 			prt_newline(&buf);


Prompt:
Given the following original C code:
unsigned		offset_into_extent;

	u16			flags;
	union {
	struct {
	u16			data_update:1,
				promote:1,
				bounce:1,
				split:1,
				have_ioref:1,
				narrow_crcs:1,
				saw_error:1,
				context:2;
	};
	u16			_state;
	};
	s16			ret;
#ifdef CONFIG_BCACHEFS_ASYNC_OBJECT_LISTS
	unsigned		list_idx;
#endif

Instruction:
bcachefs: Read error message now prints if self healing

Return the diff that fixes it:

Response:
@@ -44,6 +44,7 @@ struct bch_read_bio {
 				have_ioref:1,
 				narrow_crcs:1,
 				saw_error:1,
+				self_healing:1,
 				context:2;
 	};
 	u16			_state;


Prompt:
Given the following original C code:
goto out;
	case BTREE_ID_bucket_gens:
		ret = __bch2_run_explicit_recovery_pass(c, msg, BCH_RECOVERY_PASS_check_alloc_info, 0) ?: ret;
		goto out;
	case BTREE_ID_lru:
		ret = __bch2_run_explicit_recovery_pass(c, msg, BCH_RECOVERY_PASS_check_alloc_info, 0) ?: ret;
		goto out;
	case BTREE_ID_accounting:
		ret = __bch2_run_explicit_recovery_pass(c, msg, BCH_RECOVERY_PASS_check_allocations, 0) ?: ret;
		goto out;
	case BTREE_ID_snapshots:
		ret = __bch2_run_explicit_recovery_pass(c, msg, BCH_RECOVERY_PASS_reconstruct_snapshots, 0) ?: ret;
		ret = __bch2_run_explicit_recovery_pass(c, msg, BCH_RECOVERY_PASS_scan_for_btree_nodes, 0) ?: ret;
		goto out;
	default:
		ret = __bch2_run_explicit_recovery_pass(c, msg, BCH_RECOVERY_PASS_scan_for_btree_nodes, 0) ?: ret;
		goto out;
	}
out:
	bch2_write_super(c);

Instruction:
bcachefs: Don't persistently run scan_for_btree_nodes

Return the diff that fixes it:

Response:
@@ -99,9 +99,11 @@ int bch2_btree_lost_data(struct bch_fs *c,
 		goto out;
 	case BTREE_ID_snapshots:
 		ret = __bch2_run_explicit_recovery_pass(c, msg, BCH_RECOVERY_PASS_reconstruct_snapshots, 0) ?: ret;
+		ret = __bch2_run_explicit_recovery_pass(c, msg, BCH_RECOVERY_PASS_check_topology, 0) ?: ret;
 		ret = __bch2_run_explicit_recovery_pass(c, msg, BCH_RECOVERY_PASS_scan_for_btree_nodes, 0) ?: ret;
 		goto out;
 	default:
+		ret = __bch2_run_explicit_recovery_pass(c, msg, BCH_RECOVERY_PASS_check_topology, 0) ?: ret;
 		ret = __bch2_run_explicit_recovery_pass(c, msg, BCH_RECOVERY_PASS_scan_for_btree_nodes, 0) ?: ret;
 		goto out;
 	}


Prompt:
Given the following original C code:
return;

	enumerated_ref_put(&c->writes, BCH_WRITE_REF_async_recovery_passes);
unlock:
	up(&c->recovery.run_lock);
}

static bool recovery_pass_needs_set(struct bch_fs *c,
				    enum bch_recovery_pass pass,
				    enum bch_run_recovery_pass_flags *flags)
{
	struct bch_fs_recovery *r = &c->recovery;
	bool in_recovery = test_bit(BCH_FS_in_recovery, &c->flags);
	bool persistent = !in_recovery || !(*flags & RUN_RECOVERY_PASS_nopersistent);

	if ((*flags & RUN_RECOVERY_PASS_ratelimit) &&
	    !bch2_recovery_pass_want_ratelimit(c, pass))
		*flags &= ~RUN_RECOVERY_PASS_ratelimit;

	/*

Instruction:
bcachefs: Don't persistently run scan_for_btree_nodes

Return the diff that fixes it:

Response:
@@ -294,8 +294,13 @@ static bool recovery_pass_needs_set(struct bch_fs *c,
 				    enum bch_run_recovery_pass_flags *flags)
 {
 	struct bch_fs_recovery *r = &c->recovery;
-	bool in_recovery = test_bit(BCH_FS_in_recovery, &c->flags);
-	bool persistent = !in_recovery || !(*flags & RUN_RECOVERY_PASS_nopersistent);
+
+	/*
+	 * Never run scan_for_btree_nodes persistently: check_topology will run
+	 * it if required
+	 */
+	if (pass == BCH_RECOVERY_PASS_scan_for_btree_nodes)
+		*flags |= RUN_RECOVERY_PASS_nopersistent;

 	if ((*flags & RUN_RECOVERY_PASS_ratelimit) &&
 	    !bch2_recovery_pass_want_ratelimit(c, pass))
@@ -310,6 +315,8 @@ static bool recovery_pass_needs_set(struct bch_fs *c,
 	 * Otherwise, we run run_explicit_recovery_pass when we find damage, so
 	 * it should run again even if it's already run:
 	 */
+	bool in_recovery = test_bit(BCH_FS_in_recovery, &c->flags);
+	bool persistent = !in_recovery || !(*flags & RUN_RECOVERY_PASS_nopersistent);

 	if (persistent
 	    ? !(c->sb.recovery_passes_required & BIT_ULL(pass))
@@ -334,6 +341,7 @@ int __bch2_run_explicit_recovery_pass(struct bch_fs *c,
 	struct bch_fs_recovery *r = &c->recovery;
 	int ret = 0;

+
 	lockdep_assert_held(&c->sb_lock);

 	bch2_printbuf_make_room(out, 1024);
@@ -446,7 +454,7 @@ int bch2_require_recovery_pass(struct bch_fs *c,

 int bch2_run_print_explicit_recovery_pass(struct bch_fs *c, enum bch_recovery_pass pass)
 {
-	enum bch_run_recovery_pass_flags flags = RUN_RECOVERY_PASS_nopersistent;
+	enum bch_run_recovery_pass_flags flags = 0;

 	if (!recovery_pass_needs_set(c, pass, &flags))
 		return 0;


Prompt:
Given the following original C code:
x(extent_ptrs_unwritten,				140,	0)		\
	x(extent_ptrs_written_and_unwritten,			141,	0)		\
	x(ptr_to_invalid_device,				142,	0)		\
	x(ptr_to_duplicate_device,				143,	0)		\
	x(ptr_after_last_bucket,				144,	0)		\
	x(ptr_before_first_bucket,				145,	0)		\
	x(ptr_spans_multiple_buckets,				146,	0)		\
	x(ptr_to_missing_backpointer,				147,	FSCK_AUTOFIX)	\
	x(ptr_to_missing_alloc_key,				148,	FSCK_AUTOFIX)	\
	x(ptr_to_missing_replicas_entry,			149,	FSCK_AUTOFIX)	\
	x(ptr_to_missing_stripe,				150,	0)		\
	x(ptr_to_incorrect_stripe,				151,	0)		\
	x(ptr_gen_newer_than_bucket_gen,			152,	0)		\
	x(ptr_too_stale,					153,	0)		\
	x(stale_dirty_ptr,					154,	FSCK_AUTOFIX)	\
	x(ptr_bucket_data_type_mismatch,			155,	0)		\
	x(ptr_cached_and_erasure_coded,				156,	0)		\
	x(ptr_crc_uncompressed_size_too_small,			157,	0)		\
	x(ptr_crc_uncompressed_size_too_big,			161,	0)		\
	x(ptr_crc_uncompressed_size_mismatch,			300,	0)		\

Instruction:
bcachefs: mark more errors autofix

Return the diff that fixes it:

Response:
@@ -165,7 +165,7 @@ enum bch_fsck_flags {
 	x(ptr_to_missing_replicas_entry,			149,	FSCK_AUTOFIX)	\
 	x(ptr_to_missing_stripe,				150,	0)		\
 	x(ptr_to_incorrect_stripe,				151,	0)		\
-	x(ptr_gen_newer_than_bucket_gen,			152,	0)		\
+	x(ptr_gen_newer_than_bucket_gen,			152,	FSCK_AUTOFIX)		\
 	x(ptr_too_stale,					153,	0)		\
 	x(stale_dirty_ptr,					154,	FSCK_AUTOFIX)	\
 	x(ptr_bucket_data_type_mismatch,			155,	0)		\
@@ -236,7 +236,7 @@ enum bch_fsck_flags {
 	x(inode_multiple_links_but_nlink_0,			207,	FSCK_AUTOFIX)	\
 	x(inode_wrong_backpointer,				208,	FSCK_AUTOFIX)	\
 	x(inode_wrong_nlink,					209,	FSCK_AUTOFIX)	\
-	x(inode_has_child_snapshots_wrong,			287,	0)		\
+	x(inode_has_child_snapshots_wrong,			287,	FSCK_AUTOFIX)	\
 	x(inode_unreachable,					210,	FSCK_AUTOFIX)	\
 	x(inode_journal_seq_in_future,				299,	FSCK_AUTOFIX)	\
 	x(inode_i_sectors_underflow,				312,	FSCK_AUTOFIX)	\
@@ -279,8 +279,8 @@ enum bch_fsck_flags {
 	x(root_dir_missing,					239,	0)		\
 	x(root_inode_not_dir,					240,	0)		\
 	x(dir_loop,						241,	0)		\
-	x(hash_table_key_duplicate,				242,	0)		\
-	x(hash_table_key_wrong_offset,				243,	0)		\
+	x(hash_table_key_duplicate,				242,	FSCK_AUTOFIX)	\
+	x(hash_table_key_wrong_offset,				243,	FSCK_AUTOFIX)	\
 	x(unlinked_inode_not_on_deleted_list,			244,	FSCK_AUTOFIX)	\
 	x(reflink_p_front_pad_bad,				245,	0)		\
 	x(journal_entry_dup_same_device,			246,	0)		\


Prompt:
Given the following original C code:
#define bch2_log_msg(_c, fmt)			fmt
#define bch2_fmt_dev(_ca, fmt)			"%s: " fmt "\n", ((_ca)->name)
#define bch2_fmt_dev_offset(_ca, _offset, fmt)	"%s sector %llu: " fmt "\n", ((_ca)->name), (_offset)
#define bch2_fmt_inum(_c, _inum, fmt)		"inum %llu: " fmt "\n", (_inum)
#define bch2_fmt_inum_offset(_c, _inum, _offset, fmt)				\
	 "inum %llu offset %llu: " fmt "\n", (_inum), (_offset)

#endif

#define bch2_fmt(_c, fmt)		bch2_log_msg(_c, fmt "\n")

void bch2_print_str(struct bch_fs *, const char *, const char *);
void bch2_print_str_nonblocking(struct bch_fs *, const char *, const char *);

__printf(2, 3)
void bch2_print_opts(struct bch_opts *, const char *, ...);

__printf(2, 3)
void __bch2_print(struct bch_fs *c, const char *fmt, ...);

Instruction:
bcachefs: Fix possible console lock involved deadlock

Return the diff that fixes it:

Response:
@@ -296,7 +296,6 @@ do {									\
 #define bch2_fmt(_c, fmt)		bch2_log_msg(_c, fmt "\n")

 void bch2_print_str(struct bch_fs *, const char *, const char *);
-void bch2_print_str_nonblocking(struct bch_fs *, const char *, const char *);

 __printf(2, 3)
 void bch2_print_opts(struct bch_opts *, const char *, ...);


Prompt:
Given the following original C code:
for (struct trans_waiting_for_lock *i = g->g; i < g->g + g->nr; i++) {
		struct btree_trans *trans = i->trans;

		bch2_btree_trans_to_text(&buf, trans);

		prt_printf(&buf, "backtrace:\n");
		printbuf_indent_add(&buf, 2);
		bch2_prt_task_backtrace(&buf, trans->locking_wait.task, 2, GFP_NOWAIT);
		printbuf_indent_sub(&buf, 2);
		prt_newline(&buf);
	}

	bch2_print_str_nonblocking(g->g->trans->c, KERN_ERR, buf.buf);
	printbuf_exit(&buf);
	BUG();
}

static noinline int break_cycle(struct lock_graph *g, struct printbuf *cycle,
				struct trans_waiting_for_lock *from)
{

Instruction:
bcachefs: Fix possible console lock involved deadlock

Return the diff that fixes it:

Response:
@@ -213,7 +213,7 @@ static noinline __noreturn void break_cycle_fail(struct lock_graph *g)
 		prt_newline(&buf);
 	}

-	bch2_print_str_nonblocking(g->g->trans->c, KERN_ERR, buf.buf);
+	bch2_print_str(g->g->trans->c, KERN_ERR, buf.buf);
 	printbuf_exit(&buf);
 	BUG();
 }


Prompt:
Given the following original C code:
{
	struct printbuf buf = PRINTBUF;
	buf.atomic++;

	bch2_log_msg_start(c, &buf);

	prt_vprintf(&buf, fmt, args);
	prt_newline(&buf);

	if (trans)
		bch2_trans_updates_to_text(&buf, trans);
	bool ret = __bch2_inconsistent_error(c, &buf);
	bch2_print_str_nonblocking(c, KERN_ERR, buf.buf);

	printbuf_exit(&buf);
	return ret;
}

bool bch2_fs_inconsistent(struct bch_fs *c, const char *fmt, ...)
{

Instruction:
bcachefs: Fix possible console lock involved deadlock

Return the diff that fixes it:

Response:
@@ -69,7 +69,7 @@ static bool bch2_fs_trans_inconsistent(struct bch_fs *c, struct btree_trans *tra
 	if (trans)
 		bch2_trans_updates_to_text(&buf, trans);
 	bool ret = __bch2_inconsistent_error(c, &buf);
-	bch2_print_str_nonblocking(c, KERN_ERR, buf.buf);
+	bch2_print_str(c, KERN_ERR, buf.buf);

 	printbuf_exit(&buf);
 	return ret;


Prompt:
Given the following original C code:
const char * const bch2_dev_read_refs[] = {
	BCH_DEV_READ_REFS()
	NULL
};

const char * const bch2_dev_write_refs[] = {
	BCH_DEV_WRITE_REFS()
	NULL
};
#undef x

static void __bch2_print_str(struct bch_fs *c, const char *prefix,
			     const char *str, bool nonblocking)
{
#ifdef __KERNEL__
	struct stdio_redirect *stdio = bch2_fs_stdio_redirect(c);

	if (unlikely(stdio)) {
		bch2_stdio_redirect_printf(stdio, true, "%s", str);
		return;

Instruction:
bcachefs: Fix possible console lock involved deadlock

Return the diff that fixes it:

Response:
@@ -104,7 +104,7 @@ const char * const bch2_dev_write_refs[] = {
 #undef x

 static void __bch2_print_str(struct bch_fs *c, const char *prefix,
-			     const char *str, bool nonblocking)
+			     const char *str)
 {
 #ifdef __KERNEL__
 	struct stdio_redirect *stdio = bch2_fs_stdio_redirect(c);
@@ -114,17 +114,12 @@ static void __bch2_print_str(struct bch_fs *c, const char *prefix,
 		return;
 	}
 #endif
-	bch2_print_string_as_lines(KERN_ERR, str, nonblocking);
+	bch2_print_string_as_lines(KERN_ERR, str);
 }

 void bch2_print_str(struct bch_fs *c, const char *prefix, const char *str)
 {
-	__bch2_print_str(c, prefix, str, false);
-}
-
-void bch2_print_str_nonblocking(struct bch_fs *c, const char *prefix, const char *str)
-{
-	__bch2_print_str(c, prefix, str, true);
+	__bch2_print_str(c, prefix, str);
 }

 __printf(2, 0)


Prompt:
Given the following original C code:
}

static bool string_is_spaces(const char *str)
{
	while (*str) {
		if (*str != ' ')
			return false;
		str++;
	}
	return true;
}

void bch2_print_string_as_lines(const char *prefix, const char *lines,
				bool nonblocking)
{
	bool locked = false;
	const char *p;

	if (!lines) {
		printk("%s (null)\n", prefix);

Instruction:
bcachefs: Fix possible console lock involved deadlock

Return the diff that fixes it:

Response:
@@ -262,8 +262,7 @@ static bool string_is_spaces(const char *str)
 	return true;
 }

-void bch2_print_string_as_lines(const char *prefix, const char *lines,
-				bool nonblocking)
+void bch2_print_string_as_lines(const char *prefix, const char *lines)
 {
 	bool locked = false;
 	const char *p;
@@ -273,12 +272,7 @@ void bch2_print_string_as_lines(const char *prefix, const char *lines,
 		return;
 	}

-	if (!nonblocking) {
-		console_lock();
-		locked = true;
-	} else {
-		locked = console_trylock();
-	}
+	locked = console_trylock();

 	while (*lines) {
 		p = strchrnul(lines, '\n');


Prompt:
Given the following original C code:
: type_is(var, s64)		? "%lli\n"		\
		 : type_is(var, u64)		? "%llu\n"		\
		 : type_is(var, char *)		? "%s\n"		\
		 : "%i\n", var)

bool bch2_is_zero(const void *, size_t);

u64 bch2_read_flag_list(const char *, const char * const[]);

void bch2_prt_u64_base2_nbits(struct printbuf *, u64, unsigned);
void bch2_prt_u64_base2(struct printbuf *, u64);

void bch2_print_string_as_lines(const char *, const char *, bool);

typedef DARRAY(unsigned long) bch_stacktrace;
int bch2_save_backtrace(bch_stacktrace *stack, struct task_struct *, unsigned, gfp_t);
void bch2_prt_backtrace(struct printbuf *, bch_stacktrace *);
int bch2_prt_task_backtrace(struct printbuf *, struct task_struct *, unsigned, gfp_t);

static inline void prt_bdevname(struct printbuf *out, struct block_device *bdev)

Instruction:
bcachefs: Fix possible console lock involved deadlock

Return the diff that fixes it:

Response:
@@ -214,7 +214,7 @@ u64 bch2_read_flag_list(const char *, const char * const[]);
 void bch2_prt_u64_base2_nbits(struct printbuf *, u64, unsigned);
 void bch2_prt_u64_base2(struct printbuf *, u64);

-void bch2_print_string_as_lines(const char *, const char *, bool);
+void bch2_print_string_as_lines(const char *, const char *);

 typedef DARRAY(unsigned long) bch_stacktrace;
 int bch2_save_backtrace(bch_stacktrace *stack, struct task_struct *, unsigned, gfp_t);


Prompt:
Given the following original C code:
#include "lru.h"
#include "move.h"
#include "movinggc.h"
#include "trace.h"

#include <linux/freezer.h>
#include <linux/kthread.h>
#include <linux/math64.h>
#include <linux/sched/task.h>
#include <linux/wait.h>

struct buckets_in_flight {
	struct rhashtable	table;
	struct move_bucket	*first;
	struct move_bucket	*last;
	size_t			nr;
	size_t			sectors;

	DARRAY(struct move_bucket *) to_evacuate;
};

Instruction:
bcachefs: Don't put rhashtable on stack

Return the diff that fixes it:

Response:
@@ -28,7 +28,7 @@
 #include <linux/wait.h>

 struct buckets_in_flight {
-	struct rhashtable	table;
+	struct rhashtable	*table;
 	struct move_bucket	*first;
 	struct move_bucket	*last;
 	size_t			nr;
@@ -98,7 +98,7 @@ static int bch2_bucket_is_movable(struct btree_trans *trans,
 static void move_bucket_free(struct buckets_in_flight *list,
 			     struct move_bucket *b)
 {
-	int ret = rhashtable_remove_fast(&list->table, &b->hash,
+	int ret = rhashtable_remove_fast(list->table, &b->hash,
 					 bch_move_bucket_params);
 	BUG_ON(ret);
 	kfree(b);
@@ -133,7 +133,7 @@ static void move_buckets_wait(struct moving_context *ctxt,
 static bool bucket_in_flight(struct buckets_in_flight *list,
 			     struct move_bucket_key k)
 {
-	return rhashtable_lookup_fast(&list->table, &k, bch_move_bucket_params);
+	return rhashtable_lookup_fast(list->table, &k, bch_move_bucket_params);
 }

 static int bch2_copygc_get_buckets(struct moving_context *ctxt,
@@ -185,7 +185,7 @@ static int bch2_copygc_get_buckets(struct moving_context *ctxt,
 				goto err;
 			}

-			ret2 = rhashtable_lookup_insert_fast(&buckets_in_flight->table, &b_i->hash,
+			ret2 = rhashtable_lookup_insert_fast(buckets_in_flight->table, &b_i->hash,
 							     bch_move_bucket_params);
 			BUG_ON(ret2);

@@ -350,10 +350,13 @@ static int bch2_copygc_thread(void *arg)
 	struct buckets_in_flight buckets = {};
 	u64 last, wait;

-	int ret = rhashtable_init(&buckets.table, &bch_move_bucket_params);
+	buckets.table = kzalloc(sizeof(*buckets.table), GFP_KERNEL);
+	int ret = !buckets.table
+		? -ENOMEM
+		: rhashtable_init(buckets.table, &bch_move_bucket_params);
 	bch_err_msg(c, ret, "allocating copygc buckets in flight");
 	if (ret)
-		return ret;
+		goto err;

 	set_freezable();

@@ -421,11 +424,12 @@ static int bch2_copygc_thread(void *arg)
 	}

 	move_buckets_wait(&ctxt, &buckets, true);
-	rhashtable_destroy(&buckets.table);
+	rhashtable_destroy(buckets.table);
 	bch2_moving_ctxt_exit(&ctxt);
 	bch2_move_stats_exit(&move_stats, c);
-
-	return 0;
+err:
+	kfree(buckets.table);
+	return ret;
 }

 void bch2_copygc_stop(struct bch_fs *c)


Prompt:
Given the following original C code:
#define x(ver, passes, ...) {					\
	.recovery_passes	= passes,			\
	.version		= bcachefs_metadata_version_##ver,\
	.nr_errors		= ARRAY_SIZE(downgrade_##ver##_errors),	\
	.errors			= downgrade_##ver##_errors,	\
},
DOWNGRADE_TABLE()
#undef x
};

static int downgrade_table_extra(struct bch_fs *c, darray_char *table)
{
	struct bch_sb_field_downgrade_entry *dst = (void *) &darray_top(*table);
	unsigned bytes = sizeof(*dst) + sizeof(dst->errors[0]) * le16_to_cpu(dst->nr_errors);
	int ret = 0;

	unsigned nr_errors = le16_to_cpu(dst->nr_errors);

	switch (le16_to_cpu(dst->version)) {
	case bcachefs_metadata_version_bucket_stripe_sectors:

Instruction:
bcachefs: Fix downgrade_table_extra()

Return the diff that fixes it:

Response:
@@ -253,6 +253,7 @@ DOWNGRADE_TABLE()

 static int downgrade_table_extra(struct bch_fs *c, darray_char *table)
 {
+	unsigned dst_offset = table->nr;
 	struct bch_sb_field_downgrade_entry *dst = (void *) &darray_top(*table);
 	unsigned bytes = sizeof(*dst) + sizeof(dst->errors[0]) * le16_to_cpu(dst->nr_errors);
 	int ret = 0;
@@ -268,6 +269,9 @@ static int downgrade_table_extra(struct bch_fs *c, darray_char *table)
 			if (ret)
 				return ret;

+			dst = (void *) &table->data[dst_offset];
+			dst->nr_errors = cpu_to_le16(nr_errors + 1);
+
 			/* open coded __set_bit_le64, as dst is packed and
 			 * dst->recovery_passes is misaligned */
 			unsigned b = BCH_RECOVERY_PASS_STABLE_check_allocations;
@@ -278,7 +282,6 @@ static int downgrade_table_extra(struct bch_fs *c, darray_char *table)
 		break;
 	}

-	dst->nr_errors = cpu_to_le16(nr_errors);
 	return ret;
 }


Prompt:
Given the following original C code:
for (struct rcu_pending_list *i = p->lists; i < expired; i++)
		if (i->head && __poll_state_synchronize_rcu(p->parent->srcu, i->seq))
			rcu_pending_list_merge(expired, i);
}

#ifndef __KERNEL__
static inline void kfree_bulk(size_t nr, void ** p)
{
	while (nr--)
		kfree(*p);
}

#define local_irq_save(flags)		\
do {					\
	flags = 0;			\
} while (0)
#endif

static noinline void __process_finished_items(struct rcu_pending *pending,

Instruction:
bcachefs: Fix rcu_pending for PREEMPT_RT

Return the diff that fixes it:

Response:
@@ -182,11 +182,6 @@ static inline void kfree_bulk(size_t nr, void ** p)
 	while (nr--)
 		kfree(*p);
 }
-
-#define local_irq_save(flags)		\
-do {					\
-	flags = 0;			\
-} while (0)
 #endif

 static noinline void __process_finished_items(struct rcu_pending *pending,
@@ -429,9 +424,15 @@ __rcu_pending_enqueue(struct rcu_pending *pending, struct rcu_head *head,

 	BUG_ON((ptr != NULL) != (pending->process == RCU_PENDING_KVFREE_FN));

-	local_irq_save(flags);
-	p = this_cpu_ptr(pending->p);
-	spin_lock(&p->lock);
+	/* We could technically be scheduled before taking the lock and end up
+	 * using a different cpu's rcu_pending_pcpu: that's ok, it needs a lock
+	 * anyways
+	 *
+	 * And we have to do it this way to avoid breaking PREEMPT_RT, which
+	 * redefines how spinlocks work:
+	 */
+	p = raw_cpu_ptr(pending->p);
+	spin_lock_irqsave(&p->lock, flags);
 	rcu_gp_poll_state_t seq = __get_state_synchronize_rcu(pending->srcu);
 restart:
 	if (may_sleep &&
@@ -520,9 +521,8 @@ __rcu_pending_enqueue(struct rcu_pending *pending, struct rcu_head *head,
 		goto free_node;
 	}

-	local_irq_save(flags);
-	p = this_cpu_ptr(pending->p);
-	spin_lock(&p->lock);
+	p = raw_cpu_ptr(pending->p);
+	spin_lock_irqsave(&p->lock, flags);
 	goto restart;
 }


Prompt:
Given the following original C code:
ret =   bch2_fs_read_write_early(c) ?:
			bch2_scan_old_btree_nodes(c, &stats);
		if (ret)
			goto err;
		bch_info(c, "scanning for old btree nodes done");
	}

	ret = 0;
out:
	bch2_flush_fsck_errs(c);

	if (!IS_ERR(clean))
		kfree(clean);

	if (!ret &&
	    test_bit(BCH_FS_need_delete_dead_snapshots, &c->flags) &&
	    !c->opts.nochanges) {
		bch2_fs_read_write_early(c);
		bch2_delete_dead_snapshots_async(c);

Instruction:
bcachefs: Fix leak in bch2_fs_recovery() error path

Return the diff that fixes it:

Response:
@@ -1108,9 +1108,6 @@ int bch2_fs_recovery(struct bch_fs *c)
 out:
 	bch2_flush_fsck_errs(c);

-	if (!IS_ERR(clean))
-		kfree(clean);
-
 	if (!ret &&
 	    test_bit(BCH_FS_need_delete_dead_snapshots, &c->flags) &&
 	    !c->opts.nochanges) {
@@ -1119,6 +1116,9 @@ int bch2_fs_recovery(struct bch_fs *c)
 	}

 	bch_err_fn(c, ret);
+final_out:
+	if (!IS_ERR(clean))
+		kfree(clean);
 	return ret;
 err:
 fsck_err:
@@ -1132,7 +1132,7 @@ int bch2_fs_recovery(struct bch_fs *c)
 		bch2_print_str(c, KERN_ERR, buf.buf);
 		printbuf_exit(&buf);
 	}
-	return ret;
+	goto final_out;
 }

 int bch2_fs_initialize(struct bch_fs *c)


Prompt:
Given the following original C code:
prt_str(&buf, ":\n      got");
			for (unsigned j = 0; j < nr; j++)
				prt_printf(&buf, " %llu", dst_v[j]);

			prt_str(&buf,  "\nshould be");
			for (unsigned j = 0; j < nr; j++)
				prt_printf(&buf, " %llu", src_v[j]);

			for (unsigned j = 0; j < nr; j++)
				src_v[j] -= dst_v[j];

			if (fsck_err(trans, accounting_mismatch, "%s", buf.buf)) {
				percpu_up_write(&c->mark_lock);
				ret = commit_do(trans, NULL, NULL, 0,
						bch2_disk_accounting_mod(trans, &acc_k, src_v, nr, false));
				percpu_down_write(&c->mark_lock);
				if (ret)
					goto err;

Instruction:
bcachefs: Don't pass trans to fsck_err() in gc_accounting_done

Return the diff that fixes it:

Response:
@@ -618,7 +618,9 @@ int bch2_gc_accounting_done(struct bch_fs *c)
 			for (unsigned j = 0; j < nr; j++)
 				src_v[j] -= dst_v[j];

-			if (fsck_err(trans, accounting_mismatch, "%s", buf.buf)) {
+			bch2_trans_unlock_long(trans);
+
+			if (fsck_err(c, accounting_mismatch, "%s", buf.buf)) {
 				percpu_up_write(&c->mark_lock);
 				ret = commit_do(trans, NULL, NULL, 0,
 						bch2_disk_accounting_mod(trans, &acc_k, src_v, nr, false));


Prompt:
Given the following original C code:
ctx->c = c;
	ctx->arg = arg;

	ret = bch2_run_thread_with_file(&ctx->thr,
			&bcachefs_data_ops,
			bch2_data_thread);
	if (ret < 0)
		kfree(ctx);
	return ret;
}

static long bch2_ioctl_fs_usage(struct bch_fs *c,
				struct bch_ioctl_fs_usage __user *user_arg)
{
	struct bch_ioctl_fs_usage arg = {};
	darray_char replicas = {};
	u32 replica_entries_bytes;
	int ret = 0;

Instruction:
bcachefs: ioctl: avoid stack overflow warning

Return the diff that fixes it:

Response:
@@ -399,7 +399,7 @@ static long bch2_ioctl_data(struct bch_fs *c,
 	return ret;
 }

-static long bch2_ioctl_fs_usage(struct bch_fs *c,
+static noinline_for_stack long bch2_ioctl_fs_usage(struct bch_fs *c,
 				struct bch_ioctl_fs_usage __user *user_arg)
 {
 	struct bch_ioctl_fs_usage arg = {};
@@ -469,7 +469,7 @@ static long bch2_ioctl_query_accounting(struct bch_fs *c,
 }

 /* obsolete, didn't allow for new data types: */
-static long bch2_ioctl_dev_usage(struct bch_fs *c,
+static noinline_for_stack long bch2_ioctl_dev_usage(struct bch_fs *c,
 				 struct bch_ioctl_dev_usage __user *user_arg)
 {
 	struct bch_ioctl_dev_usage arg;


Prompt:
Given the following original C code:
struct printbuf buf1 = PRINTBUF;
	struct printbuf buf2 = PRINTBUF;
	int ret = 0;

	btree_err_on(!bch2_version_compatible(version),
		     -BCH_ERR_btree_node_read_err_incompatible,
		     c, ca, b, i, NULL,
		     btree_node_unsupported_version,
		     "unsupported bset version %u.%u",
		     BCH_VERSION_MAJOR(version),
		     BCH_VERSION_MINOR(version));

	if (btree_err_on(version < c->sb.version_min,
			 -BCH_ERR_btree_node_read_err_fixable,
			 c, NULL, b, i, NULL,
			 btree_node_bset_older_than_sb_min,
			 "bset version %u older than superblock version_min %u",
			 version, c->sb.version_min)) {
		mutex_lock(&c->sb_lock);
		c->disk_sb.sb->version_min = cpu_to_le16(version);

Instruction:
bcachefs: Fix version checks in validate_bset()

Return the diff that fixes it:

Response:
@@ -741,16 +741,22 @@ static int validate_bset(struct bch_fs *c, struct bch_dev *ca,
 		     BCH_VERSION_MAJOR(version),
 		     BCH_VERSION_MINOR(version));

-	if (btree_err_on(version < c->sb.version_min,
+	if (c->recovery.curr_pass != BCH_RECOVERY_PASS_scan_for_btree_nodes &&
+	    btree_err_on(version < c->sb.version_min,
 			 -BCH_ERR_btree_node_read_err_fixable,
 			 c, NULL, b, i, NULL,
 			 btree_node_bset_older_than_sb_min,
 			 "bset version %u older than superblock version_min %u",
 			 version, c->sb.version_min)) {
-		mutex_lock(&c->sb_lock);
-		c->disk_sb.sb->version_min = cpu_to_le16(version);
-		bch2_write_super(c);
-		mutex_unlock(&c->sb_lock);
+		if (bch2_version_compatible(version)) {
+			mutex_lock(&c->sb_lock);
+			c->disk_sb.sb->version_min = cpu_to_le16(version);
+			bch2_write_super(c);
+			mutex_unlock(&c->sb_lock);
+		} else {
+			/* We have no idea what's going on: */
+			i->version = cpu_to_le16(c->sb.version);
+		}
 	}

 	if (btree_err_on(BCH_VERSION_MAJOR(version) >


Prompt:
Given the following original C code:
if (ret)
			return ret;
	}

	return 0;
}

static void bch2_sb_members_v1_to_text(struct printbuf *out, struct bch_sb *sb,
				       struct bch_sb_field *f)
{
	struct bch_sb_field_members_v1 *mi = field_to_type(f, members_v1);
	struct bch_sb_field_disk_groups *gi = bch2_sb_field_get(sb, disk_groups);
	unsigned i;

	for (i = 0; i < sb->nr_devices; i++)
		member_to_text(out, members_v1_get(mi, i), gi, sb, i);
}

const struct bch_sb_field_ops bch_sb_field_ops_members_v1 = {
	.validate	= bch2_sb_members_v1_validate,

Instruction:
bcachefs: Don't trust sb->nr_devices in members_to_text()

Return the diff that fixes it:

Response:
@@ -325,9 +325,17 @@ static void bch2_sb_members_v1_to_text(struct printbuf *out, struct bch_sb *sb,
 {
 	struct bch_sb_field_members_v1 *mi = field_to_type(f, members_v1);
 	struct bch_sb_field_disk_groups *gi = bch2_sb_field_get(sb, disk_groups);
-	unsigned i;

-	for (i = 0; i < sb->nr_devices; i++)
+	if (vstruct_end(&mi->field) <= (void *) &mi->_members[0]) {
+		prt_printf(out, "field ends before start of entries");
+		return;
+	}
+
+	unsigned nr = (vstruct_end(&mi->field) - (void *) &mi->_members[0]) / sizeof(mi->_members[0]);
+	if (nr != sb->nr_devices)
+		prt_printf(out, "nr_devices mismatch: have %i entries, should be %u", nr, sb->nr_devices);
+
+	for (unsigned i = 0; i < min(sb->nr_devices, nr); i++)
 		member_to_text(out, members_v1_get(mi, i), gi, sb, i);
 }

@@ -341,9 +349,27 @@ static void bch2_sb_members_v2_to_text(struct printbuf *out, struct bch_sb *sb,
 {
 	struct bch_sb_field_members_v2 *mi = field_to_type(f, members_v2);
 	struct bch_sb_field_disk_groups *gi = bch2_sb_field_get(sb, disk_groups);
-	unsigned i;

-	for (i = 0; i < sb->nr_devices; i++)
+	if (vstruct_end(&mi->field) <= (void *) &mi->_members[0]) {
+		prt_printf(out, "field ends before start of entries");
+		return;
+	}
+
+	if (!le16_to_cpu(mi->member_bytes)) {
+		prt_printf(out, "member_bytes 0");
+		return;
+	}
+
+	unsigned nr = (vstruct_end(&mi->field) - (void *) &mi->_members[0]) / le16_to_cpu(mi->member_bytes);
+	if (nr != sb->nr_devices)
+		prt_printf(out, "nr_devices mismatch: have %i entries, should be %u", nr, sb->nr_devices);
+
+	/*
+	 * We call to_text() on superblock sections that haven't passed
+	 * validate, so we can't trust sb->nr_devices.
+	 */
+
+	for (unsigned i = 0; i < min(sb->nr_devices, nr); i++)
 		member_to_text(out, members_v2_get(mi, i), gi, sb, i);
 }


Prompt:
Given the following original C code:
return likely(path->locks_want >= new_locks_want && path->nodes_locked)
		? 0
		: __bch2_btree_path_upgrade(trans, path, new_locks_want);
}

/* misc: */

static inline void btree_path_set_should_be_locked(struct btree_trans *trans, struct btree_path *path)
{
	EBUG_ON(!btree_node_locked(path, path->level));
	EBUG_ON(path->uptodate);

	path->should_be_locked = true;
	trace_btree_path_should_be_locked(trans, path);
}

static inline void __btree_path_set_level_up(struct btree_trans *trans,
				      struct btree_path *path,
				      unsigned l)
{

Instruction:
bcachefs: Don't trace should_be_locked unless changing

Return the diff that fixes it:

Response:
@@ -417,8 +417,10 @@ static inline void btree_path_set_should_be_locked(struct btree_trans *trans, st
 	EBUG_ON(!btree_node_locked(path, path->level));
 	EBUG_ON(path->uptodate);

-	path->should_be_locked = true;
-	trace_btree_path_should_be_locked(trans, path);
+	if (!path->should_be_locked) {
+		path->should_be_locked = true;
+		trace_btree_path_should_be_locked(trans, path);
+	}
 }

 static inline void __btree_path_set_level_up(struct btree_trans *trans,