All of lore.kernel.org
 help / color / mirror / Atom feed
From: Richard Weinberger <richard@nod.at>
To: linux-mtd@lists.infradead.org
Cc: david@sigma-star.at, tytso@mit.edu, dedekind1@gmail.com,
	adrian.hunter@intel.com, linux-kernel@vger.kernel.org,
	linux-fsdevel@vger.kernel.org, adilger.kernel@dilger.ca,
	akpm@linux-foundation.org, linux-ext4@vger.kernel.org,
	Richard Weinberger <richard@nod.at>
Subject: [PATCH 3/6] ubifs: Use 64bit readdir cookies
Date: Thu,  1 Dec 2016 23:02:18 +0100	[thread overview]
Message-ID: <1480629741-18375-4-git-send-email-richard@nod.at> (raw)
In-Reply-To: <1480629741-18375-1-git-send-email-richard@nod.at>

This is the first step to support proper telldir/seekdir()
in UBIFS.
Let's report 64bit cookies in readdir(). The cookie is a combination
of the entry key plus the double hash value.

Signed-off-by: Richard Weinberger <richard@nod.at>
---
 fs/ubifs/dir.c   | 46 +++++++++++++++++++++++++++++++------------
 fs/ubifs/key.h   | 59 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 fs/ubifs/ubifs.h |  1 +
 3 files changed, 94 insertions(+), 12 deletions(-)

diff --git a/fs/ubifs/dir.c b/fs/ubifs/dir.c
index 883b2fdf51df..3b8c08dad75b 100644
--- a/fs/ubifs/dir.c
+++ b/fs/ubifs/dir.c
@@ -539,7 +539,7 @@ static int ubifs_readdir(struct file *file, struct dir_context *ctx)
 
 	dbg_gen("dir ino %lu, f_pos %#llx", dir->i_ino, ctx->pos);
 
-	if (ctx->pos > UBIFS_S_KEY_HASH_MASK || ctx->pos == 2)
+	if (ctx->pos == 2)
 		/*
 		 * The directory was seek'ed to a senseless position or there
 		 * are no more entries.
@@ -594,7 +594,7 @@ static int ubifs_readdir(struct file *file, struct dir_context *ctx)
 			goto out;
 		}
 
-		ctx->pos = key_hash_flash(c, &dent->key);
+		ctx->pos = key_get_dir_pos(c, file, dent);
 		file->private_data = dent;
 	}
 
@@ -604,21 +604,43 @@ static int ubifs_readdir(struct file *file, struct dir_context *ctx)
 		 * The directory was seek'ed to and is now readdir'ed.
 		 * Find the entry corresponding to @ctx->pos or the closest one.
 		 */
-		dent_key_init_hash(c, &key, dir->i_ino, ctx->pos);
-		fname_len(&nm) = 0;
-		dent = ubifs_tnc_next_ent(c, &key, &nm);
-		if (IS_ERR(dent)) {
-			err = PTR_ERR(dent);
-			goto out;
+		dent_key_init_hash(c, &key, dir->i_ino,
+				   key_get_hash_from_dir_pos(c, file, ctx->pos));
+
+		if (key_want_short_hash(file)) {
+			err = -ENOENT;
+		} else {
+			dent = kmalloc(UBIFS_MAX_DENT_NODE_SZ, GFP_NOFS);
+			if (!dent) {
+				err = -ENOMEM;
+				goto out;
+			}
+
+			err = ubifs_tnc_lookup_dh(c, &key, dent,
+				key_get_cookie_from_dir_pos(c, ctx->pos));
+		}
+		if (err) {
+			kfree(dent);
+
+			if (err < 0 && err != -ENOENT && err != -EOPNOTSUPP)
+				goto out;
+
+			fname_len(&nm) = 0;
+			dent = ubifs_tnc_next_ent(c, &key, &nm);
+			if (IS_ERR(dent)) {
+				err = PTR_ERR(dent);
+				goto out;
+			}
 		}
-		ctx->pos = key_hash_flash(c, &dent->key);
+
+		ctx->pos = key_get_dir_pos(c, file, dent);
 		file->private_data = dent;
 	}
 
 	while (1) {
-		dbg_gen("feed '%s', ino %llu, new f_pos %#x",
+		dbg_gen("feed '%s', ino %llu, new f_pos %#lx",
 			dent->name, (unsigned long long)le64_to_cpu(dent->inum),
-			key_hash_flash(c, &dent->key));
+			(unsigned long)key_get_dir_pos(c, file, dent));
 		ubifs_assert(le64_to_cpu(dent->ch.sqnum) >
 			     ubifs_inode(dir)->creat_sqnum);
 
@@ -656,7 +678,7 @@ static int ubifs_readdir(struct file *file, struct dir_context *ctx)
 		}
 
 		kfree(file->private_data);
-		ctx->pos = key_hash_flash(c, &dent->key);
+		ctx->pos = key_get_dir_pos(c, file, dent);
 		file->private_data = dent;
 		cond_resched();
 	}
diff --git a/fs/ubifs/key.h b/fs/ubifs/key.h
index 7547be512db2..2788e36ce832 100644
--- a/fs/ubifs/key.h
+++ b/fs/ubifs/key.h
@@ -397,6 +397,65 @@ static inline uint32_t key_hash_flash(const struct ubifs_info *c, const void *k)
 }
 
 /**
+ * key_want_short_hash - tests whether we can emit a 64bit hash or not.
+ * @file: the file handle of the directory
+ */
+static inline bool key_want_short_hash(struct file *file)
+{
+	if (file->f_mode & FMODE_32BITHASH)
+		return true;
+
+	if (!(file->f_mode & FMODE_64BITHASH) && is_32bit_api())
+		return true;
+
+	return false;
+}
+
+/**
+ * key_dir_pos - compute a 64bit directory cookie for readdir()
+ * @c: UBIFS file-system description object
+ * @file: the file handle of the directory
+ * @dent: the directory entry
+ */
+static inline loff_t key_get_dir_pos(const struct ubifs_info *c,
+				     struct file *file,
+				     struct ubifs_dent_node *dent)
+{
+	BUILD_BUG_ON(sizeof(loff_t) < 8);
+
+	if (key_want_short_hash(file))
+		return key_hash_flash(c, &dent->key);
+
+	return ((loff_t)key_hash_flash(c, &dent->key)) << UBIFS_DH_BITS | le32_to_cpu(dent->cookie);
+}
+
+/**
+ * key_get_hash_from_dir_pos - extracts the flash key from a directory offset.
+ * @c: UBIFS file-system description object
+ * @file: the file handle of the directory
+ * @pos: the directory offset provied by VFS
+ */
+static inline uint32_t key_get_hash_from_dir_pos(const struct ubifs_info *c,
+						 struct file *file, loff_t pos)
+{
+	if (key_want_short_hash(file))
+		return pos & UBIFS_S_KEY_HASH_MASK;
+
+	return (pos >> UBIFS_DH_BITS) & UBIFS_S_KEY_HASH_MASK;
+}
+
+/**
+ * key_get_cookie_from_dir_pos - extracts the double hash cookie from a directory offset.
+ * @c: UBIFS file-system description object
+ * @pos: the directory offset provied by VFS
+ */
+static inline uint32_t key_get_cookie_from_dir_pos(const struct ubifs_info *c,
+						   loff_t pos)
+{
+	return pos & UBIFS_DH_MASK;
+}
+
+/**
  * key_block - get data block number.
  * @c: UBIFS file-system description object
  * @key: the key to get the block number from
diff --git a/fs/ubifs/ubifs.h b/fs/ubifs/ubifs.h
index 12f3df3ced0e..0532a6f82b1d 100644
--- a/fs/ubifs/ubifs.h
+++ b/fs/ubifs/ubifs.h
@@ -40,6 +40,7 @@
 #include <linux/xattr.h>
 #include <linux/fscrypto.h>
 #include <linux/random.h>
+#include <linux/compat.h>
 #include "ubifs-media.h"
 
 /* Version of this UBIFS implementation */
-- 
2.7.3

  parent reply	other threads:[~2016-12-01 22:02 UTC|newest]

Thread overview: 28+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-12-01 22:02 [PATCH 0/6] UBIFS NFS export support Richard Weinberger
2016-12-01 22:02 ` [PATCH 1/6] ext4: Move is_32bit_api() to generic code Richard Weinberger
2016-12-12 22:18   ` Richard Weinberger
2016-12-12 22:29   ` Andreas Dilger
2016-12-01 22:02 ` [PATCH 2/6] ubifs: Provide a custom llseek for directories Richard Weinberger
2016-12-01 22:02   ` Richard Weinberger
2016-12-01 22:02 ` Richard Weinberger [this message]
2016-12-29  2:58   ` [PATCH 3/6] ubifs: Use 64bit readdir cookies J. Bruce Fields
2016-12-29  9:19     ` Richard Weinberger
2016-12-29 15:34       ` J. Bruce Fields
2016-12-29 15:49         ` Richard Weinberger
2016-12-29 16:15           ` J. Bruce Fields
2016-12-29 16:15             ` J. Bruce Fields
2016-12-29 16:36             ` Richard Weinberger
2016-12-29 16:59               ` J. Bruce Fields
2016-12-29 17:05                 ` Richard Weinberger
2016-12-29 17:05                   ` Richard Weinberger
2017-01-03 19:52                   ` J. Bruce Fields
2016-12-01 22:02 ` [PATCH 4/6] ubifs: Maintain a parent pointer Richard Weinberger
2016-12-02  9:28   ` Marcus Folkesson
2016-12-02 10:36     ` Richard Weinberger
2017-04-28  8:31   ` Hyunchul Lee
2017-04-28  9:09     ` Richard Weinberger
2016-12-01 22:02 ` [PATCH 5/6] ubifs: Implement export_operations Richard Weinberger
2016-12-01 22:02 ` [PATCH 6/6] ubifs: Wire up NFS support Richard Weinberger
2016-12-29  2:56   ` J. Bruce Fields
2016-12-29  8:48     ` Richard Weinberger
2017-05-21 20:20 [PATCH 0/6] UBIFS NFS export support v2 Richard Weinberger
2017-05-21 20:20 ` [PATCH 3/6] ubifs: Use 64bit readdir cookies Richard Weinberger

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1480629741-18375-4-git-send-email-richard@nod.at \
    --to=richard@nod.at \
    --cc=adilger.kernel@dilger.ca \
    --cc=adrian.hunter@intel.com \
    --cc=akpm@linux-foundation.org \
    --cc=david@sigma-star.at \
    --cc=dedekind1@gmail.com \
    --cc=linux-ext4@vger.kernel.org \
    --cc=linux-fsdevel@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-mtd@lists.infradead.org \
    --cc=tytso@mit.edu \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.