-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathdir.c
68 lines (65 loc) · 1.96 KB
/
dir.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
#include <asm/uaccess.h>
#include <linux/blkdev.h>
#include <linux/buffer_head.h>
#include <linux/errno.h>
#include <linux/fs.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/mm.h>
#include <linux/module.h>
#include <linux/mpage.h>
#include <linux/proc_fs.h>
#include <linux/slab.h>
#include <linux/statfs.h>
#include <linux/types.h>
#include <linux/version.h>
#include "logging.h"
#include "vvsfs.h"
// vvsfs_readdir - reads a directory and places the result using filldir, cached
// in dcache
static int vvsfs_readdir(struct file *filp, struct dir_context *ctx) {
struct inode *dir;
struct vvsfs_dir_entry *dentry;
char *data;
int i;
int num_dirs;
int err;
DEBUG_LOG("vvsfs - readdir\n");
// get the directory inode from file
dir = file_inode(filp);
data = vvsfs_read_dentries(dir, &num_dirs);
if (IS_ERR(data)) {
int err = PTR_ERR(data);
DEBUG_LOG("vvsfs - readdir - failed cached dentries read: %d\n", err);
return err;
}
// Iterate over dentries and emit them into the dcache
for (i = ctx->pos / VVSFS_DENTRYSIZE;
i < num_dirs && filp->f_pos < dir->i_size;
++i) {
dentry = READ_DENTRY_OFF(data, i);
if (!(err = dir_emit(ctx,
dentry->name,
strnlen(dentry->name, VVSFS_MAXNAME),
dentry->inode_number,
DT_UNKNOWN))) {
DEBUG_LOG("vvsfs - readdir - failed dir_emit: %d\n", err);
kfree(data);
return -ENOENT;
}
ctx->pos += VVSFS_DENTRYSIZE;
}
kfree(data);
DEBUG_LOG("vvsfs - readdir - done");
return 0;
}
const struct file_operations vvsfs_dir_operations = {
.llseek = generic_file_llseek,
.read = generic_read_dir,
#if LINUX_VERSION_CODE < KERNEL_VERSION(6, 5, 0)
.iterate = vvsfs_readdir,
#else
.iterate_shared = vvsfs_readdir,
#endif
.fsync = generic_file_fsync,
};