linux/fs/overlayfs/readdir.c

// SPDX-License-Identifier: GPL-2.0-only
/*
 *
 * Copyright (C) 2011 Novell Inc.
 */

#include <linux/fs.h>
#include <linux/slab.h>
#include <linux/namei.h>
#include <linux/file.h>
#include <linux/xattr.h>
#include <linux/rbtree.h>
#include <linux/security.h>
#include <linux/cred.h>
#include <linux/ratelimit.h>
#include "overlayfs.h"

struct ovl_cache_entry {};

struct ovl_dir_cache {};

struct ovl_readdir_data {};

struct ovl_dir_file {};

static struct ovl_cache_entry *ovl_cache_entry_from_node(struct rb_node *n)
{}

static bool ovl_cache_entry_find_link(const char *name, int len,
				      struct rb_node ***link,
				      struct rb_node **parent)
{}

static struct ovl_cache_entry *ovl_cache_entry_find(struct rb_root *root,
						    const char *name, int len)
{}

static bool ovl_calc_d_ino(struct ovl_readdir_data *rdd,
			   struct ovl_cache_entry *p)
{}

static struct ovl_cache_entry *ovl_cache_entry_new(struct ovl_readdir_data *rdd,
						   const char *name, int len,
						   u64 ino, unsigned int d_type)
{}

static bool ovl_cache_entry_add_rb(struct ovl_readdir_data *rdd,
				  const char *name, int len, u64 ino,
				  unsigned int d_type)
{}

static bool ovl_fill_lowest(struct ovl_readdir_data *rdd,
			   const char *name, int namelen,
			   loff_t offset, u64 ino, unsigned int d_type)
{}

void ovl_cache_free(struct list_head *list)
{}

void ovl_dir_cache_free(struct inode *inode)
{}

static void ovl_cache_put(struct ovl_dir_file *od, struct inode *inode)
{}

static bool ovl_fill_merge(struct dir_context *ctx, const char *name,
			  int namelen, loff_t offset, u64 ino,
			  unsigned int d_type)
{}

static int ovl_check_whiteouts(const struct path *path, struct ovl_readdir_data *rdd)
{}

static inline int ovl_dir_read(const struct path *realpath,
			       struct ovl_readdir_data *rdd)
{}

static void ovl_dir_reset(struct file *file)
{}

static int ovl_dir_read_merged(struct dentry *dentry, struct list_head *list,
	struct rb_root *root)
{}

static void ovl_seek_cursor(struct ovl_dir_file *od, loff_t pos)
{}

static struct ovl_dir_cache *ovl_cache_get(struct dentry *dentry)
{}

/* Map inode number to lower fs unique range */
static u64 ovl_remap_lower_ino(u64 ino, int xinobits, int fsid,
			       const char *name, int namelen, bool warn)
{}

/*
 * Set d_ino for upper entries if needed. Non-upper entries should always report
 * the uppermost real inode ino and should not call this function.
 *
 * When not all layer are on same fs, report real ino also for upper.
 *
 * When all layers are on the same fs, and upper has a reference to
 * copy up origin, call vfs_getattr() on the overlay entry to make
 * sure that d_ino will be consistent with st_ino from stat(2).
 *
 * Also checks the overlay.whiteout xattr by doing a full lookup which will return
 * negative in this case.
 */
static int ovl_cache_update(const struct path *path, struct ovl_cache_entry *p, bool update_ino)

{}

static bool ovl_fill_plain(struct dir_context *ctx, const char *name,
			  int namelen, loff_t offset, u64 ino,
			  unsigned int d_type)
{}

static int ovl_dir_read_impure(const struct path *path,  struct list_head *list,
			       struct rb_root *root)
{}

static struct ovl_dir_cache *ovl_cache_get_impure(const struct path *path)
{}

struct ovl_readdir_translate {};

static bool ovl_fill_real(struct dir_context *ctx, const char *name,
			   int namelen, loff_t offset, u64 ino,
			   unsigned int d_type)
{}

static bool ovl_is_impure_dir(struct file *file)
{}

static int ovl_iterate_real(struct file *file, struct dir_context *ctx)
{}


static int ovl_iterate(struct file *file, struct dir_context *ctx)
{}

static loff_t ovl_dir_llseek(struct file *file, loff_t offset, int origin)
{}

static struct file *ovl_dir_open_realfile(const struct file *file,
					  const struct path *realpath)
{}

/*
 * Like ovl_real_fdget(), returns upperfile if dir was copied up since open.
 * Unlike ovl_real_fdget(), this caches upperfile in file->private_data.
 *
 * TODO: use same abstract type for file->private_data of dir and file so
 * upperfile could also be cached for files as well.
 */
struct file *ovl_dir_real_file(const struct file *file, bool want_upper)
{}

static int ovl_dir_fsync(struct file *file, loff_t start, loff_t end,
			 int datasync)
{}

static int ovl_dir_release(struct inode *inode, struct file *file)
{}

static int ovl_dir_open(struct inode *inode, struct file *file)
{}

WRAP_DIR_ITER() // FIXME!
const struct file_operations ovl_dir_operations =;

int ovl_check_empty_dir(struct dentry *dentry, struct list_head *list)
{}

void ovl_cleanup_whiteouts(struct ovl_fs *ofs, struct dentry *upper,
			   struct list_head *list)
{}

static bool ovl_check_d_type(struct dir_context *ctx, const char *name,
			  int namelen, loff_t offset, u64 ino,
			  unsigned int d_type)
{}

/*
 * Returns 1 if d_type is supported, 0 not supported/unknown. Negative values
 * if error is encountered.
 */
int ovl_check_d_type_supported(const struct path *realpath)
{}

#define OVL_INCOMPATDIR_NAME

static int ovl_workdir_cleanup_recurse(struct ovl_fs *ofs, const struct path *path,
				       int level)
{}

int ovl_workdir_cleanup(struct ovl_fs *ofs, struct inode *dir,
			struct vfsmount *mnt, struct dentry *dentry, int level)
{}

int ovl_indexdir_cleanup(struct ovl_fs *ofs)
{}