背景

io_uring 作者在 What’s new with io_uring (2022) 中提了一句打开文件优化:LOOKUP_CACHED support for opening files. 没听过这个 LOOKUP_CACHED 特性,看着像是缓存相关,简单了解一下。

代码

光是看代码是一头雾水的。

定义如下:

#define LOOKUP_CACHED           0x200000 /* Only do cached lookup */

调用如下:

/**
 * try_to_unlazy - try to switch to ref-walk mode.
 * @nd: nameidata pathwalk data
 * Returns: true on success, false on failure
 *
 * try_to_unlazy attempts to legitimize the current nd->path and nd->root
 * for ref-walk mode.
 * Must be called from rcu-walk context.
 * Nothing should touch nameidata between try_to_unlazy() failure and
 * terminate_walk().
 */
static bool try_to_unlazy(struct nameidata *nd)
{
        struct dentry *parent = nd->path.dentry;

        BUG_ON(!(nd->flags & LOOKUP_RCU));

        if (unlikely(!legitimize_links(nd))) // 这里⭐
                goto out1;
        if (unlikely(!legitimize_path(nd, &nd->path, nd->seq)))
                goto out;
        if (unlikely(!legitimize_root(nd)))
                goto out;
        leave_rcu(nd);
        BUG_ON(nd->inode != parent->d_inode);
        return true;

out1:
        nd->path.mnt = NULL;
        nd->path.dentry = NULL;
out:
        leave_rcu(nd);
        return false;
}

static bool legitimize_links(struct nameidata *nd)
{
        int i;
        if (unlikely(nd->flags & LOOKUP_CACHED)) { // 这里⭐
                drop_links(nd);
                nd->depth = 0;
                return false;
        }
        for (i = 0; i < nd->depth; i++) {
                struct saved *last = nd->stack + i;
                if (unlikely(!legitimize_path(nd, &last->link, last->seq))) {
                        drop_links(nd);
                        nd->depth = i + 1;
                        return false;
                }
        }
        return true;
}

这里看着像是 RCU-walk 切换到 REF-walk 的路径,为什么这么做?

注释

顺着网线找到了 fs: Support for LOOKUP_CACHED / RESOLVE_CACHED,里面提到:

io_uring always punts opens to async context, since there’s no control over whether the lookup blocks or not. Add LOOKUP_CACHED to support just doing the fast RCU based lookups, which we know will not block. If we can do a cached path resolution of the filename, then we don’t have to always punt lookups for a worker.

也就是说作者认为 RCU-walk 是不阻塞的,所以 lookup flags 里面加上 LOOKUP_CACHED 可以指定打开文件时只使用 RCU-walk 间接达成目的。估计是为了让 io_uring 支持内联的 open() 操作,不必为了一些不确定性而动用线程(worker)做异步 IO 处理。