sunrpc __rpc_execute()出现ERESTARTSYS的问题

点击这里查看配套的教学视频

点击跳转到nfs课程所有目录

1 问题描述

点击这里查看省略后的日志(省略了rpc任务的打印)点击这里查看完整的日志

有些情况下还会有hung task的日志

server端是nas盘,有两个ip,再对已挂载的ip进行挂载失败,挂载另一个ip成功。

2 补丁

请查看patchset: Fix nfsv4.1 deadlock between nfs4_evict_inode() and nfs4_opendata_get_inode()

3 代码分析

根据打印的日志,同一个ip挂载不上是因为__rpc_execute()中的捕获到信号:

__rpc_execute
  dprintk("RPC: %5u sync task going to sleep\n"
  out_of_line_wait_on_bit
    __wait_on_bit
      rpc_wait_bit_killable // (*action)(
        if (signal_pending_state
        return -ERESTARTSYS // 错误码512
  dprintk("RPC: %5u got signal\n"
  rpc_exit(task, -ERESTARTSYS

打印出很多rpc任务是因为写/proc/sys/sunrpc/rpc_debug文件:

proc_dodebug
  rpc_show_tasks
    list_for_each_entry(clnt, &sn->all_clients,
    list_for_each_entry(task, &clnt->cl_tasks, // 存在任务才会打印
    rpc_show_header
    rpc_show_task

挂载的相关的流程:

mount_fs
  nfs4_remote_mount
    nfs4_create_server
      nfs4_init_server
        nfs4_set_client
          nfs_get_client
            nfs4_init_client
              nfs41_init_client
                // 再挂载同一个ip不会生成新的session
                // 但挂载另一个ip会生成新的session
                nfs4_alloc_session
                  nfs4_init_slot_table(..., "ForeChannel Slot table")
                    rpc_init_priority_wait_queue(&tbl->slot_tbl_waitq, ...)
                      __rpc_init_priority_wait_queue
                        rpc_assign_waitqueue_name
                          q->name = name;

ForeChannel Slot table队列相关的流程:

nfs4_setup_sequence
  if (nfs4_slot_tbl_draining(tbl) // 如果正在清空slot,则执行goto out_sleep
  nfs4_alloc_slot // 如果找不到空闲的slot,也执行goto out_sleep
  out_sleep:
  rpc_sleep_on_priority(&tbl->slot_tbl_waitq,
  rpc_sleep_on(&tbl->slot_tbl_waitq,

我们还可以在虚拟机中尝试把server端服务停掉,然后写文件,修改/proc/sys/sunrpc/rpc_debug文件的值时, 打印的是类似91 4080 0 8eecf24b e2badc1c 3000 66c9f56f nfsv4 GETATTR a:call_timeout q:delayq:

// 初始化delayq
init_sunrpc
  rpc_init_mempool
    rpc_init_wait_queue(&delay_queue, "delayq")

rpc_delay
  rpc_sleep_on(&delay_queue,
    __rpc_sleep_on_priority
      __rpc_add_wait_queue