From patchwork Mon Feb 28 21:52:41 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Shirish Pargaonkar X-Patchwork-Id: 597521 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by demeter1.kernel.org (8.14.4/8.14.3) with ESMTP id p1SLp64Y006061 for ; Mon, 28 Feb 2011 21:51:07 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752657Ab1B1VvF (ORCPT ); Mon, 28 Feb 2011 16:51:05 -0500 Received: from mail-vx0-f174.google.com ([209.85.220.174]:58996 "EHLO mail-vx0-f174.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752537Ab1B1VvE (ORCPT ); Mon, 28 Feb 2011 16:51:04 -0500 Received: by vxi39 with SMTP id 39so3590902vxi.19 for ; Mon, 28 Feb 2011 13:51:03 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; h=domainkey-signature:from:to:cc:subject:date:message-id:x-mailer; bh=hGZKAMfNDJXw1FeqGOfeKAlL1Tl3VGKUwNWGpW6DFlQ=; b=DVnSOzixnqOaGQIZHCd5h+2K7P0JhMg6w7mzgy/Wv1wDeVVXwSID59JKy7JMYc9EJL LURnXs3gH+b59LewlyR8CFNK7smHd9cI1Ejhpo43Z2/aHi6T6WDrGrHGPVN/qGL/7GGX ETglX0KdrNiJ+WdFi5SNlfvHvZbpUwRA2KAeY= DomainKey-Signature: a=rsa-sha1; c=nofws; d=gmail.com; s=gamma; h=from:to:cc:subject:date:message-id:x-mailer; b=cfTH89UYrTc55k9dbCNow+Sg5IYnmPKnLNZrTy59yFyIfVNH0zZv7p6OskGr/InA58 wg0vDN/eS3Fg50vpykTbQqfC9LFQKiKIHYK3t5oTsNK+W8ij4edVPbvmazy5VIbVwrli 4O+jxJhMon9EZYBpjxy6IYm5DVgrQa8kdJ0E4= Received: by 10.52.156.161 with SMTP id wf1mr5096387vdb.258.1298929863855; Mon, 28 Feb 2011 13:51:03 -0800 (PST) Received: from localhost ([32.97.110.58]) by mx.google.com with ESMTPS id c15sm1857378vcs.7.2011.02.28.13.51.02 (version=TLSv1/SSLv3 cipher=OTHER); Mon, 28 Feb 2011 13:51:03 -0800 (PST) From: shirishpargaonkar@gmail.com To: smfrench@gmail.com Cc: linux-cifs@vger.kernel.org, bfields@fieldses.org, Shirish Pargaonkar Subject: [PATCH] cifs: Allow nfsd over cifs Date: Mon, 28 Feb 2011 15:52:41 -0600 Message-Id: <1298929961-5541-1-git-send-email-shirishpargaonkar@gmail.com> X-Mailer: git-send-email 1.6.0.2 Sender: linux-cifs-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-cifs@vger.kernel.org X-Greylist: IP, sender and recipient auto-whitelisted, not delayed by milter-greylist-4.2.6 (demeter1.kernel.org [140.211.167.41]); Mon, 28 Feb 2011 21:51:07 +0000 (UTC) diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c index 13b3999..29ff05c 100644 --- a/fs/cifs/cifsfs.c +++ b/fs/cifs/cifsfs.c @@ -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; diff --git a/fs/cifs/cifsfs.h b/fs/cifs/cifsfs.h index 371d021..1d8185d 100644 --- a/fs/cifs/cifsfs.h +++ b/fs/cifs/cifsfs.h @@ -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 */ diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h index e1098c3..c7faac6 100644 --- a/fs/cifs/cifsglob.h +++ b/fs/cifs/cifsglob.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 diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h index da7a492..0d0afd2 100644 --- a/fs/cifs/cifsproto.h +++ b/fs/cifs/cifsproto.h @@ -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); diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c index dd5f229..4e9c38f 100644 --- a/fs/cifs/dir.c +++ b/fs/cifs/dir.c @@ -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; } diff --git a/fs/cifs/export.c b/fs/cifs/export.c index 55d87ac..fd8397f 100644 --- a/fs/cifs/export.c +++ b/fs/cifs/export.c @@ -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 */ diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c index 196ef60..9c86535 100644 --- a/fs/cifs/inode.c +++ b/fs/cifs/inode.c @@ -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;