Commit 3f3f6d61 authored by Linus Torvalds's avatar Linus Torvalds

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
parents 3c41df42 a91bfa67
...@@ -147,6 +147,6 @@ extern const struct export_operations cifs_export_ops; ...@@ -147,6 +147,6 @@ extern const struct export_operations cifs_export_ops;
#endif /* CONFIG_CIFS_NFSD_EXPORT */ #endif /* CONFIG_CIFS_NFSD_EXPORT */
/* when changing internal version - update following two lines at same time */ /* when changing internal version - update following two lines at same time */
#define SMB3_PRODUCT_BUILD 49 #define SMB3_PRODUCT_BUILD 50
#define CIFS_VERSION "2.49" #define CIFS_VERSION "2.50"
#endif /* _CIFSFS_H */ #endif /* _CIFSFS_H */
...@@ -1471,29 +1471,6 @@ struct cifs_io_parms { ...@@ -1471,29 +1471,6 @@ struct cifs_io_parms {
struct TCP_Server_Info *server; 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 cifs_io_request {
struct netfs_io_request rreq; struct netfs_io_request rreq;
struct cifsFileInfo *cfile; struct cifsFileInfo *cfile;
...@@ -2010,7 +1987,6 @@ require use of the stronger protocol */ ...@@ -2010,7 +1987,6 @@ require use of the stronger protocol */
* cifsFileInfo->file_info_lock cifsFileInfo->count cifs_new_fileinfo * cifsFileInfo->file_info_lock cifsFileInfo->count cifs_new_fileinfo
* ->invalidHandle initiate_cifs_search * ->invalidHandle initiate_cifs_search
* ->oplock_break_cancelled * ->oplock_break_cancelled
* cifs_aio_ctx->aio_mutex cifs_aio_ctx cifs_aio_ctx_alloc
****************************************************************************/ ****************************************************************************/
#ifdef DECLARE_GLOBALS_HERE #ifdef DECLARE_GLOBALS_HERE
......
...@@ -619,8 +619,6 @@ int __cifs_calc_signature(struct smb_rqst *rqst, ...@@ -619,8 +619,6 @@ int __cifs_calc_signature(struct smb_rqst *rqst,
struct shash_desc *shash); struct shash_desc *shash);
enum securityEnum cifs_select_sectype(struct TCP_Server_Info *, enum securityEnum cifs_select_sectype(struct TCP_Server_Info *,
enum securityEnum); 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); int cifs_alloc_hash(const char *name, struct shash_desc **sdesc);
void cifs_free_hash(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, ...@@ -1042,13 +1042,26 @@ static int reparse_info_to_fattr(struct cifs_open_info_data *data,
} }
rc = -EOPNOTSUPP; rc = -EOPNOTSUPP;
switch ((data->reparse.tag = tag)) { data->reparse.tag = tag;
case 0: /* SMB1 symlink */ if (!data->reparse.tag) {
if (server->ops->query_symlink) { if (server->ops->query_symlink) {
rc = server->ops->query_symlink(xid, tcon, rc = server->ops->query_symlink(xid, tcon,
cifs_sb, full_path, cifs_sb, full_path,
&data->symlink_target); &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; break;
case IO_REPARSE_TAG_MOUNT_POINT: case IO_REPARSE_TAG_MOUNT_POINT:
cifs_create_junction_fattr(fattr, sb); cifs_create_junction_fattr(fattr, sb);
......
...@@ -170,7 +170,10 @@ static long smb_mnt_get_fsinfo(unsigned int xid, struct cifs_tcon *tcon, ...@@ -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) static int cifs_shutdown(struct super_block *sb, unsigned long arg)
{ {
struct cifs_sb_info *sbi = CIFS_SB(sb); struct cifs_sb_info *sbi = CIFS_SB(sb);
struct tcon_link *tlink;
struct cifs_tcon *tcon;
__u32 flags; __u32 flags;
int rc;
if (!capable(CAP_SYS_ADMIN)) if (!capable(CAP_SYS_ADMIN))
return -EPERM; return -EPERM;
...@@ -178,14 +181,21 @@ static int cifs_shutdown(struct super_block *sb, unsigned long arg) ...@@ -178,14 +181,21 @@ static int cifs_shutdown(struct super_block *sb, unsigned long arg)
if (get_user(flags, (__u32 __user *)arg)) if (get_user(flags, (__u32 __user *)arg))
return -EFAULT; return -EFAULT;
if (flags > CIFS_GOING_FLAGS_NOLOGFLUSH) tlink = cifs_sb_tlink(sbi);
return -EINVAL; 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)) if (cifs_forced_shutdown(sbi))
return 0; goto shutdown_good;
cifs_dbg(VFS, "shut down requested (%d)", flags); cifs_dbg(VFS, "shut down requested (%d)", flags);
/* trace_cifs_shutdown(sb, flags);*/
/* /*
* see: * see:
...@@ -201,7 +211,8 @@ static int cifs_shutdown(struct super_block *sb, unsigned long arg) ...@@ -201,7 +211,8 @@ static int cifs_shutdown(struct super_block *sb, unsigned long arg)
*/ */
case CIFS_GOING_FLAGS_DEFAULT: case CIFS_GOING_FLAGS_DEFAULT:
cifs_dbg(FYI, "shutdown with default flag not supported\n"); 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 * 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 * 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) ...@@ -210,11 +221,18 @@ static int cifs_shutdown(struct super_block *sb, unsigned long arg)
case CIFS_GOING_FLAGS_LOGFLUSH: case CIFS_GOING_FLAGS_LOGFLUSH:
case CIFS_GOING_FLAGS_NOLOGFLUSH: case CIFS_GOING_FLAGS_NOLOGFLUSH:
sbi->mnt_cifs_flags |= CIFS_MOUNT_SHUTDOWN; sbi->mnt_cifs_flags |= CIFS_MOUNT_SHUTDOWN;
return 0; goto shutdown_good;
default: default:
return -EINVAL; rc = -EINVAL;
goto shutdown_out_err;
} }
shutdown_good:
trace_smb3_shutdown_done(flags, tcon->tid);
return 0; 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) 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(struct get_dfs_referral_rsp *rsp, u32 rsp_size, ...@@ -995,60 +995,6 @@ parse_dfs_referrals(struct get_dfs_referral_rsp *rsp, u32 rsp_size,
return rc; 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 * cifs_alloc_hash - allocate hash and hash context together
* @name: The name of the crypto hash algo * @name: The name of the crypto hash algo
......
...@@ -505,6 +505,10 @@ bool cifs_reparse_point_to_fattr(struct cifs_sb_info *cifs_sb, ...@@ -505,6 +505,10 @@ bool cifs_reparse_point_to_fattr(struct cifs_sb_info *cifs_sb,
} }
switch (tag) { 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_DFS:
case IO_REPARSE_TAG_DFSR: case IO_REPARSE_TAG_DFSR:
case IO_REPARSE_TAG_MOUNT_POINT: case IO_REPARSE_TAG_MOUNT_POINT:
......
...@@ -12,6 +12,12 @@ ...@@ -12,6 +12,12 @@
#include "fs_context.h" #include "fs_context.h"
#include "cifsglob.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) static inline dev_t reparse_nfs_mkdev(struct reparse_posix_data *buf)
{ {
u64 v = le64_to_cpu(*(__le64 *)buf->DataBuffer); u64 v = le64_to_cpu(*(__le64 *)buf->DataBuffer);
...@@ -78,10 +84,19 @@ static inline u32 reparse_mode_wsl_tag(mode_t mode) ...@@ -78,10 +84,19 @@ static inline u32 reparse_mode_wsl_tag(mode_t mode)
static inline bool reparse_inode_match(struct inode *inode, static inline bool reparse_inode_match(struct inode *inode,
struct cifs_fattr *fattr) struct cifs_fattr *fattr)
{ {
struct cifsInodeInfo *cinode = CIFS_I(inode);
struct timespec64 ctime = inode_get_ctime(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); timespec64_equal(&ctime, &fattr->cf_ctime);
} }
......
...@@ -930,6 +930,8 @@ int smb2_query_path_info(const unsigned int xid, ...@@ -930,6 +930,8 @@ int smb2_query_path_info(const unsigned int xid,
switch (rc) { switch (rc) {
case 0: case 0:
rc = parse_create_response(data, cifs_sb, &out_iov[0]);
break;
case -EOPNOTSUPP: case -EOPNOTSUPP:
/* /*
* BB TODO: When support for special files added to Samba * BB TODO: When support for special files added to Samba
...@@ -948,7 +950,8 @@ int smb2_query_path_info(const unsigned int xid, ...@@ -948,7 +950,8 @@ int smb2_query_path_info(const unsigned int xid,
cmds[num_cmds++] = SMB2_OP_GET_REPARSE; cmds[num_cmds++] = SMB2_OP_GET_REPARSE;
oparms = CIFS_OPARMS(cifs_sb, tcon, full_path, 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 | FILE_OPEN, create_options |
OPEN_REPARSE_POINT, ACL_NO_MODE); OPEN_REPARSE_POINT, ACL_NO_MODE);
cifs_get_readable_path(tcon, full_path, &cfile); cifs_get_readable_path(tcon, full_path, &cfile);
...@@ -1256,7 +1259,8 @@ int smb2_query_reparse_point(const unsigned int xid, ...@@ -1256,7 +1259,8 @@ int smb2_query_reparse_point(const unsigned int xid,
cifs_dbg(FYI, "%s: path: %s\n", __func__, full_path); cifs_dbg(FYI, "%s: path: %s\n", __func__, full_path);
cifs_get_readable_path(tcon, full_path, &cfile); 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); FILE_OPEN, OPEN_REPARSE_POINT, ACL_NO_MODE);
rc = smb2_compound_op(xid, tcon, cifs_sb, rc = smb2_compound_op(xid, tcon, cifs_sb,
full_path, &oparms, &in_iov, full_path, &oparms, &in_iov,
......
...@@ -1400,9 +1400,58 @@ DEFINE_EVENT(smb3_ioctl_class, smb3_##name, \ ...@@ -1400,9 +1400,58 @@ DEFINE_EVENT(smb3_ioctl_class, smb3_##name, \
DEFINE_SMB3_IOCTL_EVENT(ioctl); 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, DECLARE_EVENT_CLASS(smb3_credit_class,
TP_PROTO(__u64 currmid, TP_PROTO(__u64 currmid,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment