5 * Copyright (C) 1991, 1992 Linus Torvalds
8 * Copyright (C) 1993 Pascal Haible, Bruno Haible
11 * Copyright (C) 1993 Bruno Haible
13 * SystemV/Coherent directory handling functions
16 #include <linux/pagemap.h>
17 #include <linux/highmem.h>
18 #include <linux/smp_lock.h>
19 #include <linux/swap.h>
22 static int sysv_readdir(struct file
*, void *, filldir_t
);
24 const struct file_operations sysv_dir_operations
= {
25 .read
= generic_read_dir
,
26 .readdir
= sysv_readdir
,
27 .fsync
= simple_fsync
,
30 static inline void dir_put_page(struct page
*page
)
33 page_cache_release(page
);
36 static inline unsigned long dir_pages(struct inode
*inode
)
38 return (inode
->i_size
+PAGE_CACHE_SIZE
-1)>>PAGE_CACHE_SHIFT
;
41 static int dir_commit_chunk(struct page
*page
, loff_t pos
, unsigned len
)
43 struct address_space
*mapping
= page
->mapping
;
44 struct inode
*dir
= mapping
->host
;
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
);
53 err
= write_one_page(page
, 1);
59 static struct page
* dir_get_page(struct inode
*dir
, unsigned long n
)
61 struct address_space
*mapping
= dir
->i_mapping
;
62 struct page
*page
= read_mapping_page(mapping
, n
, NULL
);
68 static int sysv_readdir(struct file
* filp
, void * dirent
, filldir_t filldir
)
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
);
79 pos
= (pos
+ SYSV_DIRSIZE
-1) & ~(SYSV_DIRSIZE
-1);
80 if (pos
>= inode
->i_size
)
83 for ( ; n
< npages
; n
++, offset
= 0) {
85 struct sysv_dir_entry
*de
;
86 struct page
*page
= dir_get_page(inode
, n
);
90 kaddr
= (char *)page_address(page
);
91 de
= (struct sysv_dir_entry
*)(kaddr
+offset
);
92 limit
= kaddr
+ PAGE_CACHE_SIZE
- SYSV_DIRSIZE
;
93 for ( ;(char*)de
<= limit
; de
++) {
94 char *name
= de
->name
;
100 offset
= (char *)de
- kaddr
;
102 over
= filldir(dirent
, name
, strnlen(name
,SYSV_NAMELEN
),
103 ((loff_t
)n
<<PAGE_CACHE_SHIFT
) | offset
,
104 fs16_to_cpu(SYSV_SB(sb
), de
->inode
),
115 filp
->f_pos
= ((loff_t
)n
<< PAGE_CACHE_SHIFT
) | offset
;
120 /* compare strings: name[0..len-1] (not zero-terminated) and
121 * buffer[0..] (filled with zeroes up to buffer[0..maxlen-1])
123 static inline int namecompare(int len
, int maxlen
,
124 const char * name
, const char * buffer
)
126 if (len
< maxlen
&& buffer
[len
])
128 return !memcmp(name
, buffer
, len
);
134 * finds an entry in the specified directory with the wanted name. It
135 * returns the cache buffer in which the entry was found, and the entry
136 * itself (as a parameter - res_dir). It does NOT read the inode of the
137 * entry - you'll have to do that yourself if you want to.
139 struct sysv_dir_entry
*sysv_find_entry(struct dentry
*dentry
, struct page
**res_page
)
141 const char * name
= dentry
->d_name
.name
;
142 int namelen
= dentry
->d_name
.len
;
143 struct inode
* dir
= dentry
->d_parent
->d_inode
;
144 unsigned long start
, n
;
145 unsigned long npages
= dir_pages(dir
);
146 struct page
*page
= NULL
;
147 struct sysv_dir_entry
*de
;
151 start
= SYSV_I(dir
)->i_dir_start_lookup
;
158 page
= dir_get_page(dir
, n
);
160 kaddr
= (char*)page_address(page
);
161 de
= (struct sysv_dir_entry
*) kaddr
;
162 kaddr
+= PAGE_CACHE_SIZE
- SYSV_DIRSIZE
;
163 for ( ; (char *) de
<= kaddr
; de
++) {
166 if (namecompare(namelen
, SYSV_NAMELEN
,
175 } while (n
!= start
);
180 SYSV_I(dir
)->i_dir_start_lookup
= n
;
185 int sysv_add_link(struct dentry
*dentry
, struct inode
*inode
)
187 struct inode
*dir
= dentry
->d_parent
->d_inode
;
188 const char * name
= dentry
->d_name
.name
;
189 int namelen
= dentry
->d_name
.len
;
190 struct page
*page
= NULL
;
191 struct sysv_dir_entry
* de
;
192 unsigned long npages
= dir_pages(dir
);
198 /* We take care of directory expansion in the same loop */
199 for (n
= 0; n
<= npages
; n
++) {
200 page
= dir_get_page(dir
, n
);
204 kaddr
= (char*)page_address(page
);
205 de
= (struct sysv_dir_entry
*)kaddr
;
206 kaddr
+= PAGE_CACHE_SIZE
- SYSV_DIRSIZE
;
207 while ((char *)de
<= kaddr
) {
211 if (namecompare(namelen
, SYSV_NAMELEN
, name
, de
->name
))
221 pos
= page_offset(page
) +
222 (char*)de
- (char*)page_address(page
);
224 err
= __sysv_write_begin(NULL
, page
->mapping
, pos
, SYSV_DIRSIZE
,
225 AOP_FLAG_UNINTERRUPTIBLE
, &page
, NULL
);
228 memcpy (de
->name
, name
, namelen
);
229 memset (de
->name
+ namelen
, 0, SYSV_DIRSIZE
- namelen
- 2);
230 de
->inode
= cpu_to_fs16(SYSV_SB(inode
->i_sb
), inode
->i_ino
);
231 err
= dir_commit_chunk(page
, pos
, SYSV_DIRSIZE
);
232 dir
->i_mtime
= dir
->i_ctime
= CURRENT_TIME_SEC
;
233 mark_inode_dirty(dir
);
243 int sysv_delete_entry(struct sysv_dir_entry
*de
, struct page
*page
)
245 struct address_space
*mapping
= page
->mapping
;
246 struct inode
*inode
= (struct inode
*)mapping
->host
;
247 char *kaddr
= (char*)page_address(page
);
248 loff_t pos
= page_offset(page
) + (char *)de
- kaddr
;
252 err
= __sysv_write_begin(NULL
, mapping
, pos
, SYSV_DIRSIZE
,
253 AOP_FLAG_UNINTERRUPTIBLE
, &page
, NULL
);
256 err
= dir_commit_chunk(page
, pos
, SYSV_DIRSIZE
);
258 inode
->i_ctime
= inode
->i_mtime
= CURRENT_TIME_SEC
;
259 mark_inode_dirty(inode
);
263 int sysv_make_empty(struct inode
*inode
, struct inode
*dir
)
265 struct address_space
*mapping
= inode
->i_mapping
;
266 struct page
*page
= grab_cache_page(mapping
, 0);
267 struct sysv_dir_entry
* de
;
273 err
= __sysv_write_begin(NULL
, mapping
, 0, 2 * SYSV_DIRSIZE
,
274 AOP_FLAG_UNINTERRUPTIBLE
, &page
, NULL
);
281 base
= (char*)page_address(page
);
282 memset(base
, 0, PAGE_CACHE_SIZE
);
284 de
= (struct sysv_dir_entry
*) base
;
285 de
->inode
= cpu_to_fs16(SYSV_SB(inode
->i_sb
), inode
->i_ino
);
286 strcpy(de
->name
,".");
288 de
->inode
= cpu_to_fs16(SYSV_SB(inode
->i_sb
), dir
->i_ino
);
289 strcpy(de
->name
,"..");
292 err
= dir_commit_chunk(page
, 0, 2 * SYSV_DIRSIZE
);
294 page_cache_release(page
);
299 * routine to check that the specified directory is empty (for rmdir)
301 int sysv_empty_dir(struct inode
* inode
)
303 struct super_block
*sb
= inode
->i_sb
;
304 struct page
*page
= NULL
;
305 unsigned long i
, npages
= dir_pages(inode
);
307 for (i
= 0; i
< npages
; i
++) {
309 struct sysv_dir_entry
* de
;
310 page
= dir_get_page(inode
, i
);
315 kaddr
= (char *)page_address(page
);
316 de
= (struct sysv_dir_entry
*)kaddr
;
317 kaddr
+= PAGE_CACHE_SIZE
-SYSV_DIRSIZE
;
319 for ( ;(char *)de
<= kaddr
; de
++) {
322 /* check for . and .. */
323 if (de
->name
[0] != '.')
326 if (de
->inode
== cpu_to_fs16(SYSV_SB(sb
),
331 if (de
->name
[1] != '.' || de
->name
[2])
343 /* Releases the page */
344 void sysv_set_link(struct sysv_dir_entry
*de
, struct page
*page
,
347 struct address_space
*mapping
= page
->mapping
;
348 struct inode
*dir
= mapping
->host
;
349 loff_t pos
= page_offset(page
) +
350 (char *)de
-(char*)page_address(page
);
354 err
= __sysv_write_begin(NULL
, mapping
, pos
, SYSV_DIRSIZE
,
355 AOP_FLAG_UNINTERRUPTIBLE
, &page
, NULL
);
357 de
->inode
= cpu_to_fs16(SYSV_SB(inode
->i_sb
), inode
->i_ino
);
358 err
= dir_commit_chunk(page
, pos
, SYSV_DIRSIZE
);
360 dir
->i_mtime
= dir
->i_ctime
= CURRENT_TIME_SEC
;
361 mark_inode_dirty(dir
);
364 struct sysv_dir_entry
* sysv_dotdot (struct inode
*dir
, struct page
**p
)
366 struct page
*page
= dir_get_page(dir
, 0);
367 struct sysv_dir_entry
*de
= NULL
;
370 de
= (struct sysv_dir_entry
*) page_address(page
) + 1;
376 ino_t
sysv_inode_by_name(struct dentry
*dentry
)
379 struct sysv_dir_entry
*de
= sysv_find_entry (dentry
, &page
);
383 res
= fs16_to_cpu(SYSV_SB(dentry
->d_sb
), de
->inode
);