Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
dir.c
Go to the documentation of this file.
1 /*
2  * linux/fs/sysv/dir.c
3  *
4  * minix/dir.c
5  * Copyright (C) 1991, 1992 Linus Torvalds
6  *
7  * coh/dir.c
8  * Copyright (C) 1993 Pascal Haible, Bruno Haible
9  *
10  * sysv/dir.c
11  * Copyright (C) 1993 Bruno Haible
12  *
13  * SystemV/Coherent directory handling functions
14  */
15 
16 #include <linux/pagemap.h>
17 #include <linux/highmem.h>
18 #include <linux/swap.h>
19 #include "sysv.h"
20 
21 static int sysv_readdir(struct file *, void *, filldir_t);
22 
24  .llseek = generic_file_llseek,
25  .read = generic_read_dir,
26  .readdir = sysv_readdir,
27  .fsync = generic_file_fsync,
28 };
29 
30 static inline void dir_put_page(struct page *page)
31 {
32  kunmap(page);
33  page_cache_release(page);
34 }
35 
36 static inline unsigned long dir_pages(struct inode *inode)
37 {
38  return (inode->i_size+PAGE_CACHE_SIZE-1)>>PAGE_CACHE_SHIFT;
39 }
40 
41 static int dir_commit_chunk(struct page *page, loff_t pos, unsigned len)
42 {
43  struct address_space *mapping = page->mapping;
44  struct inode *dir = mapping->host;
45  int err = 0;
46 
47  block_write_end(NULL, mapping, pos, len, len, page, NULL);
48  if (pos+len > dir->i_size) {
49  i_size_write(dir, pos+len);
50  mark_inode_dirty(dir);
51  }
52  if (IS_DIRSYNC(dir))
53  err = write_one_page(page, 1);
54  else
55  unlock_page(page);
56  return err;
57 }
58 
59 static struct page * dir_get_page(struct inode *dir, unsigned long n)
60 {
61  struct address_space *mapping = dir->i_mapping;
62  struct page *page = read_mapping_page(mapping, n, NULL);
63  if (!IS_ERR(page))
64  kmap(page);
65  return page;
66 }
67 
68 static int sysv_readdir(struct file * filp, void * dirent, filldir_t filldir)
69 {
70  unsigned long pos = filp->f_pos;
71  struct inode *inode = filp->f_path.dentry->d_inode;
72  struct super_block *sb = inode->i_sb;
73  unsigned offset = pos & ~PAGE_CACHE_MASK;
74  unsigned long n = pos >> PAGE_CACHE_SHIFT;
75  unsigned long npages = dir_pages(inode);
76 
77  pos = (pos + SYSV_DIRSIZE-1) & ~(SYSV_DIRSIZE-1);
78  if (pos >= inode->i_size)
79  goto done;
80 
81  for ( ; n < npages; n++, offset = 0) {
82  char *kaddr, *limit;
83  struct sysv_dir_entry *de;
84  struct page *page = dir_get_page(inode, n);
85 
86  if (IS_ERR(page))
87  continue;
88  kaddr = (char *)page_address(page);
89  de = (struct sysv_dir_entry *)(kaddr+offset);
90  limit = kaddr + PAGE_CACHE_SIZE - SYSV_DIRSIZE;
91  for ( ;(char*)de <= limit; de++) {
92  char *name = de->name;
93  int over;
94 
95  if (!de->inode)
96  continue;
97 
98  offset = (char *)de - kaddr;
99 
100  over = filldir(dirent, name, strnlen(name,SYSV_NAMELEN),
101  ((loff_t)n<<PAGE_CACHE_SHIFT) | offset,
102  fs16_to_cpu(SYSV_SB(sb), de->inode),
103  DT_UNKNOWN);
104  if (over) {
105  dir_put_page(page);
106  goto done;
107  }
108  }
109  dir_put_page(page);
110  }
111 
112 done:
113  filp->f_pos = ((loff_t)n << PAGE_CACHE_SHIFT) | offset;
114  return 0;
115 }
116 
117 /* compare strings: name[0..len-1] (not zero-terminated) and
118  * buffer[0..] (filled with zeroes up to buffer[0..maxlen-1])
119  */
120 static inline int namecompare(int len, int maxlen,
121  const char * name, const char * buffer)
122 {
123  if (len < maxlen && buffer[len])
124  return 0;
125  return !memcmp(name, buffer, len);
126 }
127 
128 /*
129  * sysv_find_entry()
130  *
131  * finds an entry in the specified directory with the wanted name. It
132  * returns the cache buffer in which the entry was found, and the entry
133  * itself (as a parameter - res_dir). It does NOT read the inode of the
134  * entry - you'll have to do that yourself if you want to.
135  */
136 struct sysv_dir_entry *sysv_find_entry(struct dentry *dentry, struct page **res_page)
137 {
138  const char * name = dentry->d_name.name;
139  int namelen = dentry->d_name.len;
140  struct inode * dir = dentry->d_parent->d_inode;
141  unsigned long start, n;
142  unsigned long npages = dir_pages(dir);
143  struct page *page = NULL;
144  struct sysv_dir_entry *de;
145 
146  *res_page = NULL;
147 
148  start = SYSV_I(dir)->i_dir_start_lookup;
149  if (start >= npages)
150  start = 0;
151  n = start;
152 
153  do {
154  char *kaddr;
155  page = dir_get_page(dir, n);
156  if (!IS_ERR(page)) {
157  kaddr = (char*)page_address(page);
158  de = (struct sysv_dir_entry *) kaddr;
159  kaddr += PAGE_CACHE_SIZE - SYSV_DIRSIZE;
160  for ( ; (char *) de <= kaddr ; de++) {
161  if (!de->inode)
162  continue;
163  if (namecompare(namelen, SYSV_NAMELEN,
164  name, de->name))
165  goto found;
166  }
167  dir_put_page(page);
168  }
169 
170  if (++n >= npages)
171  n = 0;
172  } while (n != start);
173 
174  return NULL;
175 
176 found:
177  SYSV_I(dir)->i_dir_start_lookup = n;
178  *res_page = page;
179  return de;
180 }
181 
182 int sysv_add_link(struct dentry *dentry, struct inode *inode)
183 {
184  struct inode *dir = dentry->d_parent->d_inode;
185  const char * name = dentry->d_name.name;
186  int namelen = dentry->d_name.len;
187  struct page *page = NULL;
188  struct sysv_dir_entry * de;
189  unsigned long npages = dir_pages(dir);
190  unsigned long n;
191  char *kaddr;
192  loff_t pos;
193  int err;
194 
195  /* We take care of directory expansion in the same loop */
196  for (n = 0; n <= npages; n++) {
197  page = dir_get_page(dir, n);
198  err = PTR_ERR(page);
199  if (IS_ERR(page))
200  goto out;
201  kaddr = (char*)page_address(page);
202  de = (struct sysv_dir_entry *)kaddr;
203  kaddr += PAGE_CACHE_SIZE - SYSV_DIRSIZE;
204  while ((char *)de <= kaddr) {
205  if (!de->inode)
206  goto got_it;
207  err = -EEXIST;
208  if (namecompare(namelen, SYSV_NAMELEN, name, de->name))
209  goto out_page;
210  de++;
211  }
212  dir_put_page(page);
213  }
214  BUG();
215  return -EINVAL;
216 
217 got_it:
218  pos = page_offset(page) +
219  (char*)de - (char*)page_address(page);
220  lock_page(page);
221  err = sysv_prepare_chunk(page, pos, SYSV_DIRSIZE);
222  if (err)
223  goto out_unlock;
224  memcpy (de->name, name, namelen);
225  memset (de->name + namelen, 0, SYSV_DIRSIZE - namelen - 2);
226  de->inode = cpu_to_fs16(SYSV_SB(inode->i_sb), inode->i_ino);
227  err = dir_commit_chunk(page, pos, SYSV_DIRSIZE);
228  dir->i_mtime = dir->i_ctime = CURRENT_TIME_SEC;
229  mark_inode_dirty(dir);
230 out_page:
231  dir_put_page(page);
232 out:
233  return err;
234 out_unlock:
235  unlock_page(page);
236  goto out_page;
237 }
238 
239 int sysv_delete_entry(struct sysv_dir_entry *de, struct page *page)
240 {
241  struct inode *inode = page->mapping->host;
242  char *kaddr = (char*)page_address(page);
243  loff_t pos = page_offset(page) + (char *)de - kaddr;
244  int err;
245 
246  lock_page(page);
247  err = sysv_prepare_chunk(page, pos, SYSV_DIRSIZE);
248  BUG_ON(err);
249  de->inode = 0;
250  err = dir_commit_chunk(page, pos, SYSV_DIRSIZE);
251  dir_put_page(page);
252  inode->i_ctime = inode->i_mtime = CURRENT_TIME_SEC;
253  mark_inode_dirty(inode);
254  return err;
255 }
256 
257 int sysv_make_empty(struct inode *inode, struct inode *dir)
258 {
259  struct page *page = grab_cache_page(inode->i_mapping, 0);
260  struct sysv_dir_entry * de;
261  char *base;
262  int err;
263 
264  if (!page)
265  return -ENOMEM;
266  err = sysv_prepare_chunk(page, 0, 2 * SYSV_DIRSIZE);
267  if (err) {
268  unlock_page(page);
269  goto fail;
270  }
271  kmap(page);
272 
273  base = (char*)page_address(page);
274  memset(base, 0, PAGE_CACHE_SIZE);
275 
276  de = (struct sysv_dir_entry *) base;
277  de->inode = cpu_to_fs16(SYSV_SB(inode->i_sb), inode->i_ino);
278  strcpy(de->name,".");
279  de++;
280  de->inode = cpu_to_fs16(SYSV_SB(inode->i_sb), dir->i_ino);
281  strcpy(de->name,"..");
282 
283  kunmap(page);
284  err = dir_commit_chunk(page, 0, 2 * SYSV_DIRSIZE);
285 fail:
286  page_cache_release(page);
287  return err;
288 }
289 
290 /*
291  * routine to check that the specified directory is empty (for rmdir)
292  */
293 int sysv_empty_dir(struct inode * inode)
294 {
295  struct super_block *sb = inode->i_sb;
296  struct page *page = NULL;
297  unsigned long i, npages = dir_pages(inode);
298 
299  for (i = 0; i < npages; i++) {
300  char *kaddr;
301  struct sysv_dir_entry * de;
302  page = dir_get_page(inode, i);
303 
304  if (IS_ERR(page))
305  continue;
306 
307  kaddr = (char *)page_address(page);
308  de = (struct sysv_dir_entry *)kaddr;
309  kaddr += PAGE_CACHE_SIZE-SYSV_DIRSIZE;
310 
311  for ( ;(char *)de <= kaddr; de++) {
312  if (!de->inode)
313  continue;
314  /* check for . and .. */
315  if (de->name[0] != '.')
316  goto not_empty;
317  if (!de->name[1]) {
318  if (de->inode == cpu_to_fs16(SYSV_SB(sb),
319  inode->i_ino))
320  continue;
321  goto not_empty;
322  }
323  if (de->name[1] != '.' || de->name[2])
324  goto not_empty;
325  }
326  dir_put_page(page);
327  }
328  return 1;
329 
330 not_empty:
331  dir_put_page(page);
332  return 0;
333 }
334 
335 /* Releases the page */
336 void sysv_set_link(struct sysv_dir_entry *de, struct page *page,
337  struct inode *inode)
338 {
339  struct inode *dir = page->mapping->host;
340  loff_t pos = page_offset(page) +
341  (char *)de-(char*)page_address(page);
342  int err;
343 
344  lock_page(page);
345  err = sysv_prepare_chunk(page, pos, SYSV_DIRSIZE);
346  BUG_ON(err);
347  de->inode = cpu_to_fs16(SYSV_SB(inode->i_sb), inode->i_ino);
348  err = dir_commit_chunk(page, pos, SYSV_DIRSIZE);
349  dir_put_page(page);
350  dir->i_mtime = dir->i_ctime = CURRENT_TIME_SEC;
351  mark_inode_dirty(dir);
352 }
353 
354 struct sysv_dir_entry * sysv_dotdot (struct inode *dir, struct page **p)
355 {
356  struct page *page = dir_get_page(dir, 0);
357  struct sysv_dir_entry *de = NULL;
358 
359  if (!IS_ERR(page)) {
360  de = (struct sysv_dir_entry*) page_address(page) + 1;
361  *p = page;
362  }
363  return de;
364 }
365 
367 {
368  struct page *page;
369  struct sysv_dir_entry *de = sysv_find_entry (dentry, &page);
370  ino_t res = 0;
371 
372  if (de) {
373  res = fs16_to_cpu(SYSV_SB(dentry->d_sb), de->inode);
374  dir_put_page(page);
375  }
376  return res;
377 }