~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/fs/nilfs2/dir.c

Version: ~ [ linux-5.6 ] ~ [ linux-5.5.13 ] ~ [ linux-5.4.28 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.113 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.174 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.217 ] ~ [ linux-4.8.17 ] ~ [ linux-4.7.10 ] ~ [ linux-4.6.7 ] ~ [ linux-4.5.7 ] ~ [ linux-4.4.217 ] ~ [ linux-4.3.6 ] ~ [ linux-4.2.8 ] ~ [ linux-4.1.52 ] ~ [ linux-4.0.9 ] ~ [ linux-3.19.8 ] ~ [ linux-3.18.140 ] ~ [ linux-3.17.8 ] ~ [ linux-3.16.82 ] ~ [ linux-3.15.10 ] ~ [ linux-3.14.79 ] ~ [ linux-3.13.11 ] ~ [ linux-3.12.74 ] ~ [ linux-3.11.10 ] ~ [ linux-3.10.108 ] ~ [ linux-3.9.11 ] ~ [ linux-3.8.13 ] ~ [ linux-3.7.10 ] ~ [ linux-3.6.11 ] ~ [ linux-3.5.7 ] ~ [ linux-3.4.113 ] ~ [ linux-3.3.8 ] ~ [ linux-3.2.102 ] ~ [ linux-3.1.10 ] ~ [ linux-3.0.101 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.5 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 /*
  2  * dir.c - NILFS directory entry operations
  3  *
  4  * Copyright (C) 2005-2008 Nippon Telegraph and Telephone Corporation.
  5  *
  6  * This program is free software; you can redistribute it and/or modify
  7  * it under the terms of the GNU General Public License as published by
  8  * the Free Software Foundation; either version 2 of the License, or
  9  * (at your option) any later version.
 10  *
 11  * This program is distributed in the hope that it will be useful,
 12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
 13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 14  * GNU General Public License for more details.
 15  *
 16  * You should have received a copy of the GNU General Public License
 17  * along with this program; if not, write to the Free Software
 18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 19  *
 20  * Modified for NILFS by Amagai Yoshiji <amagai@osrg.net>
 21  */
 22 /*
 23  *  linux/fs/ext2/dir.c
 24  *
 25  * Copyright (C) 1992, 1993, 1994, 1995
 26  * Remy Card (card@masi.ibp.fr)
 27  * Laboratoire MASI - Institut Blaise Pascal
 28  * Universite Pierre et Marie Curie (Paris VI)
 29  *
 30  *  from
 31  *
 32  *  linux/fs/minix/dir.c
 33  *
 34  *  Copyright (C) 1991, 1992  Linus Torvalds
 35  *
 36  *  ext2 directory handling functions
 37  *
 38  *  Big-endian to little-endian byte-swapping/bitmaps by
 39  *        David S. Miller (davem@caip.rutgers.edu), 1995
 40  *
 41  * All code that works with directory layout had been switched to pagecache
 42  * and moved here. AV
 43  */
 44 
 45 #include <linux/pagemap.h>
 46 #include "nilfs.h"
 47 #include "page.h"
 48 
 49 /*
 50  * nilfs uses block-sized chunks. Arguably, sector-sized ones would be
 51  * more robust, but we have what we have
 52  */
 53 static inline unsigned nilfs_chunk_size(struct inode *inode)
 54 {
 55         return inode->i_sb->s_blocksize;
 56 }
 57 
 58 static inline void nilfs_put_page(struct page *page)
 59 {
 60         kunmap(page);
 61         page_cache_release(page);
 62 }
 63 
 64 static inline unsigned long dir_pages(struct inode *inode)
 65 {
 66         return (inode->i_size+PAGE_CACHE_SIZE-1)>>PAGE_CACHE_SHIFT;
 67 }
 68 
 69 /*
 70  * Return the offset into page `page_nr' of the last valid
 71  * byte in that page, plus one.
 72  */
 73 static unsigned nilfs_last_byte(struct inode *inode, unsigned long page_nr)
 74 {
 75         unsigned last_byte = inode->i_size;
 76 
 77         last_byte -= page_nr << PAGE_CACHE_SHIFT;
 78         if (last_byte > PAGE_CACHE_SIZE)
 79                 last_byte = PAGE_CACHE_SIZE;
 80         return last_byte;
 81 }
 82 
 83 static int nilfs_prepare_chunk(struct page *page, unsigned from, unsigned to)
 84 {
 85         loff_t pos = page_offset(page) + from;
 86         return __block_write_begin(page, pos, to - from, nilfs_get_block);
 87 }
 88 
 89 static void nilfs_commit_chunk(struct page *page,
 90                                struct address_space *mapping,
 91                                unsigned from, unsigned to)
 92 {
 93         struct inode *dir = mapping->host;
 94         loff_t pos = page_offset(page) + from;
 95         unsigned len = to - from;
 96         unsigned nr_dirty, copied;
 97         int err;
 98 
 99         nr_dirty = nilfs_page_count_clean_buffers(page, from, to);
100         copied = block_write_end(NULL, mapping, pos, len, len, page, NULL);
101         if (pos + copied > dir->i_size)
102                 i_size_write(dir, pos + copied);
103         if (IS_DIRSYNC(dir))
104                 nilfs_set_transaction_flag(NILFS_TI_SYNC);
105         err = nilfs_set_file_dirty(dir, nr_dirty);
106         WARN_ON(err); /* do not happen */
107         unlock_page(page);
108 }
109 
110 static void nilfs_check_page(struct page *page)
111 {
112         struct inode *dir = page->mapping->host;
113         struct super_block *sb = dir->i_sb;
114         unsigned chunk_size = nilfs_chunk_size(dir);
115         char *kaddr = page_address(page);
116         unsigned offs, rec_len;
117         unsigned limit = PAGE_CACHE_SIZE;
118         struct nilfs_dir_entry *p;
119         char *error;
120 
121         if ((dir->i_size >> PAGE_CACHE_SHIFT) == page->index) {
122                 limit = dir->i_size & ~PAGE_CACHE_MASK;
123                 if (limit & (chunk_size - 1))
124                         goto Ebadsize;
125                 if (!limit)
126                         goto out;
127         }
128         for (offs = 0; offs <= limit - NILFS_DIR_REC_LEN(1); offs += rec_len) {
129                 p = (struct nilfs_dir_entry *)(kaddr + offs);
130                 rec_len = nilfs_rec_len_from_disk(p->rec_len);
131 
132                 if (rec_len < NILFS_DIR_REC_LEN(1))
133                         goto Eshort;
134                 if (rec_len & 3)
135                         goto Ealign;
136                 if (rec_len < NILFS_DIR_REC_LEN(p->name_len))
137                         goto Enamelen;
138                 if (((offs + rec_len - 1) ^ offs) & ~(chunk_size-1))
139                         goto Espan;
140         }
141         if (offs != limit)
142                 goto Eend;
143 out:
144         SetPageChecked(page);
145         return;
146 
147         /* Too bad, we had an error */
148 
149 Ebadsize:
150         nilfs_error(sb, "nilfs_check_page",
151                     "size of directory #%lu is not a multiple of chunk size",
152                     dir->i_ino
153         );
154         goto fail;
155 Eshort:
156         error = "rec_len is smaller than minimal";
157         goto bad_entry;
158 Ealign:
159         error = "unaligned directory entry";
160         goto bad_entry;
161 Enamelen:
162         error = "rec_len is too small for name_len";
163         goto bad_entry;
164 Espan:
165         error = "directory entry across blocks";
166 bad_entry:
167         nilfs_error(sb, "nilfs_check_page", "bad entry in directory #%lu: %s - "
168                     "offset=%lu, inode=%lu, rec_len=%d, name_len=%d",
169                     dir->i_ino, error, (page->index<<PAGE_CACHE_SHIFT)+offs,
170                     (unsigned long) le64_to_cpu(p->inode),
171                     rec_len, p->name_len);
172         goto fail;
173 Eend:
174         p = (struct nilfs_dir_entry *)(kaddr + offs);
175         nilfs_error(sb, "nilfs_check_page",
176                     "entry in directory #%lu spans the page boundary"
177                     "offset=%lu, inode=%lu",
178                     dir->i_ino, (page->index<<PAGE_CACHE_SHIFT)+offs,
179                     (unsigned long) le64_to_cpu(p->inode));
180 fail:
181         SetPageChecked(page);
182         SetPageError(page);
183 }
184 
185 static struct page *nilfs_get_page(struct inode *dir, unsigned long n)
186 {
187         struct address_space *mapping = dir->i_mapping;
188         struct page *page = read_mapping_page(mapping, n, NULL);
189 
190         if (!IS_ERR(page)) {
191                 kmap(page);
192                 if (!PageChecked(page))
193                         nilfs_check_page(page);
194                 if (PageError(page))
195                         goto fail;
196         }
197         return page;
198 
199 fail:
200         nilfs_put_page(page);
201         return ERR_PTR(-EIO);
202 }
203 
204 /*
205  * NOTE! unlike strncmp, nilfs_match returns 1 for success, 0 for failure.
206  *
207  * len <= NILFS_NAME_LEN and de != NULL are guaranteed by caller.
208  */
209 static int
210 nilfs_match(int len, const unsigned char *name, struct nilfs_dir_entry *de)
211 {
212         if (len != de->name_len)
213                 return 0;
214         if (!de->inode)
215                 return 0;
216         return !memcmp(name, de->name, len);
217 }
218 
219 /*
220  * p is at least 6 bytes before the end of page
221  */
222 static struct nilfs_dir_entry *nilfs_next_entry(struct nilfs_dir_entry *p)
223 {
224         return (struct nilfs_dir_entry *)((char *)p +
225                                           nilfs_rec_len_from_disk(p->rec_len));
226 }
227 
228 static unsigned char
229 nilfs_filetype_table[NILFS_FT_MAX] = {
230         [NILFS_FT_UNKNOWN]      = DT_UNKNOWN,
231         [NILFS_FT_REG_FILE]     = DT_REG,
232         [NILFS_FT_DIR]          = DT_DIR,
233         [NILFS_FT_CHRDEV]       = DT_CHR,
234         [NILFS_FT_BLKDEV]       = DT_BLK,
235         [NILFS_FT_FIFO]         = DT_FIFO,
236         [NILFS_FT_SOCK]         = DT_SOCK,
237         [NILFS_FT_SYMLINK]      = DT_LNK,
238 };
239 
240 #define S_SHIFT 12
241 static unsigned char
242 nilfs_type_by_mode[S_IFMT >> S_SHIFT] = {
243         [S_IFREG >> S_SHIFT]    = NILFS_FT_REG_FILE,
244         [S_IFDIR >> S_SHIFT]    = NILFS_FT_DIR,
245         [S_IFCHR >> S_SHIFT]    = NILFS_FT_CHRDEV,
246         [S_IFBLK >> S_SHIFT]    = NILFS_FT_BLKDEV,
247         [S_IFIFO >> S_SHIFT]    = NILFS_FT_FIFO,
248         [S_IFSOCK >> S_SHIFT]   = NILFS_FT_SOCK,
249         [S_IFLNK >> S_SHIFT]    = NILFS_FT_SYMLINK,
250 };
251 
252 static void nilfs_set_de_type(struct nilfs_dir_entry *de, struct inode *inode)
253 {
254         umode_t mode = inode->i_mode;
255 
256         de->file_type = nilfs_type_by_mode[(mode & S_IFMT)>>S_SHIFT];
257 }
258 
259 static int nilfs_readdir(struct file *file, struct dir_context *ctx)
260 {
261         loff_t pos = ctx->pos;
262         struct inode *inode = file_inode(file);
263         struct super_block *sb = inode->i_sb;
264         unsigned int offset = pos & ~PAGE_CACHE_MASK;
265         unsigned long n = pos >> PAGE_CACHE_SHIFT;
266         unsigned long npages = dir_pages(inode);
267 /*      unsigned chunk_mask = ~(nilfs_chunk_size(inode)-1); */
268 
269         if (pos > inode->i_size - NILFS_DIR_REC_LEN(1))
270                 return 0;
271 
272         for ( ; n < npages; n++, offset = 0) {
273                 char *kaddr, *limit;
274                 struct nilfs_dir_entry *de;
275                 struct page *page = nilfs_get_page(inode, n);
276 
277                 if (IS_ERR(page)) {
278                         nilfs_error(sb, __func__, "bad page in #%lu",
279                                     inode->i_ino);
280                         ctx->pos += PAGE_CACHE_SIZE - offset;
281                         return -EIO;
282                 }
283                 kaddr = page_address(page);
284                 de = (struct nilfs_dir_entry *)(kaddr + offset);
285                 limit = kaddr + nilfs_last_byte(inode, n) -
286                         NILFS_DIR_REC_LEN(1);
287                 for ( ; (char *)de <= limit; de = nilfs_next_entry(de)) {
288                         if (de->rec_len == 0) {
289                                 nilfs_error(sb, __func__,
290                                             "zero-length directory entry");
291                                 nilfs_put_page(page);
292                                 return -EIO;
293                         }
294                         if (de->inode) {
295                                 unsigned char t;
296 
297                                 if (de->file_type < NILFS_FT_MAX)
298                                         t = nilfs_filetype_table[de->file_type];
299                                 else
300                                         t = DT_UNKNOWN;
301 
302                                 if (!dir_emit(ctx, de->name, de->name_len,
303                                                 le64_to_cpu(de->inode), t)) {
304                                         nilfs_put_page(page);
305                                         return 0;
306                                 }
307                         }
308                         ctx->pos += nilfs_rec_len_from_disk(de->rec_len);
309                 }
310                 nilfs_put_page(page);
311         }
312         return 0;
313 }
314 
315 /*
316  *      nilfs_find_entry()
317  *
318  * finds an entry in the specified directory with the wanted name. It
319  * returns the page in which the entry was found, and the entry itself
320  * (as a parameter - res_dir). Page is returned mapped and unlocked.
321  * Entry is guaranteed to be valid.
322  */
323 struct nilfs_dir_entry *
324 nilfs_find_entry(struct inode *dir, const struct qstr *qstr,
325                  struct page **res_page)
326 {
327         const unsigned char *name = qstr->name;
328         int namelen = qstr->len;
329         unsigned reclen = NILFS_DIR_REC_LEN(namelen);
330         unsigned long start, n;
331         unsigned long npages = dir_pages(dir);
332         struct page *page = NULL;
333         struct nilfs_inode_info *ei = NILFS_I(dir);
334         struct nilfs_dir_entry *de;
335 
336         if (npages == 0)
337                 goto out;
338 
339         /* OFFSET_CACHE */
340         *res_page = NULL;
341 
342         start = ei->i_dir_start_lookup;
343         if (start >= npages)
344                 start = 0;
345         n = start;
346         do {
347                 char *kaddr;
348                 page = nilfs_get_page(dir, n);
349                 if (!IS_ERR(page)) {
350                         kaddr = page_address(page);
351                         de = (struct nilfs_dir_entry *)kaddr;
352                         kaddr += nilfs_last_byte(dir, n) - reclen;
353                         while ((char *) de <= kaddr) {
354                                 if (de->rec_len == 0) {
355                                         nilfs_error(dir->i_sb, __func__,
356                                                 "zero-length directory entry");
357                                         nilfs_put_page(page);
358                                         goto out;
359                                 }
360                                 if (nilfs_match(namelen, name, de))
361                                         goto found;
362                                 de = nilfs_next_entry(de);
363                         }
364                         nilfs_put_page(page);
365                 }
366                 if (++n >= npages)
367                         n = 0;
368                 /* next page is past the blocks we've got */
369                 if (unlikely(n > (dir->i_blocks >> (PAGE_CACHE_SHIFT - 9)))) {
370                         nilfs_error(dir->i_sb, __func__,
371                                "dir %lu size %lld exceeds block count %llu",
372                                dir->i_ino, dir->i_size,
373                                (unsigned long long)dir->i_blocks);
374                         goto out;
375                 }
376         } while (n != start);
377 out:
378         return NULL;
379 
380 found:
381         *res_page = page;
382         ei->i_dir_start_lookup = n;
383         return de;
384 }
385 
386 struct nilfs_dir_entry *nilfs_dotdot(struct inode *dir, struct page **p)
387 {
388         struct page *page = nilfs_get_page(dir, 0);
389         struct nilfs_dir_entry *de = NULL;
390 
391         if (!IS_ERR(page)) {
392                 de = nilfs_next_entry(
393                         (struct nilfs_dir_entry *)page_address(page));
394                 *p = page;
395         }
396         return de;
397 }
398 
399 ino_t nilfs_inode_by_name(struct inode *dir, const struct qstr *qstr)
400 {
401         ino_t res = 0;
402         struct nilfs_dir_entry *de;
403         struct page *page;
404 
405         de = nilfs_find_entry(dir, qstr, &page);
406         if (de) {
407                 res = le64_to_cpu(de->inode);
408                 kunmap(page);
409                 page_cache_release(page);
410         }
411         return res;
412 }
413 
414 /* Releases the page */
415 void nilfs_set_link(struct inode *dir, struct nilfs_dir_entry *de,
416                     struct page *page, struct inode *inode)
417 {
418         unsigned from = (char *) de - (char *) page_address(page);
419         unsigned to = from + nilfs_rec_len_from_disk(de->rec_len);
420         struct address_space *mapping = page->mapping;
421         int err;
422 
423         lock_page(page);
424         err = nilfs_prepare_chunk(page, from, to);
425         BUG_ON(err);
426         de->inode = cpu_to_le64(inode->i_ino);
427         nilfs_set_de_type(de, inode);
428         nilfs_commit_chunk(page, mapping, from, to);
429         nilfs_put_page(page);
430         dir->i_mtime = dir->i_ctime = CURRENT_TIME;
431 }
432 
433 /*
434  *      Parent is locked.
435  */
436 int nilfs_add_link(struct dentry *dentry, struct inode *inode)
437 {
438         struct inode *dir = dentry->d_parent->d_inode;
439         const unsigned char *name = dentry->d_name.name;
440         int namelen = dentry->d_name.len;
441         unsigned chunk_size = nilfs_chunk_size(dir);
442         unsigned reclen = NILFS_DIR_REC_LEN(namelen);
443         unsigned short rec_len, name_len;
444         struct page *page = NULL;
445         struct nilfs_dir_entry *de;
446         unsigned long npages = dir_pages(dir);
447         unsigned long n;
448         char *kaddr;
449         unsigned from, to;
450         int err;
451 
452         /*
453          * We take care of directory expansion in the same loop.
454          * This code plays outside i_size, so it locks the page
455          * to protect that region.
456          */
457         for (n = 0; n <= npages; n++) {
458                 char *dir_end;
459 
460                 page = nilfs_get_page(dir, n);
461                 err = PTR_ERR(page);
462                 if (IS_ERR(page))
463                         goto out;
464                 lock_page(page);
465                 kaddr = page_address(page);
466                 dir_end = kaddr + nilfs_last_byte(dir, n);
467                 de = (struct nilfs_dir_entry *)kaddr;
468                 kaddr += PAGE_CACHE_SIZE - reclen;
469                 while ((char *)de <= kaddr) {
470                         if ((char *)de == dir_end) {
471                                 /* We hit i_size */
472                                 name_len = 0;
473                                 rec_len = chunk_size;
474                                 de->rec_len = nilfs_rec_len_to_disk(chunk_size);
475                                 de->inode = 0;
476                                 goto got_it;
477                         }
478                         if (de->rec_len == 0) {
479                                 nilfs_error(dir->i_sb, __func__,
480                                             "zero-length directory entry");
481                                 err = -EIO;
482                                 goto out_unlock;
483                         }
484                         err = -EEXIST;
485                         if (nilfs_match(namelen, name, de))
486                                 goto out_unlock;
487                         name_len = NILFS_DIR_REC_LEN(de->name_len);
488                         rec_len = nilfs_rec_len_from_disk(de->rec_len);
489                         if (!de->inode && rec_len >= reclen)
490                                 goto got_it;
491                         if (rec_len >= name_len + reclen)
492                                 goto got_it;
493                         de = (struct nilfs_dir_entry *)((char *)de + rec_len);
494                 }
495                 unlock_page(page);
496                 nilfs_put_page(page);
497         }
498         BUG();
499         return -EINVAL;
500 
501 got_it:
502         from = (char *)de - (char *)page_address(page);
503         to = from + rec_len;
504         err = nilfs_prepare_chunk(page, from, to);
505         if (err)
506                 goto out_unlock;
507         if (de->inode) {
508                 struct nilfs_dir_entry *de1;
509 
510                 de1 = (struct nilfs_dir_entry *)((char *)de + name_len);
511                 de1->rec_len = nilfs_rec_len_to_disk(rec_len - name_len);
512                 de->rec_len = nilfs_rec_len_to_disk(name_len);
513                 de = de1;
514         }
515         de->name_len = namelen;
516         memcpy(de->name, name, namelen);
517         de->inode = cpu_to_le64(inode->i_ino);
518         nilfs_set_de_type(de, inode);
519         nilfs_commit_chunk(page, page->mapping, from, to);
520         dir->i_mtime = dir->i_ctime = CURRENT_TIME;
521         nilfs_mark_inode_dirty(dir);
522         /* OFFSET_CACHE */
523 out_put:
524         nilfs_put_page(page);
525 out:
526         return err;
527 out_unlock:
528         unlock_page(page);
529         goto out_put;
530 }
531 
532 /*
533  * nilfs_delete_entry deletes a directory entry by merging it with the
534  * previous entry. Page is up-to-date. Releases the page.
535  */
536 int nilfs_delete_entry(struct nilfs_dir_entry *dir, struct page *page)
537 {
538         struct address_space *mapping = page->mapping;
539         struct inode *inode = mapping->host;
540         char *kaddr = page_address(page);
541         unsigned from = ((char *)dir - kaddr) & ~(nilfs_chunk_size(inode) - 1);
542         unsigned to = ((char *)dir - kaddr) +
543                 nilfs_rec_len_from_disk(dir->rec_len);
544         struct nilfs_dir_entry *pde = NULL;
545         struct nilfs_dir_entry *de = (struct nilfs_dir_entry *)(kaddr + from);
546         int err;
547 
548         while ((char *)de < (char *)dir) {
549                 if (de->rec_len == 0) {
550                         nilfs_error(inode->i_sb, __func__,
551                                     "zero-length directory entry");
552                         err = -EIO;
553                         goto out;
554                 }
555                 pde = de;
556                 de = nilfs_next_entry(de);
557         }
558         if (pde)
559                 from = (char *)pde - (char *)page_address(page);
560         lock_page(page);
561         err = nilfs_prepare_chunk(page, from, to);
562         BUG_ON(err);
563         if (pde)
564                 pde->rec_len = nilfs_rec_len_to_disk(to - from);
565         dir->inode = 0;
566         nilfs_commit_chunk(page, mapping, from, to);
567         inode->i_ctime = inode->i_mtime = CURRENT_TIME;
568 out:
569         nilfs_put_page(page);
570         return err;
571 }
572 
573 /*
574  * Set the first fragment of directory.
575  */
576 int nilfs_make_empty(struct inode *inode, struct inode *parent)
577 {
578         struct address_space *mapping = inode->i_mapping;
579         struct page *page = grab_cache_page(mapping, 0);
580         unsigned chunk_size = nilfs_chunk_size(inode);
581         struct nilfs_dir_entry *de;
582         int err;
583         void *kaddr;
584 
585         if (!page)
586                 return -ENOMEM;
587 
588         err = nilfs_prepare_chunk(page, 0, chunk_size);
589         if (unlikely(err)) {
590                 unlock_page(page);
591                 goto fail;
592         }
593         kaddr = kmap_atomic(page);
594         memset(kaddr, 0, chunk_size);
595         de = (struct nilfs_dir_entry *)kaddr;
596         de->name_len = 1;
597         de->rec_len = nilfs_rec_len_to_disk(NILFS_DIR_REC_LEN(1));
598         memcpy(de->name, ".\0\0", 4);
599         de->inode = cpu_to_le64(inode->i_ino);
600         nilfs_set_de_type(de, inode);
601 
602         de = (struct nilfs_dir_entry *)(kaddr + NILFS_DIR_REC_LEN(1));
603         de->name_len = 2;
604         de->rec_len = nilfs_rec_len_to_disk(chunk_size - NILFS_DIR_REC_LEN(1));
605         de->inode = cpu_to_le64(parent->i_ino);
606         memcpy(de->name, "..\0", 4);
607         nilfs_set_de_type(de, inode);
608         kunmap_atomic(kaddr);
609         nilfs_commit_chunk(page, mapping, 0, chunk_size);
610 fail:
611         page_cache_release(page);
612         return err;
613 }
614 
615 /*
616  * routine to check that the specified directory is empty (for rmdir)
617  */
618 int nilfs_empty_dir(struct inode *inode)
619 {
620         struct page *page = NULL;
621         unsigned long i, npages = dir_pages(inode);
622 
623         for (i = 0; i < npages; i++) {
624                 char *kaddr;
625                 struct nilfs_dir_entry *de;
626 
627                 page = nilfs_get_page(inode, i);
628                 if (IS_ERR(page))
629                         continue;
630 
631                 kaddr = page_address(page);
632                 de = (struct nilfs_dir_entry *)kaddr;
633                 kaddr += nilfs_last_byte(inode, i) - NILFS_DIR_REC_LEN(1);
634 
635                 while ((char *)de <= kaddr) {
636                         if (de->rec_len == 0) {
637                                 nilfs_error(inode->i_sb, __func__,
638                                             "zero-length directory entry "
639                                             "(kaddr=%p, de=%p)\n", kaddr, de);
640                                 goto not_empty;
641                         }
642                         if (de->inode != 0) {
643                                 /* check for . and .. */
644                                 if (de->name[0] != '.')
645                                         goto not_empty;
646                                 if (de->name_len > 2)
647                                         goto not_empty;
648                                 if (de->name_len < 2) {
649                                         if (de->inode !=
650                                             cpu_to_le64(inode->i_ino))
651                                                 goto not_empty;
652                                 } else if (de->name[1] != '.')
653                                         goto not_empty;
654                         }
655                         de = nilfs_next_entry(de);
656                 }
657                 nilfs_put_page(page);
658         }
659         return 1;
660 
661 not_empty:
662         nilfs_put_page(page);
663         return 0;
664 }
665 
666 const struct file_operations nilfs_dir_operations = {
667         .llseek         = generic_file_llseek,
668         .read           = generic_read_dir,
669         .iterate        = nilfs_readdir,
670         .unlocked_ioctl = nilfs_ioctl,
671 #ifdef CONFIG_COMPAT
672         .compat_ioctl   = nilfs_compat_ioctl,
673 #endif  /* CONFIG_COMPAT */
674         .fsync          = nilfs_sync_file,
675 
676 };
677 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | Wiki (Japanese) | Wiki (English) | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

osdn.jp