Linux kernel & device driver programming

Cross-Referenced Linux and Device Driver Code

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