Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit cbb0aba6 authored by Sachin Prabhu's avatar Sachin Prabhu Committed by Steve French
Browse files

cifs: Add create MFSymlinks to protocol ops struct



Add a new protocol ops function create_mf_symlink and have
create_mf_symlink() use it.

This patchset moves the MFSymlink operations completely to the
ops structure so that we only use the right protocol versions when
querying or creating MFSymlinks.

Signed-off-by: default avatarSachin Prabhu <sprabhu@redhat.com>
Reviewed-by: default avatarJeff Layton <jlayton@redhat.com>
Signed-off-by: default avatarSteve French <smfrench@gmail.com>
parent 8205d1bb
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -373,6 +373,9 @@ struct smb_version_operations {
	int (*query_mf_symlink)(unsigned int, struct cifs_tcon *,
				struct cifs_sb_info *, const unsigned char *,
				char *, unsigned int *);
	int (*create_mf_symlink)(unsigned int, struct cifs_tcon *,
				 struct cifs_sb_info *, const unsigned char *,
				 char *, unsigned int *);
	/* if we can do cache read operations */
	bool (*is_read_op)(__u32);
	/* set oplock level for the inode */
+4 −0
Original line number Diff line number Diff line
@@ -500,4 +500,8 @@ int cifs_query_mf_symlink(unsigned int xid, struct cifs_tcon *tcon,
			  struct cifs_sb_info *cifs_sb,
			  const unsigned char *path, char *pbuf,
			  unsigned int *pbytes_read);
int cifs_create_mf_symlink(unsigned int xid, struct cifs_tcon *tcon,
			   struct cifs_sb_info *cifs_sb,
			   const unsigned char *path, char *pbuf,
			   unsigned int *pbytes_written);
#endif			/* _CIFSPROTO_H */
+46 −42
Original line number Diff line number Diff line
@@ -180,61 +180,33 @@ format_mf_symlink(u8 *buf, unsigned int buf_len, const char *link_str)

static int
create_mf_symlink(const unsigned int xid, struct cifs_tcon *tcon,
		    const char *fromName, const char *toName,
		    struct cifs_sb_info *cifs_sb)
		  struct cifs_sb_info *cifs_sb, const char *fromName,
		  const char *toName)
{
	int rc;
	int oplock = 0;
	int remap;
	int create_options = CREATE_NOT_DIR;
	__u16 netfid = 0;
	u8 *buf;
	unsigned int bytes_written = 0;
	struct cifs_io_parms io_parms;
	struct nls_table *nls_codepage;

	nls_codepage = cifs_sb->local_nls;
	remap = cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR;

	buf = kmalloc(CIFS_MF_SYMLINK_FILE_SIZE, GFP_KERNEL);
	if (!buf)
		return -ENOMEM;

	rc = format_mf_symlink(buf, CIFS_MF_SYMLINK_FILE_SIZE, toName);
	if (rc != 0) {
		kfree(buf);
		return rc;
	}
	if (rc)
		goto out;

	if (backup_cred(cifs_sb))
		create_options |= CREATE_OPEN_BACKUP_INTENT;
	rc = tcon->ses->server->ops->create_mf_symlink(xid, tcon, cifs_sb,
					fromName, buf, &bytes_written);
	if (rc)
		goto out;

	rc = CIFSSMBOpen(xid, tcon, fromName, FILE_CREATE, GENERIC_WRITE,
			 create_options, &netfid, &oplock, NULL,
			 nls_codepage, remap);
	if (rc != 0) {
	if (bytes_written != CIFS_MF_SYMLINK_FILE_SIZE)
		rc = -EIO;
out:
	kfree(buf);
	return rc;
}

	io_parms.netfid = netfid;
	io_parms.pid = current->tgid;
	io_parms.tcon = tcon;
	io_parms.offset = 0;
	io_parms.length = CIFS_MF_SYMLINK_FILE_SIZE;

	rc = CIFSSMBWrite(xid, &io_parms, &bytes_written, buf, NULL, 0);
	CIFSSMBClose(xid, tcon, netfid);
	kfree(buf);
	if (rc != 0)
		return rc;

	if (bytes_written != CIFS_MF_SYMLINK_FILE_SIZE)
		return -EIO;

	return 0;
}

static int
query_mf_symlink(const unsigned int xid, struct cifs_tcon *tcon,
		 struct cifs_sb_info *cifs_sb, const unsigned char *path,
@@ -319,6 +291,39 @@ cifs_query_mf_symlink(unsigned int xid, struct cifs_tcon *tcon,
	return rc;
}

int
cifs_create_mf_symlink(unsigned int xid, struct cifs_tcon *tcon,
		       struct cifs_sb_info *cifs_sb, const unsigned char *path,
		       char *pbuf, unsigned int *pbytes_written)
{
	int rc;
	int oplock = 0;
	__u16 netfid = 0;
	struct cifs_io_parms io_parms;
	int create_options = CREATE_NOT_DIR;

	if (backup_cred(cifs_sb))
		create_options |= CREATE_OPEN_BACKUP_INTENT;

	rc = CIFSSMBOpen(xid, tcon, path, FILE_CREATE, GENERIC_WRITE,
			 create_options, &netfid, &oplock, NULL,
			 cifs_sb->local_nls,
			 cifs_sb->mnt_cifs_flags &
				CIFS_MOUNT_MAP_SPECIAL_CHR);
	if (rc)
		return rc;

	io_parms.netfid = netfid;
	io_parms.pid = current->tgid;
	io_parms.tcon = tcon;
	io_parms.offset = 0;
	io_parms.length = CIFS_MF_SYMLINK_FILE_SIZE;

	rc = CIFSSMBWrite(xid, &io_parms, pbytes_written, pbuf, NULL, 0);
	CIFSSMBClose(xid, tcon, netfid);
	return rc;
}

int
check_mf_symlink(unsigned int xid, struct cifs_tcon *tcon,
		 struct cifs_sb_info *cifs_sb, struct cifs_fattr *fattr,
@@ -553,8 +558,7 @@ cifs_symlink(struct inode *inode, struct dentry *direntry, const char *symname)

	/* BB what if DFS and this volume is on different share? BB */
	if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS)
		rc = create_mf_symlink(xid, pTcon, full_path, symname,
					cifs_sb);
		rc = create_mf_symlink(xid, pTcon, cifs_sb, full_path, symname);
	else if (pTcon->unix_ext)
		rc = CIFSUnixCreateSymLink(xid, pTcon, full_path, symname,
					   cifs_sb->local_nls);
+1 −0
Original line number Diff line number Diff line
@@ -1010,6 +1010,7 @@ struct smb_version_operations smb1_operations = {
	.mand_unlock_range = cifs_unlock_range,
	.push_mand_locks = cifs_push_mandatory_locks,
	.query_mf_symlink = cifs_query_mf_symlink,
	.create_mf_symlink = cifs_create_mf_symlink,
	.is_read_op = cifs_is_read_op,
};