code: func (runner *runner) restoreInternal(args []string, data []byte, flush FlushFlag, counters RestoreCountersFlag) error {
  	runner.mu.Lock()
  	defer runner.mu.Unlock()
  
  	trace := utiltrace.New("iptables restore")
  	defer trace.LogIfLong(2 * time.Second)
  
  	if !flush {
  		args = append(args, "--noflush")
  	}
  	if counters {
  		args = append(args, "--counters")
  	}
  
  	// Grab the iptables lock to prevent iptables-restore and iptables
  	// from stepping on each other.  iptables-restore 1.6.2 will have
  	// a --wait option like iptables itself, but that's not widely deployed.
  	if len(runner.restoreWaitFlag) == 0 {
  		locker, err := grabIptablesLocks(runner.lockfilePath)
  		if err != nil {
  			return err
  		}
  		trace.Step("Locks grabbed")
  		defer func(locker iptablesLocker) {
  			if err := locker.Close(); err != nil {
  				klog.Errorf("Failed to close iptables locks: %v", err)
  			}
  		}(locker)
  	}
  
  	// run the command and return the output or an error including the output and error
  	fullArgs := append(runner.restoreWaitFlag, args...)
  	iptablesRestoreCmd := iptablesRestoreCommand(runner.protocol)
  	klog.V(4).Infof("running %s %v", iptablesRestoreCmd, fullArgs)
  	cmd := runner.exec.Command(iptablesRestoreCmd, fullArgs...)
  	cmd.SetStdin(bytes.NewBuffer(data))
  	b, err := cmd.CombinedOutput()
  	if err != nil {
  		return fmt.Errorf("%v (%s)", err, b)
  	}
  	return nil
  }
docs: // restoreInternal is the shared part of Restore/RestoreAll