OpenCores
URL https://opencores.org/ocsvn/test_project/test_project/trunk

Subversion Repositories test_project

[/] [test_project/] [trunk/] [linux_sd_driver/] [fs/] [ext2/] [namei.c] - Blame information for rev 62

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 62 marcus.erl
/*
2
 * linux/fs/ext2/namei.c
3
 *
4
 * Rewrite to pagecache. Almost all code had been changed, so blame me
5
 * if the things go wrong. Please, send bug reports to
6
 * viro@parcelfarce.linux.theplanet.co.uk
7
 *
8
 * Stuff here is basically a glue between the VFS and generic UNIXish
9
 * filesystem that keeps everything in pagecache. All knowledge of the
10
 * directory layout is in fs/ext2/dir.c - it turned out to be easily separatable
11
 * and it's easier to debug that way. In principle we might want to
12
 * generalize that a bit and turn it into a library. Or not.
13
 *
14
 * The only non-static object here is ext2_dir_inode_operations.
15
 *
16
 * TODO: get rid of kmap() use, add readahead.
17
 *
18
 * Copyright (C) 1992, 1993, 1994, 1995
19
 * Remy Card (card@masi.ibp.fr)
20
 * Laboratoire MASI - Institut Blaise Pascal
21
 * Universite Pierre et Marie Curie (Paris VI)
22
 *
23
 *  from
24
 *
25
 *  linux/fs/minix/namei.c
26
 *
27
 *  Copyright (C) 1991, 1992  Linus Torvalds
28
 *
29
 *  Big-endian to little-endian byte-swapping/bitmaps by
30
 *        David S. Miller (davem@caip.rutgers.edu), 1995
31
 */
32
 
33
#include <linux/pagemap.h>
34
#include "ext2.h"
35
#include "xattr.h"
36
#include "acl.h"
37
#include "xip.h"
38
 
39
static inline int ext2_add_nondir(struct dentry *dentry, struct inode *inode)
40
{
41
        int err = ext2_add_link(dentry, inode);
42
        if (!err) {
43
                d_instantiate(dentry, inode);
44
                return 0;
45
        }
46
        inode_dec_link_count(inode);
47
        iput(inode);
48
        return err;
49
}
50
 
51
/*
52
 * Methods themselves.
53
 */
54
 
55
static struct dentry *ext2_lookup(struct inode * dir, struct dentry *dentry, struct nameidata *nd)
56
{
57
        struct inode * inode;
58
        ino_t ino;
59
 
60
        if (dentry->d_name.len > EXT2_NAME_LEN)
61
                return ERR_PTR(-ENAMETOOLONG);
62
 
63
        ino = ext2_inode_by_name(dir, dentry);
64
        inode = NULL;
65
        if (ino) {
66
                inode = iget(dir->i_sb, ino);
67
                if (!inode)
68
                        return ERR_PTR(-EACCES);
69
        }
70
        return d_splice_alias(inode, dentry);
71
}
72
 
73
struct dentry *ext2_get_parent(struct dentry *child)
74
{
75
        unsigned long ino;
76
        struct dentry *parent;
77
        struct inode *inode;
78
        struct dentry dotdot;
79
 
80
        dotdot.d_name.name = "..";
81
        dotdot.d_name.len = 2;
82
 
83
        ino = ext2_inode_by_name(child->d_inode, &dotdot);
84
        if (!ino)
85
                return ERR_PTR(-ENOENT);
86
        inode = iget(child->d_inode->i_sb, ino);
87
 
88
        if (!inode)
89
                return ERR_PTR(-EACCES);
90
        parent = d_alloc_anon(inode);
91
        if (!parent) {
92
                iput(inode);
93
                parent = ERR_PTR(-ENOMEM);
94
        }
95
        return parent;
96
}
97
 
98
/*
99
 * By the time this is called, we already have created
100
 * the directory cache entry for the new file, but it
101
 * is so far negative - it has no inode.
102
 *
103
 * If the create succeeds, we fill in the inode information
104
 * with d_instantiate().
105
 */
106
static int ext2_create (struct inode * dir, struct dentry * dentry, int mode, struct nameidata *nd)
107
{
108
        struct inode * inode = ext2_new_inode (dir, mode);
109
        int err = PTR_ERR(inode);
110
        if (!IS_ERR(inode)) {
111
                inode->i_op = &ext2_file_inode_operations;
112
                if (ext2_use_xip(inode->i_sb)) {
113
                        inode->i_mapping->a_ops = &ext2_aops_xip;
114
                        inode->i_fop = &ext2_xip_file_operations;
115
                } else if (test_opt(inode->i_sb, NOBH)) {
116
                        inode->i_mapping->a_ops = &ext2_nobh_aops;
117
                        inode->i_fop = &ext2_file_operations;
118
                } else {
119
                        inode->i_mapping->a_ops = &ext2_aops;
120
                        inode->i_fop = &ext2_file_operations;
121
                }
122
                mark_inode_dirty(inode);
123
                err = ext2_add_nondir(dentry, inode);
124
        }
125
        return err;
126
}
127
 
128
static int ext2_mknod (struct inode * dir, struct dentry *dentry, int mode, dev_t rdev)
129
{
130
        struct inode * inode;
131
        int err;
132
 
133
        if (!new_valid_dev(rdev))
134
                return -EINVAL;
135
 
136
        inode = ext2_new_inode (dir, mode);
137
        err = PTR_ERR(inode);
138
        if (!IS_ERR(inode)) {
139
                init_special_inode(inode, inode->i_mode, rdev);
140
#ifdef CONFIG_EXT2_FS_XATTR
141
                inode->i_op = &ext2_special_inode_operations;
142
#endif
143
                mark_inode_dirty(inode);
144
                err = ext2_add_nondir(dentry, inode);
145
        }
146
        return err;
147
}
148
 
149
static int ext2_symlink (struct inode * dir, struct dentry * dentry,
150
        const char * symname)
151
{
152
        struct super_block * sb = dir->i_sb;
153
        int err = -ENAMETOOLONG;
154
        unsigned l = strlen(symname)+1;
155
        struct inode * inode;
156
 
157
        if (l > sb->s_blocksize)
158
                goto out;
159
 
160
        inode = ext2_new_inode (dir, S_IFLNK | S_IRWXUGO);
161
        err = PTR_ERR(inode);
162
        if (IS_ERR(inode))
163
                goto out;
164
 
165
        if (l > sizeof (EXT2_I(inode)->i_data)) {
166
                /* slow symlink */
167
                inode->i_op = &ext2_symlink_inode_operations;
168
                if (test_opt(inode->i_sb, NOBH))
169
                        inode->i_mapping->a_ops = &ext2_nobh_aops;
170
                else
171
                        inode->i_mapping->a_ops = &ext2_aops;
172
                err = page_symlink(inode, symname, l);
173
                if (err)
174
                        goto out_fail;
175
        } else {
176
                /* fast symlink */
177
                inode->i_op = &ext2_fast_symlink_inode_operations;
178
                memcpy((char*)(EXT2_I(inode)->i_data),symname,l);
179
                inode->i_size = l-1;
180
        }
181
        mark_inode_dirty(inode);
182
 
183
        err = ext2_add_nondir(dentry, inode);
184
out:
185
        return err;
186
 
187
out_fail:
188
        inode_dec_link_count(inode);
189
        iput (inode);
190
        goto out;
191
}
192
 
193
static int ext2_link (struct dentry * old_dentry, struct inode * dir,
194
        struct dentry *dentry)
195
{
196
        struct inode *inode = old_dentry->d_inode;
197
 
198
        if (inode->i_nlink >= EXT2_LINK_MAX)
199
                return -EMLINK;
200
 
201
        inode->i_ctime = CURRENT_TIME_SEC;
202
        inode_inc_link_count(inode);
203
        atomic_inc(&inode->i_count);
204
 
205
        return ext2_add_nondir(dentry, inode);
206
}
207
 
208
static int ext2_mkdir(struct inode * dir, struct dentry * dentry, int mode)
209
{
210
        struct inode * inode;
211
        int err = -EMLINK;
212
 
213
        if (dir->i_nlink >= EXT2_LINK_MAX)
214
                goto out;
215
 
216
        inode_inc_link_count(dir);
217
 
218
        inode = ext2_new_inode (dir, S_IFDIR | mode);
219
        err = PTR_ERR(inode);
220
        if (IS_ERR(inode))
221
                goto out_dir;
222
 
223
        inode->i_op = &ext2_dir_inode_operations;
224
        inode->i_fop = &ext2_dir_operations;
225
        if (test_opt(inode->i_sb, NOBH))
226
                inode->i_mapping->a_ops = &ext2_nobh_aops;
227
        else
228
                inode->i_mapping->a_ops = &ext2_aops;
229
 
230
        inode_inc_link_count(inode);
231
 
232
        err = ext2_make_empty(inode, dir);
233
        if (err)
234
                goto out_fail;
235
 
236
        err = ext2_add_link(dentry, inode);
237
        if (err)
238
                goto out_fail;
239
 
240
        d_instantiate(dentry, inode);
241
out:
242
        return err;
243
 
244
out_fail:
245
        inode_dec_link_count(inode);
246
        inode_dec_link_count(inode);
247
        iput(inode);
248
out_dir:
249
        inode_dec_link_count(dir);
250
        goto out;
251
}
252
 
253
static int ext2_unlink(struct inode * dir, struct dentry *dentry)
254
{
255
        struct inode * inode = dentry->d_inode;
256
        struct ext2_dir_entry_2 * de;
257
        struct page * page;
258
        int err = -ENOENT;
259
 
260
        de = ext2_find_entry (dir, dentry, &page);
261
        if (!de)
262
                goto out;
263
 
264
        err = ext2_delete_entry (de, page);
265
        if (err)
266
                goto out;
267
 
268
        inode->i_ctime = dir->i_ctime;
269
        inode_dec_link_count(inode);
270
        err = 0;
271
out:
272
        return err;
273
}
274
 
275
static int ext2_rmdir (struct inode * dir, struct dentry *dentry)
276
{
277
        struct inode * inode = dentry->d_inode;
278
        int err = -ENOTEMPTY;
279
 
280
        if (ext2_empty_dir(inode)) {
281
                err = ext2_unlink(dir, dentry);
282
                if (!err) {
283
                        inode->i_size = 0;
284
                        inode_dec_link_count(inode);
285
                        inode_dec_link_count(dir);
286
                }
287
        }
288
        return err;
289
}
290
 
291
static int ext2_rename (struct inode * old_dir, struct dentry * old_dentry,
292
        struct inode * new_dir, struct dentry * new_dentry )
293
{
294
        struct inode * old_inode = old_dentry->d_inode;
295
        struct inode * new_inode = new_dentry->d_inode;
296
        struct page * dir_page = NULL;
297
        struct ext2_dir_entry_2 * dir_de = NULL;
298
        struct page * old_page;
299
        struct ext2_dir_entry_2 * old_de;
300
        int err = -ENOENT;
301
 
302
        old_de = ext2_find_entry (old_dir, old_dentry, &old_page);
303
        if (!old_de)
304
                goto out;
305
 
306
        if (S_ISDIR(old_inode->i_mode)) {
307
                err = -EIO;
308
                dir_de = ext2_dotdot(old_inode, &dir_page);
309
                if (!dir_de)
310
                        goto out_old;
311
        }
312
 
313
        if (new_inode) {
314
                struct page *new_page;
315
                struct ext2_dir_entry_2 *new_de;
316
 
317
                err = -ENOTEMPTY;
318
                if (dir_de && !ext2_empty_dir (new_inode))
319
                        goto out_dir;
320
 
321
                err = -ENOENT;
322
                new_de = ext2_find_entry (new_dir, new_dentry, &new_page);
323
                if (!new_de)
324
                        goto out_dir;
325
                inode_inc_link_count(old_inode);
326
                ext2_set_link(new_dir, new_de, new_page, old_inode);
327
                new_inode->i_ctime = CURRENT_TIME_SEC;
328
                if (dir_de)
329
                        drop_nlink(new_inode);
330
                inode_dec_link_count(new_inode);
331
        } else {
332
                if (dir_de) {
333
                        err = -EMLINK;
334
                        if (new_dir->i_nlink >= EXT2_LINK_MAX)
335
                                goto out_dir;
336
                }
337
                inode_inc_link_count(old_inode);
338
                err = ext2_add_link(new_dentry, old_inode);
339
                if (err) {
340
                        inode_dec_link_count(old_inode);
341
                        goto out_dir;
342
                }
343
                if (dir_de)
344
                        inode_inc_link_count(new_dir);
345
        }
346
 
347
        /*
348
         * Like most other Unix systems, set the ctime for inodes on a
349
         * rename.
350
         * inode_dec_link_count() will mark the inode dirty.
351
         */
352
        old_inode->i_ctime = CURRENT_TIME_SEC;
353
 
354
        ext2_delete_entry (old_de, old_page);
355
        inode_dec_link_count(old_inode);
356
 
357
        if (dir_de) {
358
                ext2_set_link(old_inode, dir_de, dir_page, new_dir);
359
                inode_dec_link_count(old_dir);
360
        }
361
        return 0;
362
 
363
 
364
out_dir:
365
        if (dir_de) {
366
                kunmap(dir_page);
367
                page_cache_release(dir_page);
368
        }
369
out_old:
370
        kunmap(old_page);
371
        page_cache_release(old_page);
372
out:
373
        return err;
374
}
375
 
376
const struct inode_operations ext2_dir_inode_operations = {
377
        .create         = ext2_create,
378
        .lookup         = ext2_lookup,
379
        .link           = ext2_link,
380
        .unlink         = ext2_unlink,
381
        .symlink        = ext2_symlink,
382
        .mkdir          = ext2_mkdir,
383
        .rmdir          = ext2_rmdir,
384
        .mknod          = ext2_mknod,
385
        .rename         = ext2_rename,
386
#ifdef CONFIG_EXT2_FS_XATTR
387
        .setxattr       = generic_setxattr,
388
        .getxattr       = generic_getxattr,
389
        .listxattr      = ext2_listxattr,
390
        .removexattr    = generic_removexattr,
391
#endif
392
        .setattr        = ext2_setattr,
393
        .permission     = ext2_permission,
394
};
395
 
396
const struct inode_operations ext2_special_inode_operations = {
397
#ifdef CONFIG_EXT2_FS_XATTR
398
        .setxattr       = generic_setxattr,
399
        .getxattr       = generic_getxattr,
400
        .listxattr      = ext2_listxattr,
401
        .removexattr    = generic_removexattr,
402
#endif
403
        .setattr        = ext2_setattr,
404
        .permission     = ext2_permission,
405
};

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.