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