Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
namei.c
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2005, 2006
3  * Avishay Traeger ([email protected])
4  * Copyright (C) 2008, 2009
5  * Boaz Harrosh <[email protected]>
6  *
7  * Copyrights for code taken from ext2:
8  * Copyright (C) 1992, 1993, 1994, 1995
9  * Remy Card ([email protected])
10  * Laboratoire MASI - Institut Blaise Pascal
11  * Universite Pierre et Marie Curie (Paris VI)
12  * from
13  * linux/fs/minix/inode.c
14  * Copyright (C) 1991, 1992 Linus Torvalds
15  *
16  * This file is part of exofs.
17  *
18  * exofs is free software; you can redistribute it and/or modify
19  * it under the terms of the GNU General Public License as published by
20  * the Free Software Foundation. Since it is based on ext2, and the only
21  * valid version of GPL for the Linux kernel is version 2, the only valid
22  * version of GPL for exofs is version 2.
23  *
24  * exofs is distributed in the hope that it will be useful,
25  * but WITHOUT ANY WARRANTY; without even the implied warranty of
26  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
27  * GNU General Public License for more details.
28  *
29  * You should have received a copy of the GNU General Public License
30  * along with exofs; if not, write to the Free Software
31  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
32  */
33 
34 #include "exofs.h"
35 
36 static inline int exofs_add_nondir(struct dentry *dentry, struct inode *inode)
37 {
38  int err = exofs_add_link(dentry, inode);
39  if (!err) {
40  d_instantiate(dentry, inode);
41  return 0;
42  }
43  inode_dec_link_count(inode);
44  iput(inode);
45  return err;
46 }
47 
48 static struct dentry *exofs_lookup(struct inode *dir, struct dentry *dentry,
49  unsigned int flags)
50 {
51  struct inode *inode;
52  ino_t ino;
53 
54  if (dentry->d_name.len > EXOFS_NAME_LEN)
55  return ERR_PTR(-ENAMETOOLONG);
56 
57  ino = exofs_inode_by_name(dir, dentry);
58  inode = ino ? exofs_iget(dir->i_sb, ino) : NULL;
59  return d_splice_alias(inode, dentry);
60 }
61 
62 static int exofs_create(struct inode *dir, struct dentry *dentry, umode_t mode,
63  bool excl)
64 {
65  struct inode *inode = exofs_new_inode(dir, mode);
66  int err = PTR_ERR(inode);
67  if (!IS_ERR(inode)) {
69  inode->i_fop = &exofs_file_operations;
70  inode->i_mapping->a_ops = &exofs_aops;
71  mark_inode_dirty(inode);
72  err = exofs_add_nondir(dentry, inode);
73  }
74  return err;
75 }
76 
77 static int exofs_mknod(struct inode *dir, struct dentry *dentry, umode_t mode,
78  dev_t rdev)
79 {
80  struct inode *inode;
81  int err;
82 
83  if (!new_valid_dev(rdev))
84  return -EINVAL;
85 
86  inode = exofs_new_inode(dir, mode);
87  err = PTR_ERR(inode);
88  if (!IS_ERR(inode)) {
89  init_special_inode(inode, inode->i_mode, rdev);
90  mark_inode_dirty(inode);
91  err = exofs_add_nondir(dentry, inode);
92  }
93  return err;
94 }
95 
96 static int exofs_symlink(struct inode *dir, struct dentry *dentry,
97  const char *symname)
98 {
99  struct super_block *sb = dir->i_sb;
100  int err = -ENAMETOOLONG;
101  unsigned l = strlen(symname)+1;
102  struct inode *inode;
103  struct exofs_i_info *oi;
104 
105  if (l > sb->s_blocksize)
106  goto out;
107 
108  inode = exofs_new_inode(dir, S_IFLNK | S_IRWXUGO);
109  err = PTR_ERR(inode);
110  if (IS_ERR(inode))
111  goto out;
112 
113  oi = exofs_i(inode);
114  if (l > sizeof(oi->i_data)) {
115  /* slow symlink */
117  inode->i_mapping->a_ops = &exofs_aops;
118  memset(oi->i_data, 0, sizeof(oi->i_data));
119 
120  err = page_symlink(inode, symname, l);
121  if (err)
122  goto out_fail;
123  } else {
124  /* fast symlink */
126  memcpy(oi->i_data, symname, l);
127  inode->i_size = l-1;
128  }
129  mark_inode_dirty(inode);
130 
131  err = exofs_add_nondir(dentry, inode);
132 out:
133  return err;
134 
135 out_fail:
136  inode_dec_link_count(inode);
137  iput(inode);
138  goto out;
139 }
140 
141 static int exofs_link(struct dentry *old_dentry, struct inode *dir,
142  struct dentry *dentry)
143 {
144  struct inode *inode = old_dentry->d_inode;
145 
146  inode->i_ctime = CURRENT_TIME;
147  inode_inc_link_count(inode);
148  ihold(inode);
149 
150  return exofs_add_nondir(dentry, inode);
151 }
152 
153 static int exofs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
154 {
155  struct inode *inode;
156  int err;
157 
158  inode_inc_link_count(dir);
159 
160  inode = exofs_new_inode(dir, S_IFDIR | mode);
161  err = PTR_ERR(inode);
162  if (IS_ERR(inode))
163  goto out_dir;
164 
166  inode->i_fop = &exofs_dir_operations;
167  inode->i_mapping->a_ops = &exofs_aops;
168 
169  inode_inc_link_count(inode);
170 
171  err = exofs_make_empty(inode, dir);
172  if (err)
173  goto out_fail;
174 
175  err = exofs_add_link(dentry, inode);
176  if (err)
177  goto out_fail;
178 
179  d_instantiate(dentry, inode);
180 out:
181  return err;
182 
183 out_fail:
184  inode_dec_link_count(inode);
185  inode_dec_link_count(inode);
186  iput(inode);
187 out_dir:
188  inode_dec_link_count(dir);
189  goto out;
190 }
191 
192 static int exofs_unlink(struct inode *dir, struct dentry *dentry)
193 {
194  struct inode *inode = dentry->d_inode;
195  struct exofs_dir_entry *de;
196  struct page *page;
197  int err = -ENOENT;
198 
199  de = exofs_find_entry(dir, dentry, &page);
200  if (!de)
201  goto out;
202 
203  err = exofs_delete_entry(de, page);
204  if (err)
205  goto out;
206 
207  inode->i_ctime = dir->i_ctime;
208  inode_dec_link_count(inode);
209  err = 0;
210 out:
211  return err;
212 }
213 
214 static int exofs_rmdir(struct inode *dir, struct dentry *dentry)
215 {
216  struct inode *inode = dentry->d_inode;
217  int err = -ENOTEMPTY;
218 
219  if (exofs_empty_dir(inode)) {
220  err = exofs_unlink(dir, dentry);
221  if (!err) {
222  inode->i_size = 0;
223  inode_dec_link_count(inode);
224  inode_dec_link_count(dir);
225  }
226  }
227  return err;
228 }
229 
230 static int exofs_rename(struct inode *old_dir, struct dentry *old_dentry,
231  struct inode *new_dir, struct dentry *new_dentry)
232 {
233  struct inode *old_inode = old_dentry->d_inode;
234  struct inode *new_inode = new_dentry->d_inode;
235  struct page *dir_page = NULL;
236  struct exofs_dir_entry *dir_de = NULL;
237  struct page *old_page;
238  struct exofs_dir_entry *old_de;
239  int err = -ENOENT;
240 
241  old_de = exofs_find_entry(old_dir, old_dentry, &old_page);
242  if (!old_de)
243  goto out;
244 
245  if (S_ISDIR(old_inode->i_mode)) {
246  err = -EIO;
247  dir_de = exofs_dotdot(old_inode, &dir_page);
248  if (!dir_de)
249  goto out_old;
250  }
251 
252  if (new_inode) {
253  struct page *new_page;
254  struct exofs_dir_entry *new_de;
255 
256  err = -ENOTEMPTY;
257  if (dir_de && !exofs_empty_dir(new_inode))
258  goto out_dir;
259 
260  err = -ENOENT;
261  new_de = exofs_find_entry(new_dir, new_dentry, &new_page);
262  if (!new_de)
263  goto out_dir;
264  err = exofs_set_link(new_dir, new_de, new_page, old_inode);
265  new_inode->i_ctime = CURRENT_TIME;
266  if (dir_de)
267  drop_nlink(new_inode);
268  inode_dec_link_count(new_inode);
269  if (err)
270  goto out_dir;
271  } else {
272  err = exofs_add_link(new_dentry, old_inode);
273  if (err)
274  goto out_dir;
275  if (dir_de)
276  inode_inc_link_count(new_dir);
277  }
278 
279  old_inode->i_ctime = CURRENT_TIME;
280 
281  exofs_delete_entry(old_de, old_page);
282  mark_inode_dirty(old_inode);
283 
284  if (dir_de) {
285  err = exofs_set_link(old_inode, dir_de, dir_page, new_dir);
286  inode_dec_link_count(old_dir);
287  if (err)
288  goto out_dir;
289  }
290  return 0;
291 
292 
293 out_dir:
294  if (dir_de) {
295  kunmap(dir_page);
296  page_cache_release(dir_page);
297  }
298 out_old:
299  kunmap(old_page);
300  page_cache_release(old_page);
301 out:
302  return err;
303 }
304 
306  .create = exofs_create,
307  .lookup = exofs_lookup,
308  .link = exofs_link,
309  .unlink = exofs_unlink,
310  .symlink = exofs_symlink,
311  .mkdir = exofs_mkdir,
312  .rmdir = exofs_rmdir,
313  .mknod = exofs_mknod,
314  .rename = exofs_rename,
315  .setattr = exofs_setattr,
316 };
317 
319  .setattr = exofs_setattr,
320 };