@@ -187,12 +187,12 @@ cifs_read_super(struct super_block *sb, void *data,
else
sb->s_d_op = &cifs_dentry_ops;
-#ifdef CIFS_NFSD_EXPORT
+#ifdef CONFIG_CIFS_NFSD_EXPORT
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) {
cFYI(1, "export ops supported");
sb->s_export_op = &cifs_export_ops;
}
-#endif /* CIFS_NFSD_EXPORT */
+#endif /* CONFIG_CIFS_NFSD_EXPORT */
return 0;
@@ -123,9 +123,9 @@ extern ssize_t cifs_getxattr(struct dentry *, const char *, void *, size_t);
extern ssize_t cifs_listxattr(struct dentry *, char *, size_t);
extern long cifs_ioctl(struct file *filep, unsigned int cmd, unsigned long arg);
-#ifdef CIFS_NFSD_EXPORT
+#ifdef CONFIG_CIFS_NFSD_EXPORT
extern const struct export_operations cifs_export_ops;
-#endif /* CIFS_NFSD_EXPORT */
+#endif /* CONFIG_CIFS_NFSD_EXPORT */
#define CIFS_VERSION "1.71"
#endif /* _CIFSFS_H */
@@ -672,6 +672,11 @@ static inline void free_dfs_info_array(struct dfs_info3_param *param,
kfree(param);
}
+struct cifs_fid {
+ u64 cino;
+ u64 cpino;
+};
+
#define MID_FREE 0
#define MID_REQUEST_ALLOCATED 1
#define MID_REQUEST_SUBMITTED 2
@@ -432,6 +432,8 @@ extern int mdfour(unsigned char *, unsigned char *, int);
extern int E_md4hash(const unsigned char *passwd, unsigned char *p16);
extern void SMBencrypt(unsigned char *passwd, const unsigned char *c8,
unsigned char *p24);
+extern int cifs_find_inode_id(struct inode *, void *);
+extern int cifs_init_inode(struct inode *, void *);
extern void E_P16(unsigned char *p14, unsigned char *p16);
extern void E_P24(unsigned char *p21, const unsigned char *c8,
unsigned char *p24);
@@ -491,6 +491,7 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry,
struct inode *newInode = NULL;
char *full_path = NULL;
struct file *filp;
+ struct dentry *spdirentry = NULL;
xid = GetXid();
@@ -586,7 +587,9 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry,
parent_dir_inode->i_sb, xid, NULL);
if ((rc == 0) && (newInode != NULL)) {
- d_add(direntry, newInode);
+ spdirentry = d_splice_alias(newInode, direntry);
+ if (spdirentry)
+ return spdirentry;
if (posix_open) {
filp = lookup_instantiate_filp(nd, direntry,
generic_file_open);
@@ -631,7 +634,7 @@ lookup_out:
static int
cifs_d_revalidate(struct dentry *direntry, struct nameidata *nd)
{
- if (nd->flags & LOOKUP_RCU)
+ if (nd && nd->flags & LOOKUP_RCU)
return -ECHILD;
if (direntry->d_inode) {
@@ -642,18 +645,11 @@ cifs_d_revalidate(struct dentry *direntry, struct nameidata *nd)
}
/*
- * This may be nfsd (or something), anyway, we can't see the
- * intent of this. So, since this can be for creation, drop it.
- */
- if (!nd)
- return 0;
-
- /*
* Drop the negative dentry, in order to make sure to use the
* case sensitive name which is specified by user if this is
* for creation.
*/
- if (!(nd->flags & (LOOKUP_CONTINUE | LOOKUP_PARENT))) {
+ if (nd && !(nd->flags & (LOOKUP_CONTINUE | LOOKUP_PARENT))) {
if (nd->flags & (LOOKUP_CREATE | LOOKUP_RENAME_TARGET))
return 0;
}
@@ -44,24 +44,52 @@
#include "cifsglob.h"
#include "cifs_debug.h"
#include "cifsfs.h"
+#include "cifsproto.h"
-#ifdef CIFS_NFSD_EXPORT
-static struct dentry *cifs_get_parent(struct dentry *dentry)
+#ifdef CONFIG_CIFS_NFSD_EXPORT
+static int cifs_encode_fh(struct dentry *dentry, __u32 *fh, int *lenp,
+ int connectable)
{
- /* BB need to add code here eventually to enable export via NFSD */
- cFYI(1, "get parent for %p", dentry);
- return ERR_PTR(-EACCES);
+ struct cifs_fid *cfid = (struct cifs_fid *)fh;
+ struct inode *inode = dentry->d_inode;
+
+ cfid->cino = inode->i_ino;
+
+ /*
+ * There is not a type to send ino32_gen32_parentino32_gen32 to
+ * accomodate two 64 bit inode numbers. So always return this type.
+ */
+ return FILEID_INO32_GEN;
}
-const struct export_operations cifs_export_ops = {
- .get_parent = cifs_get_parent,
-/* Following five export operations are unneeded so far and can default:
- .get_dentry =
- .get_name =
- .find_exported_dentry =
- .decode_fh =
- .encode_fs = */
-};
+static struct dentry *
+cifs_fh_to_dentry(struct super_block *sb, struct fid *fh,
+ int fh_len, int fh_type)
+{
+ struct cifs_fid *cfid = (struct cifs_fid *)fh;
+ struct inode *inode = NULL;
+ struct cifs_fattr fattr;
+
-#endif /* CIFS_NFSD_EXPORT */
+ if (fh_type != FILEID_INO32_GEN && fh_type != FILEID_INO32_GEN_PARENT) {
+ cERROR(1, "%s: Can't handle fh type: %d", __func__, fh_type);
+ return ERR_PTR(-EINVAL);
+ }
+ if (!cfid->cino)
+ return ERR_PTR(-ESTALE);
+
+ fattr.cf_uniqueid = cfid->cino;
+ inode = iget5_locked(sb, cfid->cino, cifs_find_inode_id,
+ cifs_init_inode, &fattr);
+ if (IS_ERR(inode))
+ return ERR_CAST(inode);
+
+ return d_obtain_alias(inode);
+}
+
+const struct export_operations cifs_export_ops = {
+ .encode_fh = cifs_encode_fh,
+ .fh_to_dentry = cifs_fh_to_dentry
+};
+#endif /* CONFIG_CIFS_NFSD_EXPORT */
@@ -777,6 +777,19 @@ char *cifs_build_path_to_root(struct cifs_sb_info *cifs_sb,
return full_path;
}
+int
+cifs_find_inode_id(struct inode *inode, void *opaque)
+{
+ int rc = 0;
+ struct cifs_fattr *fattr = (struct cifs_fattr *) opaque;
+
+ /* match inode with uniqueid */
+ if (CIFS_I(inode)->uniqueid == fattr->cf_uniqueid)
+ rc = 1;
+
+ return rc;
+}
+
static int
cifs_find_inode(struct inode *inode, void *opaque)
{
@@ -801,7 +814,7 @@ cifs_find_inode(struct inode *inode, void *opaque)
return 1;
}
-static int
+int
cifs_init_inode(struct inode *inode, void *opaque)
{
struct cifs_fattr *fattr = (struct cifs_fattr *) opaque;