mirror of
https://github.com/torvalds/linux.git
synced 2024-11-22 20:22:09 +00:00
Seven ksmbd server fixes
-----BEGIN PGP SIGNATURE----- iQGzBAABCgAdFiEE6fsu8pdIjtWE/DpLiiy9cAdyT1EFAmVkHAAACgkQiiy9cAdy T1GTHwv+O0zp+oiqPezYFnDIp387AjDneUnSlGXyt9Xki0x3i84KiCMlrEnh3W0X rej+Dqnxi0/559L4HPUg0fhibFh2eClN1/B28isbep9vYKSv9AH1z1zN8/g1RV5r SI+eog1RvBx5DVGuH4+2ChbEJ1ys5StTzEUa4Csln6VCbfTa5rL1X3Lzukc8gPxf Qp3fun74xINSHDk2yvEr5Con9inu0NQOT+0IEaT5fCxZVb33tMtFt1NH3n4v+wL3 SsGhrFvP6GBhSx/m2cPofXquEtE+iHa2/5KYrbP8ypGTFxx5VtRvQrPv/U5y0xme sh/C6xiYBc4QmhQf44vmt4OKhLEYTsSOUk2TO8QAgSJc1sIe6VJrwbhmqJsD6YMI YyLb1CAN54Yz3Gdi4wrD3uC5BAHr1Ybsx4at6P/7SxyTdILHDZyg9occS23Jd3kq Tv/iLz+EQPU0uZavhLug4gFezCpHl3YXa6kVHgwz0rpIHHXUOoNQCe8MjsQSz6wE a/FqkgZ2 =tLLt -----END PGP SIGNATURE----- Merge tag '6.7-rc3-smb3-server-fixes' of git://git.samba.org/ksmbd Pull smb server fixes from Steve French: - Memory leak fix - Fix possible deadlock in open - Multiple SMB3 leasing (caching) fixes including: - incorrect open count (found via xfstest generic/002 with leases) - lease breaking incorrect serialization - lease break error handling fix - fix sending async response when lease pending - Async command fix * tag '6.7-rc3-smb3-server-fixes' of git://git.samba.org/ksmbd: ksmbd: don't update ->op_state as OPLOCK_STATE_NONE on error ksmbd: move setting SMB2_FLAGS_ASYNC_COMMAND and AsyncId ksmbd: release interim response after sending status pending response ksmbd: move oplock handling after unlock parent dir ksmbd: separately allocate ci per dentry ksmbd: fix possible deadlock in smb2_open ksmbd: prevent memory leak on error return
This commit is contained in:
commit
df60cee26a
@ -56,6 +56,9 @@ void ksmbd_free_work_struct(struct ksmbd_work *work)
|
||||
kfree(work->tr_buf);
|
||||
kvfree(work->request_buf);
|
||||
kfree(work->iov);
|
||||
if (!list_empty(&work->interim_entry))
|
||||
list_del(&work->interim_entry);
|
||||
|
||||
if (work->async_id)
|
||||
ksmbd_release_id(&work->conn->async_ida, work->async_id);
|
||||
kmem_cache_free(work_cache, work);
|
||||
@ -106,7 +109,7 @@ static inline void __ksmbd_iov_pin(struct ksmbd_work *work, void *ib,
|
||||
static int __ksmbd_iov_pin_rsp(struct ksmbd_work *work, void *ib, int len,
|
||||
void *aux_buf, unsigned int aux_size)
|
||||
{
|
||||
struct aux_read *ar;
|
||||
struct aux_read *ar = NULL;
|
||||
int need_iov_cnt = 1;
|
||||
|
||||
if (aux_size) {
|
||||
@ -123,8 +126,11 @@ static int __ksmbd_iov_pin_rsp(struct ksmbd_work *work, void *ib, int len,
|
||||
new = krealloc(work->iov,
|
||||
sizeof(struct kvec) * work->iov_alloc_cnt,
|
||||
GFP_KERNEL | __GFP_ZERO);
|
||||
if (!new)
|
||||
if (!new) {
|
||||
kfree(ar);
|
||||
work->iov_alloc_cnt -= 4;
|
||||
return -ENOMEM;
|
||||
}
|
||||
work->iov = new;
|
||||
}
|
||||
|
||||
|
@ -833,7 +833,8 @@ static int smb2_lease_break_noti(struct oplock_info *opinfo)
|
||||
interim_entry);
|
||||
setup_async_work(in_work, NULL, NULL);
|
||||
smb2_send_interim_resp(in_work, STATUS_PENDING);
|
||||
list_del(&in_work->interim_entry);
|
||||
list_del_init(&in_work->interim_entry);
|
||||
release_async_work(in_work);
|
||||
}
|
||||
INIT_WORK(&work->work, __smb2_lease_break_noti);
|
||||
ksmbd_queue_work(work);
|
||||
|
@ -657,13 +657,9 @@ smb2_get_name(const char *src, const int maxlen, struct nls_table *local_nls)
|
||||
|
||||
int setup_async_work(struct ksmbd_work *work, void (*fn)(void **), void **arg)
|
||||
{
|
||||
struct smb2_hdr *rsp_hdr;
|
||||
struct ksmbd_conn *conn = work->conn;
|
||||
int id;
|
||||
|
||||
rsp_hdr = ksmbd_resp_buf_next(work);
|
||||
rsp_hdr->Flags |= SMB2_FLAGS_ASYNC_COMMAND;
|
||||
|
||||
id = ksmbd_acquire_async_msg_id(&conn->async_ida);
|
||||
if (id < 0) {
|
||||
pr_err("Failed to alloc async message id\n");
|
||||
@ -671,7 +667,6 @@ int setup_async_work(struct ksmbd_work *work, void (*fn)(void **), void **arg)
|
||||
}
|
||||
work->asynchronous = true;
|
||||
work->async_id = id;
|
||||
rsp_hdr->Id.AsyncId = cpu_to_le64(id);
|
||||
|
||||
ksmbd_debug(SMB,
|
||||
"Send interim Response to inform async request id : %d\n",
|
||||
@ -723,6 +718,8 @@ void smb2_send_interim_resp(struct ksmbd_work *work, __le32 status)
|
||||
__SMB2_HEADER_STRUCTURE_SIZE);
|
||||
|
||||
rsp_hdr = smb2_get_msg(in_work->response_buf);
|
||||
rsp_hdr->Flags |= SMB2_FLAGS_ASYNC_COMMAND;
|
||||
rsp_hdr->Id.AsyncId = cpu_to_le64(work->async_id);
|
||||
smb2_set_err_rsp(in_work);
|
||||
rsp_hdr->Status = status;
|
||||
|
||||
@ -2380,7 +2377,8 @@ static int smb2_set_ea(struct smb2_ea_info *eabuf, unsigned int buf_len,
|
||||
rc = 0;
|
||||
} else {
|
||||
rc = ksmbd_vfs_setxattr(idmap, path, attr_name, value,
|
||||
le16_to_cpu(eabuf->EaValueLength), 0);
|
||||
le16_to_cpu(eabuf->EaValueLength),
|
||||
0, true);
|
||||
if (rc < 0) {
|
||||
ksmbd_debug(SMB,
|
||||
"ksmbd_vfs_setxattr is failed(%d)\n",
|
||||
@ -2443,7 +2441,7 @@ static noinline int smb2_set_stream_name_xattr(const struct path *path,
|
||||
return -EBADF;
|
||||
}
|
||||
|
||||
rc = ksmbd_vfs_setxattr(idmap, path, xattr_stream_name, NULL, 0, 0);
|
||||
rc = ksmbd_vfs_setxattr(idmap, path, xattr_stream_name, NULL, 0, 0, false);
|
||||
if (rc < 0)
|
||||
pr_err("Failed to store XATTR stream name :%d\n", rc);
|
||||
return 0;
|
||||
@ -2518,7 +2516,7 @@ static void smb2_new_xattrs(struct ksmbd_tree_connect *tcon, const struct path *
|
||||
da.flags = XATTR_DOSINFO_ATTRIB | XATTR_DOSINFO_CREATE_TIME |
|
||||
XATTR_DOSINFO_ITIME;
|
||||
|
||||
rc = ksmbd_vfs_set_dos_attrib_xattr(mnt_idmap(path->mnt), path, &da);
|
||||
rc = ksmbd_vfs_set_dos_attrib_xattr(mnt_idmap(path->mnt), path, &da, false);
|
||||
if (rc)
|
||||
ksmbd_debug(SMB, "failed to store file attribute into xattr\n");
|
||||
}
|
||||
@ -2608,7 +2606,7 @@ static int smb2_create_sd_buffer(struct ksmbd_work *work,
|
||||
sizeof(struct create_sd_buf_req))
|
||||
return -EINVAL;
|
||||
return set_info_sec(work->conn, work->tcon, path, &sd_buf->ntsd,
|
||||
le32_to_cpu(sd_buf->ccontext.DataLength), true);
|
||||
le32_to_cpu(sd_buf->ccontext.DataLength), true, false);
|
||||
}
|
||||
|
||||
static void ksmbd_acls_fattr(struct smb_fattr *fattr,
|
||||
@ -2690,7 +2688,7 @@ int smb2_open(struct ksmbd_work *work)
|
||||
*(char *)req->Buffer == '\\') {
|
||||
pr_err("not allow directory name included leading slash\n");
|
||||
rc = -EINVAL;
|
||||
goto err_out1;
|
||||
goto err_out2;
|
||||
}
|
||||
|
||||
name = smb2_get_name(req->Buffer,
|
||||
@ -2701,7 +2699,7 @@ int smb2_open(struct ksmbd_work *work)
|
||||
if (rc != -ENOMEM)
|
||||
rc = -ENOENT;
|
||||
name = NULL;
|
||||
goto err_out1;
|
||||
goto err_out2;
|
||||
}
|
||||
|
||||
ksmbd_debug(SMB, "converted name = %s\n", name);
|
||||
@ -2709,28 +2707,28 @@ int smb2_open(struct ksmbd_work *work)
|
||||
if (!test_share_config_flag(work->tcon->share_conf,
|
||||
KSMBD_SHARE_FLAG_STREAMS)) {
|
||||
rc = -EBADF;
|
||||
goto err_out1;
|
||||
goto err_out2;
|
||||
}
|
||||
rc = parse_stream_name(name, &stream_name, &s_type);
|
||||
if (rc < 0)
|
||||
goto err_out1;
|
||||
goto err_out2;
|
||||
}
|
||||
|
||||
rc = ksmbd_validate_filename(name);
|
||||
if (rc < 0)
|
||||
goto err_out1;
|
||||
goto err_out2;
|
||||
|
||||
if (ksmbd_share_veto_filename(share, name)) {
|
||||
rc = -ENOENT;
|
||||
ksmbd_debug(SMB, "Reject open(), vetoed file: %s\n",
|
||||
name);
|
||||
goto err_out1;
|
||||
goto err_out2;
|
||||
}
|
||||
} else {
|
||||
name = kstrdup("", GFP_KERNEL);
|
||||
if (!name) {
|
||||
rc = -ENOMEM;
|
||||
goto err_out1;
|
||||
goto err_out2;
|
||||
}
|
||||
}
|
||||
|
||||
@ -2743,14 +2741,14 @@ int smb2_open(struct ksmbd_work *work)
|
||||
le32_to_cpu(req->ImpersonationLevel));
|
||||
rc = -EIO;
|
||||
rsp->hdr.Status = STATUS_BAD_IMPERSONATION_LEVEL;
|
||||
goto err_out1;
|
||||
goto err_out2;
|
||||
}
|
||||
|
||||
if (req->CreateOptions && !(req->CreateOptions & CREATE_OPTIONS_MASK_LE)) {
|
||||
pr_err("Invalid create options : 0x%x\n",
|
||||
le32_to_cpu(req->CreateOptions));
|
||||
rc = -EINVAL;
|
||||
goto err_out1;
|
||||
goto err_out2;
|
||||
} else {
|
||||
if (req->CreateOptions & FILE_SEQUENTIAL_ONLY_LE &&
|
||||
req->CreateOptions & FILE_RANDOM_ACCESS_LE)
|
||||
@ -2760,13 +2758,13 @@ int smb2_open(struct ksmbd_work *work)
|
||||
(FILE_OPEN_BY_FILE_ID_LE | CREATE_TREE_CONNECTION |
|
||||
FILE_RESERVE_OPFILTER_LE)) {
|
||||
rc = -EOPNOTSUPP;
|
||||
goto err_out1;
|
||||
goto err_out2;
|
||||
}
|
||||
|
||||
if (req->CreateOptions & FILE_DIRECTORY_FILE_LE) {
|
||||
if (req->CreateOptions & FILE_NON_DIRECTORY_FILE_LE) {
|
||||
rc = -EINVAL;
|
||||
goto err_out1;
|
||||
goto err_out2;
|
||||
} else if (req->CreateOptions & FILE_NO_COMPRESSION_LE) {
|
||||
req->CreateOptions = ~(FILE_NO_COMPRESSION_LE);
|
||||
}
|
||||
@ -2778,21 +2776,21 @@ int smb2_open(struct ksmbd_work *work)
|
||||
pr_err("Invalid create disposition : 0x%x\n",
|
||||
le32_to_cpu(req->CreateDisposition));
|
||||
rc = -EINVAL;
|
||||
goto err_out1;
|
||||
goto err_out2;
|
||||
}
|
||||
|
||||
if (!(req->DesiredAccess & DESIRED_ACCESS_MASK)) {
|
||||
pr_err("Invalid desired access : 0x%x\n",
|
||||
le32_to_cpu(req->DesiredAccess));
|
||||
rc = -EACCES;
|
||||
goto err_out1;
|
||||
goto err_out2;
|
||||
}
|
||||
|
||||
if (req->FileAttributes && !(req->FileAttributes & FILE_ATTRIBUTE_MASK_LE)) {
|
||||
pr_err("Invalid file attribute : 0x%x\n",
|
||||
le32_to_cpu(req->FileAttributes));
|
||||
rc = -EINVAL;
|
||||
goto err_out1;
|
||||
goto err_out2;
|
||||
}
|
||||
|
||||
if (req->CreateContextsOffset) {
|
||||
@ -2800,19 +2798,19 @@ int smb2_open(struct ksmbd_work *work)
|
||||
context = smb2_find_context_vals(req, SMB2_CREATE_EA_BUFFER, 4);
|
||||
if (IS_ERR(context)) {
|
||||
rc = PTR_ERR(context);
|
||||
goto err_out1;
|
||||
goto err_out2;
|
||||
} else if (context) {
|
||||
ea_buf = (struct create_ea_buf_req *)context;
|
||||
if (le16_to_cpu(context->DataOffset) +
|
||||
le32_to_cpu(context->DataLength) <
|
||||
sizeof(struct create_ea_buf_req)) {
|
||||
rc = -EINVAL;
|
||||
goto err_out1;
|
||||
goto err_out2;
|
||||
}
|
||||
if (req->CreateOptions & FILE_NO_EA_KNOWLEDGE_LE) {
|
||||
rsp->hdr.Status = STATUS_ACCESS_DENIED;
|
||||
rc = -EACCES;
|
||||
goto err_out1;
|
||||
goto err_out2;
|
||||
}
|
||||
}
|
||||
|
||||
@ -2820,7 +2818,7 @@ int smb2_open(struct ksmbd_work *work)
|
||||
SMB2_CREATE_QUERY_MAXIMAL_ACCESS_REQUEST, 4);
|
||||
if (IS_ERR(context)) {
|
||||
rc = PTR_ERR(context);
|
||||
goto err_out1;
|
||||
goto err_out2;
|
||||
} else if (context) {
|
||||
ksmbd_debug(SMB,
|
||||
"get query maximal access context\n");
|
||||
@ -2831,11 +2829,11 @@ int smb2_open(struct ksmbd_work *work)
|
||||
SMB2_CREATE_TIMEWARP_REQUEST, 4);
|
||||
if (IS_ERR(context)) {
|
||||
rc = PTR_ERR(context);
|
||||
goto err_out1;
|
||||
goto err_out2;
|
||||
} else if (context) {
|
||||
ksmbd_debug(SMB, "get timewarp context\n");
|
||||
rc = -EBADF;
|
||||
goto err_out1;
|
||||
goto err_out2;
|
||||
}
|
||||
|
||||
if (tcon->posix_extensions) {
|
||||
@ -2843,7 +2841,7 @@ int smb2_open(struct ksmbd_work *work)
|
||||
SMB2_CREATE_TAG_POSIX, 16);
|
||||
if (IS_ERR(context)) {
|
||||
rc = PTR_ERR(context);
|
||||
goto err_out1;
|
||||
goto err_out2;
|
||||
} else if (context) {
|
||||
struct create_posix *posix =
|
||||
(struct create_posix *)context;
|
||||
@ -2851,7 +2849,7 @@ int smb2_open(struct ksmbd_work *work)
|
||||
le32_to_cpu(context->DataLength) <
|
||||
sizeof(struct create_posix) - 4) {
|
||||
rc = -EINVAL;
|
||||
goto err_out1;
|
||||
goto err_out2;
|
||||
}
|
||||
ksmbd_debug(SMB, "get posix context\n");
|
||||
|
||||
@ -2863,7 +2861,7 @@ int smb2_open(struct ksmbd_work *work)
|
||||
|
||||
if (ksmbd_override_fsids(work)) {
|
||||
rc = -ENOMEM;
|
||||
goto err_out1;
|
||||
goto err_out2;
|
||||
}
|
||||
|
||||
rc = ksmbd_vfs_kern_path_locked(work, name, LOOKUP_NO_SYMLINKS,
|
||||
@ -3038,7 +3036,7 @@ int smb2_open(struct ksmbd_work *work)
|
||||
}
|
||||
}
|
||||
|
||||
rc = ksmbd_query_inode_status(d_inode(path.dentry->d_parent));
|
||||
rc = ksmbd_query_inode_status(path.dentry->d_parent);
|
||||
if (rc == KSMBD_INODE_STATUS_PENDING_DELETE) {
|
||||
rc = -EBUSY;
|
||||
goto err_out;
|
||||
@ -3152,7 +3150,8 @@ int smb2_open(struct ksmbd_work *work)
|
||||
idmap,
|
||||
&path,
|
||||
pntsd,
|
||||
pntsd_size);
|
||||
pntsd_size,
|
||||
false);
|
||||
kfree(pntsd);
|
||||
if (rc)
|
||||
pr_err("failed to store ntacl in xattr : %d\n",
|
||||
@ -3175,11 +3174,6 @@ int smb2_open(struct ksmbd_work *work)
|
||||
|
||||
fp->attrib_only = !(req->DesiredAccess & ~(FILE_READ_ATTRIBUTES_LE |
|
||||
FILE_WRITE_ATTRIBUTES_LE | FILE_SYNCHRONIZE_LE));
|
||||
if (!S_ISDIR(file_inode(filp)->i_mode) && open_flags & O_TRUNC &&
|
||||
!fp->attrib_only && !stream_name) {
|
||||
smb_break_all_oplock(work, fp);
|
||||
need_truncate = 1;
|
||||
}
|
||||
|
||||
/* fp should be searchable through ksmbd_inode.m_fp_list
|
||||
* after daccess, saccess, attrib_only, and stream are
|
||||
@ -3195,86 +3189,6 @@ int smb2_open(struct ksmbd_work *work)
|
||||
goto err_out;
|
||||
}
|
||||
|
||||
share_ret = ksmbd_smb_check_shared_mode(fp->filp, fp);
|
||||
if (!test_share_config_flag(work->tcon->share_conf, KSMBD_SHARE_FLAG_OPLOCKS) ||
|
||||
(req_op_level == SMB2_OPLOCK_LEVEL_LEASE &&
|
||||
!(conn->vals->capabilities & SMB2_GLOBAL_CAP_LEASING))) {
|
||||
if (share_ret < 0 && !S_ISDIR(file_inode(fp->filp)->i_mode)) {
|
||||
rc = share_ret;
|
||||
goto err_out;
|
||||
}
|
||||
} else {
|
||||
if (req_op_level == SMB2_OPLOCK_LEVEL_LEASE) {
|
||||
req_op_level = smb2_map_lease_to_oplock(lc->req_state);
|
||||
ksmbd_debug(SMB,
|
||||
"lease req for(%s) req oplock state 0x%x, lease state 0x%x\n",
|
||||
name, req_op_level, lc->req_state);
|
||||
rc = find_same_lease_key(sess, fp->f_ci, lc);
|
||||
if (rc)
|
||||
goto err_out;
|
||||
} else if (open_flags == O_RDONLY &&
|
||||
(req_op_level == SMB2_OPLOCK_LEVEL_BATCH ||
|
||||
req_op_level == SMB2_OPLOCK_LEVEL_EXCLUSIVE))
|
||||
req_op_level = SMB2_OPLOCK_LEVEL_II;
|
||||
|
||||
rc = smb_grant_oplock(work, req_op_level,
|
||||
fp->persistent_id, fp,
|
||||
le32_to_cpu(req->hdr.Id.SyncId.TreeId),
|
||||
lc, share_ret);
|
||||
if (rc < 0)
|
||||
goto err_out;
|
||||
}
|
||||
|
||||
if (req->CreateOptions & FILE_DELETE_ON_CLOSE_LE)
|
||||
ksmbd_fd_set_delete_on_close(fp, file_info);
|
||||
|
||||
if (need_truncate) {
|
||||
rc = smb2_create_truncate(&path);
|
||||
if (rc)
|
||||
goto err_out;
|
||||
}
|
||||
|
||||
if (req->CreateContextsOffset) {
|
||||
struct create_alloc_size_req *az_req;
|
||||
|
||||
az_req = (struct create_alloc_size_req *)smb2_find_context_vals(req,
|
||||
SMB2_CREATE_ALLOCATION_SIZE, 4);
|
||||
if (IS_ERR(az_req)) {
|
||||
rc = PTR_ERR(az_req);
|
||||
goto err_out;
|
||||
} else if (az_req) {
|
||||
loff_t alloc_size;
|
||||
int err;
|
||||
|
||||
if (le16_to_cpu(az_req->ccontext.DataOffset) +
|
||||
le32_to_cpu(az_req->ccontext.DataLength) <
|
||||
sizeof(struct create_alloc_size_req)) {
|
||||
rc = -EINVAL;
|
||||
goto err_out;
|
||||
}
|
||||
alloc_size = le64_to_cpu(az_req->AllocationSize);
|
||||
ksmbd_debug(SMB,
|
||||
"request smb2 create allocate size : %llu\n",
|
||||
alloc_size);
|
||||
smb_break_all_levII_oplock(work, fp, 1);
|
||||
err = vfs_fallocate(fp->filp, FALLOC_FL_KEEP_SIZE, 0,
|
||||
alloc_size);
|
||||
if (err < 0)
|
||||
ksmbd_debug(SMB,
|
||||
"vfs_fallocate is failed : %d\n",
|
||||
err);
|
||||
}
|
||||
|
||||
context = smb2_find_context_vals(req, SMB2_CREATE_QUERY_ON_DISK_ID, 4);
|
||||
if (IS_ERR(context)) {
|
||||
rc = PTR_ERR(context);
|
||||
goto err_out;
|
||||
} else if (context) {
|
||||
ksmbd_debug(SMB, "get query on disk id context\n");
|
||||
query_disk_id = 1;
|
||||
}
|
||||
}
|
||||
|
||||
rc = ksmbd_vfs_getattr(&path, &stat);
|
||||
if (rc)
|
||||
goto err_out;
|
||||
@ -3292,6 +3206,95 @@ int smb2_open(struct ksmbd_work *work)
|
||||
else
|
||||
smb2_new_xattrs(tcon, &path, fp);
|
||||
|
||||
if (file_present || created)
|
||||
ksmbd_vfs_kern_path_unlock(&parent_path, &path);
|
||||
|
||||
if (!S_ISDIR(file_inode(filp)->i_mode) && open_flags & O_TRUNC &&
|
||||
!fp->attrib_only && !stream_name) {
|
||||
smb_break_all_oplock(work, fp);
|
||||
need_truncate = 1;
|
||||
}
|
||||
|
||||
share_ret = ksmbd_smb_check_shared_mode(fp->filp, fp);
|
||||
if (!test_share_config_flag(work->tcon->share_conf, KSMBD_SHARE_FLAG_OPLOCKS) ||
|
||||
(req_op_level == SMB2_OPLOCK_LEVEL_LEASE &&
|
||||
!(conn->vals->capabilities & SMB2_GLOBAL_CAP_LEASING))) {
|
||||
if (share_ret < 0 && !S_ISDIR(file_inode(fp->filp)->i_mode)) {
|
||||
rc = share_ret;
|
||||
goto err_out1;
|
||||
}
|
||||
} else {
|
||||
if (req_op_level == SMB2_OPLOCK_LEVEL_LEASE) {
|
||||
req_op_level = smb2_map_lease_to_oplock(lc->req_state);
|
||||
ksmbd_debug(SMB,
|
||||
"lease req for(%s) req oplock state 0x%x, lease state 0x%x\n",
|
||||
name, req_op_level, lc->req_state);
|
||||
rc = find_same_lease_key(sess, fp->f_ci, lc);
|
||||
if (rc)
|
||||
goto err_out1;
|
||||
} else if (open_flags == O_RDONLY &&
|
||||
(req_op_level == SMB2_OPLOCK_LEVEL_BATCH ||
|
||||
req_op_level == SMB2_OPLOCK_LEVEL_EXCLUSIVE))
|
||||
req_op_level = SMB2_OPLOCK_LEVEL_II;
|
||||
|
||||
rc = smb_grant_oplock(work, req_op_level,
|
||||
fp->persistent_id, fp,
|
||||
le32_to_cpu(req->hdr.Id.SyncId.TreeId),
|
||||
lc, share_ret);
|
||||
if (rc < 0)
|
||||
goto err_out1;
|
||||
}
|
||||
|
||||
if (req->CreateOptions & FILE_DELETE_ON_CLOSE_LE)
|
||||
ksmbd_fd_set_delete_on_close(fp, file_info);
|
||||
|
||||
if (need_truncate) {
|
||||
rc = smb2_create_truncate(&fp->filp->f_path);
|
||||
if (rc)
|
||||
goto err_out1;
|
||||
}
|
||||
|
||||
if (req->CreateContextsOffset) {
|
||||
struct create_alloc_size_req *az_req;
|
||||
|
||||
az_req = (struct create_alloc_size_req *)smb2_find_context_vals(req,
|
||||
SMB2_CREATE_ALLOCATION_SIZE, 4);
|
||||
if (IS_ERR(az_req)) {
|
||||
rc = PTR_ERR(az_req);
|
||||
goto err_out1;
|
||||
} else if (az_req) {
|
||||
loff_t alloc_size;
|
||||
int err;
|
||||
|
||||
if (le16_to_cpu(az_req->ccontext.DataOffset) +
|
||||
le32_to_cpu(az_req->ccontext.DataLength) <
|
||||
sizeof(struct create_alloc_size_req)) {
|
||||
rc = -EINVAL;
|
||||
goto err_out1;
|
||||
}
|
||||
alloc_size = le64_to_cpu(az_req->AllocationSize);
|
||||
ksmbd_debug(SMB,
|
||||
"request smb2 create allocate size : %llu\n",
|
||||
alloc_size);
|
||||
smb_break_all_levII_oplock(work, fp, 1);
|
||||
err = vfs_fallocate(fp->filp, FALLOC_FL_KEEP_SIZE, 0,
|
||||
alloc_size);
|
||||
if (err < 0)
|
||||
ksmbd_debug(SMB,
|
||||
"vfs_fallocate is failed : %d\n",
|
||||
err);
|
||||
}
|
||||
|
||||
context = smb2_find_context_vals(req, SMB2_CREATE_QUERY_ON_DISK_ID, 4);
|
||||
if (IS_ERR(context)) {
|
||||
rc = PTR_ERR(context);
|
||||
goto err_out1;
|
||||
} else if (context) {
|
||||
ksmbd_debug(SMB, "get query on disk id context\n");
|
||||
query_disk_id = 1;
|
||||
}
|
||||
}
|
||||
|
||||
memcpy(fp->client_guid, conn->ClientGUID, SMB2_CLIENT_GUID_SIZE);
|
||||
|
||||
rsp->StructureSize = cpu_to_le16(89);
|
||||
@ -3398,13 +3401,13 @@ int smb2_open(struct ksmbd_work *work)
|
||||
}
|
||||
|
||||
err_out:
|
||||
if (file_present || created) {
|
||||
inode_unlock(d_inode(parent_path.dentry));
|
||||
path_put(&path);
|
||||
path_put(&parent_path);
|
||||
}
|
||||
ksmbd_revert_fsids(work);
|
||||
if (rc && (file_present || created))
|
||||
ksmbd_vfs_kern_path_unlock(&parent_path, &path);
|
||||
|
||||
err_out1:
|
||||
ksmbd_revert_fsids(work);
|
||||
|
||||
err_out2:
|
||||
if (!rc) {
|
||||
ksmbd_update_fstate(&work->sess->file_table, fp, FP_INITED);
|
||||
rc = ksmbd_iov_pin_rsp(work, (void *)rsp, iov_len);
|
||||
@ -5537,7 +5540,7 @@ static int smb2_rename(struct ksmbd_work *work,
|
||||
rc = ksmbd_vfs_setxattr(file_mnt_idmap(fp->filp),
|
||||
&fp->filp->f_path,
|
||||
xattr_stream_name,
|
||||
NULL, 0, 0);
|
||||
NULL, 0, 0, true);
|
||||
if (rc < 0) {
|
||||
pr_err("failed to store stream name in xattr: %d\n",
|
||||
rc);
|
||||
@ -5630,11 +5633,9 @@ static int smb2_create_link(struct ksmbd_work *work,
|
||||
if (rc)
|
||||
rc = -EINVAL;
|
||||
out:
|
||||
if (file_present) {
|
||||
inode_unlock(d_inode(parent_path.dentry));
|
||||
path_put(&path);
|
||||
path_put(&parent_path);
|
||||
}
|
||||
if (file_present)
|
||||
ksmbd_vfs_kern_path_unlock(&parent_path, &path);
|
||||
|
||||
if (!IS_ERR(link_name))
|
||||
kfree(link_name);
|
||||
kfree(pathname);
|
||||
@ -5701,7 +5702,8 @@ static int set_file_basic_info(struct ksmbd_file *fp,
|
||||
da.flags = XATTR_DOSINFO_ATTRIB | XATTR_DOSINFO_CREATE_TIME |
|
||||
XATTR_DOSINFO_ITIME;
|
||||
|
||||
rc = ksmbd_vfs_set_dos_attrib_xattr(idmap, &filp->f_path, &da);
|
||||
rc = ksmbd_vfs_set_dos_attrib_xattr(idmap, &filp->f_path, &da,
|
||||
true);
|
||||
if (rc)
|
||||
ksmbd_debug(SMB,
|
||||
"failed to restore file attribute in EA\n");
|
||||
@ -6013,7 +6015,7 @@ static int smb2_set_info_sec(struct ksmbd_file *fp, int addition_info,
|
||||
fp->saccess |= FILE_SHARE_DELETE_LE;
|
||||
|
||||
return set_info_sec(fp->conn, fp->tcon, &fp->filp->f_path, pntsd,
|
||||
buf_len, false);
|
||||
buf_len, false, true);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -7582,7 +7584,8 @@ static inline int fsctl_set_sparse(struct ksmbd_work *work, u64 id,
|
||||
|
||||
da.attr = le32_to_cpu(fp->f_ci->m_fattr);
|
||||
ret = ksmbd_vfs_set_dos_attrib_xattr(idmap,
|
||||
&fp->filp->f_path, &da);
|
||||
&fp->filp->f_path,
|
||||
&da, true);
|
||||
if (ret)
|
||||
fp->f_ci->m_fattr = old_fattr;
|
||||
}
|
||||
@ -8231,7 +8234,6 @@ static void smb21_lease_break_ack(struct ksmbd_work *work)
|
||||
return;
|
||||
|
||||
err_out:
|
||||
opinfo->op_state = OPLOCK_STATE_NONE;
|
||||
wake_up_interruptible_all(&opinfo->oplock_q);
|
||||
atomic_dec(&opinfo->breaking_cnt);
|
||||
wake_up_interruptible_all(&opinfo->oplock_brk);
|
||||
|
@ -1185,7 +1185,7 @@ pass:
|
||||
pntsd_size += sizeof(struct smb_acl) + nt_size;
|
||||
}
|
||||
|
||||
ksmbd_vfs_set_sd_xattr(conn, idmap, path, pntsd, pntsd_size);
|
||||
ksmbd_vfs_set_sd_xattr(conn, idmap, path, pntsd, pntsd_size, false);
|
||||
kfree(pntsd);
|
||||
}
|
||||
|
||||
@ -1377,7 +1377,7 @@ err_out:
|
||||
|
||||
int set_info_sec(struct ksmbd_conn *conn, struct ksmbd_tree_connect *tcon,
|
||||
const struct path *path, struct smb_ntsd *pntsd, int ntsd_len,
|
||||
bool type_check)
|
||||
bool type_check, bool get_write)
|
||||
{
|
||||
int rc;
|
||||
struct smb_fattr fattr = {{0}};
|
||||
@ -1437,7 +1437,8 @@ int set_info_sec(struct ksmbd_conn *conn, struct ksmbd_tree_connect *tcon,
|
||||
if (test_share_config_flag(tcon->share_conf, KSMBD_SHARE_FLAG_ACL_XATTR)) {
|
||||
/* Update WinACL in xattr */
|
||||
ksmbd_vfs_remove_sd_xattrs(idmap, path);
|
||||
ksmbd_vfs_set_sd_xattr(conn, idmap, path, pntsd, ntsd_len);
|
||||
ksmbd_vfs_set_sd_xattr(conn, idmap, path, pntsd, ntsd_len,
|
||||
get_write);
|
||||
}
|
||||
|
||||
out:
|
||||
|
@ -207,7 +207,7 @@ int smb_check_perm_dacl(struct ksmbd_conn *conn, const struct path *path,
|
||||
__le32 *pdaccess, int uid);
|
||||
int set_info_sec(struct ksmbd_conn *conn, struct ksmbd_tree_connect *tcon,
|
||||
const struct path *path, struct smb_ntsd *pntsd, int ntsd_len,
|
||||
bool type_check);
|
||||
bool type_check, bool get_write);
|
||||
void id_to_sid(unsigned int cid, uint sidtype, struct smb_sid *ssid);
|
||||
void ksmbd_init_domain(u32 *sub_auth);
|
||||
|
||||
|
@ -97,6 +97,13 @@ static int ksmbd_vfs_path_lookup_locked(struct ksmbd_share_config *share_conf,
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
err = mnt_want_write(parent_path->mnt);
|
||||
if (err) {
|
||||
path_put(parent_path);
|
||||
putname(filename);
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
inode_lock_nested(parent_path->dentry->d_inode, I_MUTEX_PARENT);
|
||||
d = lookup_one_qstr_excl(&last, parent_path->dentry, 0);
|
||||
if (IS_ERR(d))
|
||||
@ -123,6 +130,7 @@ static int ksmbd_vfs_path_lookup_locked(struct ksmbd_share_config *share_conf,
|
||||
|
||||
err_out:
|
||||
inode_unlock(d_inode(parent_path->dentry));
|
||||
mnt_drop_write(parent_path->mnt);
|
||||
path_put(parent_path);
|
||||
putname(filename);
|
||||
return -ENOENT;
|
||||
@ -451,7 +459,8 @@ static int ksmbd_vfs_stream_write(struct ksmbd_file *fp, char *buf, loff_t *pos,
|
||||
fp->stream.name,
|
||||
(void *)stream_buf,
|
||||
size,
|
||||
0);
|
||||
0,
|
||||
true);
|
||||
if (err < 0)
|
||||
goto out;
|
||||
|
||||
@ -593,10 +602,6 @@ int ksmbd_vfs_remove_file(struct ksmbd_work *work, const struct path *path)
|
||||
goto out_err;
|
||||
}
|
||||
|
||||
err = mnt_want_write(path->mnt);
|
||||
if (err)
|
||||
goto out_err;
|
||||
|
||||
idmap = mnt_idmap(path->mnt);
|
||||
if (S_ISDIR(d_inode(path->dentry)->i_mode)) {
|
||||
err = vfs_rmdir(idmap, d_inode(parent), path->dentry);
|
||||
@ -607,7 +612,6 @@ int ksmbd_vfs_remove_file(struct ksmbd_work *work, const struct path *path)
|
||||
if (err)
|
||||
ksmbd_debug(VFS, "unlink failed, err %d\n", err);
|
||||
}
|
||||
mnt_drop_write(path->mnt);
|
||||
|
||||
out_err:
|
||||
ksmbd_revert_fsids(work);
|
||||
@ -715,7 +719,7 @@ retry:
|
||||
goto out3;
|
||||
}
|
||||
|
||||
parent_fp = ksmbd_lookup_fd_inode(d_inode(old_child->d_parent));
|
||||
parent_fp = ksmbd_lookup_fd_inode(old_child->d_parent);
|
||||
if (parent_fp) {
|
||||
if (parent_fp->daccess & FILE_DELETE_LE) {
|
||||
pr_err("parent dir is opened with delete access\n");
|
||||
@ -907,18 +911,22 @@ ssize_t ksmbd_vfs_getxattr(struct mnt_idmap *idmap,
|
||||
* @attr_value: xattr value to set
|
||||
* @attr_size: size of xattr value
|
||||
* @flags: destination buffer length
|
||||
* @get_write: get write access to a mount
|
||||
*
|
||||
* Return: 0 on success, otherwise error
|
||||
*/
|
||||
int ksmbd_vfs_setxattr(struct mnt_idmap *idmap,
|
||||
const struct path *path, const char *attr_name,
|
||||
void *attr_value, size_t attr_size, int flags)
|
||||
void *attr_value, size_t attr_size, int flags,
|
||||
bool get_write)
|
||||
{
|
||||
int err;
|
||||
|
||||
err = mnt_want_write(path->mnt);
|
||||
if (err)
|
||||
return err;
|
||||
if (get_write == true) {
|
||||
err = mnt_want_write(path->mnt);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
|
||||
err = vfs_setxattr(idmap,
|
||||
path->dentry,
|
||||
@ -928,7 +936,8 @@ int ksmbd_vfs_setxattr(struct mnt_idmap *idmap,
|
||||
flags);
|
||||
if (err)
|
||||
ksmbd_debug(VFS, "setxattr failed, err %d\n", err);
|
||||
mnt_drop_write(path->mnt);
|
||||
if (get_write == true)
|
||||
mnt_drop_write(path->mnt);
|
||||
return err;
|
||||
}
|
||||
|
||||
@ -1252,6 +1261,13 @@ out1:
|
||||
}
|
||||
|
||||
if (!err) {
|
||||
err = mnt_want_write(parent_path->mnt);
|
||||
if (err) {
|
||||
path_put(path);
|
||||
path_put(parent_path);
|
||||
return err;
|
||||
}
|
||||
|
||||
err = ksmbd_vfs_lock_parent(parent_path->dentry, path->dentry);
|
||||
if (err) {
|
||||
path_put(path);
|
||||
@ -1261,6 +1277,14 @@ out1:
|
||||
return err;
|
||||
}
|
||||
|
||||
void ksmbd_vfs_kern_path_unlock(struct path *parent_path, struct path *path)
|
||||
{
|
||||
inode_unlock(d_inode(parent_path->dentry));
|
||||
mnt_drop_write(parent_path->mnt);
|
||||
path_put(path);
|
||||
path_put(parent_path);
|
||||
}
|
||||
|
||||
struct dentry *ksmbd_vfs_kern_path_create(struct ksmbd_work *work,
|
||||
const char *name,
|
||||
unsigned int flags,
|
||||
@ -1415,7 +1439,8 @@ out:
|
||||
int ksmbd_vfs_set_sd_xattr(struct ksmbd_conn *conn,
|
||||
struct mnt_idmap *idmap,
|
||||
const struct path *path,
|
||||
struct smb_ntsd *pntsd, int len)
|
||||
struct smb_ntsd *pntsd, int len,
|
||||
bool get_write)
|
||||
{
|
||||
int rc;
|
||||
struct ndr sd_ndr = {0}, acl_ndr = {0};
|
||||
@ -1475,7 +1500,7 @@ int ksmbd_vfs_set_sd_xattr(struct ksmbd_conn *conn,
|
||||
|
||||
rc = ksmbd_vfs_setxattr(idmap, path,
|
||||
XATTR_NAME_SD, sd_ndr.data,
|
||||
sd_ndr.offset, 0);
|
||||
sd_ndr.offset, 0, get_write);
|
||||
if (rc < 0)
|
||||
pr_err("Failed to store XATTR ntacl :%d\n", rc);
|
||||
|
||||
@ -1564,7 +1589,8 @@ free_n_data:
|
||||
|
||||
int ksmbd_vfs_set_dos_attrib_xattr(struct mnt_idmap *idmap,
|
||||
const struct path *path,
|
||||
struct xattr_dos_attrib *da)
|
||||
struct xattr_dos_attrib *da,
|
||||
bool get_write)
|
||||
{
|
||||
struct ndr n;
|
||||
int err;
|
||||
@ -1574,7 +1600,7 @@ int ksmbd_vfs_set_dos_attrib_xattr(struct mnt_idmap *idmap,
|
||||
return err;
|
||||
|
||||
err = ksmbd_vfs_setxattr(idmap, path, XATTR_NAME_DOS_ATTRIBUTE,
|
||||
(void *)n.data, n.offset, 0);
|
||||
(void *)n.data, n.offset, 0, get_write);
|
||||
if (err)
|
||||
ksmbd_debug(SMB, "failed to store dos attribute in xattr\n");
|
||||
kfree(n.data);
|
||||
@ -1846,10 +1872,6 @@ int ksmbd_vfs_set_init_posix_acl(struct mnt_idmap *idmap,
|
||||
}
|
||||
posix_state_to_acl(&acl_state, acls->a_entries);
|
||||
|
||||
rc = mnt_want_write(path->mnt);
|
||||
if (rc)
|
||||
goto out_err;
|
||||
|
||||
rc = set_posix_acl(idmap, dentry, ACL_TYPE_ACCESS, acls);
|
||||
if (rc < 0)
|
||||
ksmbd_debug(SMB, "Set posix acl(ACL_TYPE_ACCESS) failed, rc : %d\n",
|
||||
@ -1861,9 +1883,7 @@ int ksmbd_vfs_set_init_posix_acl(struct mnt_idmap *idmap,
|
||||
ksmbd_debug(SMB, "Set posix acl(ACL_TYPE_DEFAULT) failed, rc : %d\n",
|
||||
rc);
|
||||
}
|
||||
mnt_drop_write(path->mnt);
|
||||
|
||||
out_err:
|
||||
free_acl_state(&acl_state);
|
||||
posix_acl_release(acls);
|
||||
return rc;
|
||||
@ -1893,10 +1913,6 @@ int ksmbd_vfs_inherit_posix_acl(struct mnt_idmap *idmap,
|
||||
}
|
||||
}
|
||||
|
||||
rc = mnt_want_write(path->mnt);
|
||||
if (rc)
|
||||
goto out_err;
|
||||
|
||||
rc = set_posix_acl(idmap, dentry, ACL_TYPE_ACCESS, acls);
|
||||
if (rc < 0)
|
||||
ksmbd_debug(SMB, "Set posix acl(ACL_TYPE_ACCESS) failed, rc : %d\n",
|
||||
@ -1908,9 +1924,7 @@ int ksmbd_vfs_inherit_posix_acl(struct mnt_idmap *idmap,
|
||||
ksmbd_debug(SMB, "Set posix acl(ACL_TYPE_DEFAULT) failed, rc : %d\n",
|
||||
rc);
|
||||
}
|
||||
mnt_drop_write(path->mnt);
|
||||
|
||||
out_err:
|
||||
posix_acl_release(acls);
|
||||
return rc;
|
||||
}
|
||||
|
@ -109,7 +109,8 @@ ssize_t ksmbd_vfs_casexattr_len(struct mnt_idmap *idmap,
|
||||
int attr_name_len);
|
||||
int ksmbd_vfs_setxattr(struct mnt_idmap *idmap,
|
||||
const struct path *path, const char *attr_name,
|
||||
void *attr_value, size_t attr_size, int flags);
|
||||
void *attr_value, size_t attr_size, int flags,
|
||||
bool get_write);
|
||||
int ksmbd_vfs_xattr_stream_name(char *stream_name, char **xattr_stream_name,
|
||||
size_t *xattr_stream_name_size, int s_type);
|
||||
int ksmbd_vfs_remove_xattr(struct mnt_idmap *idmap,
|
||||
@ -117,6 +118,7 @@ int ksmbd_vfs_remove_xattr(struct mnt_idmap *idmap,
|
||||
int ksmbd_vfs_kern_path_locked(struct ksmbd_work *work, char *name,
|
||||
unsigned int flags, struct path *parent_path,
|
||||
struct path *path, bool caseless);
|
||||
void ksmbd_vfs_kern_path_unlock(struct path *parent_path, struct path *path);
|
||||
struct dentry *ksmbd_vfs_kern_path_create(struct ksmbd_work *work,
|
||||
const char *name,
|
||||
unsigned int flags,
|
||||
@ -144,14 +146,16 @@ int ksmbd_vfs_remove_sd_xattrs(struct mnt_idmap *idmap, const struct path *path)
|
||||
int ksmbd_vfs_set_sd_xattr(struct ksmbd_conn *conn,
|
||||
struct mnt_idmap *idmap,
|
||||
const struct path *path,
|
||||
struct smb_ntsd *pntsd, int len);
|
||||
struct smb_ntsd *pntsd, int len,
|
||||
bool get_write);
|
||||
int ksmbd_vfs_get_sd_xattr(struct ksmbd_conn *conn,
|
||||
struct mnt_idmap *idmap,
|
||||
struct dentry *dentry,
|
||||
struct smb_ntsd **pntsd);
|
||||
int ksmbd_vfs_set_dos_attrib_xattr(struct mnt_idmap *idmap,
|
||||
const struct path *path,
|
||||
struct xattr_dos_attrib *da);
|
||||
struct xattr_dos_attrib *da,
|
||||
bool get_write);
|
||||
int ksmbd_vfs_get_dos_attrib_xattr(struct mnt_idmap *idmap,
|
||||
struct dentry *dentry,
|
||||
struct xattr_dos_attrib *da);
|
||||
|
@ -66,14 +66,14 @@ static unsigned long inode_hash(struct super_block *sb, unsigned long hashval)
|
||||
return tmp & inode_hash_mask;
|
||||
}
|
||||
|
||||
static struct ksmbd_inode *__ksmbd_inode_lookup(struct inode *inode)
|
||||
static struct ksmbd_inode *__ksmbd_inode_lookup(struct dentry *de)
|
||||
{
|
||||
struct hlist_head *head = inode_hashtable +
|
||||
inode_hash(inode->i_sb, inode->i_ino);
|
||||
inode_hash(d_inode(de)->i_sb, (unsigned long)de);
|
||||
struct ksmbd_inode *ci = NULL, *ret_ci = NULL;
|
||||
|
||||
hlist_for_each_entry(ci, head, m_hash) {
|
||||
if (ci->m_inode == inode) {
|
||||
if (ci->m_de == de) {
|
||||
if (atomic_inc_not_zero(&ci->m_count))
|
||||
ret_ci = ci;
|
||||
break;
|
||||
@ -84,26 +84,16 @@ static struct ksmbd_inode *__ksmbd_inode_lookup(struct inode *inode)
|
||||
|
||||
static struct ksmbd_inode *ksmbd_inode_lookup(struct ksmbd_file *fp)
|
||||
{
|
||||
return __ksmbd_inode_lookup(file_inode(fp->filp));
|
||||
return __ksmbd_inode_lookup(fp->filp->f_path.dentry);
|
||||
}
|
||||
|
||||
static struct ksmbd_inode *ksmbd_inode_lookup_by_vfsinode(struct inode *inode)
|
||||
{
|
||||
struct ksmbd_inode *ci;
|
||||
|
||||
read_lock(&inode_hash_lock);
|
||||
ci = __ksmbd_inode_lookup(inode);
|
||||
read_unlock(&inode_hash_lock);
|
||||
return ci;
|
||||
}
|
||||
|
||||
int ksmbd_query_inode_status(struct inode *inode)
|
||||
int ksmbd_query_inode_status(struct dentry *dentry)
|
||||
{
|
||||
struct ksmbd_inode *ci;
|
||||
int ret = KSMBD_INODE_STATUS_UNKNOWN;
|
||||
|
||||
read_lock(&inode_hash_lock);
|
||||
ci = __ksmbd_inode_lookup(inode);
|
||||
ci = __ksmbd_inode_lookup(dentry);
|
||||
if (ci) {
|
||||
ret = KSMBD_INODE_STATUS_OK;
|
||||
if (ci->m_flags & (S_DEL_PENDING | S_DEL_ON_CLS))
|
||||
@ -143,7 +133,7 @@ void ksmbd_fd_set_delete_on_close(struct ksmbd_file *fp,
|
||||
static void ksmbd_inode_hash(struct ksmbd_inode *ci)
|
||||
{
|
||||
struct hlist_head *b = inode_hashtable +
|
||||
inode_hash(ci->m_inode->i_sb, ci->m_inode->i_ino);
|
||||
inode_hash(d_inode(ci->m_de)->i_sb, (unsigned long)ci->m_de);
|
||||
|
||||
hlist_add_head(&ci->m_hash, b);
|
||||
}
|
||||
@ -157,7 +147,6 @@ static void ksmbd_inode_unhash(struct ksmbd_inode *ci)
|
||||
|
||||
static int ksmbd_inode_init(struct ksmbd_inode *ci, struct ksmbd_file *fp)
|
||||
{
|
||||
ci->m_inode = file_inode(fp->filp);
|
||||
atomic_set(&ci->m_count, 1);
|
||||
atomic_set(&ci->op_count, 0);
|
||||
atomic_set(&ci->sop_count, 0);
|
||||
@ -166,6 +155,7 @@ static int ksmbd_inode_init(struct ksmbd_inode *ci, struct ksmbd_file *fp)
|
||||
INIT_LIST_HEAD(&ci->m_fp_list);
|
||||
INIT_LIST_HEAD(&ci->m_op_list);
|
||||
rwlock_init(&ci->m_lock);
|
||||
ci->m_de = fp->filp->f_path.dentry;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -488,12 +478,15 @@ struct ksmbd_file *ksmbd_lookup_fd_cguid(char *cguid)
|
||||
return fp;
|
||||
}
|
||||
|
||||
struct ksmbd_file *ksmbd_lookup_fd_inode(struct inode *inode)
|
||||
struct ksmbd_file *ksmbd_lookup_fd_inode(struct dentry *dentry)
|
||||
{
|
||||
struct ksmbd_file *lfp;
|
||||
struct ksmbd_inode *ci;
|
||||
struct inode *inode = d_inode(dentry);
|
||||
|
||||
ci = ksmbd_inode_lookup_by_vfsinode(inode);
|
||||
read_lock(&inode_hash_lock);
|
||||
ci = __ksmbd_inode_lookup(dentry);
|
||||
read_unlock(&inode_hash_lock);
|
||||
if (!ci)
|
||||
return NULL;
|
||||
|
||||
|
@ -51,7 +51,7 @@ struct ksmbd_inode {
|
||||
atomic_t op_count;
|
||||
/* opinfo count for streams */
|
||||
atomic_t sop_count;
|
||||
struct inode *m_inode;
|
||||
struct dentry *m_de;
|
||||
unsigned int m_flags;
|
||||
struct hlist_node m_hash;
|
||||
struct list_head m_fp_list;
|
||||
@ -140,7 +140,7 @@ struct ksmbd_file *ksmbd_lookup_fd_slow(struct ksmbd_work *work, u64 id,
|
||||
void ksmbd_fd_put(struct ksmbd_work *work, struct ksmbd_file *fp);
|
||||
struct ksmbd_file *ksmbd_lookup_durable_fd(unsigned long long id);
|
||||
struct ksmbd_file *ksmbd_lookup_fd_cguid(char *cguid);
|
||||
struct ksmbd_file *ksmbd_lookup_fd_inode(struct inode *inode);
|
||||
struct ksmbd_file *ksmbd_lookup_fd_inode(struct dentry *dentry);
|
||||
unsigned int ksmbd_open_durable_fd(struct ksmbd_file *fp);
|
||||
struct ksmbd_file *ksmbd_open_fd(struct ksmbd_work *work, struct file *filp);
|
||||
void ksmbd_close_tree_conn_fds(struct ksmbd_work *work);
|
||||
@ -164,7 +164,7 @@ enum KSMBD_INODE_STATUS {
|
||||
KSMBD_INODE_STATUS_PENDING_DELETE,
|
||||
};
|
||||
|
||||
int ksmbd_query_inode_status(struct inode *inode);
|
||||
int ksmbd_query_inode_status(struct dentry *dentry);
|
||||
bool ksmbd_inode_pending_delete(struct ksmbd_file *fp);
|
||||
void ksmbd_set_inode_pending_delete(struct ksmbd_file *fp);
|
||||
void ksmbd_clear_inode_pending_delete(struct ksmbd_file *fp);
|
||||
|
Loading…
Reference in New Issue
Block a user