[PATCH] PATCH - Create "export_operations" interface for filesystems to describe
[opensuse:kernel.git] / fs / ext2 / namei.c
1 /*
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 "ext2.h"
33 #include <linux/pagemap.h>
34
35 /*
36  * Couple of helper functions - make the code slightly cleaner.
37  */
38
39 static inline void ext2_inc_count(struct inode *inode)
40 {
41         inode->i_nlink++;
42         mark_inode_dirty(inode);
43 }
44
45 static inline void ext2_dec_count(struct inode *inode)
46 {
47         inode->i_nlink--;
48         mark_inode_dirty(inode);
49 }
50
51 static inline int ext2_add_nondir(struct dentry *dentry, struct inode *inode)
52 {
53         int err = ext2_add_link(dentry, inode);
54         if (!err) {
55                 d_instantiate(dentry, inode);
56                 return 0;
57         }
58         ext2_dec_count(inode);
59         iput(inode);
60         return err;
61 }
62
63 /*
64  * Methods themselves.
65  */
66
67 static struct dentry *ext2_lookup(struct inode * dir, struct dentry *dentry)
68 {
69         struct inode * inode;
70         ino_t ino;
71         
72         if (dentry->d_name.len > EXT2_NAME_LEN)
73                 return ERR_PTR(-ENAMETOOLONG);
74
75         ino = ext2_inode_by_name(dir, dentry);
76         inode = NULL;
77         if (ino) {
78                 inode = iget(dir->i_sb, ino);
79                 if (!inode)
80                         return ERR_PTR(-EACCES);
81         }
82         if (inode)
83                 return d_splice_alias(inode, dentry);
84         d_add(dentry, inode);
85         return NULL;
86 }
87
88 struct dentry *ext2_get_parent(struct dentry *child)
89 {
90         unsigned long ino;
91         struct dentry *parent;
92         struct inode *inode;
93         struct dentry dotdot;
94
95         dotdot.d_name.name = "..";
96         dotdot.d_name.len = 2;
97
98         ino = ext2_inode_by_name(child->d_inode, &dotdot);
99         if (!ino)
100                 return ERR_PTR(-ENOENT);
101         inode = iget(child->d_inode->i_sb, ino);
102
103         if (!inode)
104                 return ERR_PTR(-EACCES);
105         parent = d_alloc_anon(inode);
106         if (!parent) {
107                 iput(inode);
108                 parent = ERR_PTR(-ENOMEM);
109         }
110         return parent;
111
112
113 /*
114  * By the time this is called, we already have created
115  * the directory cache entry for the new file, but it
116  * is so far negative - it has no inode.
117  *
118  * If the create succeeds, we fill in the inode information
119  * with d_instantiate(). 
120  */
121 static int ext2_create (struct inode * dir, struct dentry * dentry, int mode)
122 {
123         struct inode * inode = ext2_new_inode (dir, mode);
124         int err = PTR_ERR(inode);
125         if (!IS_ERR(inode)) {
126                 inode->i_op = &ext2_file_inode_operations;
127                 inode->i_fop = &ext2_file_operations;
128                 inode->i_mapping->a_ops = &ext2_aops;
129                 mark_inode_dirty(inode);
130                 err = ext2_add_nondir(dentry, inode);
131         }
132         return err;
133 }
134
135 static int ext2_mknod (struct inode * dir, struct dentry *dentry, int mode, int rdev)
136 {
137         struct inode * inode = ext2_new_inode (dir, mode);
138         int err = PTR_ERR(inode);
139         if (!IS_ERR(inode)) {
140                 init_special_inode(inode, mode, rdev);
141                 mark_inode_dirty(inode);
142                 err = ext2_add_nondir(dentry, inode);
143         }
144         return err;
145 }
146
147 static int ext2_symlink (struct inode * dir, struct dentry * dentry,
148         const char * symname)
149 {
150         struct super_block * sb = dir->i_sb;
151         int err = -ENAMETOOLONG;
152         unsigned l = strlen(symname)+1;
153         struct inode * inode;
154
155         if (l > sb->s_blocksize)
156                 goto out;
157
158         inode = ext2_new_inode (dir, S_IFLNK | S_IRWXUGO);
159         err = PTR_ERR(inode);
160         if (IS_ERR(inode))
161                 goto out;
162
163         if (l > sizeof (EXT2_I(inode)->i_data)) {
164                 /* slow symlink */
165                 inode->i_op = &page_symlink_inode_operations;
166                 inode->i_mapping->a_ops = &ext2_aops;
167                 err = block_symlink(inode, symname, l);
168                 if (err)
169                         goto out_fail;
170         } else {
171                 /* fast symlink */
172                 inode->i_op = &ext2_fast_symlink_inode_operations;
173                 memcpy((char*)(EXT2_I(inode)->i_data),symname,l);
174                 inode->i_size = l-1;
175         }
176         mark_inode_dirty(inode);
177
178         err = ext2_add_nondir(dentry, inode);
179 out:
180         return err;
181
182 out_fail:
183         ext2_dec_count(inode);
184         iput (inode);
185         goto out;
186 }
187
188 static int ext2_link (struct dentry * old_dentry, struct inode * dir,
189         struct dentry *dentry)
190 {
191         struct inode *inode = old_dentry->d_inode;
192
193         if (inode->i_nlink >= EXT2_LINK_MAX)
194                 return -EMLINK;
195
196         inode->i_ctime = CURRENT_TIME;
197         ext2_inc_count(inode);
198         atomic_inc(&inode->i_count);
199
200         return ext2_add_nondir(dentry, inode);
201 }
202
203 static int ext2_mkdir(struct inode * dir, struct dentry * dentry, int mode)
204 {
205         struct inode * inode;
206         int err = -EMLINK;
207
208         if (dir->i_nlink >= EXT2_LINK_MAX)
209                 goto out;
210
211         ext2_inc_count(dir);
212
213         inode = ext2_new_inode (dir, S_IFDIR | mode);
214         err = PTR_ERR(inode);
215         if (IS_ERR(inode))
216                 goto out_dir;
217
218         inode->i_op = &ext2_dir_inode_operations;
219         inode->i_fop = &ext2_dir_operations;
220         inode->i_mapping->a_ops = &ext2_aops;
221
222         ext2_inc_count(inode);
223
224         err = ext2_make_empty(inode, dir);
225         if (err)
226                 goto out_fail;
227
228         err = ext2_add_link(dentry, inode);
229         if (err)
230                 goto out_fail;
231
232         d_instantiate(dentry, inode);
233 out:
234         return err;
235
236 out_fail:
237         ext2_dec_count(inode);
238         ext2_dec_count(inode);
239         iput(inode);
240 out_dir:
241         ext2_dec_count(dir);
242         goto out;
243 }
244
245 static int ext2_unlink(struct inode * dir, struct dentry *dentry)
246 {
247         struct inode * inode = dentry->d_inode;
248         struct ext2_dir_entry_2 * de;
249         struct page * page;
250         int err = -ENOENT;
251
252         de = ext2_find_entry (dir, dentry, &page);
253         if (!de)
254                 goto out;
255
256         err = ext2_delete_entry (de, page);
257         if (err)
258                 goto out;
259
260         inode->i_ctime = dir->i_ctime;
261         ext2_dec_count(inode);
262         err = 0;
263 out:
264         return err;
265 }
266
267 static int ext2_rmdir (struct inode * dir, struct dentry *dentry)
268 {
269         struct inode * inode = dentry->d_inode;
270         int err = -ENOTEMPTY;
271
272         if (ext2_empty_dir(inode)) {
273                 err = ext2_unlink(dir, dentry);
274                 if (!err) {
275                         inode->i_size = 0;
276                         ext2_dec_count(inode);
277                         ext2_dec_count(dir);
278                 }
279         }
280         return err;
281 }
282
283 static int ext2_rename (struct inode * old_dir, struct dentry * old_dentry,
284         struct inode * new_dir, struct dentry * new_dentry )
285 {
286         struct inode * old_inode = old_dentry->d_inode;
287         struct inode * new_inode = new_dentry->d_inode;
288         struct page * dir_page = NULL;
289         struct ext2_dir_entry_2 * dir_de = NULL;
290         struct page * old_page;
291         struct ext2_dir_entry_2 * old_de;
292         int err = -ENOENT;
293
294         old_de = ext2_find_entry (old_dir, old_dentry, &old_page);
295         if (!old_de)
296                 goto out;
297
298         if (S_ISDIR(old_inode->i_mode)) {
299                 err = -EIO;
300                 dir_de = ext2_dotdot(old_inode, &dir_page);
301                 if (!dir_de)
302                         goto out_old;
303         }
304
305         if (new_inode) {
306                 struct page *new_page;
307                 struct ext2_dir_entry_2 *new_de;
308
309                 err = -ENOTEMPTY;
310                 if (dir_de && !ext2_empty_dir (new_inode))
311                         goto out_dir;
312
313                 err = -ENOENT;
314                 new_de = ext2_find_entry (new_dir, new_dentry, &new_page);
315                 if (!new_de)
316                         goto out_dir;
317                 ext2_inc_count(old_inode);
318                 ext2_set_link(new_dir, new_de, new_page, old_inode);
319                 new_inode->i_ctime = CURRENT_TIME;
320                 if (dir_de)
321                         new_inode->i_nlink--;
322                 ext2_dec_count(new_inode);
323         } else {
324                 if (dir_de) {
325                         err = -EMLINK;
326                         if (new_dir->i_nlink >= EXT2_LINK_MAX)
327                                 goto out_dir;
328                 }
329                 ext2_inc_count(old_inode);
330                 err = ext2_add_link(new_dentry, old_inode);
331                 if (err) {
332                         ext2_dec_count(old_inode);
333                         goto out_dir;
334                 }
335                 if (dir_de)
336                         ext2_inc_count(new_dir);
337         }
338
339         ext2_delete_entry (old_de, old_page);
340         ext2_dec_count(old_inode);
341
342         if (dir_de) {
343                 ext2_set_link(old_inode, dir_de, dir_page, new_dir);
344                 ext2_dec_count(old_dir);
345         }
346         return 0;
347
348
349 out_dir:
350         if (dir_de) {
351                 kunmap(dir_page);
352                 page_cache_release(dir_page);
353         }
354 out_old:
355         kunmap(old_page);
356         page_cache_release(old_page);
357 out:
358         return err;
359 }
360
361 struct inode_operations ext2_dir_inode_operations = {
362         create:         ext2_create,
363         lookup:         ext2_lookup,
364         link:           ext2_link,
365         unlink:         ext2_unlink,
366         symlink:        ext2_symlink,
367         mkdir:          ext2_mkdir,
368         rmdir:          ext2_rmdir,
369         mknod:          ext2_mknod,
370         rename:         ext2_rename,
371 };