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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [fs/] [ext2/] [namei.c] - Blame information for rev 1275

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1275 phoenix
/*
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 viro@math.psu.edu
6
 *
7
 * Stuff here is basically a glue between the VFS and generic UNIXish
8
 * filesystem that keeps everything in pagecache. All knowledge of the
9
 * directory layout is in fs/ext2/dir.c - it turned out to be easily separatable
10
 * and it's easier to debug that way. In principle we might want to
11
 * generalize that a bit and turn it into a library. Or not.
12
 *
13
 * The only non-static object here is ext2_dir_inode_operations.
14
 *
15
 * TODO: get rid of kmap() use, add readahead.
16
 *
17
 * Copyright (C) 1992, 1993, 1994, 1995
18
 * Remy Card (card@masi.ibp.fr)
19
 * Laboratoire MASI - Institut Blaise Pascal
20
 * Universite Pierre et Marie Curie (Paris VI)
21
 *
22
 *  from
23
 *
24
 *  linux/fs/minix/namei.c
25
 *
26
 *  Copyright (C) 1991, 1992  Linus Torvalds
27
 *
28
 *  Big-endian to little-endian byte-swapping/bitmaps by
29
 *        David S. Miller (davem@caip.rutgers.edu), 1995
30
 */
31
 
32
#include <linux/fs.h>
33
#include <linux/ext2_fs.h>
34
#include <linux/pagemap.h>
35
 
36
/*
37
 * Couple of helper functions - make the code slightly cleaner.
38
 */
39
 
40
static inline void ext2_inc_count(struct inode *inode)
41
{
42
        inode->i_nlink++;
43
        mark_inode_dirty(inode);
44
}
45
 
46
static inline void ext2_dec_count(struct inode *inode)
47
{
48
        inode->i_nlink--;
49
        mark_inode_dirty(inode);
50
}
51
 
52
static inline int ext2_add_nondir(struct dentry *dentry, struct inode *inode)
53
{
54
        int err = ext2_add_link(dentry, inode);
55
        if (!err) {
56
                d_instantiate(dentry, inode);
57
                return 0;
58
        }
59
        ext2_dec_count(inode);
60
        iput(inode);
61
        return err;
62
}
63
 
64
/*
65
 * Methods themselves.
66
 */
67
 
68
static struct dentry *ext2_lookup(struct inode * dir, struct dentry *dentry)
69
{
70
        struct inode * inode;
71
        ino_t ino;
72
 
73
        if (dentry->d_name.len > EXT2_NAME_LEN)
74
                return ERR_PTR(-ENAMETOOLONG);
75
 
76
        ino = ext2_inode_by_name(dir, dentry);
77
        inode = NULL;
78
        if (ino) {
79
                inode = iget(dir->i_sb, ino);
80
                if (!inode)
81
                        return ERR_PTR(-EACCES);
82
        }
83
        d_add(dentry, inode);
84
        return NULL;
85
}
86
 
87
/*
88
 * By the time this is called, we already have created
89
 * the directory cache entry for the new file, but it
90
 * is so far negative - it has no inode.
91
 *
92
 * If the create succeeds, we fill in the inode information
93
 * with d_instantiate().
94
 */
95
static int ext2_create (struct inode * dir, struct dentry * dentry, int mode)
96
{
97
        struct inode * inode = ext2_new_inode (dir, mode);
98
        int err = PTR_ERR(inode);
99
        if (!IS_ERR(inode)) {
100
                inode->i_op = &ext2_file_inode_operations;
101
                inode->i_fop = &ext2_file_operations;
102
                inode->i_mapping->a_ops = &ext2_aops;
103
                mark_inode_dirty(inode);
104
                err = ext2_add_nondir(dentry, inode);
105
        }
106
        return err;
107
}
108
 
109
static int ext2_mknod (struct inode * dir, struct dentry *dentry, int mode, int rdev)
110
{
111
        struct inode * inode = ext2_new_inode (dir, mode);
112
        int err = PTR_ERR(inode);
113
        if (!IS_ERR(inode)) {
114
                init_special_inode(inode, mode, rdev);
115
                mark_inode_dirty(inode);
116
                err = ext2_add_nondir(dentry, inode);
117
        }
118
        return err;
119
}
120
 
121
static int ext2_symlink (struct inode * dir, struct dentry * dentry,
122
        const char * symname)
123
{
124
        struct super_block * sb = dir->i_sb;
125
        int err = -ENAMETOOLONG;
126
        unsigned l = strlen(symname)+1;
127
        struct inode * inode;
128
 
129
        if (l > sb->s_blocksize)
130
                goto out;
131
 
132
        inode = ext2_new_inode (dir, S_IFLNK | S_IRWXUGO);
133
        err = PTR_ERR(inode);
134
        if (IS_ERR(inode))
135
                goto out;
136
 
137
        if (l > sizeof (inode->u.ext2_i.i_data)) {
138
                /* slow symlink */
139
                inode->i_op = &page_symlink_inode_operations;
140
                inode->i_mapping->a_ops = &ext2_aops;
141
                err = block_symlink(inode, symname, l);
142
                if (err)
143
                        goto out_fail;
144
        } else {
145
                /* fast symlink */
146
                inode->i_op = &ext2_fast_symlink_inode_operations;
147
                memcpy((char*)&inode->u.ext2_i.i_data,symname,l);
148
                inode->i_size = l-1;
149
        }
150
        mark_inode_dirty(inode);
151
 
152
        err = ext2_add_nondir(dentry, inode);
153
out:
154
        return err;
155
 
156
out_fail:
157
        ext2_dec_count(inode);
158
        iput (inode);
159
        goto out;
160
}
161
 
162
static int ext2_link (struct dentry * old_dentry, struct inode * dir,
163
        struct dentry *dentry)
164
{
165
        struct inode *inode = old_dentry->d_inode;
166
 
167
        if (S_ISDIR(inode->i_mode))
168
                return -EPERM;
169
 
170
        if (inode->i_nlink >= EXT2_LINK_MAX)
171
                return -EMLINK;
172
 
173
        inode->i_ctime = CURRENT_TIME;
174
        ext2_inc_count(inode);
175
        atomic_inc(&inode->i_count);
176
 
177
        return ext2_add_nondir(dentry, inode);
178
}
179
 
180
static int ext2_mkdir(struct inode * dir, struct dentry * dentry, int mode)
181
{
182
        struct inode * inode;
183
        int err = -EMLINK;
184
 
185
        if (dir->i_nlink >= EXT2_LINK_MAX)
186
                goto out;
187
 
188
        ext2_inc_count(dir);
189
 
190
        inode = ext2_new_inode (dir, S_IFDIR | mode);
191
        err = PTR_ERR(inode);
192
        if (IS_ERR(inode))
193
                goto out_dir;
194
 
195
        inode->i_op = &ext2_dir_inode_operations;
196
        inode->i_fop = &ext2_dir_operations;
197
        inode->i_mapping->a_ops = &ext2_aops;
198
 
199
        ext2_inc_count(inode);
200
 
201
        err = ext2_make_empty(inode, dir);
202
        if (err)
203
                goto out_fail;
204
 
205
        err = ext2_add_link(dentry, inode);
206
        if (err)
207
                goto out_fail;
208
 
209
        d_instantiate(dentry, inode);
210
out:
211
        return err;
212
 
213
out_fail:
214
        ext2_dec_count(inode);
215
        ext2_dec_count(inode);
216
        iput(inode);
217
out_dir:
218
        ext2_dec_count(dir);
219
        goto out;
220
}
221
 
222
static int ext2_unlink(struct inode * dir, struct dentry *dentry)
223
{
224
        struct inode * inode = dentry->d_inode;
225
        struct ext2_dir_entry_2 * de;
226
        struct page * page;
227
        int err = -ENOENT;
228
 
229
        de = ext2_find_entry (dir, dentry, &page);
230
        if (!de)
231
                goto out;
232
 
233
        err = ext2_delete_entry (de, page);
234
        if (err)
235
                goto out;
236
 
237
        inode->i_ctime = dir->i_ctime;
238
        ext2_dec_count(inode);
239
        err = 0;
240
out:
241
        return err;
242
}
243
 
244
static int ext2_rmdir (struct inode * dir, struct dentry *dentry)
245
{
246
        struct inode * inode = dentry->d_inode;
247
        int err = -ENOTEMPTY;
248
 
249
        if (ext2_empty_dir(inode)) {
250
                err = ext2_unlink(dir, dentry);
251
                if (!err) {
252
                        inode->i_size = 0;
253
                        ext2_dec_count(inode);
254
                        ext2_dec_count(dir);
255
                }
256
        }
257
        return err;
258
}
259
 
260
static int ext2_rename (struct inode * old_dir, struct dentry * old_dentry,
261
        struct inode * new_dir, struct dentry * new_dentry )
262
{
263
        struct inode * old_inode = old_dentry->d_inode;
264
        struct inode * new_inode = new_dentry->d_inode;
265
        struct page * dir_page = NULL;
266
        struct ext2_dir_entry_2 * dir_de = NULL;
267
        struct page * old_page;
268
        struct ext2_dir_entry_2 * old_de;
269
        int err = -ENOENT;
270
 
271
        old_de = ext2_find_entry (old_dir, old_dentry, &old_page);
272
        if (!old_de)
273
                goto out;
274
 
275
        if (S_ISDIR(old_inode->i_mode)) {
276
                err = -EIO;
277
                dir_de = ext2_dotdot(old_inode, &dir_page);
278
                if (!dir_de)
279
                        goto out_old;
280
        }
281
 
282
        if (new_inode) {
283
                struct page *new_page;
284
                struct ext2_dir_entry_2 *new_de;
285
 
286
                err = -ENOTEMPTY;
287
                if (dir_de && !ext2_empty_dir (new_inode))
288
                        goto out_dir;
289
 
290
                err = -ENOENT;
291
                new_de = ext2_find_entry (new_dir, new_dentry, &new_page);
292
                if (!new_de)
293
                        goto out_dir;
294
                ext2_inc_count(old_inode);
295
                ext2_set_link(new_dir, new_de, new_page, old_inode);
296
                new_inode->i_ctime = CURRENT_TIME;
297
                if (dir_de)
298
                        new_inode->i_nlink--;
299
                ext2_dec_count(new_inode);
300
        } else {
301
                if (dir_de) {
302
                        err = -EMLINK;
303
                        if (new_dir->i_nlink >= EXT2_LINK_MAX)
304
                                goto out_dir;
305
                }
306
                ext2_inc_count(old_inode);
307
                err = ext2_add_link(new_dentry, old_inode);
308
                if (err) {
309
                        ext2_dec_count(old_inode);
310
                        goto out_dir;
311
                }
312
                if (dir_de)
313
                        ext2_inc_count(new_dir);
314
        }
315
 
316
        ext2_delete_entry (old_de, old_page);
317
        ext2_dec_count(old_inode);
318
 
319
        if (dir_de) {
320
                ext2_set_link(old_inode, dir_de, dir_page, new_dir);
321
                ext2_dec_count(old_dir);
322
        }
323
        return 0;
324
 
325
 
326
out_dir:
327
        if (dir_de) {
328
                kunmap(dir_page);
329
                page_cache_release(dir_page);
330
        }
331
out_old:
332
        kunmap(old_page);
333
        page_cache_release(old_page);
334
out:
335
        return err;
336
}
337
 
338
struct inode_operations ext2_dir_inode_operations = {
339
        create:         ext2_create,
340
        lookup:         ext2_lookup,
341
        link:           ext2_link,
342
        unlink:         ext2_unlink,
343
        symlink:        ext2_symlink,
344
        mkdir:          ext2_mkdir,
345
        rmdir:          ext2_rmdir,
346
        mknod:          ext2_mknod,
347
        rename:         ext2_rename,
348
};

powered by: WebSVN 2.1.0

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