@@ -31,6 +31,7 @@
#include "xfs_inode_item.h"
#include "xfs_trace.h"
#include "xfs_icache.h"
+#include "xfs_dir2_priv.h"
/*
* Note that we only accept fileids which are long enough rather than allow
@@ -240,10 +241,90 @@ xfs_fs_nfs_commit_metadata(
return _xfs_log_force_lsn(mp, lsn, XFS_LOG_SYNC, NULL);
}
+struct getdents_callback {
+ struct dir_context ctx;
+ char *name; /* name that was found. It already points to a
+ buffer NAME_MAX+1 is size */
+ u64 ino; /* the inum we are looking for */
+ int found; /* inode matched? */
+ int sequence; /* sequence counter */
+};
+
+/*
+ * A rather strange filldir function to capture
+ * the name matching the specified inode number.
+ */
+static int filldir_one(void * __buf, const char * name, int len,
+ loff_t pos, u64 ino, unsigned int d_type)
+{
+ struct getdents_callback *buf = __buf;
+ int result = 0;
+
+ buf->sequence++;
+ if (buf->ino == ino && len <= NAME_MAX) {
+ memcpy(buf->name, name, len);
+ buf->name[len] = '\0';
+ buf->found = 1;
+ result = -1;
+ }
+ return result;
+}
+
+STATIC int
+xfs_fs_get_name(
+ struct dentry *parent,
+ char *name,
+ struct dentry *child)
+{
+ struct inode *dir = parent->d_inode;
+ int error;
+ struct xfs_inode *ip = XFS_I(child->d_inode);
+ struct getdents_callback buffer = {
+ .ctx.actor = filldir_one,
+ .name = name,
+ .ino = ip->i_ino
+ };
+ size_t bufsize;
+
+ error = -ENOTDIR;
+ if (!dir || !S_ISDIR(dir->i_mode))
+ goto out;
+
+ /* See comment in fs/xfs/xfs_file.c:xfs_file_readdir */
+ bufsize = (size_t)min_t(loff_t, 32768, ip->i_d.di_size);
+
+ buffer.sequence = 0;
+ while (1) {
+ int old_seq = buffer.sequence;
+
+ error = mutex_lock_killable(&dir->i_mutex);
+ if (error)
+ goto out;
+ if (!IS_DEADDIR(dir))
+ error = -xfs_readdir(ip, &buffer.ctx, bufsize);
+ mutex_unlock(&dir->i_mutex);
+ if (buffer.found) {
+ error = 0;
+ break;
+ }
+
+ if (error)
+ break;
+
+ error = -ENOENT;
+ if (old_seq == buffer.sequence)
+ break;
+ }
+
+out:
+ return error;
+}
+
const struct export_operations xfs_export_operations = {
.encode_fh = xfs_fs_encode_fh,
.fh_to_dentry = xfs_fs_fh_to_dentry,
.fh_to_parent = xfs_fs_fh_to_parent,
.get_parent = xfs_fs_get_parent,
.commit_metadata = xfs_fs_nfs_commit_metadata,
+ .get_name = xfs_fs_get_name
};