mirror of
https://github.com/torvalds/linux.git
synced 2024-11-21 19:41:42 +00:00
'smb3 client fixes
-----BEGIN PGP SIGNATURE----- iQGzBAABCgAdFiEE6fsu8pdIjtWE/DpLiiy9cAdyT1EFAmauj9AACgkQiiy9cAdy T1G4HgwAvdAPAn2BAFYT/SaXfkN3EX78mcGe85wA8CXQep7q/ik+3xAwvNMKOWmo OYmem3TqdfK4N4wkXCWd7TpKI+DZQAyt9ocIk8MhDWoIxp2A1nX/80SJUjTAJWvg 8Q2HBZu8GfYyw8PW9KfR4hBOixvA8dLXZI7vNSvHP4S7XA10OP/HFTkwi4pPlkLF ZuSZNMU0Enwmzay1pUkVp9r2dq1ZDKtilbFFmN+bnuMoAigp//HDFFxx/zjIXCqb FdhA+bl9Wj1f2r164qDRHoVg2kVX2lyIzhQJtAWdIqxPEAfUgZCu//KN5NgdstYx sQID8DL0MDeDYRhvuoAVinLpLvJFVf0O4K43f5kY1HXA4JFn//lY9zPNE4FLuwrw Ez+WsB70YHhof14n5w1hgcDE5XMeLZLa3SbVNoyhTW4C7xjJj1cqMEfnqZTGUsLx s2sZJnLhoX0aThTp9+Wc4KLy9Z8QjOy3GMmc7tmCtwHfYJTocly8wfWCrR9VYvBP yVIhZCbt =MKOr -----END PGP SIGNATURE----- Merge tag '6.11-rc1-smb-client-fixes' of git://git.samba.org/sfrench/cifs-2.6 Pull smb client fixes from Steve French: - two reparse point fixes - minor cleanup - additional trace point (to help debug a recent problem) * tag '6.11-rc1-smb-client-fixes' of git://git.samba.org/sfrench/cifs-2.6: cifs: update internal version number smb: client: fix FSCTL_GET_REPARSE_POINT against NetApp smb3: add dynamic tracepoints for shutdown ioctl cifs: Remove cifs_aio_ctx smb: client: handle lack of FSCTL_GET_REPARSE_POINT support
This commit is contained in:
commit
3f3f6d6123
@ -147,6 +147,6 @@ extern const struct export_operations cifs_export_ops;
|
||||
#endif /* CONFIG_CIFS_NFSD_EXPORT */
|
||||
|
||||
/* when changing internal version - update following two lines at same time */
|
||||
#define SMB3_PRODUCT_BUILD 49
|
||||
#define CIFS_VERSION "2.49"
|
||||
#define SMB3_PRODUCT_BUILD 50
|
||||
#define CIFS_VERSION "2.50"
|
||||
#endif /* _CIFSFS_H */
|
||||
|
@ -1471,29 +1471,6 @@ struct cifs_io_parms {
|
||||
struct TCP_Server_Info *server;
|
||||
};
|
||||
|
||||
struct cifs_aio_ctx {
|
||||
struct kref refcount;
|
||||
struct list_head list;
|
||||
struct mutex aio_mutex;
|
||||
struct completion done;
|
||||
struct iov_iter iter;
|
||||
struct kiocb *iocb;
|
||||
struct cifsFileInfo *cfile;
|
||||
struct bio_vec *bv;
|
||||
loff_t pos;
|
||||
unsigned int nr_pinned_pages;
|
||||
ssize_t rc;
|
||||
unsigned int len;
|
||||
unsigned int total_len;
|
||||
unsigned int bv_need_unpin; /* If ->bv[] needs unpinning */
|
||||
bool should_dirty;
|
||||
/*
|
||||
* Indicates if this aio_ctx is for direct_io,
|
||||
* If yes, iter is a copy of the user passed iov_iter
|
||||
*/
|
||||
bool direct_io;
|
||||
};
|
||||
|
||||
struct cifs_io_request {
|
||||
struct netfs_io_request rreq;
|
||||
struct cifsFileInfo *cfile;
|
||||
@ -2010,7 +1987,6 @@ require use of the stronger protocol */
|
||||
* cifsFileInfo->file_info_lock cifsFileInfo->count cifs_new_fileinfo
|
||||
* ->invalidHandle initiate_cifs_search
|
||||
* ->oplock_break_cancelled
|
||||
* cifs_aio_ctx->aio_mutex cifs_aio_ctx cifs_aio_ctx_alloc
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef DECLARE_GLOBALS_HERE
|
||||
|
@ -619,8 +619,6 @@ int __cifs_calc_signature(struct smb_rqst *rqst,
|
||||
struct shash_desc *shash);
|
||||
enum securityEnum cifs_select_sectype(struct TCP_Server_Info *,
|
||||
enum securityEnum);
|
||||
struct cifs_aio_ctx *cifs_aio_ctx_alloc(void);
|
||||
void cifs_aio_ctx_release(struct kref *refcount);
|
||||
|
||||
int cifs_alloc_hash(const char *name, struct shash_desc **sdesc);
|
||||
void cifs_free_hash(struct shash_desc **sdesc);
|
||||
|
@ -1042,13 +1042,26 @@ static int reparse_info_to_fattr(struct cifs_open_info_data *data,
|
||||
}
|
||||
|
||||
rc = -EOPNOTSUPP;
|
||||
switch ((data->reparse.tag = tag)) {
|
||||
case 0: /* SMB1 symlink */
|
||||
data->reparse.tag = tag;
|
||||
if (!data->reparse.tag) {
|
||||
if (server->ops->query_symlink) {
|
||||
rc = server->ops->query_symlink(xid, tcon,
|
||||
cifs_sb, full_path,
|
||||
&data->symlink_target);
|
||||
}
|
||||
if (rc == -EOPNOTSUPP)
|
||||
data->reparse.tag = IO_REPARSE_TAG_INTERNAL;
|
||||
}
|
||||
|
||||
switch (data->reparse.tag) {
|
||||
case 0: /* SMB1 symlink */
|
||||
break;
|
||||
case IO_REPARSE_TAG_INTERNAL:
|
||||
rc = 0;
|
||||
if (le32_to_cpu(data->fi.Attributes) & ATTR_DIRECTORY) {
|
||||
cifs_create_junction_fattr(fattr, sb);
|
||||
goto out;
|
||||
}
|
||||
break;
|
||||
case IO_REPARSE_TAG_MOUNT_POINT:
|
||||
cifs_create_junction_fattr(fattr, sb);
|
||||
|
@ -170,7 +170,10 @@ static long smb_mnt_get_fsinfo(unsigned int xid, struct cifs_tcon *tcon,
|
||||
static int cifs_shutdown(struct super_block *sb, unsigned long arg)
|
||||
{
|
||||
struct cifs_sb_info *sbi = CIFS_SB(sb);
|
||||
struct tcon_link *tlink;
|
||||
struct cifs_tcon *tcon;
|
||||
__u32 flags;
|
||||
int rc;
|
||||
|
||||
if (!capable(CAP_SYS_ADMIN))
|
||||
return -EPERM;
|
||||
@ -178,14 +181,21 @@ static int cifs_shutdown(struct super_block *sb, unsigned long arg)
|
||||
if (get_user(flags, (__u32 __user *)arg))
|
||||
return -EFAULT;
|
||||
|
||||
if (flags > CIFS_GOING_FLAGS_NOLOGFLUSH)
|
||||
return -EINVAL;
|
||||
tlink = cifs_sb_tlink(sbi);
|
||||
if (IS_ERR(tlink))
|
||||
return PTR_ERR(tlink);
|
||||
tcon = tlink_tcon(tlink);
|
||||
|
||||
trace_smb3_shutdown_enter(flags, tcon->tid);
|
||||
if (flags > CIFS_GOING_FLAGS_NOLOGFLUSH) {
|
||||
rc = -EINVAL;
|
||||
goto shutdown_out_err;
|
||||
}
|
||||
|
||||
if (cifs_forced_shutdown(sbi))
|
||||
return 0;
|
||||
goto shutdown_good;
|
||||
|
||||
cifs_dbg(VFS, "shut down requested (%d)", flags);
|
||||
/* trace_cifs_shutdown(sb, flags);*/
|
||||
|
||||
/*
|
||||
* see:
|
||||
@ -201,7 +211,8 @@ static int cifs_shutdown(struct super_block *sb, unsigned long arg)
|
||||
*/
|
||||
case CIFS_GOING_FLAGS_DEFAULT:
|
||||
cifs_dbg(FYI, "shutdown with default flag not supported\n");
|
||||
return -EINVAL;
|
||||
rc = -EINVAL;
|
||||
goto shutdown_out_err;
|
||||
/*
|
||||
* FLAGS_LOGFLUSH is easy since it asks to write out metadata (not
|
||||
* data) but metadata writes are not cached on the client, so can treat
|
||||
@ -210,11 +221,18 @@ static int cifs_shutdown(struct super_block *sb, unsigned long arg)
|
||||
case CIFS_GOING_FLAGS_LOGFLUSH:
|
||||
case CIFS_GOING_FLAGS_NOLOGFLUSH:
|
||||
sbi->mnt_cifs_flags |= CIFS_MOUNT_SHUTDOWN;
|
||||
return 0;
|
||||
goto shutdown_good;
|
||||
default:
|
||||
return -EINVAL;
|
||||
rc = -EINVAL;
|
||||
goto shutdown_out_err;
|
||||
}
|
||||
|
||||
shutdown_good:
|
||||
trace_smb3_shutdown_done(flags, tcon->tid);
|
||||
return 0;
|
||||
shutdown_out_err:
|
||||
trace_smb3_shutdown_err(rc, flags, tcon->tid);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int cifs_dump_full_key(struct cifs_tcon *tcon, struct smb3_full_key_debug_info __user *in)
|
||||
|
@ -995,60 +995,6 @@ parse_DFS_referrals_exit:
|
||||
return rc;
|
||||
}
|
||||
|
||||
struct cifs_aio_ctx *
|
||||
cifs_aio_ctx_alloc(void)
|
||||
{
|
||||
struct cifs_aio_ctx *ctx;
|
||||
|
||||
/*
|
||||
* Must use kzalloc to initialize ctx->bv to NULL and ctx->direct_io
|
||||
* to false so that we know when we have to unreference pages within
|
||||
* cifs_aio_ctx_release()
|
||||
*/
|
||||
ctx = kzalloc(sizeof(struct cifs_aio_ctx), GFP_KERNEL);
|
||||
if (!ctx)
|
||||
return NULL;
|
||||
|
||||
INIT_LIST_HEAD(&ctx->list);
|
||||
mutex_init(&ctx->aio_mutex);
|
||||
init_completion(&ctx->done);
|
||||
kref_init(&ctx->refcount);
|
||||
return ctx;
|
||||
}
|
||||
|
||||
void
|
||||
cifs_aio_ctx_release(struct kref *refcount)
|
||||
{
|
||||
struct cifs_aio_ctx *ctx = container_of(refcount,
|
||||
struct cifs_aio_ctx, refcount);
|
||||
|
||||
cifsFileInfo_put(ctx->cfile);
|
||||
|
||||
/*
|
||||
* ctx->bv is only set if setup_aio_ctx_iter() was call successfuly
|
||||
* which means that iov_iter_extract_pages() was a success and thus
|
||||
* that we may have references or pins on pages that we need to
|
||||
* release.
|
||||
*/
|
||||
if (ctx->bv) {
|
||||
if (ctx->should_dirty || ctx->bv_need_unpin) {
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < ctx->nr_pinned_pages; i++) {
|
||||
struct page *page = ctx->bv[i].bv_page;
|
||||
|
||||
if (ctx->should_dirty)
|
||||
set_page_dirty(page);
|
||||
if (ctx->bv_need_unpin)
|
||||
unpin_user_page(page);
|
||||
}
|
||||
}
|
||||
kvfree(ctx->bv);
|
||||
}
|
||||
|
||||
kfree(ctx);
|
||||
}
|
||||
|
||||
/**
|
||||
* cifs_alloc_hash - allocate hash and hash context together
|
||||
* @name: The name of the crypto hash algo
|
||||
|
@ -505,6 +505,10 @@ bool cifs_reparse_point_to_fattr(struct cifs_sb_info *cifs_sb,
|
||||
}
|
||||
|
||||
switch (tag) {
|
||||
case IO_REPARSE_TAG_INTERNAL:
|
||||
if (!(fattr->cf_cifsattrs & ATTR_DIRECTORY))
|
||||
return false;
|
||||
fallthrough;
|
||||
case IO_REPARSE_TAG_DFS:
|
||||
case IO_REPARSE_TAG_DFSR:
|
||||
case IO_REPARSE_TAG_MOUNT_POINT:
|
||||
|
@ -12,6 +12,12 @@
|
||||
#include "fs_context.h"
|
||||
#include "cifsglob.h"
|
||||
|
||||
/*
|
||||
* Used only by cifs.ko to ignore reparse points from files when client or
|
||||
* server doesn't support FSCTL_GET_REPARSE_POINT.
|
||||
*/
|
||||
#define IO_REPARSE_TAG_INTERNAL ((__u32)~0U)
|
||||
|
||||
static inline dev_t reparse_nfs_mkdev(struct reparse_posix_data *buf)
|
||||
{
|
||||
u64 v = le64_to_cpu(*(__le64 *)buf->DataBuffer);
|
||||
@ -78,10 +84,19 @@ static inline u32 reparse_mode_wsl_tag(mode_t mode)
|
||||
static inline bool reparse_inode_match(struct inode *inode,
|
||||
struct cifs_fattr *fattr)
|
||||
{
|
||||
struct cifsInodeInfo *cinode = CIFS_I(inode);
|
||||
struct timespec64 ctime = inode_get_ctime(inode);
|
||||
|
||||
return (CIFS_I(inode)->cifsAttrs & ATTR_REPARSE) &&
|
||||
CIFS_I(inode)->reparse_tag == fattr->cf_cifstag &&
|
||||
/*
|
||||
* Do not match reparse tags when client or server doesn't support
|
||||
* FSCTL_GET_REPARSE_POINT. @fattr->cf_cifstag should contain correct
|
||||
* reparse tag from query dir response but the client won't be able to
|
||||
* read the reparse point data anyway. This spares us a revalidation.
|
||||
*/
|
||||
if (cinode->reparse_tag != IO_REPARSE_TAG_INTERNAL &&
|
||||
cinode->reparse_tag != fattr->cf_cifstag)
|
||||
return false;
|
||||
return (cinode->cifsAttrs & ATTR_REPARSE) &&
|
||||
timespec64_equal(&ctime, &fattr->cf_ctime);
|
||||
}
|
||||
|
||||
|
@ -930,6 +930,8 @@ int smb2_query_path_info(const unsigned int xid,
|
||||
|
||||
switch (rc) {
|
||||
case 0:
|
||||
rc = parse_create_response(data, cifs_sb, &out_iov[0]);
|
||||
break;
|
||||
case -EOPNOTSUPP:
|
||||
/*
|
||||
* BB TODO: When support for special files added to Samba
|
||||
@ -948,7 +950,8 @@ int smb2_query_path_info(const unsigned int xid,
|
||||
cmds[num_cmds++] = SMB2_OP_GET_REPARSE;
|
||||
|
||||
oparms = CIFS_OPARMS(cifs_sb, tcon, full_path,
|
||||
FILE_READ_ATTRIBUTES | FILE_READ_EA,
|
||||
FILE_READ_ATTRIBUTES |
|
||||
FILE_READ_EA | SYNCHRONIZE,
|
||||
FILE_OPEN, create_options |
|
||||
OPEN_REPARSE_POINT, ACL_NO_MODE);
|
||||
cifs_get_readable_path(tcon, full_path, &cfile);
|
||||
@ -1256,7 +1259,8 @@ int smb2_query_reparse_point(const unsigned int xid,
|
||||
cifs_dbg(FYI, "%s: path: %s\n", __func__, full_path);
|
||||
|
||||
cifs_get_readable_path(tcon, full_path, &cfile);
|
||||
oparms = CIFS_OPARMS(cifs_sb, tcon, full_path, FILE_READ_ATTRIBUTES,
|
||||
oparms = CIFS_OPARMS(cifs_sb, tcon, full_path,
|
||||
FILE_READ_ATTRIBUTES | FILE_READ_EA | SYNCHRONIZE,
|
||||
FILE_OPEN, OPEN_REPARSE_POINT, ACL_NO_MODE);
|
||||
rc = smb2_compound_op(xid, tcon, cifs_sb,
|
||||
full_path, &oparms, &in_iov,
|
||||
|
@ -1388,7 +1388,7 @@ DECLARE_EVENT_CLASS(smb3_ioctl_class,
|
||||
__entry->command = command;
|
||||
),
|
||||
TP_printk("xid=%u fid=0x%llx ioctl cmd=0x%x",
|
||||
__entry->xid, __entry->fid, __entry->command)
|
||||
__entry->xid, __entry->fid, __entry->command)
|
||||
)
|
||||
|
||||
#define DEFINE_SMB3_IOCTL_EVENT(name) \
|
||||
@ -1400,9 +1400,58 @@ DEFINE_EVENT(smb3_ioctl_class, smb3_##name, \
|
||||
|
||||
DEFINE_SMB3_IOCTL_EVENT(ioctl);
|
||||
|
||||
DECLARE_EVENT_CLASS(smb3_shutdown_class,
|
||||
TP_PROTO(__u32 flags,
|
||||
__u32 tid),
|
||||
TP_ARGS(flags, tid),
|
||||
TP_STRUCT__entry(
|
||||
__field(__u32, flags)
|
||||
__field(__u32, tid)
|
||||
),
|
||||
TP_fast_assign(
|
||||
__entry->flags = flags;
|
||||
__entry->tid = tid;
|
||||
),
|
||||
TP_printk("flags=0x%x tid=0x%x",
|
||||
__entry->flags, __entry->tid)
|
||||
)
|
||||
|
||||
#define DEFINE_SMB3_SHUTDOWN_EVENT(name) \
|
||||
DEFINE_EVENT(smb3_shutdown_class, smb3_##name, \
|
||||
TP_PROTO(__u32 flags, \
|
||||
__u32 tid), \
|
||||
TP_ARGS(flags, tid))
|
||||
|
||||
DEFINE_SMB3_SHUTDOWN_EVENT(shutdown_enter);
|
||||
DEFINE_SMB3_SHUTDOWN_EVENT(shutdown_done);
|
||||
|
||||
DECLARE_EVENT_CLASS(smb3_shutdown_err_class,
|
||||
TP_PROTO(int rc,
|
||||
__u32 flags,
|
||||
__u32 tid),
|
||||
TP_ARGS(rc, flags, tid),
|
||||
TP_STRUCT__entry(
|
||||
__field(int, rc)
|
||||
__field(__u32, flags)
|
||||
__field(__u32, tid)
|
||||
),
|
||||
TP_fast_assign(
|
||||
__entry->rc = rc;
|
||||
__entry->flags = flags;
|
||||
__entry->tid = tid;
|
||||
),
|
||||
TP_printk("rc=%d flags=0x%x tid=0x%x",
|
||||
__entry->rc, __entry->flags, __entry->tid)
|
||||
)
|
||||
|
||||
#define DEFINE_SMB3_SHUTDOWN_ERR_EVENT(name) \
|
||||
DEFINE_EVENT(smb3_shutdown_err_class, smb3_##name, \
|
||||
TP_PROTO(int rc, \
|
||||
__u32 flags, \
|
||||
__u32 tid), \
|
||||
TP_ARGS(rc, flags, tid))
|
||||
|
||||
DEFINE_SMB3_SHUTDOWN_ERR_EVENT(shutdown_err);
|
||||
|
||||
DECLARE_EVENT_CLASS(smb3_credit_class,
|
||||
TP_PROTO(__u64 currmid,
|
||||
|
Loading…
Reference in New Issue
Block a user