.f_ver = 0x0000000000000000 };
EXPORT_SYMBOL(LUSTRE_BFL_FID);
-/** Special fid for ".lustre" directory */
-const struct lu_fid LU_DOT_LUSTRE_FID = { .f_seq = FID_SEQ_DOT_LUSTRE,
- .f_oid = FID_OID_DOT_LUSTRE,
- .f_ver = 0x0000000000000000 };
-EXPORT_SYMBOL(LU_DOT_LUSTRE_FID);
-
-/** Special fid for "fid" special object in .lustre */
-const struct lu_fid LU_OBF_FID = { .f_seq = FID_SEQ_DOT_LUSTRE,
- .f_oid = FID_OID_DOT_LUSTRE_OBF,
- .f_ver = 0x0000000000000000 };
-EXPORT_SYMBOL(LU_OBF_FID);
-
/** Special fid for "lost+found" special object in .lustre */
const struct lu_fid LU_LPF_FID = { .f_seq = FID_SEQ_DOT_LUSTRE,
.f_oid = FID_OID_DOT_LUSTRE_LPF,
extern const struct lu_seq_range LUSTRE_SEQ_SPACE_RANGE;
extern const struct lu_seq_range LUSTRE_SEQ_ZERO_RANGE;
extern const struct lu_fid LUSTRE_BFL_FID;
-extern const struct lu_fid LU_OBF_FID;
extern const struct lu_fid LU_LPF_FID;
-extern const struct lu_fid LU_DOT_LUSTRE_FID;
extern const struct lu_fid LU_BACKEND_LPF_FID;
enum {
* the root FID will still be IGIF */
static inline int fid_is_root(const struct lu_fid *fid)
{
- return unlikely((fid_seq(fid) == FID_SEQ_ROOT &&
- fid_oid(fid) == FID_OID_ROOT));
+ return unlikely(lu_fid_eq(fid, &LU_ROOT_FID));
}
static inline int fid_is_dot_lustre(const struct lu_fid *fid)
{
- return unlikely(fid_seq(fid) == FID_SEQ_DOT_LUSTRE &&
- fid_oid(fid) == FID_OID_DOT_LUSTRE);
+ return unlikely(lu_fid_eq(fid, &LU_DOT_LUSTRE_FID));
}
static inline int fid_is_obf(const struct lu_fid *fid)
{
- return unlikely(fid_seq(fid) == FID_SEQ_DOT_LUSTRE &&
- fid_oid(fid) == FID_OID_DOT_LUSTRE_OBF);
+ return unlikely(lu_fid_eq(fid, &LU_OBF_FID));
}
static inline int fid_is_otable_it(const struct lu_fid *fid)
#include <linux/types.h>
#include <linux/lustre/lustre_idl.h>
+/** Special fid for root directory */
+static const struct lu_fid LU_ROOT_FID = {
+ .f_seq = FID_SEQ_ROOT,
+ .f_oid = FID_OID_ROOT,
+ .f_ver = 0x0000000000000000
+};
+
+/** Special fid for ".lustre" directory */
+static const struct lu_fid LU_DOT_LUSTRE_FID = {
+ .f_seq = FID_SEQ_DOT_LUSTRE,
+ .f_oid = FID_OID_DOT_LUSTRE,
+ .f_ver = 0x0000000000000000
+};
+
+/** Special fid for "fid" special object in .lustre */
+static const struct lu_fid LU_OBF_FID = {
+ .f_seq = FID_SEQ_DOT_LUSTRE,
+ .f_oid = FID_OID_DOT_LUSTRE_OBF,
+ .f_ver = 0x0000000000000000
+};
+
/** returns fid object sequence */
static inline __u64 fid_seq(const struct lu_fid *fid)
{
*/
#define DEBUG_SUBSYSTEM S_LLITE
-#include "llite_internal.h"
#include <linux/exportfs.h>
+#include <lustre_fid.h>
+#include "llite_internal.h"
+
u32 get_uuid2int(const char *name, int len)
{
u32 key0 = 0x12a3fe2d, key1 = 0x37abe8f9;
static struct dentry *
ll_iget_for_nfs(struct super_block *sb, struct lu_fid *fid, struct lu_fid *parent)
{
- struct inode *inode;
+ bool is_dot_lustre = fid_is_dot_lustre(fid);
struct dentry *result;
+ struct inode *inode;
ENTRY;
-
if (!fid_is_sane(fid))
RETURN(ERR_PTR(-ESTALE));
CDEBUG(D_INFO, "Get dentry for fid: "DFID"\n", PFID(fid));
+ if (fid_is_root(fid))
+ RETURN(dget(sb->s_root));
+
inode = search_inode_for_lustre(sb, fid);
if (IS_ERR(inode))
RETURN(ERR_CAST(inode));
RETURN(ERR_PTR(-ESTALE));
}
+ /* Both LU_DOT_LUSTRE_FID and LU_OBF_FID are special fids that
+ * don't match to a real searchable file, so they need special
+ * handling.
+ */
+ if (is_dot_lustre || fid_is_obf(fid)) {
+ struct qstr dot_name = QSTR_INIT(".lustre",
+ strlen(".lustre"));
+ struct dentry *dot, *obf;
+
+ inode_lock(d_inode(sb->s_root));
+ dot = d_lookup(sb->s_root, &dot_name);
+ if (!dot) {
+ struct inode *tmp = inode;
+
+ dot = d_alloc(sb->s_root, &dot_name);
+ if (!dot) {
+ inode_unlock(d_inode(sb->s_root));
+ iput(inode);
+ RETURN(ERR_PTR(-ENOMEM));
+ }
+
+ if (!ll_d_setup(dot, true)) {
+ inode_unlock(d_inode(sb->s_root));
+ obf = ERR_PTR(-ENOMEM);
+ goto free_dot;
+ }
+
+ /* We are requesting OBF fid then locate inode of
+ * .lustre FID
+ */
+ if (!is_dot_lustre) {
+ tmp = search_inode_for_lustre(sb,
+ &LU_DOT_LUSTRE_FID);
+ if (IS_ERR(tmp)) {
+ inode_unlock(d_inode(sb->s_root));
+ obf = ERR_CAST(tmp);
+ goto free_dot;
+ }
+ }
+ /* Successfully add .lustre dentry to dcache. For future
+ * failures for the obf case we don't need to iput the
+ * .lustre inode.
+ */
+ d_add(dot, tmp);
+ }
+ inode_unlock(d_inode(sb->s_root));
+
+ if (!is_dot_lustre) {
+ struct qstr obf_name = QSTR_INIT("fid", strlen("fid"));
+
+ inode_lock(d_inode(dot));
+ obf = d_lookup(dot, &obf_name);
+ if (!obf) {
+ obf = d_alloc(dot, &obf_name);
+ if (!obf) {
+ inode_unlock(d_inode(dot));
+ obf = ERR_PTR(-ENOMEM);
+ goto free_dot;
+ }
+
+ if (!ll_d_setup(obf, true)) {
+ dput(obf);
+ inode_unlock(d_inode(dot));
+ obf = ERR_PTR(-ENOMEM);
+ goto free_dot;
+ }
+ d_add(obf, inode);
+ }
+ inode_unlock(d_inode(dot));
+free_dot:
+ if (IS_ERR(obf))
+ iput(inode);
+ dput(dot);
+ result = obf;
+ } else {
+ result = dot;
+ }
+ RETURN(result);
+ }
+
/* N.B. d_obtain_alias() drops inode ref on error */
result = d_obtain_alias(inode);
if (IS_ERR(result))
#include <time.h>
#include <lustre/lustreapi.h>
-#include <linux/lustre/lustre_idl.h>
+#include <linux/lustre/lustre_fid.h>
#define ERROR(fmt, ...) \
fprintf(stderr, "%s: %s:%d: %s: " fmt "\n", \
}
}
+/* Test special FIDs for lustre */
+static void test31(void)
+{
+ int fd;
+
+ fd = llapi_open_by_fid(mainpath, &LU_ROOT_FID, O_RDONLY);
+ ASSERTF(fd >= 0, "llapi_open_by_fid for " DFID_NOBRACE ": %s",
+ PFID(&LU_ROOT_FID), strerror(errno));
+
+ fd = llapi_open_by_fid(mainpath, &LU_DOT_LUSTRE_FID, O_RDONLY);
+ ASSERTF(fd >= 0, "llapi_open_by_fid for " DFID_NOBRACE ": %s",
+ PFID(&LU_DOT_LUSTRE_FID), strerror(errno));
+
+ fd = llapi_open_by_fid(mainpath, &LU_OBF_FID, O_RDONLY);
+ ASSERTF(fd >= 0, "llapi_open_by_fid for " DFID_NOBRACE ": %s",
+ PFID(&LU_OBF_FID), strerror(errno));
+}
+
/* Test llapi_fd2parent/llapi_path2parent on mainpath (whatever its
* type). mainpath must exist. */
static void help_test40(void)
PERFORM(test12);
PERFORM(test20);
PERFORM(test30);
+ PERFORM(test31);
PERFORM(test40);
PERFORM(test41);
PERFORM(test42);