static int smb_readdir(struct file *filp, void *dirent, filldir_t filldir) { struct dentry *dentry = filp->f_dentry; struct inode *dir = dentry->d_inode; struct cache_head *cachep = NULL; int result; VERBOSE("reading %s/%s, f_pos=%d\n", DENTRY_PATH(dentry), (int) filp->f_pos); result = 0; switch ((unsigned int) filp->f_pos) { case 0: if (filldir(dirent, ".", 1, 0, dir->i_ino) < 0) goto out; filp->f_pos = 1; case 1: if (filldir(dirent, "..", 2, 1, dentry->d_parent->d_inode->i_ino) < 0) goto out; filp->f_pos = 2; } /* * Make sure our inode is up-to-date. */ result = smb_revalidate_inode(dentry); if (result) goto out; /* * Get the cache pointer ... */ result = -EIO; cachep = smb_get_dircache(dentry); if (!cachep) goto out; /* * Make sure the cache is up-to-date. * * To detect changes on the server we refill on each "new" access. * * Directory mtime would be nice to use for finding changes, * unfortunately some servers (NT4) doesn't update on local changes. */ if (!cachep->valid || filp->f_pos == 2) { result = smb_refill_dircache(cachep, dentry); if (result) goto out; } result = 0; while (1) { struct cache_dirent this_dirent, *entry = &this_dirent; if (!smb_find_in_cache(cachep, filp->f_pos, entry)) break; /* * Check whether to look up the inode number. */ if (!entry->ino) { struct qstr qname; /* N.B. Make cache_dirent name a qstr! */ qname.name = entry->name; qname.len = entry->len; entry->ino = find_inode_number(dentry, &qname); if (!entry->ino) entry->ino = smb_invent_inos(1); } if (filldir(dirent, entry->name, entry->len, filp->f_pos, entry->ino) < 0) break; filp->f_pos += 1; } /* * Release the dircache. */ out: if (cachep) { smb_free_dircache(cachep); } return result; }
static int smb_readdir(struct file *filp, void *dirent, filldir_t filldir) { struct dentry *dentry = filp->f_dentry; struct inode *dir = dentry->d_inode; struct cache_head *cachep; int result; #ifdef SMBFS_DEBUG_VERBOSE printk("smb_readdir: reading %s/%s, f_pos=%d\n", dentry->d_parent->d_name.name, dentry->d_name.name, (int) filp->f_pos); #endif /* * Make sure our inode is up-to-date. */ result = smb_revalidate_inode(dentry); if (result) goto out; /* * Get the cache pointer ... */ result = -EIO; cachep = smb_get_dircache(dentry); if (!cachep) goto out; /* * Make sure the cache is up-to-date. */ if (!cachep->valid) { result = smb_refill_dircache(cachep, dentry); if (result) goto out_free; } result = 0; switch ((unsigned int) filp->f_pos) { case 0: if (filldir(dirent, ".", 1, 0, dir->i_ino) < 0) goto out_free; filp->f_pos = 1; case 1: if (filldir(dirent, "..", 2, 1, dentry->d_parent->d_inode->i_ino) < 0) goto out_free; filp->f_pos = 2; } while (1) { struct cache_dirent this_dirent, *entry = &this_dirent; if (!smb_find_in_cache(cachep, filp->f_pos, entry)) break; /* * Check whether to look up the inode number. */ if (!entry->ino) { struct qstr qname; /* N.B. Make cache_dirent name a qstr! */ qname.name = entry->name; qname.len = entry->len; entry->ino = find_inode_number(dentry, &qname); if (!entry->ino) entry->ino = smb_invent_inos(1); } if (filldir(dirent, entry->name, entry->len, filp->f_pos, entry->ino) < 0) break; filp->f_pos += 1; } /* * Release the dircache. */ out_free: smb_free_dircache(cachep); out: return result; }