I have a large land cover raster with classified integer values from 2-22. There are some single or double pixel no-data gaps where I merged 2 adjacent tifs together. If this were a continuous raster I would use the GDAL fill nodata tool to remove these holes but because this is a discrete raster I need to preserve the values I would like a tool that uses the majority value of the pixels adjacent to the nodata pixel instead of the interpolated value.
Past self, you can use the Grass algorithm r.neighbors in QGIS to do this.
First create a mask layer that is the inverse of the layer you want to fill. This means that all the NoData cells you want to be filled need to have a value, any value, and all the other cells are NoData.
Run the Fill NoData Cells algo with a value not in the rest of your dataset.
Run the Reclassify by Table with a single row that is the former NoData value you just assigned as Min, Max, and Value.
Turn on the use no data when no range matches value to make all other values in the dataset NoData.
Then run r.neighbors with your original layer as your Input Raster Layer and your mask layer as your Raster layer to select the cells which should be processed. Set the Neighborhood operation to mode. The neighborhood size is a bit tricky. You want it to be large enough to fill your largest gaps but not so large that it throws off your values or takes forever to run.
If you set up a model maybe keep the value low and run it a number of times.