linux/fs/exofs/dir.c
<<
>>
Prefs
   1/*
   2 * Copyright (C) 2005, 2006
   3 * Avishay Traeger (avishay@gmail.com)
   4 * Copyright (C) 2008, 2009
   5 * Boaz Harrosh <ooo@electrozaur.com>
   6 *
   7 * Copyrights for code taken from ext2:
   8 *     Copyright (C) 1992, 1993, 1994, 1995
   9 *     Remy Card (card@masi.ibp.fr)
  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
  36static inline unsigned exofs_chunk_size(struct inode *inode)
  37{
  38        return inode->i_sb->s_blocksize;
  39}
  40
  41static inline void exofs_put_page(struct page *page)
  42{
  43        kunmap(page);
  44        put_page(page);
  45}
  46
  47static unsigned exofs_last_byte(struct inode *inode, unsigned long page_nr)
  48{
  49        loff_t last_byte = inode->i_size;
  50
  51        last_byte -= page_nr << PAGE_SHIFT;
  52        if (last_byte > PAGE_SIZE)
  53                last_byte = PAGE_SIZE;
  54        return last_byte;
  55}
  56
  57static int exofs_commit_chunk(struct page *page, loff_t pos, unsigned len)
  58{
  59        struct address_space *mapping = page->mapping;
  60        struct inode *dir = mapping->host;
  61        int err = 0;
  62
  63        dir->i_version++;
  64
  65        if (!PageUptodate(page))
  66                SetPageUptodate(page);
  67
  68        if (pos+len > dir->i_size) {
  69                i_size_write(dir, pos+len);
  70                mark_inode_dirty(dir);
  71        }
  72        set_page_dirty(page);
  73
  74        if (IS_DIRSYNC(dir))
  75                err = write_one_page(page, 1);
  76        else
  77                unlock_page(page);
  78
  79        return err;
  80}
  81
  82static void exofs_check_page(struct page *page)
  83{
  84        struct inode *dir = page->mapping->host;
  85        unsigned chunk_size = exofs_chunk_size(dir);
  86        char *kaddr = page_address(page);
  87        unsigned offs, rec_len;
  88        unsigned limit = PAGE_SIZE;
  89        struct exofs_dir_entry *p;
  90        char *error;
  91
  92        /* if the page is the last one in the directory */
  93        if ((dir->i_size >> PAGE_SHIFT) == page->index) {
  94                limit = dir->i_size & ~PAGE_MASK;
  95                if (limit & (chunk_size - 1))
  96                        goto Ebadsize;
  97                if (!limit)
  98                        goto out;
  99        }
 100        for (offs = 0; offs <= limit - EXOFS_DIR_REC_LEN(1); offs += rec_len) {
 101                p = (struct exofs_dir_entry *)(kaddr + offs);
 102                rec_len = le16_to_cpu(p->rec_len);
 103
 104                if (rec_len < EXOFS_DIR_REC_LEN(1))
 105                        goto Eshort;
 106                if (rec_len & 3)
 107                        goto Ealign;
 108                if (rec_len < EXOFS_DIR_REC_LEN(p->name_len))
 109                        goto Enamelen;
 110                if (((offs + rec_len - 1) ^ offs) & ~(chunk_size-1))
 111                        goto Espan;
 112        }
 113        if (offs != limit)
 114                goto Eend;
 115out:
 116        SetPageChecked(page);
 117        return;
 118
 119Ebadsize:
 120        EXOFS_ERR("ERROR [exofs_check_page]: "
 121                "size of directory(0x%lx) is not a multiple of chunk size\n",
 122                dir->i_ino
 123        );
 124        goto fail;
 125Eshort:
 126        error = "rec_len is smaller than minimal";
 127        goto bad_entry;
 128Ealign:
 129        error = "unaligned directory entry";
 130        goto bad_entry;
 131Enamelen:
 132        error = "rec_len is too small for name_len";
 133        goto bad_entry;
 134Espan:
 135        error = "directory entry across blocks";
 136        goto bad_entry;
 137bad_entry:
 138        EXOFS_ERR(
 139                "ERROR [exofs_check_page]: bad entry in directory(0x%lx): %s - "
 140                "offset=%lu, inode=0x%llu, rec_len=%d, name_len=%d\n",
 141                dir->i_ino, error, (page->index<<PAGE_SHIFT)+offs,
 142                _LLU(le64_to_cpu(p->inode_no)),
 143                rec_len, p->name_len);
 144        goto fail;
 145Eend:
 146        p = (struct exofs_dir_entry *)(kaddr + offs);
 147        EXOFS_ERR("ERROR [exofs_check_page]: "
 148                "entry in directory(0x%lx) spans the page boundary"
 149                "offset=%lu, inode=0x%llx\n",
 150                dir->i_ino, (page->index<<PAGE_SHIFT)+offs,
 151                _LLU(le64_to_cpu(p->inode_no)));
 152fail:
 153        SetPageChecked(page);
 154        SetPageError(page);
 155}
 156
 157static struct page *exofs_get_page(struct inode *dir, unsigned long n)
 158{
 159        struct address_space *mapping = dir->i_mapping;
 160        struct page *page = read_mapping_page(mapping, n, NULL);
 161
 162        if (!IS_ERR(page)) {
 163                kmap(page);
 164                if (!PageChecked(page))
 165                        exofs_check_page(page);
 166                if (PageError(page))
 167                        goto fail;
 168        }
 169        return page;
 170
 171fail:
 172        exofs_put_page(page);
 173        return ERR_PTR(-EIO);
 174}
 175
 176static inline int exofs_match(int len, const unsigned char *name,
 177                                        struct exofs_dir_entry *de)
 178{
 179        if (len != de->name_len)
 180                return 0;
 181        if (!de->inode_no)
 182                return 0;
 183        return !memcmp(name, de->name, len);
 184}
 185
 186static inline
 187struct exofs_dir_entry *exofs_next_entry(struct exofs_dir_entry *p)
 188{
 189        return (struct exofs_dir_entry *)((char *)p + le16_to_cpu(p->rec_len));
 190}
 191
 192static inline unsigned
 193exofs_validate_entry(char *base, unsigned offset, unsigned mask)
 194{
 195        struct exofs_dir_entry *de = (struct exofs_dir_entry *)(base + offset);
 196        struct exofs_dir_entry *p =
 197                        (struct exofs_dir_entry *)(base + (offset&mask));
 198        while ((char *)p < (char *)de) {
 199                if (p->rec_len == 0)
 200                        break;
 201                p = exofs_next_entry(p);
 202        }
 203        return (char *)p - base;
 204}
 205
 206static unsigned char exofs_filetype_table[EXOFS_FT_MAX] = {
 207        [EXOFS_FT_UNKNOWN]      = DT_UNKNOWN,
 208        [EXOFS_FT_REG_FILE]     = DT_REG,
 209        [EXOFS_FT_DIR]          = DT_DIR,
 210        [EXOFS_FT_CHRDEV]       = DT_CHR,
 211        [EXOFS_FT_BLKDEV]       = DT_BLK,
 212        [EXOFS_FT_FIFO]         = DT_FIFO,
 213        [EXOFS_FT_SOCK]         = DT_SOCK,
 214        [EXOFS_FT_SYMLINK]      = DT_LNK,
 215};
 216
 217#define S_SHIFT 12
 218static unsigned char exofs_type_by_mode[S_IFMT >> S_SHIFT] = {
 219        [S_IFREG >> S_SHIFT]    = EXOFS_FT_REG_FILE,
 220        [S_IFDIR >> S_SHIFT]    = EXOFS_FT_DIR,
 221        [S_IFCHR >> S_SHIFT]    = EXOFS_FT_CHRDEV,
 222        [S_IFBLK >> S_SHIFT]    = EXOFS_FT_BLKDEV,
 223        [S_IFIFO >> S_SHIFT]    = EXOFS_FT_FIFO,
 224        [S_IFSOCK >> S_SHIFT]   = EXOFS_FT_SOCK,
 225        [S_IFLNK >> S_SHIFT]    = EXOFS_FT_SYMLINK,
 226};
 227
 228static inline
 229void exofs_set_de_type(struct exofs_dir_entry *de, struct inode *inode)
 230{
 231        umode_t mode = inode->i_mode;
 232        de->file_type = exofs_type_by_mode[(mode & S_IFMT) >> S_SHIFT];
 233}
 234
 235static int
 236exofs_readdir(struct file *file, struct dir_context *ctx)
 237{
 238        loff_t pos = ctx->pos;
 239        struct inode *inode = file_inode(file);
 240        unsigned int offset = pos & ~PAGE_MASK;
 241        unsigned long n = pos >> PAGE_SHIFT;
 242        unsigned long npages = dir_pages(inode);
 243        unsigned chunk_mask = ~(exofs_chunk_size(inode)-1);
 244        int need_revalidate = (file->f_version != inode->i_version);
 245
 246        if (pos > inode->i_size - EXOFS_DIR_REC_LEN(1))
 247                return 0;
 248
 249        for ( ; n < npages; n++, offset = 0) {
 250                char *kaddr, *limit;
 251                struct exofs_dir_entry *de;
 252                struct page *page = exofs_get_page(inode, n);
 253
 254                if (IS_ERR(page)) {
 255                        EXOFS_ERR("ERROR: bad page in directory(0x%lx)\n",
 256                                  inode->i_ino);
 257                        ctx->pos += PAGE_SIZE - offset;
 258                        return PTR_ERR(page);
 259                }
 260                kaddr = page_address(page);
 261                if (unlikely(need_revalidate)) {
 262                        if (offset) {
 263                                offset = exofs_validate_entry(kaddr, offset,
 264                                                                chunk_mask);
 265                                ctx->pos = (n<<PAGE_SHIFT) + offset;
 266                        }
 267                        file->f_version = inode->i_version;
 268                        need_revalidate = 0;
 269                }
 270                de = (struct exofs_dir_entry *)(kaddr + offset);
 271                limit = kaddr + exofs_last_byte(inode, n) -
 272                                                        EXOFS_DIR_REC_LEN(1);
 273                for (; (char *)de <= limit; de = exofs_next_entry(de)) {
 274                        if (de->rec_len == 0) {
 275                                EXOFS_ERR("ERROR: "
 276                                     "zero-length entry in directory(0x%lx)\n",
 277                                     inode->i_ino);
 278                                exofs_put_page(page);
 279                                return -EIO;
 280                        }
 281                        if (de->inode_no) {
 282                                unsigned char t;
 283
 284                                if (de->file_type < EXOFS_FT_MAX)
 285                                        t = exofs_filetype_table[de->file_type];
 286                                else
 287                                        t = DT_UNKNOWN;
 288
 289                                if (!dir_emit(ctx, de->name, de->name_len,
 290                                                le64_to_cpu(de->inode_no),
 291                                                t)) {
 292                                        exofs_put_page(page);
 293                                        return 0;
 294                                }
 295                        }
 296                        ctx->pos += le16_to_cpu(de->rec_len);
 297                }
 298                exofs_put_page(page);
 299        }
 300        return 0;
 301}
 302
 303struct exofs_dir_entry *exofs_find_entry(struct inode *dir,
 304                        struct dentry *dentry, struct page **res_page)
 305{
 306        const unsigned char *name = dentry->d_name.name;
 307        int namelen = dentry->d_name.len;
 308        unsigned reclen = EXOFS_DIR_REC_LEN(namelen);
 309        unsigned long start, n;
 310        unsigned long npages = dir_pages(dir);
 311        struct page *page = NULL;
 312        struct exofs_i_info *oi = exofs_i(dir);
 313        struct exofs_dir_entry *de;
 314
 315        if (npages == 0)
 316                goto out;
 317
 318        *res_page = NULL;
 319
 320        start = oi->i_dir_start_lookup;
 321        if (start >= npages)
 322                start = 0;
 323        n = start;
 324        do {
 325                char *kaddr;
 326                page = exofs_get_page(dir, n);
 327                if (!IS_ERR(page)) {
 328                        kaddr = page_address(page);
 329                        de = (struct exofs_dir_entry *) kaddr;
 330                        kaddr += exofs_last_byte(dir, n) - reclen;
 331                        while ((char *) de <= kaddr) {
 332                                if (de->rec_len == 0) {
 333                                        EXOFS_ERR("ERROR: zero-length entry in "
 334                                                  "directory(0x%lx)\n",
 335                                                  dir->i_ino);
 336                                        exofs_put_page(page);
 337                                        goto out;
 338                                }
 339                                if (exofs_match(namelen, name, de))
 340                                        goto found;
 341                                de = exofs_next_entry(de);
 342                        }
 343                        exofs_put_page(page);
 344                }
 345                if (++n >= npages)
 346                        n = 0;
 347        } while (n != start);
 348out:
 349        return NULL;
 350
 351found:
 352        *res_page = page;
 353        oi->i_dir_start_lookup = n;
 354        return de;
 355}
 356
 357struct exofs_dir_entry *exofs_dotdot(struct inode *dir, struct page **p)
 358{
 359        struct page *page = exofs_get_page(dir, 0);
 360        struct exofs_dir_entry *de = NULL;
 361
 362        if (!IS_ERR(page)) {
 363                de = exofs_next_entry(
 364                                (struct exofs_dir_entry *)page_address(page));
 365                *p = page;
 366        }
 367        return de;
 368}
 369
 370ino_t exofs_parent_ino(struct dentry *child)
 371{
 372        struct page *page;
 373        struct exofs_dir_entry *de;
 374        ino_t ino;
 375
 376        de = exofs_dotdot(d_inode(child), &page);
 377        if (!de)
 378                return 0;
 379
 380        ino = le64_to_cpu(de->inode_no);
 381        exofs_put_page(page);
 382        return ino;
 383}
 384
 385ino_t exofs_inode_by_name(struct inode *dir, struct dentry *dentry)
 386{
 387        ino_t res = 0;
 388        struct exofs_dir_entry *de;
 389        struct page *page;
 390
 391        de = exofs_find_entry(dir, dentry, &page);
 392        if (de) {
 393                res = le64_to_cpu(de->inode_no);
 394                exofs_put_page(page);
 395        }
 396        return res;
 397}
 398
 399int exofs_set_link(struct inode *dir, struct exofs_dir_entry *de,
 400                        struct page *page, struct inode *inode)
 401{
 402        loff_t pos = page_offset(page) +
 403                        (char *) de - (char *) page_address(page);
 404        unsigned len = le16_to_cpu(de->rec_len);
 405        int err;
 406
 407        lock_page(page);
 408        err = exofs_write_begin(NULL, page->mapping, pos, len,
 409                                AOP_FLAG_UNINTERRUPTIBLE, &page, NULL);
 410        if (err)
 411                EXOFS_ERR("exofs_set_link: exofs_write_begin FAILED => %d\n",
 412                          err);
 413
 414        de->inode_no = cpu_to_le64(inode->i_ino);
 415        exofs_set_de_type(de, inode);
 416        if (likely(!err))
 417                err = exofs_commit_chunk(page, pos, len);
 418        exofs_put_page(page);
 419        dir->i_mtime = dir->i_ctime = CURRENT_TIME;
 420        mark_inode_dirty(dir);
 421        return err;
 422}
 423
 424int exofs_add_link(struct dentry *dentry, struct inode *inode)
 425{
 426        struct inode *dir = d_inode(dentry->d_parent);
 427        const unsigned char *name = dentry->d_name.name;
 428        int namelen = dentry->d_name.len;
 429        unsigned chunk_size = exofs_chunk_size(dir);
 430        unsigned reclen = EXOFS_DIR_REC_LEN(namelen);
 431        unsigned short rec_len, name_len;
 432        struct page *page = NULL;
 433        struct exofs_sb_info *sbi = inode->i_sb->s_fs_info;
 434        struct exofs_dir_entry *de;
 435        unsigned long npages = dir_pages(dir);
 436        unsigned long n;
 437        char *kaddr;
 438        loff_t pos;
 439        int err;
 440
 441        for (n = 0; n <= npages; n++) {
 442                char *dir_end;
 443
 444                page = exofs_get_page(dir, n);
 445                err = PTR_ERR(page);
 446                if (IS_ERR(page))
 447                        goto out;
 448                lock_page(page);
 449                kaddr = page_address(page);
 450                dir_end = kaddr + exofs_last_byte(dir, n);
 451                de = (struct exofs_dir_entry *)kaddr;
 452                kaddr += PAGE_SIZE - reclen;
 453                while ((char *)de <= kaddr) {
 454                        if ((char *)de == dir_end) {
 455                                name_len = 0;
 456                                rec_len = chunk_size;
 457                                de->rec_len = cpu_to_le16(chunk_size);
 458                                de->inode_no = 0;
 459                                goto got_it;
 460                        }
 461                        if (de->rec_len == 0) {
 462                                EXOFS_ERR("ERROR: exofs_add_link: "
 463                                      "zero-length entry in directory(0x%lx)\n",
 464                                      inode->i_ino);
 465                                err = -EIO;
 466                                goto out_unlock;
 467                        }
 468                        err = -EEXIST;
 469                        if (exofs_match(namelen, name, de))
 470                                goto out_unlock;
 471                        name_len = EXOFS_DIR_REC_LEN(de->name_len);
 472                        rec_len = le16_to_cpu(de->rec_len);
 473                        if (!de->inode_no && rec_len >= reclen)
 474                                goto got_it;
 475                        if (rec_len >= name_len + reclen)
 476                                goto got_it;
 477                        de = (struct exofs_dir_entry *) ((char *) de + rec_len);
 478                }
 479                unlock_page(page);
 480                exofs_put_page(page);
 481        }
 482
 483        EXOFS_ERR("exofs_add_link: BAD dentry=%p or inode=0x%lx\n",
 484                  dentry, inode->i_ino);
 485        return -EINVAL;
 486
 487got_it:
 488        pos = page_offset(page) +
 489                (char *)de - (char *)page_address(page);
 490        err = exofs_write_begin(NULL, page->mapping, pos, rec_len, 0,
 491                                                        &page, NULL);
 492        if (err)
 493                goto out_unlock;
 494        if (de->inode_no) {
 495                struct exofs_dir_entry *de1 =
 496                        (struct exofs_dir_entry *)((char *)de + name_len);
 497                de1->rec_len = cpu_to_le16(rec_len - name_len);
 498                de->rec_len = cpu_to_le16(name_len);
 499                de = de1;
 500        }
 501        de->name_len = namelen;
 502        memcpy(de->name, name, namelen);
 503        de->inode_no = cpu_to_le64(inode->i_ino);
 504        exofs_set_de_type(de, inode);
 505        err = exofs_commit_chunk(page, pos, rec_len);
 506        dir->i_mtime = dir->i_ctime = CURRENT_TIME;
 507        mark_inode_dirty(dir);
 508        sbi->s_numfiles++;
 509
 510out_put:
 511        exofs_put_page(page);
 512out:
 513        return err;
 514out_unlock:
 515        unlock_page(page);
 516        goto out_put;
 517}
 518
 519int exofs_delete_entry(struct exofs_dir_entry *dir, struct page *page)
 520{
 521        struct address_space *mapping = page->mapping;
 522        struct inode *inode = mapping->host;
 523        struct exofs_sb_info *sbi = inode->i_sb->s_fs_info;
 524        char *kaddr = page_address(page);
 525        unsigned from = ((char *)dir - kaddr) & ~(exofs_chunk_size(inode)-1);
 526        unsigned to = ((char *)dir - kaddr) + le16_to_cpu(dir->rec_len);
 527        loff_t pos;
 528        struct exofs_dir_entry *pde = NULL;
 529        struct exofs_dir_entry *de = (struct exofs_dir_entry *) (kaddr + from);
 530        int err;
 531
 532        while (de < dir) {
 533                if (de->rec_len == 0) {
 534                        EXOFS_ERR("ERROR: exofs_delete_entry:"
 535                                  "zero-length entry in directory(0x%lx)\n",
 536                                  inode->i_ino);
 537                        err = -EIO;
 538                        goto out;
 539                }
 540                pde = de;
 541                de = exofs_next_entry(de);
 542        }
 543        if (pde)
 544                from = (char *)pde - (char *)page_address(page);
 545        pos = page_offset(page) + from;
 546        lock_page(page);
 547        err = exofs_write_begin(NULL, page->mapping, pos, to - from, 0,
 548                                                        &page, NULL);
 549        if (err)
 550                EXOFS_ERR("exofs_delete_entry: exofs_write_begin FAILED => %d\n",
 551                          err);
 552        if (pde)
 553                pde->rec_len = cpu_to_le16(to - from);
 554        dir->inode_no = 0;
 555        if (likely(!err))
 556                err = exofs_commit_chunk(page, pos, to - from);
 557        inode->i_ctime = inode->i_mtime = CURRENT_TIME;
 558        mark_inode_dirty(inode);
 559        sbi->s_numfiles--;
 560out:
 561        exofs_put_page(page);
 562        return err;
 563}
 564
 565/* kept aligned on 4 bytes */
 566#define THIS_DIR ".\0\0"
 567#define PARENT_DIR "..\0"
 568
 569int exofs_make_empty(struct inode *inode, struct inode *parent)
 570{
 571        struct address_space *mapping = inode->i_mapping;
 572        struct page *page = grab_cache_page(mapping, 0);
 573        unsigned chunk_size = exofs_chunk_size(inode);
 574        struct exofs_dir_entry *de;
 575        int err;
 576        void *kaddr;
 577
 578        if (!page)
 579                return -ENOMEM;
 580
 581        err = exofs_write_begin(NULL, page->mapping, 0, chunk_size, 0,
 582                                                        &page, NULL);
 583        if (err) {
 584                unlock_page(page);
 585                goto fail;
 586        }
 587
 588        kaddr = kmap_atomic(page);
 589        de = (struct exofs_dir_entry *)kaddr;
 590        de->name_len = 1;
 591        de->rec_len = cpu_to_le16(EXOFS_DIR_REC_LEN(1));
 592        memcpy(de->name, THIS_DIR, sizeof(THIS_DIR));
 593        de->inode_no = cpu_to_le64(inode->i_ino);
 594        exofs_set_de_type(de, inode);
 595
 596        de = (struct exofs_dir_entry *)(kaddr + EXOFS_DIR_REC_LEN(1));
 597        de->name_len = 2;
 598        de->rec_len = cpu_to_le16(chunk_size - EXOFS_DIR_REC_LEN(1));
 599        de->inode_no = cpu_to_le64(parent->i_ino);
 600        memcpy(de->name, PARENT_DIR, sizeof(PARENT_DIR));
 601        exofs_set_de_type(de, inode);
 602        kunmap_atomic(kaddr);
 603        err = exofs_commit_chunk(page, 0, chunk_size);
 604fail:
 605        put_page(page);
 606        return err;
 607}
 608
 609int exofs_empty_dir(struct inode *inode)
 610{
 611        struct page *page = NULL;
 612        unsigned long i, npages = dir_pages(inode);
 613
 614        for (i = 0; i < npages; i++) {
 615                char *kaddr;
 616                struct exofs_dir_entry *de;
 617                page = exofs_get_page(inode, i);
 618
 619                if (IS_ERR(page))
 620                        continue;
 621
 622                kaddr = page_address(page);
 623                de = (struct exofs_dir_entry *)kaddr;
 624                kaddr += exofs_last_byte(inode, i) - EXOFS_DIR_REC_LEN(1);
 625
 626                while ((char *)de <= kaddr) {
 627                        if (de->rec_len == 0) {
 628                                EXOFS_ERR("ERROR: exofs_empty_dir: "
 629                                          "zero-length directory entry"
 630                                          "kaddr=%p, de=%p\n", kaddr, de);
 631                                goto not_empty;
 632                        }
 633                        if (de->inode_no != 0) {
 634                                /* check for . and .. */
 635                                if (de->name[0] != '.')
 636                                        goto not_empty;
 637                                if (de->name_len > 2)
 638                                        goto not_empty;
 639                                if (de->name_len < 2) {
 640                                        if (le64_to_cpu(de->inode_no) !=
 641                                            inode->i_ino)
 642                                                goto not_empty;
 643                                } else if (de->name[1] != '.')
 644                                        goto not_empty;
 645                        }
 646                        de = exofs_next_entry(de);
 647                }
 648                exofs_put_page(page);
 649        }
 650        return 1;
 651
 652not_empty:
 653        exofs_put_page(page);
 654        return 0;
 655}
 656
 657const struct file_operations exofs_dir_operations = {
 658        .llseek         = generic_file_llseek,
 659        .read           = generic_read_dir,
 660        .iterate        = exofs_readdir,
 661};
 662