diff options
Diffstat (limited to 'fs/logfs/dir.c')
| -rw-r--r-- | fs/logfs/dir.c | 104 |
1 files changed, 37 insertions, 67 deletions
diff --git a/fs/logfs/dir.c b/fs/logfs/dir.c index 409dfd65e9a..6bdc347008f 100644 --- a/fs/logfs/dir.c +++ b/fs/logfs/dir.c @@ -71,7 +71,7 @@ static int write_dir(struct inode *dir, struct logfs_disk_dentry *dd, static int write_inode(struct inode *inode) { - return __logfs_write_inode(inode, WF_LOCK); + return __logfs_write_inode(inode, NULL, WF_LOCK); } static s64 dir_seek_data(struct inode *inode, s64 pos) @@ -92,7 +92,7 @@ static int beyond_eof(struct inode *inode, loff_t bix) * so short names (len <= 9) don't even occupy the complete 32bit name * space. A prime >256 ensures short names quickly spread the 32bit * name space. Add about 26 for the estimated amount of information - * of each character and pick a prime nearby, preferrably a bit-sparse + * of each character and pick a prime nearby, preferably a bit-sparse * one. */ static u32 hash_32(const char *s, int len, u32 seed) @@ -177,17 +177,17 @@ static struct page *logfs_get_dd_page(struct inode *dir, struct dentry *dentry) (filler_t *)logfs_readpage, NULL); if (IS_ERR(page)) return page; - dd = kmap_atomic(page, KM_USER0); + dd = kmap_atomic(page); BUG_ON(dd->namelen == 0); if (name->len != be16_to_cpu(dd->namelen) || memcmp(name->name, dd->name, name->len)) { - kunmap_atomic(dd, KM_USER0); + kunmap_atomic(dd); page_cache_release(page); continue; } - kunmap_atomic(dd, KM_USER0); + kunmap_atomic(dd); return page; } return NULL; @@ -197,7 +197,7 @@ static int logfs_remove_inode(struct inode *inode) { int ret; - inode->i_nlink--; + drop_nlink(inode); ret = write_inode(inode); LOGFS_BUG_ON(ret, inode->i_sb); return ret; @@ -281,17 +281,23 @@ static int logfs_rmdir(struct inode *dir, struct dentry *dentry) /* FIXME: readdir currently has it's own dir_walk code. I don't see a good * way to combine the two copies */ -#define IMPLICIT_NODES 2 -static int __logfs_readdir(struct file *file, void *buf, filldir_t filldir) +static int logfs_readdir(struct file *file, struct dir_context *ctx) { - struct inode *dir = file->f_dentry->d_inode; - loff_t pos = file->f_pos - IMPLICIT_NODES; + struct inode *dir = file_inode(file); + loff_t pos; struct page *page; struct logfs_disk_dentry *dd; - int full; + if (ctx->pos < 0) + return -EINVAL; + + if (!dir_emit_dots(file, ctx)) + return 0; + + pos = ctx->pos - 2; BUG_ON(pos < 0); - for (;; pos++) { + for (;; pos++, ctx->pos++) { + bool full; if (beyond_eof(dir, pos)) break; if (!logfs_exist_block(dir, pos)) { @@ -306,42 +312,17 @@ static int __logfs_readdir(struct file *file, void *buf, filldir_t filldir) dd = kmap(page); BUG_ON(dd->namelen == 0); - full = filldir(buf, (char *)dd->name, be16_to_cpu(dd->namelen), - pos, be64_to_cpu(dd->ino), dd->type); + full = !dir_emit(ctx, (char *)dd->name, + be16_to_cpu(dd->namelen), + be64_to_cpu(dd->ino), dd->type); kunmap(page); page_cache_release(page); if (full) break; } - - file->f_pos = pos + IMPLICIT_NODES; return 0; } -static int logfs_readdir(struct file *file, void *buf, filldir_t filldir) -{ - struct inode *inode = file->f_dentry->d_inode; - ino_t pino = parent_ino(file->f_dentry); - int err; - - if (file->f_pos < 0) - return -EINVAL; - - if (file->f_pos == 0) { - if (filldir(buf, ".", 1, 1, inode->i_ino, DT_DIR) < 0) - return 0; - file->f_pos++; - } - if (file->f_pos == 1) { - if (filldir(buf, "..", 2, 2, pino, DT_DIR) < 0) - return 0; - file->f_pos++; - } - - err = __logfs_readdir(file, buf, filldir); - return err; -} - static void logfs_set_name(struct logfs_disk_dentry *dd, struct qstr *name) { dd->namelen = cpu_to_be16(name->len); @@ -349,7 +330,7 @@ static void logfs_set_name(struct logfs_disk_dentry *dd, struct qstr *name) } static struct dentry *logfs_lookup(struct inode *dir, struct dentry *dentry, - struct nameidata *nd) + unsigned int flags) { struct page *page; struct logfs_disk_dentry *dd; @@ -365,17 +346,15 @@ static struct dentry *logfs_lookup(struct inode *dir, struct dentry *dentry, return NULL; } index = page->index; - dd = kmap_atomic(page, KM_USER0); + dd = kmap_atomic(page); ino = be64_to_cpu(dd->ino); - kunmap_atomic(dd, KM_USER0); + kunmap_atomic(dd); page_cache_release(page); inode = logfs_iget(dir->i_sb, ino); - if (IS_ERR(inode)) { + if (IS_ERR(inode)) printk(KERN_ERR"LogFS: Cannot read inode #%llx for dentry (%lx, %lx)n", ino, dir->i_ino, index); - return ERR_CAST(inode); - } return d_splice_alias(inode, dentry); } @@ -404,12 +383,12 @@ static int logfs_write_dir(struct inode *dir, struct dentry *dentry, if (!page) return -ENOMEM; - dd = kmap_atomic(page, KM_USER0); + dd = kmap_atomic(page); memset(dd, 0, sizeof(*dd)); dd->ino = cpu_to_be64(inode->i_ino); dd->type = logfs_type(inode); logfs_set_name(dd, &dentry->d_name); - kunmap_atomic(dd, KM_USER0); + kunmap_atomic(dd); err = logfs_write_buf(dir, page, WF_LOCK); unlock_page(page); @@ -435,7 +414,7 @@ static int __logfs_create(struct inode *dir, struct dentry *dentry, ta = kzalloc(sizeof(*ta), GFP_KERNEL); if (!ta) { - inode->i_nlink--; + drop_nlink(inode); iput(inode); return -ENOMEM; } @@ -458,7 +437,7 @@ static int __logfs_create(struct inode *dir, struct dentry *dentry, abort_transaction(inode, ta); li->li_flags |= LOGFS_IF_STILLBORN; /* FIXME: truncate symlink */ - inode->i_nlink--; + drop_nlink(inode); iput(inode); goto out; } @@ -484,7 +463,7 @@ out: return ret; } -static int logfs_mkdir(struct inode *dir, struct dentry *dentry, int mode) +static int logfs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode) { struct inode *inode; @@ -503,8 +482,8 @@ static int logfs_mkdir(struct inode *dir, struct dentry *dentry, int mode) return __logfs_create(dir, dentry, inode, NULL, 0); } -static int logfs_create(struct inode *dir, struct dentry *dentry, int mode, - struct nameidata *nd) +static int logfs_create(struct inode *dir, struct dentry *dentry, umode_t mode, + bool excl) { struct inode *inode; @@ -519,7 +498,7 @@ static int logfs_create(struct inode *dir, struct dentry *dentry, int mode, return __logfs_create(dir, dentry, inode, NULL, 0); } -static int logfs_mknod(struct inode *dir, struct dentry *dentry, int mode, +static int logfs_mknod(struct inode *dir, struct dentry *dentry, umode_t mode, dev_t rdev) { struct inode *inode; @@ -555,22 +534,14 @@ static int logfs_symlink(struct inode *dir, struct dentry *dentry, return __logfs_create(dir, dentry, inode, target, destlen); } -static int logfs_permission(struct inode *inode, int mask) -{ - return generic_permission(inode, mask, NULL); -} - static int logfs_link(struct dentry *old_dentry, struct inode *dir, struct dentry *dentry) { struct inode *inode = old_dentry->d_inode; - if (inode->i_nlink >= LOGFS_LINK_MAX) - return -EMLINK; - inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME; ihold(inode); - inode->i_nlink++; + inc_nlink(inode); mark_inode_dirty_sync(inode); return __logfs_create(dir, dentry, inode, NULL, 0); @@ -586,9 +557,9 @@ static int logfs_get_dd(struct inode *dir, struct dentry *dentry, if (IS_ERR(page)) return PTR_ERR(page); *pos = page->index; - map = kmap_atomic(page, KM_USER0); + map = kmap_atomic(page); memcpy(dd, map, sizeof(*dd)); - kunmap_atomic(map, KM_USER0); + kunmap_atomic(map); page_cache_release(page); return 0; } @@ -818,14 +789,13 @@ const struct inode_operations logfs_dir_iops = { .mknod = logfs_mknod, .rename = logfs_rename, .rmdir = logfs_rmdir, - .permission = logfs_permission, .symlink = logfs_symlink, .unlink = logfs_unlink, }; const struct file_operations logfs_dir_fops = { .fsync = logfs_fsync, .unlocked_ioctl = logfs_ioctl, - .readdir = logfs_readdir, + .iterate = logfs_readdir, .read = generic_read_dir, .llseek = default_llseek, }; |
