mkatiyar / testfs

Simple block based test filesystem for linux

testfs / namei.c
100644 144 lines (126 sloc) 3.843 kb
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
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
/***********************************************************/
/* This is the readme for the testfs filesystem */
/* Author : Manish Katiyar <mkatiyar@gmail.com> */
/* Description : A simple disk based filesystem for linux */
/* Date : 08/01/09 */
/* Version : 0.01 */
/* Distributed under GPL */
/***********************************************************/
#include<linux/fs.h>
#include "testfs.h"
 
static int testfs_add_dentry(struct dentry *dentry, struct inode *inode)
{
int err = testfs_add_link(dentry, inode);
if (!err) {
/*
* Attach the negative dentry with the inode
*/
d_instantiate(dentry, inode);
unlock_new_inode(inode);
return 0;
}
inode_dec_link_count(inode);
unlock_new_inode(inode);
iput(inode);
return err;
}
 
static int testfs_create(struct inode *dir, struct dentry *dentry, int mode, struct nameidata *nd)
{
struct inode *inode = testfs_new_inode(dir, mode);
int err = PTR_ERR(inode);
if (!IS_ERR(inode)) {
 
testfs_debug("creating new file \"%s\" with inode %lu\n",dentry->d_name.name, inode->i_ino);
/*
* Initialize the new inode with proper
* function pointers
*/
inode->i_op = &testfs_file_inode_operations;
inode->i_fop = &testfs_file_operations;
inode->i_mapping->a_ops = &testfs_aops;
 
/* Mark the inode dirty so that it gets written */
mark_inode_dirty(inode);
 
/* Add this inode to the directory */
err = testfs_add_dentry(dentry, inode);
}
testfs_debug("I hope nothing is wrong here err = %d\n",err);
return err;
}
 
static struct dentry *testfs_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
{
struct inode *inode = NULL;
unsigned int ino;
 
//testfs_debug("Looking up file \"%s\" in dir inode %lu\n",dentry->d_name.name, dir->i_ino);
if(dentry->d_name.len > TESTFS_MAX_NAME_LEN)
return ERR_PTR(-ENAMETOOLONG);
 
ino = testfs_inode_by_name(dir, &dentry->d_name);
 
if (ino) {
inode = testfs_iget(dir->i_sb, ino);
if (IS_ERR(inode))
return ERR_CAST(inode);
}
 
return d_splice_alias(inode, dentry);
}
 
static int testfs_unlink(struct inode *dir, struct dentry *dentry)
{
struct inode *inode = dentry->d_inode;
struct testfs_dir_entry *de;
struct page *page;
int err = -ENOENT;
 
testfs_debug("Deleting file \"%s\"\n",dentry->d_name.name);
de = testfs_find_dentry(dir, &dentry->d_name, &page);
if (!de) {
testfs_debug("Unable to find requested filename\n");
goto out;
}
 
err = testfs_delete_entry(de, page);
if (err) {
goto out;
}
inode_dec_link_count(inode);
out:
return err;
}
 
static int testfs_symlink(struct inode *dir, struct dentry *dentry, const char *symname)
{
int err;
struct super_block *sb = dir->i_sb;
int len = strlen(symname) + 1;
struct inode *inode;
if (len > sb->s_blocksize) {
err = -ENAMETOOLONG;
goto out;
}
inode = testfs_new_inode(dir, S_IFLNK|S_IRWXUGO);
err = PTR_ERR(inode);
if(IS_ERR(inode)) {
testfs_error("Error creating new inode errno = %d\n", err);
goto out;
}
 
/* Assign the required function pointers to the new symlink inode */
inode->i_op = &testfs_symlink_inode_operations;
inode->i_mapping->a_ops = &testfs_aops;
err = page_symlink(inode, symname, len);
if(err)
goto out_fail;
 
mark_inode_dirty(inode);
err = testfs_add_dentry(dentry, inode);
out:
return err;
out_fail:
inode_dec_link_count(inode);
unlock_new_inode(inode);
iput(inode);
return err;
}
 
const struct inode_operations testfs_dir_inode_operations = {
.create = testfs_create,
.lookup = testfs_lookup,
//.link = testfs_link,
.unlink = testfs_unlink,
//.mkdir = testfs_mkdir,
//.rmdir = testfs_rmdir,
//.rename = testfs_rename,
.symlink = testfs_symlink,
.setattr = testfs_setattr,
.permission = testfs_permission,
};