Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/fs/exofs/namei.c
15112 views
1
/*
2
* Copyright (C) 2005, 2006
3
* Avishay Traeger ([email protected])
4
* Copyright (C) 2008, 2009
5
* Boaz Harrosh <[email protected]>
6
*
7
* Copyrights for code taken from ext2:
8
* Copyright (C) 1992, 1993, 1994, 1995
9
* Remy Card ([email protected])
10
* Laboratoire MASI - Institut Blaise Pascal
11
* Universite Pierre et Marie Curie (Paris VI)
12
* from
13
* linux/fs/minix/inode.c
14
* Copyright (C) 1991, 1992 Linus Torvalds
15
*
16
* This file is part of exofs.
17
*
18
* exofs is free software; you can redistribute it and/or modify
19
* it under the terms of the GNU General Public License as published by
20
* the Free Software Foundation. Since it is based on ext2, and the only
21
* valid version of GPL for the Linux kernel is version 2, the only valid
22
* version of GPL for exofs is version 2.
23
*
24
* exofs is distributed in the hope that it will be useful,
25
* but WITHOUT ANY WARRANTY; without even the implied warranty of
26
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
27
* GNU General Public License for more details.
28
*
29
* You should have received a copy of the GNU General Public License
30
* along with exofs; if not, write to the Free Software
31
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
32
*/
33
34
#include "exofs.h"
35
36
static inline int exofs_add_nondir(struct dentry *dentry, struct inode *inode)
37
{
38
int err = exofs_add_link(dentry, inode);
39
if (!err) {
40
d_instantiate(dentry, inode);
41
return 0;
42
}
43
inode_dec_link_count(inode);
44
iput(inode);
45
return err;
46
}
47
48
static struct dentry *exofs_lookup(struct inode *dir, struct dentry *dentry,
49
struct nameidata *nd)
50
{
51
struct inode *inode;
52
ino_t ino;
53
54
if (dentry->d_name.len > EXOFS_NAME_LEN)
55
return ERR_PTR(-ENAMETOOLONG);
56
57
ino = exofs_inode_by_name(dir, dentry);
58
inode = NULL;
59
if (ino) {
60
inode = exofs_iget(dir->i_sb, ino);
61
if (IS_ERR(inode))
62
return ERR_CAST(inode);
63
}
64
return d_splice_alias(inode, dentry);
65
}
66
67
static int exofs_create(struct inode *dir, struct dentry *dentry, int mode,
68
struct nameidata *nd)
69
{
70
struct inode *inode = exofs_new_inode(dir, mode);
71
int err = PTR_ERR(inode);
72
if (!IS_ERR(inode)) {
73
inode->i_op = &exofs_file_inode_operations;
74
inode->i_fop = &exofs_file_operations;
75
inode->i_mapping->a_ops = &exofs_aops;
76
mark_inode_dirty(inode);
77
err = exofs_add_nondir(dentry, inode);
78
}
79
return err;
80
}
81
82
static int exofs_mknod(struct inode *dir, struct dentry *dentry, int mode,
83
dev_t rdev)
84
{
85
struct inode *inode;
86
int err;
87
88
if (!new_valid_dev(rdev))
89
return -EINVAL;
90
91
inode = exofs_new_inode(dir, mode);
92
err = PTR_ERR(inode);
93
if (!IS_ERR(inode)) {
94
init_special_inode(inode, inode->i_mode, rdev);
95
mark_inode_dirty(inode);
96
err = exofs_add_nondir(dentry, inode);
97
}
98
return err;
99
}
100
101
static int exofs_symlink(struct inode *dir, struct dentry *dentry,
102
const char *symname)
103
{
104
struct super_block *sb = dir->i_sb;
105
int err = -ENAMETOOLONG;
106
unsigned l = strlen(symname)+1;
107
struct inode *inode;
108
struct exofs_i_info *oi;
109
110
if (l > sb->s_blocksize)
111
goto out;
112
113
inode = exofs_new_inode(dir, S_IFLNK | S_IRWXUGO);
114
err = PTR_ERR(inode);
115
if (IS_ERR(inode))
116
goto out;
117
118
oi = exofs_i(inode);
119
if (l > sizeof(oi->i_data)) {
120
/* slow symlink */
121
inode->i_op = &exofs_symlink_inode_operations;
122
inode->i_mapping->a_ops = &exofs_aops;
123
memset(oi->i_data, 0, sizeof(oi->i_data));
124
125
err = page_symlink(inode, symname, l);
126
if (err)
127
goto out_fail;
128
} else {
129
/* fast symlink */
130
inode->i_op = &exofs_fast_symlink_inode_operations;
131
memcpy(oi->i_data, symname, l);
132
inode->i_size = l-1;
133
}
134
mark_inode_dirty(inode);
135
136
err = exofs_add_nondir(dentry, inode);
137
out:
138
return err;
139
140
out_fail:
141
inode_dec_link_count(inode);
142
iput(inode);
143
goto out;
144
}
145
146
static int exofs_link(struct dentry *old_dentry, struct inode *dir,
147
struct dentry *dentry)
148
{
149
struct inode *inode = old_dentry->d_inode;
150
151
if (inode->i_nlink >= EXOFS_LINK_MAX)
152
return -EMLINK;
153
154
inode->i_ctime = CURRENT_TIME;
155
inode_inc_link_count(inode);
156
ihold(inode);
157
158
return exofs_add_nondir(dentry, inode);
159
}
160
161
static int exofs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
162
{
163
struct inode *inode;
164
int err = -EMLINK;
165
166
if (dir->i_nlink >= EXOFS_LINK_MAX)
167
goto out;
168
169
inode_inc_link_count(dir);
170
171
inode = exofs_new_inode(dir, S_IFDIR | mode);
172
err = PTR_ERR(inode);
173
if (IS_ERR(inode))
174
goto out_dir;
175
176
inode->i_op = &exofs_dir_inode_operations;
177
inode->i_fop = &exofs_dir_operations;
178
inode->i_mapping->a_ops = &exofs_aops;
179
180
inode_inc_link_count(inode);
181
182
err = exofs_make_empty(inode, dir);
183
if (err)
184
goto out_fail;
185
186
err = exofs_add_link(dentry, inode);
187
if (err)
188
goto out_fail;
189
190
d_instantiate(dentry, inode);
191
out:
192
return err;
193
194
out_fail:
195
inode_dec_link_count(inode);
196
inode_dec_link_count(inode);
197
iput(inode);
198
out_dir:
199
inode_dec_link_count(dir);
200
goto out;
201
}
202
203
static int exofs_unlink(struct inode *dir, struct dentry *dentry)
204
{
205
struct inode *inode = dentry->d_inode;
206
struct exofs_dir_entry *de;
207
struct page *page;
208
int err = -ENOENT;
209
210
de = exofs_find_entry(dir, dentry, &page);
211
if (!de)
212
goto out;
213
214
err = exofs_delete_entry(de, page);
215
if (err)
216
goto out;
217
218
inode->i_ctime = dir->i_ctime;
219
inode_dec_link_count(inode);
220
err = 0;
221
out:
222
return err;
223
}
224
225
static int exofs_rmdir(struct inode *dir, struct dentry *dentry)
226
{
227
struct inode *inode = dentry->d_inode;
228
int err = -ENOTEMPTY;
229
230
if (exofs_empty_dir(inode)) {
231
err = exofs_unlink(dir, dentry);
232
if (!err) {
233
inode->i_size = 0;
234
inode_dec_link_count(inode);
235
inode_dec_link_count(dir);
236
}
237
}
238
return err;
239
}
240
241
static int exofs_rename(struct inode *old_dir, struct dentry *old_dentry,
242
struct inode *new_dir, struct dentry *new_dentry)
243
{
244
struct inode *old_inode = old_dentry->d_inode;
245
struct inode *new_inode = new_dentry->d_inode;
246
struct page *dir_page = NULL;
247
struct exofs_dir_entry *dir_de = NULL;
248
struct page *old_page;
249
struct exofs_dir_entry *old_de;
250
int err = -ENOENT;
251
252
old_de = exofs_find_entry(old_dir, old_dentry, &old_page);
253
if (!old_de)
254
goto out;
255
256
if (S_ISDIR(old_inode->i_mode)) {
257
err = -EIO;
258
dir_de = exofs_dotdot(old_inode, &dir_page);
259
if (!dir_de)
260
goto out_old;
261
}
262
263
if (new_inode) {
264
struct page *new_page;
265
struct exofs_dir_entry *new_de;
266
267
err = -ENOTEMPTY;
268
if (dir_de && !exofs_empty_dir(new_inode))
269
goto out_dir;
270
271
err = -ENOENT;
272
new_de = exofs_find_entry(new_dir, new_dentry, &new_page);
273
if (!new_de)
274
goto out_dir;
275
err = exofs_set_link(new_dir, new_de, new_page, old_inode);
276
new_inode->i_ctime = CURRENT_TIME;
277
if (dir_de)
278
drop_nlink(new_inode);
279
inode_dec_link_count(new_inode);
280
if (err)
281
goto out_dir;
282
} else {
283
if (dir_de) {
284
err = -EMLINK;
285
if (new_dir->i_nlink >= EXOFS_LINK_MAX)
286
goto out_dir;
287
}
288
err = exofs_add_link(new_dentry, old_inode);
289
if (err)
290
goto out_dir;
291
if (dir_de)
292
inode_inc_link_count(new_dir);
293
}
294
295
old_inode->i_ctime = CURRENT_TIME;
296
297
exofs_delete_entry(old_de, old_page);
298
mark_inode_dirty(old_inode);
299
300
if (dir_de) {
301
err = exofs_set_link(old_inode, dir_de, dir_page, new_dir);
302
inode_dec_link_count(old_dir);
303
if (err)
304
goto out_dir;
305
}
306
return 0;
307
308
309
out_dir:
310
if (dir_de) {
311
kunmap(dir_page);
312
page_cache_release(dir_page);
313
}
314
out_old:
315
kunmap(old_page);
316
page_cache_release(old_page);
317
out:
318
return err;
319
}
320
321
const struct inode_operations exofs_dir_inode_operations = {
322
.create = exofs_create,
323
.lookup = exofs_lookup,
324
.link = exofs_link,
325
.unlink = exofs_unlink,
326
.symlink = exofs_symlink,
327
.mkdir = exofs_mkdir,
328
.rmdir = exofs_rmdir,
329
.mknod = exofs_mknod,
330
.rename = exofs_rename,
331
.setattr = exofs_setattr,
332
};
333
334
const struct inode_operations exofs_special_inode_operations = {
335
.setattr = exofs_setattr,
336
};
337
338