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
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
|
/*
RAWFS: Raw file system for NAND flash
Copyright (C) 2012-2015 Perry Hsu <perry.hsu@mediatek.com>"
This program can be distributed under the terms of the GNU GPL.
See the file COPYING.
*/
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/crc32.h>
#include "rawfs.h"
int rawfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
{
struct inode *inode = filp->f_path.dentry->d_inode;
struct dentry *dentry = filp->f_path.dentry;
struct super_block *sb = inode->i_sb;
struct rawfs_sb_info *sbi = RAWFS_SB(sb);
int total_cnt = 0; /* Total entries we found in hlist */
loff_t cpos;
unsigned long ino;
cpos = filp->f_pos;
/* Read dir will execute twice. */
if (inode->i_ino == RAWFS_ROOT_INO)
RAWFS_PRINT(RAWFS_DBG_DIR, "rawfs_readdir, root, pos %lld\n", cpos);
else
RAWFS_PRINT(RAWFS_DBG_DIR, "rawfs_readdir, %s, i_id %X, i_ino %X, pos %lld\n",
dentry->d_name.name, RAWFS_I(inode)->i_id, (unsigned)inode->i_ino, cpos);
switch (cpos) {
case 0:
ino = dentry->d_inode->i_ino;
if (filldir(dirent, ".", 1, cpos, ino, DT_DIR) < 0)
break;
filp->f_pos++;
cpos++;
/* fallthrough */
case 1:
ino = parent_ino(dentry);
if (filldir(dirent, "..", 2, cpos, ino, DT_DIR) < 0)
break;
filp->f_pos++;
cpos++;
/* fallthrough */
default:
{
struct rawfs_file_list_entry *entry;
struct list_head *lists[2];
int i;
lists[0] = &sbi->folder_list;
lists[1] = &sbi->file_list;
mutex_lock(&sbi->file_list_lock);
for (i = 0; i < 2; i++) {
list_for_each_entry(entry, lists[i], list)
{
int name_len;
/* Matching sub-directory */
if (entry->file_info.i_parent_folder_id !=
RAWFS_I(dentry->d_inode)->i_id) {
RAWFS_PRINT(RAWFS_DBG_DIR,
"readdir: skip %s, parent folder id %X, target folder %X\n",
entry->file_info.i_name,
entry->file_info.i_parent_folder_id,
RAWFS_I(dentry->d_inode)->i_id);
continue;
}
total_cnt++;
if ((total_cnt+2) <= cpos) { /* skip first N + 2 (. & ..)
entiries, if cpos doesn't start from zero */
RAWFS_PRINT(RAWFS_DBG_DIR,
"readdir: cpos=%lld, total cnt=%d, %s\n", cpos, total_cnt,
entry->file_info.i_name);
continue;
}
name_len = strlen(entry->file_info.i_name);
if (filldir(dirent,
entry->file_info.i_name,
name_len,
cpos,
entry->file_info.i_id,
(S_ISDIR(entry->file_info.i_mode)?DT_DIR:DT_REG)) < 0)
goto out;
filp->f_pos++;
cpos++;
}
}
}
out:
mutex_unlock(&sbi->file_list_lock);
break;
}
return 0;
}
EXPORT_SYMBOL_GPL(rawfs_readdir);
int rawfs_file_sync(struct file *file, loff_t start, loff_t end,
int datasync)
{
struct inode *inode = file->f_path.dentry->d_inode;
RAWFS_PRINT(RAWFS_DBG_DIR, "fsync, i_ino %ld\n", inode->i_ino);
return 0;
}
EXPORT_SYMBOL_GPL(rawfs_file_sync);
MODULE_AUTHOR("Perry Hsu <perry.hsu@mediatek.com>");
MODULE_DESCRIPTION("RAW file system for NAND flash");
MODULE_LICENSE("GPL");
|