-
Notifications
You must be signed in to change notification settings - Fork 8
/
vfs_ops.c
260 lines (224 loc) · 6.39 KB
/
vfs_ops.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
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
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
/* Copyright 2001, 2002, 2003 by Hans Reiser, licensing governed by
* reiser4/README */
/* Interface to VFS. Reiser4 {super|export|dentry}_operations are defined
here. */
#include "forward.h"
#include "debug.h"
#include "dformat.h"
#include "coord.h"
#include "plugin/item/item.h"
#include "plugin/file/file.h"
#include "plugin/security/perm.h"
#include "plugin/disk_format/disk_format.h"
#include "plugin/plugin.h"
#include "plugin/plugin_set.h"
#include "plugin/object.h"
#include "txnmgr.h"
#include "jnode.h"
#include "znode.h"
#include "block_alloc.h"
#include "tree.h"
#include "vfs_ops.h"
#include "inode.h"
#include "page_cache.h"
#include "ktxnmgrd.h"
#include "super.h"
#include "reiser4.h"
#include "entd.h"
#include "status_flags.h"
#include "flush.h"
#include "dscale.h"
#include <linux/profile.h>
#include <linux/types.h>
#include <linux/mount.h>
#include <linux/vfs.h>
#include <linux/mm.h>
#include <linux/buffer_head.h>
#include <linux/dcache.h>
#include <linux/list.h>
#include <linux/pagemap.h>
#include <linux/slab.h>
#include <linux/seq_file.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/writeback.h>
#include <linux/blkdev.h>
#include <linux/security.h>
#include <linux/reboot.h>
#include <linux/rcupdate.h>
/* update inode stat-data by calling plugin */
int reiser4_update_sd(struct inode *object)
{
file_plugin *fplug;
assert("nikita-2338", object != NULL);
/* check for read-only file system. */
if (IS_RDONLY(object))
return 0;
fplug = inode_file_plugin(object);
assert("nikita-2339", fplug != NULL);
return fplug->write_sd_by_inode(object);
}
/* helper function: increase inode nlink count and call plugin method to save
updated stat-data.
Used by link/create and during creation of dot and dotdot in mkdir
*/
int reiser4_add_nlink(struct inode *object /* object to which link is added */ ,
struct inode *parent /* parent where new entry will be */
,
int write_sd_p /* true if stat-data has to be
* updated */ )
{
file_plugin *fplug;
int result;
assert("nikita-1351", object != NULL);
fplug = inode_file_plugin(object);
assert("nikita-1445", fplug != NULL);
/* ask plugin whether it can add yet another link to this
object */
if (!fplug->can_add_link(object))
return RETERR(-EMLINK);
assert("nikita-2211", fplug->add_link != NULL);
/* call plugin to do actual addition of link */
result = fplug->add_link(object, parent);
/* optionally update stat data */
if (result == 0 && write_sd_p)
result = fplug->write_sd_by_inode(object);
return result;
}
/* helper function: decrease inode nlink count and call plugin method to save
updated stat-data.
Used by unlink/create
*/
int reiser4_del_nlink(struct inode *object /* object from which link is
* removed */ ,
struct inode *parent /* parent where entry was */ ,
int write_sd_p /* true is stat-data has to be
* updated */ )
{
file_plugin *fplug;
int result;
assert("nikita-1349", object != NULL);
fplug = inode_file_plugin(object);
assert("nikita-1350", fplug != NULL);
assert("nikita-1446", object->i_nlink > 0);
assert("nikita-2210", fplug->rem_link != NULL);
/* call plugin to do actual deletion of link */
result = fplug->rem_link(object, parent);
/* optionally update stat data */
if (result == 0 && write_sd_p)
result = fplug->write_sd_by_inode(object);
return result;
}
/* Release reiser4 dentry. This is d_op->d_release() method. */
static void reiser4_d_release(struct dentry *dentry /* dentry released */ )
{
reiser4_free_dentry_fsdata(dentry);
}
/*
* Called by reiser4_sync_inodes(), during speculative write-back (through
* pdflush, or balance_dirty_pages()).
*/
void reiser4_writeout(struct super_block *sb, struct writeback_control *wbc)
{
long written = 0;
int repeats = 0;
int result;
/*
* Performs early flushing, trying to free some memory. If there
* is nothing to flush, commits some atoms.
*
* Commit all atoms if reiser4_writepages_dispatch() is called
* from sys_sync() or sys_fsync()
*/
if (wbc->sync_mode != WB_SYNC_NONE) {
txnmgr_force_commit_all(sb, 0);
return;
}
BUG_ON(reiser4_get_super_fake(sb) == NULL);
do {
long nr_submitted = 0;
jnode *node = NULL;
/* do not put more requests to overload write queue */
if (bdi_write_congested(inode_to_bdi(reiser4_get_super_fake(sb)))) {
//blk_flush_plug(current);
break;
}
repeats++;
BUG_ON(wbc->nr_to_write <= 0);
if (get_current_context()->entd) {
entd_context *ent = get_entd_context(sb);
if (ent->cur_request->node)
/*
* this is ent thread and it managed to capture
* requested page itself - start flush from
* that page
*/
node = ent->cur_request->node;
}
result = flush_some_atom(node, &nr_submitted, wbc,
JNODE_FLUSH_WRITE_BLOCKS);
if (result != 0)
warning("nikita-31001", "Flush failed: %i", result);
if (node)
/* drop the reference aquired
in find_or_create_extent() */
jput(node);
if (!nr_submitted)
break;
wbc->nr_to_write -= nr_submitted;
written += nr_submitted;
} while (wbc->nr_to_write > 0);
}
/* tell VM how many pages were dirtied */
void reiser4_throttle_write(struct inode *inode)
{
reiser4_context *ctx;
ctx = get_current_context();
reiser4_txn_restart(ctx);
current->journal_info = NULL;
balance_dirty_pages_ratelimited(inode->i_mapping);
current->journal_info = ctx;
}
const int REISER4_MAGIC_OFFSET = 16 * 4096; /* offset to magic string from the
* beginning of device */
/*
* Reiser4 initialization/shutdown.
*
* Code below performs global reiser4 initialization that is done either as
* part of kernel initialization (when reiser4 is statically built-in), or
* during reiser4 module load (when compiled as module).
*/
void reiser4_handle_error(void)
{
struct super_block *sb = reiser4_get_current_sb();
if (!sb)
return;
reiser4_status_write(REISER4_STATUS_DAMAGED, 0,
"Filesystem error occured");
switch (get_super_private(sb)->onerror) {
case 1:
reiser4_panic("foobar-42", "Filesystem error occured\n");
default:
if (sb_rdonly(sb))
return;
sb->s_flags |= SB_RDONLY;
break;
}
}
struct dentry_operations reiser4_dentry_operations = {
.d_revalidate = NULL,
.d_hash = NULL,
.d_compare = NULL,
.d_delete = NULL,
.d_release = reiser4_d_release,
.d_iput = NULL,
};
/* Make Linus happy.
Local variables:
c-indentation-style: "K&R"
mode-name: "LC"
c-basic-offset: 8
tab-width: 8
fill-column: 120
End:
*/