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

Subversion Repositories or1k

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

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1275 phoenix
/*
2
 *  linux/fs/minix/namei.c
3
 *
4
 *  Copyright (C) 1991, 1992  Linus Torvalds
5
 */
6
 
7
#include <linux/fs.h>
8
#include <linux/minix_fs.h>
9
#include <linux/pagemap.h>
10
 
11
static inline void inc_count(struct inode *inode)
12
{
13
        inode->i_nlink++;
14
        mark_inode_dirty(inode);
15
}
16
 
17
static inline void dec_count(struct inode *inode)
18
{
19
        inode->i_nlink--;
20
        mark_inode_dirty(inode);
21
}
22
 
23
static int add_nondir(struct dentry *dentry, struct inode *inode)
24
{
25
        int err = minix_add_link(dentry, inode);
26
        if (!err) {
27
                d_instantiate(dentry, inode);
28
                return 0;
29
        }
30
        dec_count(inode);
31
        iput(inode);
32
        return err;
33
}
34
 
35
static int minix_hash(struct dentry *dentry, struct qstr *qstr)
36
{
37
        unsigned long hash;
38
        int i;
39
        const unsigned char *name;
40
 
41
        i = dentry->d_inode->i_sb->u.minix_sb.s_namelen;
42
        if (i >= qstr->len)
43
                return 0;
44
        /* Truncate the name in place, avoids having to define a compare
45
           function. */
46
        qstr->len = i;
47
        name = qstr->name;
48
        hash = init_name_hash();
49
        while (i--)
50
                hash = partial_name_hash(*name++, hash);
51
        qstr->hash = end_name_hash(hash);
52
        return 0;
53
}
54
 
55
struct dentry_operations minix_dentry_operations = {
56
        d_hash:         minix_hash,
57
};
58
 
59
static struct dentry *minix_lookup(struct inode * dir, struct dentry *dentry)
60
{
61
        struct inode * inode = NULL;
62
        ino_t ino;
63
 
64
        dentry->d_op = dir->i_sb->s_root->d_op;
65
 
66
        if (dentry->d_name.len > dir->i_sb->u.minix_sb.s_namelen)
67
                return ERR_PTR(-ENAMETOOLONG);
68
 
69
        ino = minix_inode_by_name(dentry);
70
        if (ino) {
71
                inode = iget(dir->i_sb, ino);
72
 
73
                if (!inode)
74
                        return ERR_PTR(-EACCES);
75
        }
76
        d_add(dentry, inode);
77
        return NULL;
78
}
79
 
80
static int minix_mknod(struct inode * dir, struct dentry *dentry, int mode, int rdev)
81
{
82
        int error;
83
        struct inode * inode = minix_new_inode(dir, &error);
84
 
85
        if (inode) {
86
                inode->i_mode = mode;
87
                minix_set_inode(inode, rdev);
88
                mark_inode_dirty(inode);
89
                error = add_nondir(dentry, inode);
90
        }
91
        return error;
92
}
93
 
94
static int minix_create(struct inode * dir, struct dentry *dentry, int mode)
95
{
96
        return minix_mknod(dir, dentry, mode, 0);
97
}
98
 
99
static int minix_symlink(struct inode * dir, struct dentry *dentry,
100
          const char * symname)
101
{
102
        int err = -ENAMETOOLONG;
103
        int i = strlen(symname)+1;
104
        struct inode * inode;
105
 
106
        if (i > dir->i_sb->s_blocksize)
107
                goto out;
108
 
109
        inode = minix_new_inode(dir, &err);
110
        if (!inode)
111
                goto out;
112
 
113
        inode->i_mode = S_IFLNK | 0777;
114
        minix_set_inode(inode, 0);
115
        err = block_symlink(inode, symname, i);
116
        if (err)
117
                goto out_fail;
118
 
119
        err = add_nondir(dentry, inode);
120
out:
121
        return err;
122
 
123
out_fail:
124
        dec_count(inode);
125
        iput(inode);
126
        goto out;
127
}
128
 
129
static int minix_link(struct dentry * old_dentry, struct inode * dir,
130
        struct dentry *dentry)
131
{
132
        struct inode *inode = old_dentry->d_inode;
133
 
134
        if (S_ISDIR(inode->i_mode))
135
                return -EPERM;
136
 
137
        if (inode->i_nlink >= inode->i_sb->u.minix_sb.s_link_max)
138
                return -EMLINK;
139
 
140
        inode->i_ctime = CURRENT_TIME;
141
        inc_count(inode);
142
        atomic_inc(&inode->i_count);
143
        return add_nondir(dentry, inode);
144
}
145
 
146
static int minix_mkdir(struct inode * dir, struct dentry *dentry, int mode)
147
{
148
        struct inode * inode;
149
        int err = -EMLINK;
150
 
151
        if (dir->i_nlink >= dir->i_sb->u.minix_sb.s_link_max)
152
                goto out;
153
 
154
        inc_count(dir);
155
 
156
        inode = minix_new_inode(dir, &err);
157
        if (!inode)
158
                goto out_dir;
159
 
160
        inode->i_mode = S_IFDIR | mode;
161
        if (dir->i_mode & S_ISGID)
162
                inode->i_mode |= S_ISGID;
163
        minix_set_inode(inode, 0);
164
 
165
        inc_count(inode);
166
 
167
        err = minix_make_empty(inode, dir);
168
        if (err)
169
                goto out_fail;
170
 
171
        err = minix_add_link(dentry, inode);
172
        if (err)
173
                goto out_fail;
174
 
175
        d_instantiate(dentry, inode);
176
out:
177
        return err;
178
 
179
out_fail:
180
        dec_count(inode);
181
        dec_count(inode);
182
        iput(inode);
183
out_dir:
184
        dec_count(dir);
185
        goto out;
186
}
187
 
188
static int minix_unlink(struct inode * dir, struct dentry *dentry)
189
{
190
        int err = -ENOENT;
191
        struct inode * inode = dentry->d_inode;
192
        struct page * page;
193
        struct minix_dir_entry * de;
194
 
195
        de = minix_find_entry(dentry, &page);
196
        if (!de)
197
                goto end_unlink;
198
 
199
        err = minix_delete_entry(de, page);
200
        if (err)
201
                goto end_unlink;
202
 
203
        inode->i_ctime = dir->i_ctime;
204
        dec_count(inode);
205
end_unlink:
206
        return err;
207
}
208
 
209
static int minix_rmdir(struct inode * dir, struct dentry *dentry)
210
{
211
        struct inode * inode = dentry->d_inode;
212
        int err = -ENOTEMPTY;
213
 
214
        if (minix_empty_dir(inode)) {
215
                err = minix_unlink(dir, dentry);
216
                if (!err) {
217
                        dec_count(dir);
218
                        dec_count(inode);
219
                }
220
        }
221
        return err;
222
}
223
 
224
static int minix_rename(struct inode * old_dir, struct dentry *old_dentry,
225
                           struct inode * new_dir, struct dentry *new_dentry)
226
{
227
        struct minix_sb_info * info = &old_dir->i_sb->u.minix_sb;
228
        struct inode * old_inode = old_dentry->d_inode;
229
        struct inode * new_inode = new_dentry->d_inode;
230
        struct page * dir_page = NULL;
231
        struct minix_dir_entry * dir_de = NULL;
232
        struct page * old_page;
233
        struct minix_dir_entry * old_de;
234
        int err = -ENOENT;
235
 
236
        old_de = minix_find_entry(old_dentry, &old_page);
237
        if (!old_de)
238
                goto out;
239
 
240
        if (S_ISDIR(old_inode->i_mode)) {
241
                err = -EIO;
242
                dir_de = minix_dotdot(old_inode, &dir_page);
243
                if (!dir_de)
244
                        goto out_old;
245
        }
246
 
247
        if (new_inode) {
248
                struct page * new_page;
249
                struct minix_dir_entry * new_de;
250
 
251
                err = -ENOTEMPTY;
252
                if (dir_de && !minix_empty_dir(new_inode))
253
                        goto out_dir;
254
 
255
                err = -ENOENT;
256
                new_de = minix_find_entry(new_dentry, &new_page);
257
                if (!new_de)
258
                        goto out_dir;
259
                inc_count(old_inode);
260
                minix_set_link(new_de, new_page, old_inode);
261
                new_inode->i_ctime = CURRENT_TIME;
262
                if (dir_de)
263
                        new_inode->i_nlink--;
264
                dec_count(new_inode);
265
        } else {
266
                if (dir_de) {
267
                        err = -EMLINK;
268
                        if (new_dir->i_nlink >= info->s_link_max)
269
                                goto out_dir;
270
                }
271
                inc_count(old_inode);
272
                err = minix_add_link(new_dentry, old_inode);
273
                if (err) {
274
                        dec_count(old_inode);
275
                        goto out_dir;
276
                }
277
                if (dir_de)
278
                        inc_count(new_dir);
279
        }
280
 
281
        minix_delete_entry(old_de, old_page);
282
        dec_count(old_inode);
283
 
284
        if (dir_de) {
285
                minix_set_link(dir_de, dir_page, new_dir);
286
                dec_count(old_dir);
287
        }
288
        return 0;
289
 
290
out_dir:
291
        if (dir_de) {
292
                kunmap(dir_page);
293
                page_cache_release(dir_page);
294
        }
295
out_old:
296
        kunmap(old_page);
297
        page_cache_release(old_page);
298
out:
299
        return err;
300
}
301
 
302
/*
303
 * directories can handle most operations...
304
 */
305
struct inode_operations minix_dir_inode_operations = {
306
        create:         minix_create,
307
        lookup:         minix_lookup,
308
        link:           minix_link,
309
        unlink:         minix_unlink,
310
        symlink:        minix_symlink,
311
        mkdir:          minix_mkdir,
312
        rmdir:          minix_rmdir,
313
        mknod:          minix_mknod,
314
        rename:         minix_rename,
315
};

powered by: WebSVN 2.1.0

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