From: Paulo Alcantara <pc@manguebit.com>
To: smfrench@gmail.com
Cc: linux-cifs@vger.kernel.org, Paulo Alcantara <pc@manguebit.com>
Subject: [PATCH 7/7] smb: client: handle reparse points over SMB3 POSIX
Date: Tue, 21 Nov 2023 20:12:58 -0300 [thread overview]
Message-ID: <20231121231258.29562-7-pc@manguebit.com> (raw)
In-Reply-To: <20231121231258.29562-1-pc@manguebit.com>
Add support for creating and listing special files via reparse points
when using SMB3 POSIX extensions.
Signed-off-by: Paulo Alcantara (SUSE) <pc@manguebit.com>
---
fs/smb/client/cifsproto.h | 8 +++--
fs/smb/client/dir.c | 7 ++--
fs/smb/client/file.c | 10 +++---
fs/smb/client/inode.c | 71 ++++++++++++++++++++++++++-------------
fs/smb/client/link.c | 10 +++---
fs/smb/client/smb2inode.c | 21 ++++++++----
6 files changed, 84 insertions(+), 43 deletions(-)
diff --git a/fs/smb/client/cifsproto.h b/fs/smb/client/cifsproto.h
index 46feaa0880bd..0adeaa84b662 100644
--- a/fs/smb/client/cifsproto.h
+++ b/fs/smb/client/cifsproto.h
@@ -211,8 +211,12 @@ int cifs_get_inode_info(struct inode **inode, const char *full_path,
bool cifs_reparse_point_to_fattr(struct cifs_sb_info *cifs_sb,
struct cifs_fattr *fattr,
struct cifs_open_info_data *data);
-extern int smb311_posix_get_inode_info(struct inode **pinode, const char *search_path,
- struct super_block *sb, unsigned int xid);
+
+extern int smb311_posix_get_inode_info(struct inode **inode,
+ const char *full_path,
+ struct cifs_open_info_data *data,
+ struct super_block *sb,
+ const unsigned int xid);
extern int cifs_get_inode_info_unix(struct inode **pinode,
const unsigned char *search_path,
struct super_block *sb, unsigned int xid);
diff --git a/fs/smb/client/dir.c b/fs/smb/client/dir.c
index 580a27a3a7e6..89333d9bce36 100644
--- a/fs/smb/client/dir.c
+++ b/fs/smb/client/dir.c
@@ -680,9 +680,10 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry,
full_path, d_inode(direntry));
again:
- if (pTcon->posix_extensions)
- rc = smb311_posix_get_inode_info(&newInode, full_path, parent_dir_inode->i_sb, xid);
- else if (pTcon->unix_ext) {
+ if (pTcon->posix_extensions) {
+ rc = smb311_posix_get_inode_info(&newInode, full_path, NULL,
+ parent_dir_inode->i_sb, xid);
+ } else if (pTcon->unix_ext) {
rc = cifs_get_inode_info_unix(&newInode, full_path,
parent_dir_inode->i_sb, xid);
} else {
diff --git a/fs/smb/client/file.c b/fs/smb/client/file.c
index cf17e3dd703e..2b69c4e79b17 100644
--- a/fs/smb/client/file.c
+++ b/fs/smb/client/file.c
@@ -1020,14 +1020,16 @@ cifs_reopen_file(struct cifsFileInfo *cfile, bool can_flush)
if (!is_interrupt_error(rc))
mapping_set_error(inode->i_mapping, rc);
- if (tcon->posix_extensions)
- rc = smb311_posix_get_inode_info(&inode, full_path, inode->i_sb, xid);
- else if (tcon->unix_ext)
+ if (tcon->posix_extensions) {
+ rc = smb311_posix_get_inode_info(&inode, full_path,
+ NULL, inode->i_sb, xid);
+ } else if (tcon->unix_ext) {
rc = cifs_get_inode_info_unix(&inode, full_path,
inode->i_sb, xid);
- else
+ } else {
rc = cifs_get_inode_info(&inode, full_path, NULL,
inode->i_sb, xid, NULL);
+ }
}
/*
* Else we are writing out data to server already and could deadlock if
diff --git a/fs/smb/client/inode.c b/fs/smb/client/inode.c
index 88b7cf23348c..7baa02940bce 100644
--- a/fs/smb/client/inode.c
+++ b/fs/smb/client/inode.c
@@ -1059,7 +1059,9 @@ static int reparse_info_to_fattr(struct cifs_open_info_data *data,
const unsigned int xid,
struct cifs_tcon *tcon,
const char *full_path,
- struct cifs_fattr *fattr)
+ struct cifs_fattr *fattr,
+ struct cifs_sid *owner,
+ struct cifs_sid *group)
{
struct TCP_Server_Info *server = tcon->ses->server;
struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
@@ -1100,7 +1102,10 @@ static int reparse_info_to_fattr(struct cifs_open_info_data *data,
break;
}
- cifs_open_info_to_fattr(fattr, data, sb);
+ if (tcon->posix_extensions)
+ smb311_posix_info_to_fattr(fattr, data, owner, group, sb);
+ else
+ cifs_open_info_to_fattr(fattr, data, sb);
out:
free_rsp_buf(rsp_buftype, rsp_iov.iov_base);
return rc;
@@ -1151,7 +1156,8 @@ static int cifs_get_fattr(struct cifs_open_info_data *data,
*/
if (cifs_open_data_reparse(data)) {
rc = reparse_info_to_fattr(data, sb, xid, tcon,
- full_path, fattr);
+ full_path, fattr,
+ NULL, NULL);
} else {
cifs_open_info_to_fattr(fattr, data, sb);
}
@@ -1289,12 +1295,13 @@ int cifs_get_inode_info(struct inode **inode,
return rc;
}
-static int smb311_posix_get_fattr(struct cifs_fattr *fattr,
+static int smb311_posix_get_fattr(struct cifs_open_info_data *data,
+ struct cifs_fattr *fattr,
const char *full_path,
struct super_block *sb,
const unsigned int xid)
{
- struct cifs_open_info_data data = {};
+ struct cifs_open_info_data tmp_data = {};
struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
struct cifs_tcon *tcon;
struct tcon_link *tlink;
@@ -1308,12 +1315,14 @@ static int smb311_posix_get_fattr(struct cifs_fattr *fattr,
tcon = tlink_tcon(tlink);
/*
- * 1. Fetch file metadata
+ * 1. Fetch file metadata if not provided (data)
*/
-
- rc = smb311_posix_query_path_info(xid, tcon, cifs_sb,
- full_path, &data,
- &owner, &group);
+ if (!data) {
+ rc = smb311_posix_query_path_info(xid, tcon, cifs_sb,
+ full_path, &tmp_data,
+ &owner, &group);
+ data = &tmp_data;
+ }
/*
* 2. Convert it to internal cifs metadata (fattr)
@@ -1321,7 +1330,14 @@ static int smb311_posix_get_fattr(struct cifs_fattr *fattr,
switch (rc) {
case 0:
- smb311_posix_info_to_fattr(fattr, &data, &owner, &group, sb);
+ if (cifs_open_data_reparse(data)) {
+ rc = reparse_info_to_fattr(data, sb, xid, tcon,
+ full_path, fattr,
+ &owner, &group);
+ } else {
+ smb311_posix_info_to_fattr(fattr, data,
+ &owner, &group, sb);
+ }
break;
case -EREMOTE:
/* DFS link, no metadata available on this server */
@@ -1352,12 +1368,15 @@ static int smb311_posix_get_fattr(struct cifs_fattr *fattr,
out:
cifs_put_tlink(tlink);
- cifs_free_open_info(&data);
+ cifs_free_open_info(data);
return rc;
}
-int smb311_posix_get_inode_info(struct inode **inode, const char *full_path,
- struct super_block *sb, const unsigned int xid)
+int smb311_posix_get_inode_info(struct inode **inode,
+ const char *full_path,
+ struct cifs_open_info_data *data,
+ struct super_block *sb,
+ const unsigned int xid)
{
struct cifs_fattr fattr = {};
int rc;
@@ -1367,7 +1386,7 @@ int smb311_posix_get_inode_info(struct inode **inode, const char *full_path,
return 0;
}
- rc = smb311_posix_get_fattr(&fattr, full_path, sb, xid);
+ rc = smb311_posix_get_fattr(data, &fattr, full_path, sb, xid);
if (rc)
goto out;
@@ -1515,7 +1534,7 @@ struct inode *cifs_root_iget(struct super_block *sb)
convert_delimiter(path, CIFS_DIR_SEP(cifs_sb));
if (tcon->posix_extensions)
- rc = smb311_posix_get_fattr(&fattr, path, sb, xid);
+ rc = smb311_posix_get_fattr(NULL, &fattr, path, sb, xid);
else
rc = cifs_get_fattr(NULL, sb, xid, NULL, &fattr, &inode, path);
@@ -1888,16 +1907,18 @@ cifs_mkdir_qinfo(struct inode *parent, struct dentry *dentry, umode_t mode,
int rc = 0;
struct inode *inode = NULL;
- if (tcon->posix_extensions)
- rc = smb311_posix_get_inode_info(&inode, full_path, parent->i_sb, xid);
+ if (tcon->posix_extensions) {
+ rc = smb311_posix_get_inode_info(&inode, full_path,
+ NULL, parent->i_sb, xid);
#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY
- else if (tcon->unix_ext)
+ } else if (tcon->unix_ext) {
rc = cifs_get_inode_info_unix(&inode, full_path, parent->i_sb,
xid);
#endif /* CONFIG_CIFS_ALLOW_INSECURE_LEGACY */
- else
+ } else {
rc = cifs_get_inode_info(&inode, full_path, NULL, parent->i_sb,
xid, NULL);
+ }
if (rc)
return rc;
@@ -2578,13 +2599,15 @@ int cifs_revalidate_dentry_attr(struct dentry *dentry)
dentry, cifs_get_time(dentry), jiffies);
again:
- if (cifs_sb_master_tcon(CIFS_SB(sb))->posix_extensions)
- rc = smb311_posix_get_inode_info(&inode, full_path, sb, xid);
- else if (cifs_sb_master_tcon(CIFS_SB(sb))->unix_ext)
+ if (cifs_sb_master_tcon(CIFS_SB(sb))->posix_extensions) {
+ rc = smb311_posix_get_inode_info(&inode, full_path,
+ NULL, sb, xid);
+ } else if (cifs_sb_master_tcon(CIFS_SB(sb))->unix_ext) {
rc = cifs_get_inode_info_unix(&inode, full_path, sb, xid);
- else
+ } else {
rc = cifs_get_inode_info(&inode, full_path, NULL, sb,
xid, NULL);
+ }
if (rc == -EAGAIN && count++ < 10)
goto again;
out:
diff --git a/fs/smb/client/link.c b/fs/smb/client/link.c
index 5c91376d1c1f..82fb069c6ce4 100644
--- a/fs/smb/client/link.c
+++ b/fs/smb/client/link.c
@@ -619,14 +619,16 @@ cifs_symlink(struct mnt_idmap *idmap, struct inode *inode,
}
if (rc == 0) {
- if (pTcon->posix_extensions)
- rc = smb311_posix_get_inode_info(&newinode, full_path, inode->i_sb, xid);
- else if (pTcon->unix_ext)
+ if (pTcon->posix_extensions) {
+ rc = smb311_posix_get_inode_info(&newinode, full_path,
+ NULL, inode->i_sb, xid);
+ } else if (pTcon->unix_ext) {
rc = cifs_get_inode_info_unix(&newinode, full_path,
inode->i_sb, xid);
- else
+ } else {
rc = cifs_get_inode_info(&newinode, full_path, NULL,
inode->i_sb, xid, NULL);
+ }
if (rc != 0) {
cifs_dbg(FYI, "Create symlink ok, getinodeinfo fail rc = %d\n",
diff --git a/fs/smb/client/smb2inode.c b/fs/smb/client/smb2inode.c
index c09da386a36b..0d2c58e5051b 100644
--- a/fs/smb/client/smb2inode.c
+++ b/fs/smb/client/smb2inode.c
@@ -540,14 +540,23 @@ struct inode *smb2_get_reparse_inode(struct cifs_open_info_data *data,
struct inode *new = NULL;
int rc;
+ /*
+ * Since we know it is a reparse point already, query info it
+ * directly and provide cached file metadata to *get_inode_info() calls
+ * in order to avoid extra roundtrips.
+ */
if (tcon->posix_extensions) {
- rc = smb311_posix_get_inode_info(&new, full_path, sb, xid);
+ cifs_get_readable_path(tcon, full_path, &cfile);
+ rc = smb2_compound_op(xid, tcon, cifs_sb, full_path,
+ FILE_READ_ATTRIBUTES, FILE_OPEN,
+ OPEN_REPARSE_POINT, ACL_NO_MODE, data,
+ SMB2_OP_POSIX_QUERY_INFO, cfile, NULL,
+ NULL, NULL, NULL);
+ if (rc)
+ return ERR_PTR(rc);
+ rc = smb311_posix_get_inode_info(&new, full_path,
+ data, sb, xid);
} else {
- /*
- * Since we know it is a reparse point already, query info it
- * directly and provide cached file metadata to
- * cifs_get_inode_info() in order to avoid extra roundtrips.
- */
cifs_get_readable_path(tcon, full_path, &cfile);
rc = smb2_compound_op(xid, tcon, cifs_sb, full_path,
FILE_READ_ATTRIBUTES, FILE_OPEN,
--
2.42.1
prev parent reply other threads:[~2023-11-21 23:13 UTC|newest]
Thread overview: 17+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-11-19 18:22 [PATCH 1/3] smb: client: implement ->query_reparse_point() for SMB1 Paulo Alcantara
2023-11-19 18:22 ` [PATCH 2/3] smb: client: introduce ->parse_reparse_point() Paulo Alcantara
2023-11-19 18:22 ` [PATCH 3/3] smb: client: set correct file type from NFS reparse points Paulo Alcantara
2023-11-19 21:44 ` [PATCH v2 1/3] smb: client: implement ->query_reparse_point() for SMB1 Paulo Alcantara
2023-11-19 21:44 ` [PATCH v2 2/3] smb: client: introduce ->parse_reparse_point() Paulo Alcantara
2023-11-19 21:44 ` [PATCH v2 3/3] smb: client: set correct file type from NFS reparse points Paulo Alcantara
2023-11-20 5:49 ` Ralph Boehme
2023-11-20 14:17 ` Paulo Alcantara
2023-11-20 14:27 ` Ralph Boehme
2023-11-21 23:12 ` [PATCH 1/7] smb: client: implement ->query_reparse_point() for SMB1 Paulo Alcantara
2023-11-21 23:12 ` [PATCH 2/7] smb: client: introduce ->parse_reparse_point() Paulo Alcantara
2023-11-21 23:12 ` [PATCH 3/7] smb: client: set correct file type from NFS reparse points Paulo Alcantara
2023-11-21 23:12 ` [PATCH 4/7] smb: client: introduce cifs_sfu_make_node() Paulo Alcantara
2023-11-21 23:12 ` [PATCH 5/7] smb: client: allow creating special files via reparse points Paulo Alcantara
2023-11-22 15:16 ` Paulo Alcantara
2023-11-21 23:12 ` [PATCH 6/7] smb: client: allow creating symlinks " Paulo Alcantara
2023-11-21 23:12 ` Paulo Alcantara [this message]
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=20231121231258.29562-7-pc@manguebit.com \
--to=pc@manguebit.com \
--cc=linux-cifs@vger.kernel.org \
--cc=smfrench@gmail.com \
/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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox