Import of kernel-6.12.0-211.49.1.el10_2
This commit is contained in:
parent
1d2c3ecdad
commit
e9d74aef89
@ -12,7 +12,7 @@ RHEL_MINOR = 2
|
||||
#
|
||||
# Use this spot to avoid future merge conflicts.
|
||||
# Do not trim this comment.
|
||||
RHEL_RELEASE = 211.47.1
|
||||
RHEL_RELEASE = 211.49.1
|
||||
|
||||
#
|
||||
# RHEL_REBASE_NUM
|
||||
|
||||
@ -3046,7 +3046,7 @@ static struct request *blk_mq_get_new_requests(struct request_queue *q,
|
||||
/*
|
||||
* Check if there is a suitable cached request and return it.
|
||||
*/
|
||||
static struct request *blk_mq_peek_cached_request(struct blk_plug *plug,
|
||||
static struct request *blk_mq_get_cached_request(struct blk_plug *plug,
|
||||
struct request_queue *q, blk_opf_t opf)
|
||||
{
|
||||
enum hctx_type type = blk_mq_get_hctx_type(opf);
|
||||
@ -3062,27 +3062,10 @@ static struct request *blk_mq_peek_cached_request(struct blk_plug *plug,
|
||||
return NULL;
|
||||
if (op_is_flush(rq->cmd_flags) != op_is_flush(opf))
|
||||
return NULL;
|
||||
rq_list_pop(&plug->cached_rqs);
|
||||
return rq;
|
||||
}
|
||||
|
||||
static void blk_mq_use_cached_rq(struct request *rq, struct blk_plug *plug,
|
||||
struct bio *bio)
|
||||
{
|
||||
if (rq_list_pop(&plug->cached_rqs) != rq)
|
||||
WARN_ON_ONCE(1);
|
||||
|
||||
/*
|
||||
* If any qos ->throttle() end up blocking, we will have flushed the
|
||||
* plug and hence killed the cached_rq list as well. Pop this entry
|
||||
* before we throttle.
|
||||
*/
|
||||
rq_qos_throttle(rq->q, bio);
|
||||
|
||||
blk_mq_rq_time_init(rq, blk_time_get_ns());
|
||||
rq->cmd_flags = bio->bi_opf;
|
||||
INIT_LIST_HEAD(&rq->queuelist);
|
||||
}
|
||||
|
||||
static bool bio_unaligned(const struct bio *bio, struct request_queue *q)
|
||||
{
|
||||
unsigned int bs_mask = queue_logical_block_size(q) - 1;
|
||||
@ -3120,7 +3103,7 @@ void blk_mq_submit_bio(struct bio *bio)
|
||||
/*
|
||||
* If the plug has a cached request for this queue, try to use it.
|
||||
*/
|
||||
rq = blk_mq_peek_cached_request(plug, q, bio->bi_opf);
|
||||
rq = blk_mq_get_cached_request(plug, q, bio->bi_opf);
|
||||
|
||||
/*
|
||||
* A BIO that was released from a zone write plug has already been
|
||||
@ -3177,7 +3160,10 @@ void blk_mq_submit_bio(struct bio *bio)
|
||||
|
||||
new_request:
|
||||
if (rq) {
|
||||
blk_mq_use_cached_rq(rq, plug, bio);
|
||||
rq_qos_throttle(rq->q, bio);
|
||||
blk_mq_rq_time_init(rq, blk_time_get_ns());
|
||||
rq->cmd_flags = bio->bi_opf;
|
||||
INIT_LIST_HEAD(&rq->queuelist);
|
||||
} else {
|
||||
rq = blk_mq_get_new_requests(q, plug, bio);
|
||||
if (unlikely(!rq)) {
|
||||
@ -3223,12 +3209,10 @@ new_request:
|
||||
return;
|
||||
|
||||
queue_exit:
|
||||
/*
|
||||
* Don't drop the queue reference if we were trying to use a cached
|
||||
* request and thus didn't acquire one.
|
||||
*/
|
||||
if (!rq)
|
||||
blk_queue_exit(q);
|
||||
else
|
||||
rq_list_add_head(&plug->cached_rqs, rq);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_BLK_MQ_STACKING
|
||||
|
||||
@ -69,6 +69,9 @@ static void pcrypt_aead_done(void *data, int err)
|
||||
struct pcrypt_request *preq = aead_request_ctx(req);
|
||||
struct padata_priv *padata = pcrypt_request_padata(preq);
|
||||
|
||||
if (err == -EINPROGRESS)
|
||||
return;
|
||||
|
||||
padata->info = err;
|
||||
|
||||
padata_do_serial(padata);
|
||||
@ -82,7 +85,7 @@ static void pcrypt_aead_enc(struct padata_priv *padata)
|
||||
|
||||
ret = crypto_aead_encrypt(req);
|
||||
|
||||
if (ret == -EINPROGRESS)
|
||||
if (ret == -EINPROGRESS || ret == -EBUSY)
|
||||
return;
|
||||
|
||||
padata->info = ret;
|
||||
@ -133,7 +136,7 @@ static void pcrypt_aead_dec(struct padata_priv *padata)
|
||||
|
||||
ret = crypto_aead_decrypt(req);
|
||||
|
||||
if (ret == -EINPROGRESS)
|
||||
if (ret == -EINPROGRESS || ret == -EBUSY)
|
||||
return;
|
||||
|
||||
padata->info = ret;
|
||||
|
||||
@ -262,12 +262,19 @@ void amdgpu_gart_table_ram_free(struct amdgpu_device *adev)
|
||||
*/
|
||||
int amdgpu_gart_table_vram_alloc(struct amdgpu_device *adev)
|
||||
{
|
||||
int r;
|
||||
|
||||
if (adev->gart.bo != NULL)
|
||||
return 0;
|
||||
|
||||
return amdgpu_bo_create_kernel(adev, adev->gart.table_size, PAGE_SIZE,
|
||||
AMDGPU_GEM_DOMAIN_VRAM, &adev->gart.bo,
|
||||
NULL, (void *)&adev->gart.ptr);
|
||||
r = amdgpu_bo_create_kernel(adev, adev->gart.table_size, PAGE_SIZE,
|
||||
AMDGPU_GEM_DOMAIN_VRAM, &adev->gart.bo,
|
||||
NULL, (void *)&adev->gart.ptr);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
memset_io(adev->gart.ptr, adev->gart.gart_pte_flags, adev->gart.table_size);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -112,47 +112,6 @@ amdgpu_gem_update_timeline_node(struct drm_file *filp,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
amdgpu_gem_update_bo_mapping(struct drm_file *filp,
|
||||
struct amdgpu_bo_va *bo_va,
|
||||
uint32_t operation,
|
||||
uint64_t point,
|
||||
struct dma_fence *fence,
|
||||
struct drm_syncobj *syncobj,
|
||||
struct dma_fence_chain *chain)
|
||||
{
|
||||
struct amdgpu_bo *bo = bo_va ? bo_va->base.bo : NULL;
|
||||
struct amdgpu_fpriv *fpriv = filp->driver_priv;
|
||||
struct amdgpu_vm *vm = &fpriv->vm;
|
||||
struct dma_fence *last_update;
|
||||
|
||||
if (!syncobj)
|
||||
return;
|
||||
|
||||
/* Find the last update fence */
|
||||
switch (operation) {
|
||||
case AMDGPU_VA_OP_MAP:
|
||||
case AMDGPU_VA_OP_REPLACE:
|
||||
if (bo && (bo->tbo.base.resv == vm->root.bo->tbo.base.resv))
|
||||
last_update = vm->last_update;
|
||||
else
|
||||
last_update = bo_va->last_pt_update;
|
||||
break;
|
||||
case AMDGPU_VA_OP_UNMAP:
|
||||
case AMDGPU_VA_OP_CLEAR:
|
||||
last_update = fence;
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
/* Add fence to timeline */
|
||||
if (!point)
|
||||
drm_syncobj_replace_fence(syncobj, last_update);
|
||||
else
|
||||
drm_syncobj_add_point(syncobj, chain, last_update, point);
|
||||
}
|
||||
|
||||
static vm_fault_t amdgpu_gem_fault(struct vm_fault *vmf)
|
||||
{
|
||||
struct ttm_buffer_object *bo = vmf->vma->vm_private_data;
|
||||
@ -761,16 +720,27 @@ amdgpu_gem_va_update_vm(struct amdgpu_device *adev,
|
||||
struct amdgpu_bo_va *bo_va,
|
||||
uint32_t operation)
|
||||
{
|
||||
struct dma_fence *fence = dma_fence_get_stub();
|
||||
int r;
|
||||
struct dma_fence *fence;
|
||||
int r = 0;
|
||||
|
||||
/* Always start from the VM's existing last update fence. */
|
||||
fence = dma_fence_get(vm->last_update);
|
||||
|
||||
if (!amdgpu_vm_ready(vm))
|
||||
return fence;
|
||||
|
||||
/*
|
||||
* First clean up any freed mappings in the VM.
|
||||
*
|
||||
* amdgpu_vm_clear_freed() may replace @fence with a new fence if it
|
||||
* schedules GPU work. If nothing needs clearing, @fence can remain as
|
||||
* the original vm->last_update.
|
||||
*/
|
||||
r = amdgpu_vm_clear_freed(adev, vm, &fence);
|
||||
if (r)
|
||||
goto error;
|
||||
|
||||
/* For MAP/REPLACE we also need to update the BO mappings. */
|
||||
if (operation == AMDGPU_VA_OP_MAP ||
|
||||
operation == AMDGPU_VA_OP_REPLACE) {
|
||||
r = amdgpu_vm_bo_update(adev, bo_va, false);
|
||||
@ -778,7 +748,46 @@ amdgpu_gem_va_update_vm(struct amdgpu_device *adev,
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* Always update PDEs after we touched the mappings. */
|
||||
r = amdgpu_vm_update_pdes(adev, vm, false);
|
||||
if (r)
|
||||
goto error;
|
||||
|
||||
/*
|
||||
* Decide which fence best represents the last update:
|
||||
*
|
||||
* MAP/REPLACE:
|
||||
* - For always-valid mappings, use vm->last_update.
|
||||
* - Otherwise, export bo_va->last_pt_update.
|
||||
*
|
||||
* UNMAP/CLEAR:
|
||||
* Keep the fence returned by amdgpu_vm_clear_freed(). If no work was
|
||||
* needed, it can remain as vm->last_pt_update.
|
||||
*
|
||||
* The VM and BO update fences are always initialized to a valid value.
|
||||
* vm->last_update and bo_va->last_pt_update always start as valid fences.
|
||||
* and are never expected to be NULL.
|
||||
*/
|
||||
switch (operation) {
|
||||
case AMDGPU_VA_OP_MAP:
|
||||
case AMDGPU_VA_OP_REPLACE:
|
||||
/*
|
||||
* For MAP/REPLACE, return the page table update fence for the
|
||||
* mapping we just modified. bo_va is expected to be valid here.
|
||||
*/
|
||||
dma_fence_put(fence);
|
||||
|
||||
if (amdgpu_vm_is_bo_always_valid(vm, bo_va->base.bo))
|
||||
fence = dma_fence_get(vm->last_update);
|
||||
else
|
||||
fence = dma_fence_get(bo_va->last_pt_update);
|
||||
break;
|
||||
case AMDGPU_VA_OP_UNMAP:
|
||||
case AMDGPU_VA_OP_CLEAR:
|
||||
default:
|
||||
/* keep @fence as returned by amdgpu_vm_clear_freed() */
|
||||
break;
|
||||
}
|
||||
|
||||
error:
|
||||
if (r && r != -ERESTARTSYS)
|
||||
@ -810,6 +819,7 @@ int amdgpu_gem_va_ioctl(struct drm_device *dev, void *data,
|
||||
uint64_t vm_size;
|
||||
int r = 0;
|
||||
|
||||
/* Validate virtual address range against reserved regions. */
|
||||
if (args->va_address < AMDGPU_VA_RESERVED_BOTTOM) {
|
||||
dev_dbg(dev->dev,
|
||||
"va_address 0x%llx is in reserved area 0x%llx\n",
|
||||
@ -843,6 +853,7 @@ int amdgpu_gem_va_ioctl(struct drm_device *dev, void *data,
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Validate operation type. */
|
||||
switch (args->operation) {
|
||||
case AMDGPU_VA_OP_MAP:
|
||||
case AMDGPU_VA_OP_UNMAP:
|
||||
@ -866,6 +877,7 @@ int amdgpu_gem_va_ioctl(struct drm_device *dev, void *data,
|
||||
abo = NULL;
|
||||
}
|
||||
|
||||
/* Add input syncobj fences (if any) for synchronization. */
|
||||
r = amdgpu_gem_add_input_fence(filp,
|
||||
args->input_fence_syncobj_handles,
|
||||
args->num_syncobj_handles);
|
||||
@ -888,6 +900,7 @@ int amdgpu_gem_va_ioctl(struct drm_device *dev, void *data,
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* Resolve the BO-VA mapping for this VM/BO combination. */
|
||||
if (abo) {
|
||||
bo_va = amdgpu_vm_bo_find(&fpriv->vm, abo);
|
||||
if (!bo_va) {
|
||||
@ -900,6 +913,11 @@ int amdgpu_gem_va_ioctl(struct drm_device *dev, void *data,
|
||||
bo_va = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Prepare the timeline syncobj node if the user requested a VM
|
||||
* timeline update. This only allocates/looks up the syncobj and
|
||||
* chain node; the actual fence is attached later.
|
||||
*/
|
||||
r = amdgpu_gem_update_timeline_node(filp,
|
||||
args->vm_timeline_syncobj_out,
|
||||
args->vm_timeline_point,
|
||||
@ -931,18 +949,30 @@ int amdgpu_gem_va_ioctl(struct drm_device *dev, void *data,
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* Once the VA operation is done, update the VM and obtain the fence
|
||||
* that represents the last relevant update for this mapping. This
|
||||
* fence can then be exported to the user-visible VM timeline.
|
||||
*/
|
||||
if (!r && !(args->flags & AMDGPU_VM_DELAY_UPDATE) && !adev->debug_vm) {
|
||||
fence = amdgpu_gem_va_update_vm(adev, &fpriv->vm, bo_va,
|
||||
args->operation);
|
||||
|
||||
if (timeline_syncobj)
|
||||
amdgpu_gem_update_bo_mapping(filp, bo_va,
|
||||
args->operation,
|
||||
args->vm_timeline_point,
|
||||
fence, timeline_syncobj,
|
||||
timeline_chain);
|
||||
else
|
||||
dma_fence_put(fence);
|
||||
if (timeline_syncobj && fence) {
|
||||
if (!args->vm_timeline_point) {
|
||||
/* Replace the existing fence when no point is given. */
|
||||
drm_syncobj_replace_fence(timeline_syncobj,
|
||||
fence);
|
||||
} else {
|
||||
/* Attach the last-update fence at a specific point. */
|
||||
drm_syncobj_add_point(timeline_syncobj,
|
||||
timeline_chain,
|
||||
fence,
|
||||
args->vm_timeline_point);
|
||||
}
|
||||
}
|
||||
dma_fence_put(fence);
|
||||
|
||||
}
|
||||
|
||||
|
||||
@ -51,8 +51,6 @@
|
||||
#include "amdgpu_amdkfd.h"
|
||||
#include "amdgpu_hmm.h"
|
||||
|
||||
#define MAX_WALK_BYTE (2UL << 30)
|
||||
|
||||
/**
|
||||
* amdgpu_hmm_invalidate_gfx - callback to notify about mm change
|
||||
*
|
||||
@ -172,9 +170,10 @@ int amdgpu_hmm_range_get_pages(struct mmu_interval_notifier *notifier,
|
||||
{
|
||||
struct hmm_range *hmm_range;
|
||||
unsigned long end;
|
||||
const u64 max_bytes = SZ_2G;
|
||||
unsigned long timeout;
|
||||
unsigned long *pfns;
|
||||
int r = 0;
|
||||
int r;
|
||||
|
||||
hmm_range = kzalloc(sizeof(*hmm_range), GFP_KERNEL);
|
||||
if (unlikely(!hmm_range))
|
||||
@ -195,8 +194,9 @@ int amdgpu_hmm_range_get_pages(struct mmu_interval_notifier *notifier,
|
||||
end = start + npages * PAGE_SIZE;
|
||||
hmm_range->dev_private_owner = owner;
|
||||
|
||||
hmm_range->notifier_seq = mmu_interval_read_begin(notifier);
|
||||
do {
|
||||
hmm_range->end = min(hmm_range->start + MAX_WALK_BYTE, end);
|
||||
hmm_range->end = min(hmm_range->start + max_bytes, end);
|
||||
|
||||
pr_debug("hmm range: start = 0x%lx, end = 0x%lx",
|
||||
hmm_range->start, hmm_range->end);
|
||||
@ -204,7 +204,6 @@ int amdgpu_hmm_range_get_pages(struct mmu_interval_notifier *notifier,
|
||||
timeout = jiffies + msecs_to_jiffies(HMM_RANGE_DEFAULT_TIMEOUT);
|
||||
|
||||
retry:
|
||||
hmm_range->notifier_seq = mmu_interval_read_begin(notifier);
|
||||
r = hmm_range_fault(hmm_range);
|
||||
if (unlikely(r)) {
|
||||
if (r == -EBUSY && !time_after(jiffies, timeout))
|
||||
@ -214,7 +213,7 @@ retry:
|
||||
|
||||
if (hmm_range->end == end)
|
||||
break;
|
||||
hmm_range->hmm_pfns += MAX_WALK_BYTE >> PAGE_SHIFT;
|
||||
hmm_range->hmm_pfns += max_bytes >> PAGE_SHIFT;
|
||||
hmm_range->start = hmm_range->end;
|
||||
} while (hmm_range->end < end);
|
||||
|
||||
|
||||
@ -401,27 +401,25 @@ static int kfd_dbg_get_dev_watch_id(struct kfd_process_device *pdd, int *watch_i
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
static void kfd_dbg_clear_dev_watch_id(struct kfd_process_device *pdd, int watch_id)
|
||||
static void kfd_dbg_clear_dev_watch_id(struct kfd_process_device *pdd, u32 watch_id)
|
||||
{
|
||||
spin_lock(&pdd->dev->watch_points_lock);
|
||||
|
||||
/* process owns device watch point so safe to clear */
|
||||
if ((pdd->alloc_watch_ids >> watch_id) & 0x1) {
|
||||
pdd->alloc_watch_ids &= ~(0x1 << watch_id);
|
||||
pdd->dev->alloc_watch_ids &= ~(0x1 << watch_id);
|
||||
if (pdd->alloc_watch_ids & BIT(watch_id)) {
|
||||
pdd->alloc_watch_ids &= ~BIT(watch_id);
|
||||
pdd->dev->alloc_watch_ids &= ~BIT(watch_id);
|
||||
}
|
||||
|
||||
spin_unlock(&pdd->dev->watch_points_lock);
|
||||
}
|
||||
|
||||
static bool kfd_dbg_owns_dev_watch_id(struct kfd_process_device *pdd, int watch_id)
|
||||
static bool kfd_dbg_owns_dev_watch_id(struct kfd_process_device *pdd, u32 watch_id)
|
||||
{
|
||||
bool owns_watch_id = false;
|
||||
|
||||
spin_lock(&pdd->dev->watch_points_lock);
|
||||
owns_watch_id = watch_id < MAX_WATCH_ADDRESSES &&
|
||||
((pdd->alloc_watch_ids >> watch_id) & 0x1);
|
||||
|
||||
owns_watch_id = pdd->alloc_watch_ids & BIT(watch_id);
|
||||
spin_unlock(&pdd->dev->watch_points_lock);
|
||||
|
||||
return owns_watch_id;
|
||||
@ -432,6 +430,9 @@ int kfd_dbg_trap_clear_dev_address_watch(struct kfd_process_device *pdd,
|
||||
{
|
||||
int r;
|
||||
|
||||
if (watch_id >= MAX_WATCH_ADDRESSES)
|
||||
return -EINVAL;
|
||||
|
||||
if (!kfd_dbg_owns_dev_watch_id(pdd, watch_id))
|
||||
return -EINVAL;
|
||||
|
||||
@ -469,6 +470,9 @@ int kfd_dbg_trap_set_dev_address_watch(struct kfd_process_device *pdd,
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
if (*watch_id >= MAX_WATCH_ADDRESSES)
|
||||
return -EINVAL;
|
||||
|
||||
if (!pdd->dev->kfd->shared_resources.enable_mes) {
|
||||
r = debug_lock_and_unmap(pdd->dev->dqm);
|
||||
if (r) {
|
||||
|
||||
@ -331,6 +331,12 @@ static int kfd_event_page_set(struct kfd_process *p, void *kernel_address,
|
||||
if (p->signal_page)
|
||||
return -EBUSY;
|
||||
|
||||
if (size < KFD_SIGNAL_EVENT_LIMIT * 8) {
|
||||
pr_err("Event page size %llu is too small, need at least %lu bytes\n",
|
||||
size, (unsigned long)(KFD_SIGNAL_EVENT_LIMIT * 8));
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
page = kzalloc(sizeof(*page), GFP_KERNEL);
|
||||
if (!page)
|
||||
return -ENOMEM;
|
||||
|
||||
@ -334,8 +334,7 @@ static void checkpoint_mqd(struct mqd_manager *mm, void *mqd, void *mqd_dst, voi
|
||||
|
||||
static void restore_mqd(struct mqd_manager *mm, void **mqd,
|
||||
struct kfd_mem_obj *mqd_mem_obj, uint64_t *gart_addr,
|
||||
struct queue_properties *qp,
|
||||
const void *mqd_src,
|
||||
struct queue_properties *qp, const void *mqd_src,
|
||||
const void *ctl_stack_src, const u32 ctl_stack_size)
|
||||
{
|
||||
uint64_t addr;
|
||||
@ -351,14 +350,48 @@ static void restore_mqd(struct mqd_manager *mm, void **mqd,
|
||||
*gart_addr = addr;
|
||||
|
||||
m->cp_hqd_pq_doorbell_control =
|
||||
qp->doorbell_off <<
|
||||
CP_HQD_PQ_DOORBELL_CONTROL__DOORBELL_OFFSET__SHIFT;
|
||||
pr_debug("cp_hqd_pq_doorbell_control 0x%x\n",
|
||||
m->cp_hqd_pq_doorbell_control);
|
||||
qp->doorbell_off << CP_HQD_PQ_DOORBELL_CONTROL__DOORBELL_OFFSET__SHIFT;
|
||||
pr_debug("cp_hqd_pq_doorbell_control 0x%x\n", m->cp_hqd_pq_doorbell_control);
|
||||
|
||||
qp->is_active = 0;
|
||||
}
|
||||
|
||||
static void checkpoint_mqd_sdma(struct mqd_manager *mm,
|
||||
void *mqd,
|
||||
void *mqd_dst,
|
||||
void *ctl_stack_dst)
|
||||
{
|
||||
struct v11_sdma_mqd *m;
|
||||
|
||||
m = get_sdma_mqd(mqd);
|
||||
|
||||
memcpy(mqd_dst, m, sizeof(struct v11_sdma_mqd));
|
||||
}
|
||||
|
||||
static void restore_mqd_sdma(struct mqd_manager *mm, void **mqd,
|
||||
struct kfd_mem_obj *mqd_mem_obj, uint64_t *gart_addr,
|
||||
struct queue_properties *qp,
|
||||
const void *mqd_src,
|
||||
const void *ctl_stack_src,
|
||||
const u32 ctl_stack_size)
|
||||
{
|
||||
uint64_t addr;
|
||||
struct v11_sdma_mqd *m;
|
||||
|
||||
m = (struct v11_sdma_mqd *) mqd_mem_obj->cpu_ptr;
|
||||
addr = mqd_mem_obj->gpu_addr;
|
||||
|
||||
memcpy(m, mqd_src, sizeof(*m));
|
||||
|
||||
m->sdmax_rlcx_doorbell_offset =
|
||||
qp->doorbell_off << SDMA0_QUEUE0_DOORBELL_OFFSET__OFFSET__SHIFT;
|
||||
|
||||
*mqd = m;
|
||||
if (gart_addr)
|
||||
*gart_addr = addr;
|
||||
|
||||
qp->is_active = 0;
|
||||
}
|
||||
|
||||
static void init_mqd_hiq(struct mqd_manager *mm, void **mqd,
|
||||
struct kfd_mem_obj *mqd_mem_obj, uint64_t *gart_addr,
|
||||
@ -543,8 +576,8 @@ struct mqd_manager *mqd_manager_init_v11(enum KFD_MQD_TYPE type,
|
||||
mqd->update_mqd = update_mqd_sdma;
|
||||
mqd->destroy_mqd = kfd_destroy_mqd_sdma;
|
||||
mqd->is_occupied = kfd_is_occupied_sdma;
|
||||
mqd->checkpoint_mqd = checkpoint_mqd;
|
||||
mqd->restore_mqd = restore_mqd;
|
||||
mqd->checkpoint_mqd = checkpoint_mqd_sdma;
|
||||
mqd->restore_mqd = restore_mqd_sdma;
|
||||
mqd->mqd_size = sizeof(struct v11_sdma_mqd);
|
||||
mqd->mqd_stride = kfd_mqd_stride;
|
||||
#if defined(CONFIG_DEBUG_FS)
|
||||
|
||||
@ -288,8 +288,8 @@ bool dal_vector_reserve(struct vector *vector, uint32_t capacity)
|
||||
if (capacity <= vector->capacity)
|
||||
return true;
|
||||
|
||||
new_container = krealloc(vector->container,
|
||||
capacity * vector->struct_size, GFP_KERNEL);
|
||||
new_container = krealloc_array(vector->container,
|
||||
capacity, vector->struct_size, GFP_KERNEL);
|
||||
|
||||
if (new_container) {
|
||||
vector->container = new_container;
|
||||
|
||||
@ -2584,14 +2584,16 @@ static enum bp_result get_integrated_info_v11(
|
||||
info_v11->extdispconninfo.checksum;
|
||||
|
||||
info->dp0_ext_hdmi_slv_addr = info_v11->dp0_retimer_set.HdmiSlvAddr;
|
||||
info->dp0_ext_hdmi_reg_num = info_v11->dp0_retimer_set.HdmiRegNum;
|
||||
info->dp0_ext_hdmi_reg_num = min_t(u8, info_v11->dp0_retimer_set.HdmiRegNum,
|
||||
ARRAY_SIZE(info->dp0_ext_hdmi_reg_settings));
|
||||
for (i = 0; i < info->dp0_ext_hdmi_reg_num; i++) {
|
||||
info->dp0_ext_hdmi_reg_settings[i].i2c_reg_index =
|
||||
info_v11->dp0_retimer_set.HdmiRegSetting[i].ucI2cRegIndex;
|
||||
info->dp0_ext_hdmi_reg_settings[i].i2c_reg_val =
|
||||
info_v11->dp0_retimer_set.HdmiRegSetting[i].ucI2cRegVal;
|
||||
}
|
||||
info->dp0_ext_hdmi_6g_reg_num = info_v11->dp0_retimer_set.Hdmi6GRegNum;
|
||||
info->dp0_ext_hdmi_6g_reg_num = min_t(u8, info_v11->dp0_retimer_set.Hdmi6GRegNum,
|
||||
ARRAY_SIZE(info->dp0_ext_hdmi_6g_reg_settings));
|
||||
for (i = 0; i < info->dp0_ext_hdmi_6g_reg_num; i++) {
|
||||
info->dp0_ext_hdmi_6g_reg_settings[i].i2c_reg_index =
|
||||
info_v11->dp0_retimer_set.Hdmi6GhzRegSetting[i].ucI2cRegIndex;
|
||||
@ -2600,14 +2602,16 @@ static enum bp_result get_integrated_info_v11(
|
||||
}
|
||||
|
||||
info->dp1_ext_hdmi_slv_addr = info_v11->dp1_retimer_set.HdmiSlvAddr;
|
||||
info->dp1_ext_hdmi_reg_num = info_v11->dp1_retimer_set.HdmiRegNum;
|
||||
info->dp1_ext_hdmi_reg_num = min_t(u8, info_v11->dp1_retimer_set.HdmiRegNum,
|
||||
ARRAY_SIZE(info->dp1_ext_hdmi_reg_settings));
|
||||
for (i = 0; i < info->dp1_ext_hdmi_reg_num; i++) {
|
||||
info->dp1_ext_hdmi_reg_settings[i].i2c_reg_index =
|
||||
info_v11->dp1_retimer_set.HdmiRegSetting[i].ucI2cRegIndex;
|
||||
info->dp1_ext_hdmi_reg_settings[i].i2c_reg_val =
|
||||
info_v11->dp1_retimer_set.HdmiRegSetting[i].ucI2cRegVal;
|
||||
}
|
||||
info->dp1_ext_hdmi_6g_reg_num = info_v11->dp1_retimer_set.Hdmi6GRegNum;
|
||||
info->dp1_ext_hdmi_6g_reg_num = min_t(u8, info_v11->dp1_retimer_set.Hdmi6GRegNum,
|
||||
ARRAY_SIZE(info->dp1_ext_hdmi_6g_reg_settings));
|
||||
for (i = 0; i < info->dp1_ext_hdmi_6g_reg_num; i++) {
|
||||
info->dp1_ext_hdmi_6g_reg_settings[i].i2c_reg_index =
|
||||
info_v11->dp1_retimer_set.Hdmi6GhzRegSetting[i].ucI2cRegIndex;
|
||||
@ -2616,14 +2620,16 @@ static enum bp_result get_integrated_info_v11(
|
||||
}
|
||||
|
||||
info->dp2_ext_hdmi_slv_addr = info_v11->dp2_retimer_set.HdmiSlvAddr;
|
||||
info->dp2_ext_hdmi_reg_num = info_v11->dp2_retimer_set.HdmiRegNum;
|
||||
info->dp2_ext_hdmi_reg_num = min_t(u8, info_v11->dp2_retimer_set.HdmiRegNum,
|
||||
ARRAY_SIZE(info->dp2_ext_hdmi_reg_settings));
|
||||
for (i = 0; i < info->dp2_ext_hdmi_reg_num; i++) {
|
||||
info->dp2_ext_hdmi_reg_settings[i].i2c_reg_index =
|
||||
info_v11->dp2_retimer_set.HdmiRegSetting[i].ucI2cRegIndex;
|
||||
info->dp2_ext_hdmi_reg_settings[i].i2c_reg_val =
|
||||
info_v11->dp2_retimer_set.HdmiRegSetting[i].ucI2cRegVal;
|
||||
}
|
||||
info->dp2_ext_hdmi_6g_reg_num = info_v11->dp2_retimer_set.Hdmi6GRegNum;
|
||||
info->dp2_ext_hdmi_6g_reg_num = min_t(u8, info_v11->dp2_retimer_set.Hdmi6GRegNum,
|
||||
ARRAY_SIZE(info->dp2_ext_hdmi_6g_reg_settings));
|
||||
for (i = 0; i < info->dp2_ext_hdmi_6g_reg_num; i++) {
|
||||
info->dp2_ext_hdmi_6g_reg_settings[i].i2c_reg_index =
|
||||
info_v11->dp2_retimer_set.Hdmi6GhzRegSetting[i].ucI2cRegIndex;
|
||||
@ -2632,14 +2638,16 @@ static enum bp_result get_integrated_info_v11(
|
||||
}
|
||||
|
||||
info->dp3_ext_hdmi_slv_addr = info_v11->dp3_retimer_set.HdmiSlvAddr;
|
||||
info->dp3_ext_hdmi_reg_num = info_v11->dp3_retimer_set.HdmiRegNum;
|
||||
info->dp3_ext_hdmi_reg_num = min_t(u8, info_v11->dp3_retimer_set.HdmiRegNum,
|
||||
ARRAY_SIZE(info->dp3_ext_hdmi_reg_settings));
|
||||
for (i = 0; i < info->dp3_ext_hdmi_reg_num; i++) {
|
||||
info->dp3_ext_hdmi_reg_settings[i].i2c_reg_index =
|
||||
info_v11->dp3_retimer_set.HdmiRegSetting[i].ucI2cRegIndex;
|
||||
info->dp3_ext_hdmi_reg_settings[i].i2c_reg_val =
|
||||
info_v11->dp3_retimer_set.HdmiRegSetting[i].ucI2cRegVal;
|
||||
}
|
||||
info->dp3_ext_hdmi_6g_reg_num = info_v11->dp3_retimer_set.Hdmi6GRegNum;
|
||||
info->dp3_ext_hdmi_6g_reg_num = min_t(u8, info_v11->dp3_retimer_set.Hdmi6GRegNum,
|
||||
ARRAY_SIZE(info->dp3_ext_hdmi_6g_reg_settings));
|
||||
for (i = 0; i < info->dp3_ext_hdmi_6g_reg_num; i++) {
|
||||
info->dp3_ext_hdmi_6g_reg_settings[i].i2c_reg_index =
|
||||
info_v11->dp3_retimer_set.Hdmi6GhzRegSetting[i].ucI2cRegIndex;
|
||||
@ -2789,14 +2797,16 @@ static enum bp_result get_integrated_info_v2_1(
|
||||
info->ext_disp_conn_info.checksum =
|
||||
info_v2_1->extdispconninfo.checksum;
|
||||
info->dp0_ext_hdmi_slv_addr = info_v2_1->dp0_retimer_set.HdmiSlvAddr;
|
||||
info->dp0_ext_hdmi_reg_num = info_v2_1->dp0_retimer_set.HdmiRegNum;
|
||||
info->dp0_ext_hdmi_reg_num = min_t(u8, info_v2_1->dp0_retimer_set.HdmiRegNum,
|
||||
ARRAY_SIZE(info->dp0_ext_hdmi_reg_settings));
|
||||
for (i = 0; i < info->dp0_ext_hdmi_reg_num; i++) {
|
||||
info->dp0_ext_hdmi_reg_settings[i].i2c_reg_index =
|
||||
info_v2_1->dp0_retimer_set.HdmiRegSetting[i].ucI2cRegIndex;
|
||||
info->dp0_ext_hdmi_reg_settings[i].i2c_reg_val =
|
||||
info_v2_1->dp0_retimer_set.HdmiRegSetting[i].ucI2cRegVal;
|
||||
}
|
||||
info->dp0_ext_hdmi_6g_reg_num = info_v2_1->dp0_retimer_set.Hdmi6GRegNum;
|
||||
info->dp0_ext_hdmi_6g_reg_num = min_t(u8, info_v2_1->dp0_retimer_set.Hdmi6GRegNum,
|
||||
ARRAY_SIZE(info->dp0_ext_hdmi_6g_reg_settings));
|
||||
for (i = 0; i < info->dp0_ext_hdmi_6g_reg_num; i++) {
|
||||
info->dp0_ext_hdmi_6g_reg_settings[i].i2c_reg_index =
|
||||
info_v2_1->dp0_retimer_set.Hdmi6GhzRegSetting[i].ucI2cRegIndex;
|
||||
@ -2804,14 +2814,16 @@ static enum bp_result get_integrated_info_v2_1(
|
||||
info_v2_1->dp0_retimer_set.Hdmi6GhzRegSetting[i].ucI2cRegVal;
|
||||
}
|
||||
info->dp1_ext_hdmi_slv_addr = info_v2_1->dp1_retimer_set.HdmiSlvAddr;
|
||||
info->dp1_ext_hdmi_reg_num = info_v2_1->dp1_retimer_set.HdmiRegNum;
|
||||
info->dp1_ext_hdmi_reg_num = min_t(u8, info_v2_1->dp1_retimer_set.HdmiRegNum,
|
||||
ARRAY_SIZE(info->dp1_ext_hdmi_reg_settings));
|
||||
for (i = 0; i < info->dp1_ext_hdmi_reg_num; i++) {
|
||||
info->dp1_ext_hdmi_reg_settings[i].i2c_reg_index =
|
||||
info_v2_1->dp1_retimer_set.HdmiRegSetting[i].ucI2cRegIndex;
|
||||
info->dp1_ext_hdmi_reg_settings[i].i2c_reg_val =
|
||||
info_v2_1->dp1_retimer_set.HdmiRegSetting[i].ucI2cRegVal;
|
||||
}
|
||||
info->dp1_ext_hdmi_6g_reg_num = info_v2_1->dp1_retimer_set.Hdmi6GRegNum;
|
||||
info->dp1_ext_hdmi_6g_reg_num = min_t(u8, info_v2_1->dp1_retimer_set.Hdmi6GRegNum,
|
||||
ARRAY_SIZE(info->dp1_ext_hdmi_6g_reg_settings));
|
||||
for (i = 0; i < info->dp1_ext_hdmi_6g_reg_num; i++) {
|
||||
info->dp1_ext_hdmi_6g_reg_settings[i].i2c_reg_index =
|
||||
info_v2_1->dp1_retimer_set.Hdmi6GhzRegSetting[i].ucI2cRegIndex;
|
||||
@ -2819,14 +2831,16 @@ static enum bp_result get_integrated_info_v2_1(
|
||||
info_v2_1->dp1_retimer_set.Hdmi6GhzRegSetting[i].ucI2cRegVal;
|
||||
}
|
||||
info->dp2_ext_hdmi_slv_addr = info_v2_1->dp2_retimer_set.HdmiSlvAddr;
|
||||
info->dp2_ext_hdmi_reg_num = info_v2_1->dp2_retimer_set.HdmiRegNum;
|
||||
info->dp2_ext_hdmi_reg_num = min_t(u8, info_v2_1->dp2_retimer_set.HdmiRegNum,
|
||||
ARRAY_SIZE(info->dp2_ext_hdmi_reg_settings));
|
||||
for (i = 0; i < info->dp2_ext_hdmi_reg_num; i++) {
|
||||
info->dp2_ext_hdmi_reg_settings[i].i2c_reg_index =
|
||||
info_v2_1->dp2_retimer_set.HdmiRegSetting[i].ucI2cRegIndex;
|
||||
info->dp2_ext_hdmi_reg_settings[i].i2c_reg_val =
|
||||
info_v2_1->dp2_retimer_set.HdmiRegSetting[i].ucI2cRegVal;
|
||||
}
|
||||
info->dp2_ext_hdmi_6g_reg_num = info_v2_1->dp2_retimer_set.Hdmi6GRegNum;
|
||||
info->dp2_ext_hdmi_6g_reg_num = min_t(u8, info_v2_1->dp2_retimer_set.Hdmi6GRegNum,
|
||||
ARRAY_SIZE(info->dp2_ext_hdmi_6g_reg_settings));
|
||||
for (i = 0; i < info->dp2_ext_hdmi_6g_reg_num; i++) {
|
||||
info->dp2_ext_hdmi_6g_reg_settings[i].i2c_reg_index =
|
||||
info_v2_1->dp2_retimer_set.Hdmi6GhzRegSetting[i].ucI2cRegIndex;
|
||||
@ -2834,14 +2848,16 @@ static enum bp_result get_integrated_info_v2_1(
|
||||
info_v2_1->dp2_retimer_set.Hdmi6GhzRegSetting[i].ucI2cRegVal;
|
||||
}
|
||||
info->dp3_ext_hdmi_slv_addr = info_v2_1->dp3_retimer_set.HdmiSlvAddr;
|
||||
info->dp3_ext_hdmi_reg_num = info_v2_1->dp3_retimer_set.HdmiRegNum;
|
||||
info->dp3_ext_hdmi_reg_num = min_t(u8, info_v2_1->dp3_retimer_set.HdmiRegNum,
|
||||
ARRAY_SIZE(info->dp3_ext_hdmi_reg_settings));
|
||||
for (i = 0; i < info->dp3_ext_hdmi_reg_num; i++) {
|
||||
info->dp3_ext_hdmi_reg_settings[i].i2c_reg_index =
|
||||
info_v2_1->dp3_retimer_set.HdmiRegSetting[i].ucI2cRegIndex;
|
||||
info->dp3_ext_hdmi_reg_settings[i].i2c_reg_val =
|
||||
info_v2_1->dp3_retimer_set.HdmiRegSetting[i].ucI2cRegVal;
|
||||
}
|
||||
info->dp3_ext_hdmi_6g_reg_num = info_v2_1->dp3_retimer_set.Hdmi6GRegNum;
|
||||
info->dp3_ext_hdmi_6g_reg_num = min_t(u8, info_v2_1->dp3_retimer_set.Hdmi6GRegNum,
|
||||
ARRAY_SIZE(info->dp3_ext_hdmi_6g_reg_settings));
|
||||
for (i = 0; i < info->dp3_ext_hdmi_6g_reg_num; i++) {
|
||||
info->dp3_ext_hdmi_6g_reg_settings[i].i2c_reg_index =
|
||||
info_v2_1->dp3_retimer_set.Hdmi6GhzRegSetting[i].ucI2cRegIndex;
|
||||
|
||||
@ -5884,7 +5884,11 @@ bool dc_process_dmub_aux_transfer_async(struct dc *dc,
|
||||
uint8_t action;
|
||||
union dmub_rb_cmd cmd = {0};
|
||||
|
||||
ASSERT(payload->length <= 16);
|
||||
if (link_index >= dc->link_count || !dc->links[link_index])
|
||||
return false;
|
||||
|
||||
if (payload->length > sizeof(cmd.dp_aux_access.aux_control.dpaux.data))
|
||||
return false;
|
||||
|
||||
cmd.dp_aux_access.header.type = DMUB_CMD__DP_AUX_ACCESS;
|
||||
cmd.dp_aux_access.header.payload_bytes = 0;
|
||||
|
||||
@ -17,6 +17,17 @@
|
||||
#include "i915_gem_tiling.h"
|
||||
#include "i915_scatterlist.h"
|
||||
|
||||
/* Abuse scatterlist to store pointer instead of struct page. */
|
||||
static inline void __set_phys_vaddr(struct scatterlist *sg, void *vaddr)
|
||||
{
|
||||
sg_assign_page(sg, (struct page *)vaddr);
|
||||
}
|
||||
|
||||
static inline void *__get_phys_vaddr(struct scatterlist *sg)
|
||||
{
|
||||
return (void *)sg_page(sg);
|
||||
}
|
||||
|
||||
static int i915_gem_object_get_pages_phys(struct drm_i915_gem_object *obj)
|
||||
{
|
||||
struct address_space *mapping = obj->base.filp->f_mapping;
|
||||
@ -57,7 +68,7 @@ static int i915_gem_object_get_pages_phys(struct drm_i915_gem_object *obj)
|
||||
sg->offset = 0;
|
||||
sg->length = obj->base.size;
|
||||
|
||||
sg_assign_page(sg, (struct page *)vaddr);
|
||||
__set_phys_vaddr(sg, vaddr);
|
||||
sg_dma_address(sg) = dma;
|
||||
sg_dma_len(sg) = obj->base.size;
|
||||
|
||||
@ -98,7 +109,7 @@ i915_gem_object_put_pages_phys(struct drm_i915_gem_object *obj,
|
||||
struct sg_table *pages)
|
||||
{
|
||||
dma_addr_t dma = sg_dma_address(pages->sgl);
|
||||
void *vaddr = sg_page(pages->sgl);
|
||||
void *vaddr = __get_phys_vaddr(pages->sgl);
|
||||
|
||||
__i915_gem_object_release_shmem(obj, pages, false);
|
||||
|
||||
@ -138,7 +149,7 @@ i915_gem_object_put_pages_phys(struct drm_i915_gem_object *obj,
|
||||
int i915_gem_object_pwrite_phys(struct drm_i915_gem_object *obj,
|
||||
const struct drm_i915_gem_pwrite *args)
|
||||
{
|
||||
void *vaddr = sg_page(obj->mm.pages->sgl) + args->offset;
|
||||
void *vaddr = __get_phys_vaddr(obj->mm.pages->sgl) + args->offset;
|
||||
char __user *user_data = u64_to_user_ptr(args->data_ptr);
|
||||
struct drm_i915_private *i915 = to_i915(obj->base.dev);
|
||||
int err;
|
||||
@ -169,7 +180,7 @@ int i915_gem_object_pwrite_phys(struct drm_i915_gem_object *obj,
|
||||
int i915_gem_object_pread_phys(struct drm_i915_gem_object *obj,
|
||||
const struct drm_i915_gem_pread *args)
|
||||
{
|
||||
void *vaddr = sg_page(obj->mm.pages->sgl) + args->offset;
|
||||
void *vaddr = __get_phys_vaddr(obj->mm.pages->sgl) + args->offset;
|
||||
char __user *user_data = u64_to_user_ptr(args->data_ptr);
|
||||
int err;
|
||||
|
||||
|
||||
@ -416,8 +416,6 @@ void i915_ttm_free_cached_io_rsgt(struct drm_i915_gem_object *obj)
|
||||
int i915_ttm_purge(struct drm_i915_gem_object *obj)
|
||||
{
|
||||
struct ttm_buffer_object *bo = i915_gem_to_ttm(obj);
|
||||
struct i915_ttm_tt *i915_tt =
|
||||
container_of(bo->ttm, typeof(*i915_tt), ttm);
|
||||
struct ttm_operation_ctx ctx = {
|
||||
.interruptible = true,
|
||||
.no_wait_gpu = false,
|
||||
@ -432,16 +430,22 @@ int i915_ttm_purge(struct drm_i915_gem_object *obj)
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (bo->ttm && i915_tt->filp) {
|
||||
/*
|
||||
* The below fput(which eventually calls shmem_truncate) might
|
||||
* be delayed by worker, so when directly called to purge the
|
||||
* pages(like by the shrinker) we should try to be more
|
||||
* aggressive and release the pages immediately.
|
||||
*/
|
||||
shmem_truncate_range(file_inode(i915_tt->filp),
|
||||
0, (loff_t)-1);
|
||||
fput(fetch_and_zero(&i915_tt->filp));
|
||||
if (bo->ttm) {
|
||||
struct i915_ttm_tt *i915_tt =
|
||||
container_of(bo->ttm, typeof(*i915_tt), ttm);
|
||||
|
||||
if (i915_tt->filp) {
|
||||
/*
|
||||
* The below fput(which eventually calls shmem_truncate)
|
||||
* might be delayed by worker, so when directly called
|
||||
* to purge the pages(like by the shrinker) we should
|
||||
* try to be more aggressive and release the pages
|
||||
* immediately.
|
||||
*/
|
||||
shmem_truncate_range(file_inode(i915_tt->filp),
|
||||
0, (loff_t)-1);
|
||||
fput(fetch_and_zero(&i915_tt->filp));
|
||||
}
|
||||
}
|
||||
|
||||
obj->write_domain = 0;
|
||||
|
||||
@ -2329,8 +2329,8 @@ iscsit_handle_text_cmd(struct iscsit_conn *conn, struct iscsit_cmd *cmd,
|
||||
|
||||
if (conn->conn_ops->DataDigest) {
|
||||
iscsit_do_crypto_hash_buf(conn->conn_rx_hash,
|
||||
text_in, rx_size, 0, NULL,
|
||||
&data_crc);
|
||||
text_in, ALIGN(payload_length, 4),
|
||||
0, NULL, &data_crc);
|
||||
|
||||
if (checksum != data_crc) {
|
||||
pr_err("Text data CRC32C DataDigest"
|
||||
@ -2350,6 +2350,7 @@ iscsit_handle_text_cmd(struct iscsit_conn *conn, struct iscsit_cmd *cmd,
|
||||
" Command CmdSN: 0x%08x due to"
|
||||
" DataCRC error.\n", hdr->cmdsn);
|
||||
kfree(text_in);
|
||||
cmd->text_in_ptr = NULL;
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
|
||||
@ -339,13 +339,22 @@ static int chap_server_compute_hash(
|
||||
goto out;
|
||||
}
|
||||
break;
|
||||
case BASE64:
|
||||
case BASE64: {
|
||||
size_t r_len = strlen(chap_r);
|
||||
|
||||
while (r_len > 0 && chap_r[r_len - 1] == '=')
|
||||
r_len--;
|
||||
if (r_len > DIV_ROUND_UP(chap->digest_size * 4, 3)) {
|
||||
pr_err("Malformed CHAP_R: base64 payload too long\n");
|
||||
goto out;
|
||||
}
|
||||
if (chap_base64_decode(client_digest, chap_r, strlen(chap_r)) !=
|
||||
chap->digest_size) {
|
||||
pr_err("Malformed CHAP_R: invalid BASE64\n");
|
||||
goto out;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
pr_err("Could not find CHAP_R\n");
|
||||
goto out;
|
||||
@ -428,9 +437,11 @@ static int chap_server_compute_hash(
|
||||
}
|
||||
|
||||
if (type == HEX)
|
||||
ret = kstrtoul(&identifier[2], 0, &id);
|
||||
ret = kstrtoul(identifier, 16, &id);
|
||||
else if (type == DECIMAL)
|
||||
ret = kstrtoul(identifier, 10, &id);
|
||||
else
|
||||
ret = kstrtoul(identifier, 0, &id);
|
||||
ret = -EINVAL;
|
||||
|
||||
if (ret < 0) {
|
||||
pr_err("kstrtoul() failed for CHAP identifier: %d\n", ret);
|
||||
@ -472,6 +483,14 @@ static int chap_server_compute_hash(
|
||||
}
|
||||
break;
|
||||
case BASE64:
|
||||
/*
|
||||
* No overflow check needed: initiatorchg_binhex is
|
||||
* CHAP_CHALLENGE_STR_LEN bytes and extract_param() caps
|
||||
* initiatorchg at CHAP_CHALLENGE_STR_LEN characters, so
|
||||
* the decoded output is at most DIV_ROUND_UP(
|
||||
* (CHAP_CHALLENGE_STR_LEN - 1) * 3, 4) bytes, which is
|
||||
* less than CHAP_CHALLENGE_STR_LEN.
|
||||
*/
|
||||
initiatorchg_len = chap_base64_decode(initiatorchg_binhex,
|
||||
initiatorchg,
|
||||
strlen(initiatorchg));
|
||||
|
||||
@ -2122,6 +2122,14 @@ static long vhost_vring_set_num_addr(struct vhost_dev *d,
|
||||
BUG();
|
||||
}
|
||||
|
||||
/*
|
||||
* The metadata cache holds the IOTLB mapping that backed the previous
|
||||
* desc/avail/used addresses and vring size, both of which are being
|
||||
* replaced here. iotlb_access_ok() takes a cache hit as proof that the
|
||||
* region was validated, so the stale entries have to go.
|
||||
*/
|
||||
__vhost_vq_meta_reset(vq);
|
||||
|
||||
mutex_unlock(&vq->mutex);
|
||||
|
||||
return r;
|
||||
|
||||
@ -117,7 +117,7 @@ static const char *path_no_prefix(struct cifs_sb_info *cifs_sb,
|
||||
if (!*path)
|
||||
return path;
|
||||
|
||||
if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_USE_PREFIX_PATH) &&
|
||||
if ((cifs_sb_flags(cifs_sb) & CIFS_MOUNT_USE_PREFIX_PATH) &&
|
||||
cifs_sb->prepath) {
|
||||
len = strlen(cifs_sb->prepath) + 1;
|
||||
if (unlikely(len > strlen(path)))
|
||||
|
||||
@ -55,7 +55,7 @@ struct cifs_sb_info {
|
||||
struct nls_table *local_nls;
|
||||
struct smb3_fs_context *ctx;
|
||||
atomic_t active;
|
||||
unsigned int mnt_cifs_flags;
|
||||
atomic_t mnt_cifs_flags;
|
||||
struct delayed_work prune_tlinks;
|
||||
struct rcu_head rcu;
|
||||
|
||||
|
||||
@ -122,11 +122,3 @@ struct smb3_notify_info {
|
||||
#define CIFS_GOING_FLAGS_DEFAULT 0x0 /* going down */
|
||||
#define CIFS_GOING_FLAGS_LOGFLUSH 0x1 /* flush log but not data */
|
||||
#define CIFS_GOING_FLAGS_NOLOGFLUSH 0x2 /* don't flush log nor data */
|
||||
|
||||
static inline bool cifs_forced_shutdown(struct cifs_sb_info *sbi)
|
||||
{
|
||||
if (CIFS_MOUNT_SHUTDOWN & sbi->mnt_cifs_flags)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -12,20 +12,6 @@
|
||||
#include "cifsglob.h"
|
||||
#include "cifs_debug.h"
|
||||
|
||||
int cifs_remap(struct cifs_sb_info *cifs_sb)
|
||||
{
|
||||
int map_type;
|
||||
|
||||
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SFM_CHR)
|
||||
map_type = SFM_MAP_UNI_RSVD;
|
||||
else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR)
|
||||
map_type = SFU_MAP_UNI_RSVD;
|
||||
else
|
||||
map_type = NO_MAP_UNI_RSVD;
|
||||
|
||||
return map_type;
|
||||
}
|
||||
|
||||
/* Convert character using the SFU - "Services for Unix" remapping range */
|
||||
static bool
|
||||
convert_sfu_char(const __u16 src_char, char *target)
|
||||
|
||||
@ -22,6 +22,7 @@
|
||||
#include <linux/types.h>
|
||||
#include <linux/nls.h>
|
||||
#include "../../nls/nls_ucs2_utils.h"
|
||||
#include "cifsglob.h"
|
||||
|
||||
/*
|
||||
* Macs use an older "SFM" mapping of the symbols above. Fortunately it does
|
||||
@ -64,10 +65,21 @@ char *cifs_strndup_from_utf16(const char *src, const int maxlen,
|
||||
const struct nls_table *codepage);
|
||||
extern int cifsConvertToUTF16(__le16 *target, const char *source, int maxlen,
|
||||
const struct nls_table *cp, int mapChars);
|
||||
extern int cifs_remap(struct cifs_sb_info *cifs_sb);
|
||||
extern __le16 *cifs_strndup_to_utf16(const char *src, const int maxlen,
|
||||
int *utf16_len, const struct nls_table *cp,
|
||||
int remap);
|
||||
wchar_t cifs_toupper(wchar_t in);
|
||||
|
||||
static inline int cifs_remap(const struct cifs_sb_info *cifs_sb)
|
||||
{
|
||||
unsigned int sbflags = cifs_sb_flags(cifs_sb);
|
||||
|
||||
if (sbflags & CIFS_MOUNT_MAP_SFM_CHR)
|
||||
return SFM_MAP_UNI_RSVD;
|
||||
if (sbflags & CIFS_MOUNT_MAP_SPECIAL_CHR)
|
||||
return SFU_MAP_UNI_RSVD;
|
||||
|
||||
return NO_MAP_UNI_RSVD;
|
||||
}
|
||||
|
||||
#endif /* _CIFS_UNICODE_H */
|
||||
|
||||
@ -357,7 +357,7 @@ sid_to_id(struct cifs_sb_info *cifs_sb, struct smb_sid *psid,
|
||||
psid->num_subauth, SID_MAX_SUB_AUTHORITIES);
|
||||
}
|
||||
|
||||
if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UID_FROM_ACL) ||
|
||||
if ((cifs_sb_flags(cifs_sb) & CIFS_MOUNT_UID_FROM_ACL) ||
|
||||
(cifs_sb_master_tcon(cifs_sb)->posix_extensions)) {
|
||||
uint32_t unix_id;
|
||||
bool is_group;
|
||||
@ -891,7 +891,7 @@ static void parse_dacl(struct smb_acl *pdacl, char *end_of_acl,
|
||||
*/
|
||||
fattr->cf_mode &= ~07777;
|
||||
fattr->cf_mode |=
|
||||
le32_to_cpu(ppace[i]->sid.sub_auth[2]);
|
||||
le32_to_cpu(ppace[i]->sid.sub_auth[2]) & 07777;
|
||||
break;
|
||||
} else {
|
||||
if (compare_sids(&(ppace[i]->sid), pownersid) == 0) {
|
||||
@ -1687,7 +1687,8 @@ id_mode_to_cifs_acl(struct inode *inode, const char *path, __u64 *pnmode,
|
||||
struct smb_acl *dacl_ptr = NULL;
|
||||
struct smb_ntsd *pntsd = NULL; /* acl obtained from server */
|
||||
struct smb_ntsd *pnntsd = NULL; /* modified acl to be sent to server */
|
||||
struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
|
||||
struct cifs_sb_info *cifs_sb = CIFS_SB(inode);
|
||||
unsigned int sbflags;
|
||||
struct tcon_link *tlink;
|
||||
struct smb_version_operations *ops;
|
||||
bool mode_from_sid, id_from_sid;
|
||||
@ -1718,15 +1719,9 @@ id_mode_to_cifs_acl(struct inode *inode, const char *path, __u64 *pnmode,
|
||||
return rc;
|
||||
}
|
||||
|
||||
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MODE_FROM_SID)
|
||||
mode_from_sid = true;
|
||||
else
|
||||
mode_from_sid = false;
|
||||
|
||||
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UID_FROM_ACL)
|
||||
id_from_sid = true;
|
||||
else
|
||||
id_from_sid = false;
|
||||
sbflags = cifs_sb_flags(cifs_sb);
|
||||
mode_from_sid = sbflags & CIFS_MOUNT_MODE_FROM_SID;
|
||||
id_from_sid = sbflags & CIFS_MOUNT_UID_FROM_ACL;
|
||||
|
||||
/* Potentially, five new ACEs can be added to the ACL for U,G,O mapping */
|
||||
if (pnmode && *pnmode != NO_CHANGE_64) { /* chmod */
|
||||
|
||||
@ -227,16 +227,18 @@ cifs_sb_deactive(struct super_block *sb)
|
||||
static int
|
||||
cifs_read_super(struct super_block *sb)
|
||||
{
|
||||
struct inode *inode;
|
||||
struct cifs_sb_info *cifs_sb;
|
||||
struct cifs_tcon *tcon;
|
||||
unsigned int sbflags;
|
||||
struct timespec64 ts;
|
||||
struct inode *inode;
|
||||
int rc = 0;
|
||||
|
||||
cifs_sb = CIFS_SB(sb);
|
||||
tcon = cifs_sb_master_tcon(cifs_sb);
|
||||
sbflags = cifs_sb_flags(cifs_sb);
|
||||
|
||||
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIXACL)
|
||||
if (sbflags & CIFS_MOUNT_POSIXACL)
|
||||
sb->s_flags |= SB_POSIXACL;
|
||||
|
||||
if (tcon->snapshot_time)
|
||||
@ -312,7 +314,7 @@ cifs_read_super(struct super_block *sb)
|
||||
}
|
||||
|
||||
#ifdef CONFIG_CIFS_NFSD_EXPORT
|
||||
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) {
|
||||
if (sbflags & CIFS_MOUNT_SERVER_INUM) {
|
||||
cifs_dbg(FYI, "export ops supported\n");
|
||||
sb->s_export_op = &cifs_export_ops;
|
||||
}
|
||||
@ -390,8 +392,7 @@ statfs_out:
|
||||
|
||||
static long cifs_fallocate(struct file *file, int mode, loff_t off, loff_t len)
|
||||
{
|
||||
struct cifs_sb_info *cifs_sb = CIFS_FILE_SB(file);
|
||||
struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb);
|
||||
struct cifs_tcon *tcon = cifs_sb_master_tcon(CIFS_SB(file));
|
||||
struct TCP_Server_Info *server = tcon->ses->server;
|
||||
struct inode *inode = file_inode(file);
|
||||
int rc;
|
||||
@ -419,11 +420,9 @@ out_unlock:
|
||||
static int cifs_permission(struct mnt_idmap *idmap,
|
||||
struct inode *inode, int mask)
|
||||
{
|
||||
struct cifs_sb_info *cifs_sb;
|
||||
unsigned int sbflags = cifs_sb_flags(CIFS_SB(inode));
|
||||
|
||||
cifs_sb = CIFS_SB(inode->i_sb);
|
||||
|
||||
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_PERM) {
|
||||
if (sbflags & CIFS_MOUNT_NO_PERM) {
|
||||
if ((mask & MAY_EXEC) && !execute_ok(inode))
|
||||
return -EACCES;
|
||||
else
|
||||
@ -456,6 +455,7 @@ cifs_alloc_inode(struct super_block *sb)
|
||||
return NULL;
|
||||
cifs_inode->cifsAttrs = ATTR_ARCHIVE; /* default */
|
||||
cifs_inode->time = 0;
|
||||
cifs_inode->time_last_write = 0;
|
||||
/*
|
||||
* Until the file is open and we have gotten oplock info back from the
|
||||
* server, can not assume caching of file data or metadata.
|
||||
@ -569,15 +569,17 @@ cifs_show_security(struct seq_file *s, struct cifs_ses *ses)
|
||||
static void
|
||||
cifs_show_cache_flavor(struct seq_file *s, struct cifs_sb_info *cifs_sb)
|
||||
{
|
||||
unsigned int sbflags = cifs_sb_flags(cifs_sb);
|
||||
|
||||
seq_puts(s, ",cache=");
|
||||
|
||||
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_STRICT_IO)
|
||||
if (sbflags & CIFS_MOUNT_STRICT_IO)
|
||||
seq_puts(s, "strict");
|
||||
else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO)
|
||||
else if (sbflags & CIFS_MOUNT_DIRECT_IO)
|
||||
seq_puts(s, "none");
|
||||
else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_RW_CACHE)
|
||||
else if (sbflags & CIFS_MOUNT_RW_CACHE)
|
||||
seq_puts(s, "singleclient"); /* assume only one client access */
|
||||
else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_RO_CACHE)
|
||||
else if (sbflags & CIFS_MOUNT_RO_CACHE)
|
||||
seq_puts(s, "ro"); /* read only caching assumed */
|
||||
else
|
||||
seq_puts(s, "loose");
|
||||
@ -638,6 +640,8 @@ cifs_show_options(struct seq_file *s, struct dentry *root)
|
||||
struct cifs_sb_info *cifs_sb = CIFS_SB(root->d_sb);
|
||||
struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb);
|
||||
struct sockaddr *srcaddr;
|
||||
unsigned int sbflags;
|
||||
|
||||
srcaddr = (struct sockaddr *)&tcon->ses->server->srcaddr;
|
||||
|
||||
seq_show_option(s, "vers", tcon->ses->server->vals->version_string);
|
||||
@ -671,16 +675,17 @@ cifs_show_options(struct seq_file *s, struct dentry *root)
|
||||
(int)(srcaddr->sa_family));
|
||||
}
|
||||
|
||||
sbflags = cifs_sb_flags(cifs_sb);
|
||||
seq_printf(s, ",uid=%u",
|
||||
from_kuid_munged(&init_user_ns, cifs_sb->ctx->linux_uid));
|
||||
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_UID)
|
||||
if (sbflags & CIFS_MOUNT_OVERR_UID)
|
||||
seq_puts(s, ",forceuid");
|
||||
else
|
||||
seq_puts(s, ",noforceuid");
|
||||
|
||||
seq_printf(s, ",gid=%u",
|
||||
from_kgid_munged(&init_user_ns, cifs_sb->ctx->linux_gid));
|
||||
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_GID)
|
||||
if (sbflags & CIFS_MOUNT_OVERR_GID)
|
||||
seq_puts(s, ",forcegid");
|
||||
else
|
||||
seq_puts(s, ",noforcegid");
|
||||
@ -723,53 +728,53 @@ cifs_show_options(struct seq_file *s, struct dentry *root)
|
||||
seq_puts(s, ",unix");
|
||||
else
|
||||
seq_puts(s, ",nounix");
|
||||
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_DFS)
|
||||
if (sbflags & CIFS_MOUNT_NO_DFS)
|
||||
seq_puts(s, ",nodfs");
|
||||
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS)
|
||||
if (sbflags & CIFS_MOUNT_POSIX_PATHS)
|
||||
seq_puts(s, ",posixpaths");
|
||||
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID)
|
||||
if (sbflags & CIFS_MOUNT_SET_UID)
|
||||
seq_puts(s, ",setuids");
|
||||
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UID_FROM_ACL)
|
||||
if (sbflags & CIFS_MOUNT_UID_FROM_ACL)
|
||||
seq_puts(s, ",idsfromsid");
|
||||
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM)
|
||||
if (sbflags & CIFS_MOUNT_SERVER_INUM)
|
||||
seq_puts(s, ",serverino");
|
||||
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_RWPIDFORWARD)
|
||||
if (sbflags & CIFS_MOUNT_RWPIDFORWARD)
|
||||
seq_puts(s, ",rwpidforward");
|
||||
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NOPOSIXBRL)
|
||||
if (sbflags & CIFS_MOUNT_NOPOSIXBRL)
|
||||
seq_puts(s, ",forcemand");
|
||||
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR)
|
||||
if (sbflags & CIFS_MOUNT_NO_XATTR)
|
||||
seq_puts(s, ",nouser_xattr");
|
||||
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR)
|
||||
if (sbflags & CIFS_MOUNT_MAP_SPECIAL_CHR)
|
||||
seq_puts(s, ",mapchars");
|
||||
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SFM_CHR)
|
||||
if (sbflags & CIFS_MOUNT_MAP_SFM_CHR)
|
||||
seq_puts(s, ",mapposix");
|
||||
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL)
|
||||
if (sbflags & CIFS_MOUNT_UNX_EMUL)
|
||||
seq_puts(s, ",sfu");
|
||||
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL)
|
||||
if (sbflags & CIFS_MOUNT_NO_BRL)
|
||||
seq_puts(s, ",nobrl");
|
||||
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_HANDLE_CACHE)
|
||||
if (sbflags & CIFS_MOUNT_NO_HANDLE_CACHE)
|
||||
seq_puts(s, ",nohandlecache");
|
||||
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MODE_FROM_SID)
|
||||
if (sbflags & CIFS_MOUNT_MODE_FROM_SID)
|
||||
seq_puts(s, ",modefromsid");
|
||||
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL)
|
||||
if (sbflags & CIFS_MOUNT_CIFS_ACL)
|
||||
seq_puts(s, ",cifsacl");
|
||||
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM)
|
||||
if (sbflags & CIFS_MOUNT_DYNPERM)
|
||||
seq_puts(s, ",dynperm");
|
||||
if (root->d_sb->s_flags & SB_POSIXACL)
|
||||
seq_puts(s, ",acl");
|
||||
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS)
|
||||
if (sbflags & CIFS_MOUNT_MF_SYMLINKS)
|
||||
seq_puts(s, ",mfsymlinks");
|
||||
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_FSCACHE)
|
||||
if (sbflags & CIFS_MOUNT_FSCACHE)
|
||||
seq_puts(s, ",fsc");
|
||||
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NOSSYNC)
|
||||
if (sbflags & CIFS_MOUNT_NOSSYNC)
|
||||
seq_puts(s, ",nostrictsync");
|
||||
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_PERM)
|
||||
if (sbflags & CIFS_MOUNT_NO_PERM)
|
||||
seq_puts(s, ",noperm");
|
||||
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_BACKUPUID)
|
||||
if (sbflags & CIFS_MOUNT_CIFS_BACKUPUID)
|
||||
seq_printf(s, ",backupuid=%u",
|
||||
from_kuid_munged(&init_user_ns,
|
||||
cifs_sb->ctx->backupuid));
|
||||
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_BACKUPGID)
|
||||
if (sbflags & CIFS_MOUNT_CIFS_BACKUPGID)
|
||||
seq_printf(s, ",backupgid=%u",
|
||||
from_kgid_munged(&init_user_ns,
|
||||
cifs_sb->ctx->backupgid));
|
||||
@ -910,10 +915,10 @@ static int cifs_write_inode(struct inode *inode, struct writeback_control *wbc)
|
||||
|
||||
static int cifs_drop_inode(struct inode *inode)
|
||||
{
|
||||
struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
|
||||
unsigned int sbflags = cifs_sb_flags(CIFS_SB(inode));
|
||||
|
||||
/* no serverino => unconditional eviction */
|
||||
return !(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) ||
|
||||
return !(sbflags & CIFS_MOUNT_SERVER_INUM) ||
|
||||
generic_drop_inode(inode);
|
||||
}
|
||||
|
||||
@ -951,7 +956,7 @@ cifs_get_root(struct smb3_fs_context *ctx, struct super_block *sb)
|
||||
char *s, *p;
|
||||
char sep;
|
||||
|
||||
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_USE_PREFIX_PATH)
|
||||
if (cifs_sb_flags(cifs_sb) & CIFS_MOUNT_USE_PREFIX_PATH)
|
||||
return dget(sb->s_root);
|
||||
|
||||
full_path = cifs_build_path_to_root(ctx, cifs_sb,
|
||||
|
||||
@ -519,8 +519,10 @@ struct smb_version_operations {
|
||||
/* check for STATUS_NETWORK_SESSION_EXPIRED */
|
||||
bool (*is_session_expired)(char *);
|
||||
/* send oplock break response */
|
||||
int (*oplock_response)(struct cifs_tcon *tcon, __u64 persistent_fid, __u64 volatile_fid,
|
||||
__u16 net_fid, struct cifsInodeInfo *cifs_inode);
|
||||
int (*oplock_response)(struct cifs_tcon *tcon, __u64 persistent_fid,
|
||||
__u64 volatile_fid, __u16 net_fid,
|
||||
struct cifsInodeInfo *cifs_inode,
|
||||
unsigned int oplock);
|
||||
/* query remote filesystem */
|
||||
int (*queryfs)(const unsigned int, struct cifs_tcon *,
|
||||
const char *, struct cifs_sb_info *, struct kstatfs *);
|
||||
@ -1547,10 +1549,6 @@ int cifs_file_set_size(const unsigned int xid, struct dentry *dentry,
|
||||
#define CIFS_CACHE_RW_FLG (CIFS_CACHE_READ_FLG | CIFS_CACHE_WRITE_FLG)
|
||||
#define CIFS_CACHE_RHW_FLG (CIFS_CACHE_RW_FLG | CIFS_CACHE_HANDLE_FLG)
|
||||
|
||||
#define CIFS_CACHE_READ(cinode) ((cinode->oplock & CIFS_CACHE_READ_FLG) || (CIFS_SB(cinode->netfs.inode.i_sb)->mnt_cifs_flags & CIFS_MOUNT_RO_CACHE))
|
||||
#define CIFS_CACHE_HANDLE(cinode) (cinode->oplock & CIFS_CACHE_HANDLE_FLG)
|
||||
#define CIFS_CACHE_WRITE(cinode) ((cinode->oplock & CIFS_CACHE_WRITE_FLG) || (CIFS_SB(cinode->netfs.inode.i_sb)->mnt_cifs_flags & CIFS_MOUNT_RW_CACHE))
|
||||
|
||||
/*
|
||||
* One of these for each file inode
|
||||
*/
|
||||
@ -1582,6 +1580,7 @@ struct cifsInodeInfo {
|
||||
spinlock_t writers_lock;
|
||||
unsigned int writers; /* Number of writers on this inode */
|
||||
unsigned long time; /* jiffies of last update of inode */
|
||||
unsigned long time_last_write; /* jiffies of last writable close or truncate */
|
||||
u64 uniqueid; /* server inode number */
|
||||
u64 createtime; /* creation time on server */
|
||||
__u8 lease_key[SMB2_LEASE_KEY_SIZE]; /* lease key for this inode */
|
||||
@ -1598,24 +1597,59 @@ CIFS_I(struct inode *inode)
|
||||
return container_of(inode, struct cifsInodeInfo, netfs.inode);
|
||||
}
|
||||
|
||||
static inline struct cifs_sb_info *
|
||||
CIFS_SB(struct super_block *sb)
|
||||
static inline void *cinode_to_fsinfo(struct cifsInodeInfo *cinode)
|
||||
{
|
||||
return cinode->netfs.inode.i_sb->s_fs_info;
|
||||
}
|
||||
|
||||
static inline void *super_to_fsinfo(struct super_block *sb)
|
||||
{
|
||||
return sb->s_fs_info;
|
||||
}
|
||||
|
||||
static inline struct cifs_sb_info *
|
||||
CIFS_FILE_SB(struct file *file)
|
||||
static inline void *inode_to_fsinfo(struct inode *inode)
|
||||
{
|
||||
return CIFS_SB(file_inode(file)->i_sb);
|
||||
return inode->i_sb->s_fs_info;
|
||||
}
|
||||
|
||||
static inline void *file_to_fsinfo(struct file *file)
|
||||
{
|
||||
return file_inode(file)->i_sb->s_fs_info;
|
||||
}
|
||||
|
||||
static inline void *dentry_to_fsinfo(struct dentry *dentry)
|
||||
{
|
||||
return dentry->d_sb->s_fs_info;
|
||||
}
|
||||
|
||||
static inline void *const_dentry_to_fsinfo(const struct dentry *dentry)
|
||||
{
|
||||
return dentry->d_sb->s_fs_info;
|
||||
}
|
||||
|
||||
#define CIFS_SB(_ptr) \
|
||||
((struct cifs_sb_info *) \
|
||||
_Generic((_ptr), \
|
||||
struct cifsInodeInfo * : cinode_to_fsinfo, \
|
||||
const struct dentry * : const_dentry_to_fsinfo, \
|
||||
struct super_block * : super_to_fsinfo, \
|
||||
struct dentry * : dentry_to_fsinfo, \
|
||||
struct inode * : inode_to_fsinfo, \
|
||||
struct file * : file_to_fsinfo)(_ptr))
|
||||
|
||||
/*
|
||||
* Use atomic_t for @cifs_sb->mnt_cifs_flags as it is currently accessed
|
||||
* locklessly and may be changed concurrently by mount/remount and reconnect
|
||||
* paths.
|
||||
*/
|
||||
static inline unsigned int cifs_sb_flags(const struct cifs_sb_info *cifs_sb)
|
||||
{
|
||||
return atomic_read(&cifs_sb->mnt_cifs_flags);
|
||||
}
|
||||
|
||||
static inline char CIFS_DIR_SEP(const struct cifs_sb_info *cifs_sb)
|
||||
{
|
||||
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS)
|
||||
return '/';
|
||||
else
|
||||
return '\\';
|
||||
return (cifs_sb_flags(cifs_sb) & CIFS_MOUNT_POSIX_PATHS) ? '/' : '\\';
|
||||
}
|
||||
|
||||
static inline void
|
||||
@ -2325,4 +2359,34 @@ static inline void cifs_requeue_server_reconn(struct TCP_Server_Info *server)
|
||||
queue_delayed_work(cifsiod_wq, &server->reconnect, delay * HZ);
|
||||
}
|
||||
|
||||
static inline bool __cifs_cache_state_check(struct cifsInodeInfo *cinode,
|
||||
unsigned int oplock_flags,
|
||||
unsigned int sb_flags)
|
||||
{
|
||||
unsigned int sflags = cifs_sb_flags(CIFS_SB(cinode));
|
||||
unsigned int oplock = READ_ONCE(cinode->oplock);
|
||||
|
||||
return (oplock & oplock_flags) || (sflags & sb_flags);
|
||||
}
|
||||
|
||||
#define CIFS_CACHE_READ(cinode) \
|
||||
__cifs_cache_state_check(cinode, CIFS_CACHE_READ_FLG, \
|
||||
CIFS_MOUNT_RO_CACHE)
|
||||
#define CIFS_CACHE_HANDLE(cinode) \
|
||||
__cifs_cache_state_check(cinode, CIFS_CACHE_HANDLE_FLG, 0)
|
||||
#define CIFS_CACHE_WRITE(cinode) \
|
||||
__cifs_cache_state_check(cinode, CIFS_CACHE_WRITE_FLG, \
|
||||
CIFS_MOUNT_RW_CACHE)
|
||||
|
||||
static inline void cifs_reset_oplock(struct cifsInodeInfo *cinode)
|
||||
{
|
||||
scoped_guard(spinlock, &cinode->open_file_lock)
|
||||
WRITE_ONCE(cinode->oplock, 0);
|
||||
}
|
||||
|
||||
static inline bool cifs_forced_shutdown(const struct cifs_sb_info *sbi)
|
||||
{
|
||||
return cifs_sb_flags(sbi) & CIFS_MOUNT_SHUTDOWN;
|
||||
}
|
||||
|
||||
#endif /* _CIFS_GLOB_H */
|
||||
|
||||
@ -254,9 +254,23 @@ SendReceive(const unsigned int xid, struct cifs_ses *ses,
|
||||
goto out;
|
||||
|
||||
if (out_buf) {
|
||||
*pbytes_returned = resp_iov.iov_len;
|
||||
if (resp_iov.iov_len)
|
||||
memcpy(out_buf, resp_iov.iov_base, resp_iov.iov_len);
|
||||
/* Use smbCalcSize() for both single- and multi-part T2 responses,
|
||||
* both here and in coalesce_t2().
|
||||
*/
|
||||
unsigned int copy_len;
|
||||
if (WARN_ON_ONCE(!resp_iov.iov_base)) {
|
||||
rc = -EIO;
|
||||
goto out;
|
||||
}
|
||||
copy_len = smbCalcSize(resp_iov.iov_base);
|
||||
if (copy_len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE) {
|
||||
cifs_dbg(VFS, "response size %u exceeds buffer\n",
|
||||
copy_len);
|
||||
rc = -ENOBUFS;
|
||||
goto out;
|
||||
}
|
||||
*pbytes_returned = copy_len;
|
||||
memcpy(out_buf, resp_iov.iov_base, copy_len);
|
||||
}
|
||||
|
||||
out:
|
||||
|
||||
@ -2916,8 +2916,8 @@ compare_mount_options(struct super_block *sb, struct cifs_mnt_data *mnt_data)
|
||||
{
|
||||
struct cifs_sb_info *old = CIFS_SB(sb);
|
||||
struct cifs_sb_info *new = mnt_data->cifs_sb;
|
||||
unsigned int oldflags = old->mnt_cifs_flags & CIFS_MOUNT_MASK;
|
||||
unsigned int newflags = new->mnt_cifs_flags & CIFS_MOUNT_MASK;
|
||||
unsigned int oldflags = cifs_sb_flags(old) & CIFS_MOUNT_MASK;
|
||||
unsigned int newflags = cifs_sb_flags(new) & CIFS_MOUNT_MASK;
|
||||
|
||||
if ((sb->s_flags & CIFS_MS_MASK) != (mnt_data->flags & CIFS_MS_MASK))
|
||||
return 0;
|
||||
@ -2972,9 +2972,9 @@ static int match_prepath(struct super_block *sb,
|
||||
struct smb3_fs_context *ctx = mnt_data->ctx;
|
||||
struct cifs_sb_info *old = CIFS_SB(sb);
|
||||
struct cifs_sb_info *new = mnt_data->cifs_sb;
|
||||
bool old_set = (old->mnt_cifs_flags & CIFS_MOUNT_USE_PREFIX_PATH) &&
|
||||
bool old_set = (cifs_sb_flags(old) & CIFS_MOUNT_USE_PREFIX_PATH) &&
|
||||
old->prepath;
|
||||
bool new_set = (new->mnt_cifs_flags & CIFS_MOUNT_USE_PREFIX_PATH) &&
|
||||
bool new_set = (cifs_sb_flags(new) & CIFS_MOUNT_USE_PREFIX_PATH) &&
|
||||
new->prepath;
|
||||
|
||||
if (tcon->origin_fullpath &&
|
||||
@ -3005,7 +3005,7 @@ cifs_match_super(struct super_block *sb, void *data)
|
||||
cifs_sb = CIFS_SB(sb);
|
||||
|
||||
/* We do not want to use a superblock that has been shutdown */
|
||||
if (CIFS_MOUNT_SHUTDOWN & cifs_sb->mnt_cifs_flags) {
|
||||
if (cifs_forced_shutdown(cifs_sb)) {
|
||||
spin_unlock(&cifs_tcp_ses_lock);
|
||||
return 0;
|
||||
}
|
||||
@ -3533,18 +3533,20 @@ void reset_cifs_unix_caps(unsigned int xid, struct cifs_tcon *tcon,
|
||||
cap &= ~CIFS_UNIX_POSIX_ACL_CAP;
|
||||
else if (CIFS_UNIX_POSIX_ACL_CAP & cap) {
|
||||
cifs_dbg(FYI, "negotiated posix acl support\n");
|
||||
if (cifs_sb)
|
||||
cifs_sb->mnt_cifs_flags |=
|
||||
CIFS_MOUNT_POSIXACL;
|
||||
if (cifs_sb) {
|
||||
atomic_or(CIFS_MOUNT_POSIXACL,
|
||||
&cifs_sb->mnt_cifs_flags);
|
||||
}
|
||||
}
|
||||
|
||||
if (ctx && ctx->posix_paths == 0)
|
||||
cap &= ~CIFS_UNIX_POSIX_PATHNAMES_CAP;
|
||||
else if (cap & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
|
||||
cifs_dbg(FYI, "negotiate posix pathnames\n");
|
||||
if (cifs_sb)
|
||||
cifs_sb->mnt_cifs_flags |=
|
||||
CIFS_MOUNT_POSIX_PATHS;
|
||||
if (cifs_sb) {
|
||||
atomic_or(CIFS_MOUNT_POSIX_PATHS,
|
||||
&cifs_sb->mnt_cifs_flags);
|
||||
}
|
||||
}
|
||||
|
||||
cifs_dbg(FYI, "Negotiate caps 0x%x\n", (int)cap);
|
||||
@ -3582,6 +3584,8 @@ void reset_cifs_unix_caps(unsigned int xid, struct cifs_tcon *tcon,
|
||||
int cifs_setup_cifs_sb(struct cifs_sb_info *cifs_sb)
|
||||
{
|
||||
struct smb3_fs_context *ctx = cifs_sb->ctx;
|
||||
unsigned int sbflags;
|
||||
int rc = 0;
|
||||
|
||||
INIT_DELAYED_WORK(&cifs_sb->prune_tlinks, cifs_prune_tlinks);
|
||||
INIT_LIST_HEAD(&cifs_sb->tcon_sb_link);
|
||||
@ -3606,17 +3610,16 @@ int cifs_setup_cifs_sb(struct cifs_sb_info *cifs_sb)
|
||||
}
|
||||
ctx->local_nls = cifs_sb->local_nls;
|
||||
|
||||
smb3_update_mnt_flags(cifs_sb);
|
||||
sbflags = smb3_update_mnt_flags(cifs_sb);
|
||||
|
||||
if (ctx->direct_io)
|
||||
cifs_dbg(FYI, "mounting share using direct i/o\n");
|
||||
if (ctx->cache_ro) {
|
||||
cifs_dbg(VFS, "mounting share with read only caching. Ensure that the share will not be modified while in use.\n");
|
||||
cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_RO_CACHE;
|
||||
sbflags |= CIFS_MOUNT_RO_CACHE;
|
||||
} else if (ctx->cache_rw) {
|
||||
cifs_dbg(VFS, "mounting share in single client RW caching mode. Ensure that no other systems will be accessing the share.\n");
|
||||
cifs_sb->mnt_cifs_flags |= (CIFS_MOUNT_RO_CACHE |
|
||||
CIFS_MOUNT_RW_CACHE);
|
||||
sbflags |= CIFS_MOUNT_RO_CACHE | CIFS_MOUNT_RW_CACHE;
|
||||
}
|
||||
|
||||
if ((ctx->cifs_acl) && (ctx->dynperm))
|
||||
@ -3625,16 +3628,19 @@ int cifs_setup_cifs_sb(struct cifs_sb_info *cifs_sb)
|
||||
if (ctx->prepath) {
|
||||
cifs_sb->prepath = kstrdup(ctx->prepath, GFP_KERNEL);
|
||||
if (cifs_sb->prepath == NULL)
|
||||
return -ENOMEM;
|
||||
cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_USE_PREFIX_PATH;
|
||||
rc = -ENOMEM;
|
||||
else
|
||||
sbflags |= CIFS_MOUNT_USE_PREFIX_PATH;
|
||||
}
|
||||
|
||||
return 0;
|
||||
atomic_set(&cifs_sb->mnt_cifs_flags, sbflags);
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* Release all succeed connections */
|
||||
void cifs_mount_put_conns(struct cifs_mount_ctx *mnt_ctx)
|
||||
{
|
||||
struct cifs_sb_info *cifs_sb = mnt_ctx->cifs_sb;
|
||||
int rc = 0;
|
||||
|
||||
if (mnt_ctx->tcon)
|
||||
@ -3646,7 +3652,7 @@ void cifs_mount_put_conns(struct cifs_mount_ctx *mnt_ctx)
|
||||
mnt_ctx->ses = NULL;
|
||||
mnt_ctx->tcon = NULL;
|
||||
mnt_ctx->server = NULL;
|
||||
mnt_ctx->cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_POSIX_PATHS;
|
||||
atomic_andnot(CIFS_MOUNT_POSIX_PATHS, &cifs_sb->mnt_cifs_flags);
|
||||
free_xid(mnt_ctx->xid);
|
||||
}
|
||||
|
||||
@ -3700,15 +3706,18 @@ out:
|
||||
int cifs_mount_get_tcon(struct cifs_mount_ctx *mnt_ctx)
|
||||
{
|
||||
struct TCP_Server_Info *server;
|
||||
struct cifs_tcon *tcon = NULL;
|
||||
struct cifs_sb_info *cifs_sb;
|
||||
struct smb3_fs_context *ctx;
|
||||
struct cifs_tcon *tcon = NULL;
|
||||
unsigned int sbflags;
|
||||
int rc = 0;
|
||||
|
||||
if (WARN_ON_ONCE(!mnt_ctx || !mnt_ctx->server || !mnt_ctx->ses || !mnt_ctx->fs_ctx ||
|
||||
!mnt_ctx->cifs_sb)) {
|
||||
rc = -EINVAL;
|
||||
goto out;
|
||||
if (WARN_ON_ONCE(!mnt_ctx))
|
||||
return -EINVAL;
|
||||
if (WARN_ON_ONCE(!mnt_ctx->server || !mnt_ctx->ses ||
|
||||
!mnt_ctx->fs_ctx || !mnt_ctx->cifs_sb)) {
|
||||
mnt_ctx->tcon = NULL;
|
||||
return -EINVAL;
|
||||
}
|
||||
server = mnt_ctx->server;
|
||||
ctx = mnt_ctx->fs_ctx;
|
||||
@ -3727,9 +3736,10 @@ int cifs_mount_get_tcon(struct cifs_mount_ctx *mnt_ctx)
|
||||
* path (i.e., do not remap / and \ and do not map any special characters)
|
||||
*/
|
||||
if (tcon->posix_extensions) {
|
||||
cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_POSIX_PATHS;
|
||||
cifs_sb->mnt_cifs_flags &= ~(CIFS_MOUNT_MAP_SFM_CHR |
|
||||
CIFS_MOUNT_MAP_SPECIAL_CHR);
|
||||
atomic_or(CIFS_MOUNT_POSIX_PATHS, &cifs_sb->mnt_cifs_flags);
|
||||
atomic_andnot(CIFS_MOUNT_MAP_SFM_CHR |
|
||||
CIFS_MOUNT_MAP_SPECIAL_CHR,
|
||||
&cifs_sb->mnt_cifs_flags);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY
|
||||
@ -3753,15 +3763,15 @@ int cifs_mount_get_tcon(struct cifs_mount_ctx *mnt_ctx)
|
||||
#endif /* CONFIG_CIFS_ALLOW_INSECURE_LEGACY */
|
||||
tcon->unix_ext = 0; /* server does not support them */
|
||||
|
||||
sbflags = cifs_sb_flags(cifs_sb);
|
||||
/* do not care if a following call succeed - informational */
|
||||
if (!tcon->pipe && server->ops->qfs_tcon) {
|
||||
server->ops->qfs_tcon(mnt_ctx->xid, tcon, cifs_sb);
|
||||
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_RO_CACHE) {
|
||||
if (sbflags & CIFS_MOUNT_RO_CACHE) {
|
||||
if (tcon->fsDevInfo.DeviceCharacteristics &
|
||||
cpu_to_le32(FILE_READ_ONLY_DEVICE))
|
||||
cifs_dbg(VFS, "mounted to read only share\n");
|
||||
else if ((cifs_sb->mnt_cifs_flags &
|
||||
CIFS_MOUNT_RW_CACHE) == 0)
|
||||
else if (!(sbflags & CIFS_MOUNT_RW_CACHE))
|
||||
cifs_dbg(VFS, "read only mount of RW share\n");
|
||||
/* no need to log a RW mount of a typical RW share */
|
||||
}
|
||||
@ -3773,7 +3783,7 @@ int cifs_mount_get_tcon(struct cifs_mount_ctx *mnt_ctx)
|
||||
* Inside cifs_fscache_get_super_cookie it checks
|
||||
* that we do not get super cookie twice.
|
||||
*/
|
||||
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_FSCACHE)
|
||||
if (sbflags & CIFS_MOUNT_FSCACHE)
|
||||
cifs_fscache_get_super_cookie(tcon);
|
||||
|
||||
out:
|
||||
@ -3896,7 +3906,8 @@ int cifs_is_path_remote(struct cifs_mount_ctx *mnt_ctx)
|
||||
cifs_sb, full_path, tcon->Flags & SMB_SHARE_IS_IN_DFS);
|
||||
if (rc != 0) {
|
||||
cifs_server_dbg(VFS, "cannot query dirs between root and final path, enabling CIFS_MOUNT_USE_PREFIX_PATH\n");
|
||||
cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_USE_PREFIX_PATH;
|
||||
atomic_or(CIFS_MOUNT_USE_PREFIX_PATH,
|
||||
&cifs_sb->mnt_cifs_flags);
|
||||
rc = 0;
|
||||
}
|
||||
}
|
||||
@ -3927,7 +3938,7 @@ int cifs_mount(struct cifs_sb_info *cifs_sb, struct smb3_fs_context *ctx)
|
||||
* Force the use of prefix path to support failover on DFS paths that resolve to targets
|
||||
* that have different prefix paths.
|
||||
*/
|
||||
cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_USE_PREFIX_PATH;
|
||||
atomic_or(CIFS_MOUNT_USE_PREFIX_PATH, &cifs_sb->mnt_cifs_flags);
|
||||
kfree(cifs_sb->prepath);
|
||||
cifs_sb->prepath = ctx->prepath;
|
||||
ctx->prepath = NULL;
|
||||
@ -4547,7 +4558,7 @@ cifs_sb_tlink(struct cifs_sb_info *cifs_sb)
|
||||
kuid_t fsuid = current_fsuid();
|
||||
int err;
|
||||
|
||||
if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MULTIUSER))
|
||||
if (!(cifs_sb_flags(cifs_sb) & CIFS_MOUNT_MULTIUSER))
|
||||
return cifs_get_tlink(cifs_sb_master_tlink(cifs_sb));
|
||||
|
||||
spin_lock(&cifs_sb->tlink_tree_lock);
|
||||
|
||||
@ -1333,7 +1333,7 @@ int dfs_cache_remount_fs(struct cifs_sb_info *cifs_sb)
|
||||
* Force the use of prefix path to support failover on DFS paths that resolve to targets
|
||||
* that have different prefix paths.
|
||||
*/
|
||||
cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_USE_PREFIX_PATH;
|
||||
atomic_or(CIFS_MOUNT_USE_PREFIX_PATH, &cifs_sb->mnt_cifs_flags);
|
||||
|
||||
refresh_tcon_referral(tcon, true);
|
||||
return 0;
|
||||
|
||||
@ -83,10 +83,11 @@ char *__build_path_from_dentry_optional_prefix(struct dentry *direntry, void *pa
|
||||
const char *tree, int tree_len,
|
||||
bool prefix)
|
||||
{
|
||||
int dfsplen;
|
||||
int pplen = 0;
|
||||
struct cifs_sb_info *cifs_sb = CIFS_SB(direntry->d_sb);
|
||||
struct cifs_sb_info *cifs_sb = CIFS_SB(direntry);
|
||||
unsigned int sbflags = cifs_sb_flags(cifs_sb);
|
||||
char dirsep = CIFS_DIR_SEP(cifs_sb);
|
||||
int pplen = 0;
|
||||
int dfsplen;
|
||||
char *s;
|
||||
|
||||
if (unlikely(!page))
|
||||
@ -97,7 +98,7 @@ char *__build_path_from_dentry_optional_prefix(struct dentry *direntry, void *pa
|
||||
else
|
||||
dfsplen = 0;
|
||||
|
||||
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_USE_PREFIX_PATH)
|
||||
if (sbflags & CIFS_MOUNT_USE_PREFIX_PATH)
|
||||
pplen = cifs_sb->prepath ? strlen(cifs_sb->prepath) + 1 : 0;
|
||||
|
||||
s = dentry_path_raw(direntry, page, PATH_MAX);
|
||||
@ -124,7 +125,7 @@ char *__build_path_from_dentry_optional_prefix(struct dentry *direntry, void *pa
|
||||
if (dfsplen) {
|
||||
s -= dfsplen;
|
||||
memcpy(s, tree, dfsplen);
|
||||
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS) {
|
||||
if (sbflags & CIFS_MOUNT_POSIX_PATHS) {
|
||||
int i;
|
||||
for (i = 0; i < dfsplen; i++) {
|
||||
if (s[i] == '\\')
|
||||
@ -153,7 +154,7 @@ char *build_path_from_dentry_optional_prefix(struct dentry *direntry, void *page
|
||||
static int
|
||||
check_name(struct dentry *direntry, struct cifs_tcon *tcon)
|
||||
{
|
||||
struct cifs_sb_info *cifs_sb = CIFS_SB(direntry->d_sb);
|
||||
struct cifs_sb_info *cifs_sb = CIFS_SB(direntry);
|
||||
int i;
|
||||
|
||||
if (unlikely(tcon->fsAttrInfo.MaxPathNameComponentLength &&
|
||||
@ -161,7 +162,7 @@ check_name(struct dentry *direntry, struct cifs_tcon *tcon)
|
||||
le32_to_cpu(tcon->fsAttrInfo.MaxPathNameComponentLength)))
|
||||
return -ENAMETOOLONG;
|
||||
|
||||
if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS)) {
|
||||
if (!(cifs_sb_flags(cifs_sb) & CIFS_MOUNT_POSIX_PATHS)) {
|
||||
for (i = 0; i < direntry->d_name.len; i++) {
|
||||
if (direntry->d_name.name[i] == '\\') {
|
||||
cifs_dbg(FYI, "Invalid file name\n");
|
||||
@ -182,11 +183,12 @@ static int cifs_do_create(struct inode *inode, struct dentry *direntry, unsigned
|
||||
int rc = -ENOENT;
|
||||
int create_options = CREATE_NOT_DIR;
|
||||
int desired_access;
|
||||
struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
|
||||
struct cifs_sb_info *cifs_sb = CIFS_SB(inode);
|
||||
struct cifs_tcon *tcon = tlink_tcon(tlink);
|
||||
const char *full_path;
|
||||
void *page = alloc_dentry_path();
|
||||
struct inode *newinode = NULL;
|
||||
unsigned int sbflags = cifs_sb_flags(cifs_sb);
|
||||
int disposition;
|
||||
struct TCP_Server_Info *server = tcon->ses->server;
|
||||
struct cifs_open_parms oparms;
|
||||
@ -375,7 +377,7 @@ retry_open:
|
||||
.device = 0,
|
||||
};
|
||||
|
||||
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
|
||||
if (sbflags & CIFS_MOUNT_SET_UID) {
|
||||
args.uid = current_fsuid();
|
||||
if (inode->i_mode & S_ISGID)
|
||||
args.gid = inode->i_gid;
|
||||
@ -412,9 +414,9 @@ cifs_create_get_file_info:
|
||||
if (server->ops->set_lease_key)
|
||||
server->ops->set_lease_key(newinode, fid);
|
||||
if ((*oplock & CIFS_CREATE_ACTION) && S_ISREG(newinode->i_mode)) {
|
||||
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM)
|
||||
if (sbflags & CIFS_MOUNT_DYNPERM)
|
||||
newinode->i_mode = mode;
|
||||
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
|
||||
if (sbflags & CIFS_MOUNT_SET_UID) {
|
||||
newinode->i_uid = current_fsuid();
|
||||
if (inode->i_mode & S_ISGID)
|
||||
newinode->i_gid = inode->i_gid;
|
||||
@ -459,18 +461,20 @@ int
|
||||
cifs_atomic_open(struct inode *inode, struct dentry *direntry,
|
||||
struct file *file, unsigned int oflags, umode_t mode)
|
||||
{
|
||||
int rc;
|
||||
unsigned int xid;
|
||||
struct cifs_sb_info *cifs_sb = CIFS_SB(inode);
|
||||
struct cifs_open_info_data buf = {};
|
||||
struct TCP_Server_Info *server;
|
||||
struct cifsFileInfo *file_info;
|
||||
struct cifs_pending_open open;
|
||||
struct cifs_fid fid = {};
|
||||
struct tcon_link *tlink;
|
||||
struct cifs_tcon *tcon;
|
||||
struct TCP_Server_Info *server;
|
||||
struct cifs_fid fid = {};
|
||||
struct cifs_pending_open open;
|
||||
unsigned int sbflags;
|
||||
unsigned int xid;
|
||||
__u32 oplock;
|
||||
struct cifsFileInfo *file_info;
|
||||
struct cifs_open_info_data buf = {};
|
||||
int rc;
|
||||
|
||||
if (unlikely(cifs_forced_shutdown(CIFS_SB(inode->i_sb))))
|
||||
if (unlikely(cifs_forced_shutdown(cifs_sb)))
|
||||
return smb_EIO(smb_eio_trace_forced_shutdown);
|
||||
|
||||
/*
|
||||
@ -506,7 +510,7 @@ cifs_atomic_open(struct inode *inode, struct dentry *direntry,
|
||||
cifs_dbg(FYI, "parent inode = 0x%p name is: %pd and dentry = 0x%p\n",
|
||||
inode, direntry, direntry);
|
||||
|
||||
tlink = cifs_sb_tlink(CIFS_SB(inode->i_sb));
|
||||
tlink = cifs_sb_tlink(cifs_sb);
|
||||
if (IS_ERR(tlink)) {
|
||||
rc = PTR_ERR(tlink);
|
||||
goto out_free_xid;
|
||||
@ -543,13 +547,13 @@ cifs_atomic_open(struct inode *inode, struct dentry *direntry,
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (file->f_flags & O_DIRECT &&
|
||||
CIFS_SB(inode->i_sb)->mnt_cifs_flags & CIFS_MOUNT_STRICT_IO) {
|
||||
if (CIFS_SB(inode->i_sb)->mnt_cifs_flags & CIFS_MOUNT_NO_BRL)
|
||||
sbflags = cifs_sb_flags(cifs_sb);
|
||||
if ((file->f_flags & O_DIRECT) && (sbflags & CIFS_MOUNT_STRICT_IO)) {
|
||||
if (sbflags & CIFS_MOUNT_NO_BRL)
|
||||
file->f_op = &cifs_file_direct_nobrl_ops;
|
||||
else
|
||||
file->f_op = &cifs_file_direct_ops;
|
||||
}
|
||||
}
|
||||
|
||||
file_info = cifs_new_fileinfo(&fid, file, tlink, oplock, buf.symlink_target);
|
||||
if (file_info == NULL) {
|
||||
|
||||
@ -270,7 +270,7 @@ static void cifs_begin_writeback(struct netfs_io_request *wreq)
|
||||
static int cifs_init_request(struct netfs_io_request *rreq, struct file *file)
|
||||
{
|
||||
struct cifs_io_request *req = container_of(rreq, struct cifs_io_request, rreq);
|
||||
struct cifs_sb_info *cifs_sb = CIFS_SB(rreq->inode->i_sb);
|
||||
struct cifs_sb_info *cifs_sb = CIFS_SB(rreq->inode);
|
||||
struct cifsFileInfo *open_file = NULL;
|
||||
|
||||
rreq->rsize = cifs_sb->ctx->rsize;
|
||||
@ -281,7 +281,7 @@ static int cifs_init_request(struct netfs_io_request *rreq, struct file *file)
|
||||
open_file = file->private_data;
|
||||
rreq->netfs_priv = file->private_data;
|
||||
req->cfile = cifsFileInfo_get(open_file);
|
||||
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_RWPIDFORWARD)
|
||||
if (cifs_sb_flags(cifs_sb) & CIFS_MOUNT_RWPIDFORWARD)
|
||||
req->pid = req->cfile->pid;
|
||||
} else if (rreq->origin != NETFS_WRITEBACK) {
|
||||
WARN_ON_ONCE(1);
|
||||
@ -731,14 +731,14 @@ struct cifsFileInfo *cifs_new_fileinfo(struct cifs_fid *fid, struct file *file,
|
||||
oplock = fid->pending_open->oplock;
|
||||
list_del(&fid->pending_open->olist);
|
||||
|
||||
fid->purge_cache = false;
|
||||
server->ops->set_fid(cfile, fid, oplock);
|
||||
|
||||
list_add(&cfile->tlist, &tcon->openFileList);
|
||||
atomic_inc(&tcon->num_local_opens);
|
||||
|
||||
/* if readable file instance put first in list*/
|
||||
spin_lock(&cinode->open_file_lock);
|
||||
fid->purge_cache = false;
|
||||
server->ops->set_fid(cfile, fid, oplock);
|
||||
|
||||
if (file->f_mode & FMODE_READ)
|
||||
list_add(&cfile->flist, &cinode->openFileList);
|
||||
else
|
||||
@ -906,11 +906,19 @@ void _cifsFileInfo_put(struct cifsFileInfo *cifs_file,
|
||||
* close because it may cause a error when we open this file
|
||||
* again and get at least level II oplock.
|
||||
*/
|
||||
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_STRICT_IO)
|
||||
if (cifs_sb_flags(cifs_sb) & CIFS_MOUNT_STRICT_IO)
|
||||
set_bit(CIFS_INO_INVALID_MAPPING, &cifsi->flags);
|
||||
cifs_set_oplock_level(cifsi, 0);
|
||||
}
|
||||
|
||||
if (OPEN_FMODE(cifs_file->f_flags) & FMODE_WRITE) {
|
||||
/* Stamp while open_file_lock is held; covers all close paths
|
||||
* including background I/O. Pairs with smp_load_acquire() in
|
||||
* is_size_safe_to_change().
|
||||
*/
|
||||
smp_store_release(&cifsi->time_last_write, jiffies);
|
||||
}
|
||||
|
||||
spin_unlock(&cifsi->open_file_lock);
|
||||
spin_unlock(&tcon->open_file_lock);
|
||||
|
||||
@ -955,11 +963,11 @@ void _cifsFileInfo_put(struct cifsFileInfo *cifs_file,
|
||||
int cifs_file_flush(const unsigned int xid, struct inode *inode,
|
||||
struct cifsFileInfo *cfile)
|
||||
{
|
||||
struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
|
||||
struct cifs_sb_info *cifs_sb = CIFS_SB(inode);
|
||||
struct cifs_tcon *tcon;
|
||||
int rc;
|
||||
|
||||
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NOSSYNC)
|
||||
if (cifs_sb_flags(cifs_sb) & CIFS_MOUNT_NOSSYNC)
|
||||
return 0;
|
||||
|
||||
if (cfile && (OPEN_FMODE(cfile->f_flags) & FMODE_WRITE)) {
|
||||
@ -1015,24 +1023,24 @@ static int cifs_do_truncate(const unsigned int xid, struct dentry *dentry)
|
||||
int cifs_open(struct inode *inode, struct file *file)
|
||||
|
||||
{
|
||||
struct cifs_sb_info *cifs_sb = CIFS_SB(inode);
|
||||
struct cifs_open_info_data data = {};
|
||||
struct cifsFileInfo *cfile = NULL;
|
||||
struct TCP_Server_Info *server;
|
||||
struct cifs_pending_open open;
|
||||
bool posix_open_ok = false;
|
||||
struct cifs_fid fid = {};
|
||||
struct tcon_link *tlink;
|
||||
struct cifs_tcon *tcon;
|
||||
const char *full_path;
|
||||
unsigned int sbflags;
|
||||
int rc = -EACCES;
|
||||
unsigned int xid;
|
||||
__u32 oplock;
|
||||
struct cifs_sb_info *cifs_sb;
|
||||
struct TCP_Server_Info *server;
|
||||
struct cifs_tcon *tcon;
|
||||
struct tcon_link *tlink;
|
||||
struct cifsFileInfo *cfile = NULL;
|
||||
void *page;
|
||||
const char *full_path;
|
||||
bool posix_open_ok = false;
|
||||
struct cifs_fid fid = {};
|
||||
struct cifs_pending_open open;
|
||||
struct cifs_open_info_data data = {};
|
||||
|
||||
xid = get_xid();
|
||||
|
||||
cifs_sb = CIFS_SB(inode->i_sb);
|
||||
if (unlikely(cifs_forced_shutdown(cifs_sb))) {
|
||||
free_xid(xid);
|
||||
return smb_EIO(smb_eio_trace_forced_shutdown);
|
||||
@ -1056,9 +1064,9 @@ int cifs_open(struct inode *inode, struct file *file)
|
||||
cifs_dbg(FYI, "inode = 0x%p file flags are 0x%x for %s\n",
|
||||
inode, file->f_flags, full_path);
|
||||
|
||||
if (file->f_flags & O_DIRECT &&
|
||||
cifs_sb->mnt_cifs_flags & CIFS_MOUNT_STRICT_IO) {
|
||||
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL)
|
||||
sbflags = cifs_sb_flags(cifs_sb);
|
||||
if ((file->f_flags & O_DIRECT) && (sbflags & CIFS_MOUNT_STRICT_IO)) {
|
||||
if (sbflags & CIFS_MOUNT_NO_BRL)
|
||||
file->f_op = &cifs_file_direct_nobrl_ops;
|
||||
else
|
||||
file->f_op = &cifs_file_direct_ops;
|
||||
@ -1209,7 +1217,7 @@ cifs_relock_file(struct cifsFileInfo *cfile)
|
||||
struct cifs_tcon *tcon = tlink_tcon(cfile->tlink);
|
||||
int rc = 0;
|
||||
#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY
|
||||
struct cifs_sb_info *cifs_sb = CIFS_SB(cfile->dentry->d_sb);
|
||||
struct cifs_sb_info *cifs_sb = CIFS_SB(cinode);
|
||||
#endif /* CONFIG_CIFS_ALLOW_INSECURE_LEGACY */
|
||||
|
||||
down_read_nested(&cinode->lock_sem, SINGLE_DEPTH_NESTING);
|
||||
@ -1222,7 +1230,7 @@ cifs_relock_file(struct cifsFileInfo *cfile)
|
||||
#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY
|
||||
if (cap_unix(tcon->ses) &&
|
||||
(CIFS_UNIX_FCNTL_CAP & le64_to_cpu(tcon->fsUnixInfo.Capability)) &&
|
||||
((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NOPOSIXBRL) == 0))
|
||||
((cifs_sb_flags(cifs_sb) & CIFS_MOUNT_NOPOSIXBRL) == 0))
|
||||
rc = cifs_push_posix_locks(cfile);
|
||||
else
|
||||
#endif /* CONFIG_CIFS_ALLOW_INSECURE_LEGACY */
|
||||
@ -1410,7 +1418,8 @@ reopen_success:
|
||||
oplock = 0;
|
||||
}
|
||||
|
||||
server->ops->set_fid(cfile, &cfile->fid, oplock);
|
||||
scoped_guard(spinlock, &cinode->open_file_lock)
|
||||
server->ops->set_fid(cfile, &cfile->fid, oplock);
|
||||
if (oparms.reconnect)
|
||||
cifs_relock_file(cfile);
|
||||
|
||||
@ -1424,11 +1433,12 @@ void smb2_deferred_work_close(struct work_struct *work)
|
||||
{
|
||||
struct cifsFileInfo *cfile = container_of(work,
|
||||
struct cifsFileInfo, deferred.work);
|
||||
struct cifsInodeInfo *cinode = CIFS_I(d_inode(cfile->dentry));
|
||||
|
||||
spin_lock(&CIFS_I(d_inode(cfile->dentry))->deferred_lock);
|
||||
spin_lock(&cinode->deferred_lock);
|
||||
cifs_del_deferred_close(cfile);
|
||||
cfile->deferred_close_scheduled = false;
|
||||
spin_unlock(&CIFS_I(d_inode(cfile->dentry))->deferred_lock);
|
||||
spin_unlock(&cinode->deferred_lock);
|
||||
_cifsFileInfo_put(cfile, true, false);
|
||||
}
|
||||
|
||||
@ -1437,11 +1447,11 @@ smb2_can_defer_close(struct inode *inode, struct cifs_deferred_close *dclose)
|
||||
{
|
||||
struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
|
||||
struct cifsInodeInfo *cinode = CIFS_I(inode);
|
||||
unsigned int oplock = READ_ONCE(cinode->oplock);
|
||||
|
||||
return (cifs_sb->ctx->closetimeo && cinode->lease_granted && dclose &&
|
||||
(cinode->oplock == CIFS_CACHE_RHW_FLG ||
|
||||
cinode->oplock == CIFS_CACHE_RH_FLG) &&
|
||||
!test_bit(CIFS_INO_CLOSE_ON_LOCK, &cinode->flags));
|
||||
return cifs_sb->ctx->closetimeo && cinode->lease_granted && dclose &&
|
||||
(oplock == CIFS_CACHE_RHW_FLG || oplock == CIFS_CACHE_RH_FLG) &&
|
||||
!test_bit(CIFS_INO_CLOSE_ON_LOCK, &cinode->flags);
|
||||
|
||||
}
|
||||
|
||||
@ -2010,7 +2020,7 @@ cifs_push_locks(struct cifsFileInfo *cfile)
|
||||
struct cifs_tcon *tcon = tlink_tcon(cfile->tlink);
|
||||
int rc = 0;
|
||||
#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY
|
||||
struct cifs_sb_info *cifs_sb = CIFS_SB(cfile->dentry->d_sb);
|
||||
struct cifs_sb_info *cifs_sb = CIFS_SB(cinode);
|
||||
#endif /* CONFIG_CIFS_ALLOW_INSECURE_LEGACY */
|
||||
|
||||
/* we are going to update can_cache_brlcks here - need a write access */
|
||||
@ -2023,7 +2033,7 @@ cifs_push_locks(struct cifsFileInfo *cfile)
|
||||
#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY
|
||||
if (cap_unix(tcon->ses) &&
|
||||
(CIFS_UNIX_FCNTL_CAP & le64_to_cpu(tcon->fsUnixInfo.Capability)) &&
|
||||
((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NOPOSIXBRL) == 0))
|
||||
((cifs_sb_flags(cifs_sb) & CIFS_MOUNT_NOPOSIXBRL) == 0))
|
||||
rc = cifs_push_posix_locks(cfile);
|
||||
else
|
||||
#endif /* CONFIG_CIFS_ALLOW_INSECURE_LEGACY */
|
||||
@ -2371,7 +2381,7 @@ cifs_setlk(struct file *file, struct file_lock *flock, __u32 type,
|
||||
cifs_zap_mapping(inode);
|
||||
cifs_dbg(FYI, "Set no oplock for inode=%p due to mand locks\n",
|
||||
inode);
|
||||
CIFS_I(inode)->oplock = 0;
|
||||
cifs_reset_oplock(CIFS_I(inode));
|
||||
}
|
||||
|
||||
rc = server->ops->mand_lock(xid, cfile, flock->fl_start, length,
|
||||
@ -2427,11 +2437,11 @@ int cifs_flock(struct file *file, int cmd, struct file_lock *fl)
|
||||
|
||||
cifs_read_flock(fl, &type, &lock, &unlock, &wait_flag,
|
||||
tcon->ses->server);
|
||||
cifs_sb = CIFS_FILE_SB(file);
|
||||
cifs_sb = CIFS_SB(file);
|
||||
|
||||
if (cap_unix(tcon->ses) &&
|
||||
(CIFS_UNIX_FCNTL_CAP & le64_to_cpu(tcon->fsUnixInfo.Capability)) &&
|
||||
((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NOPOSIXBRL) == 0))
|
||||
((cifs_sb_flags(cifs_sb) & CIFS_MOUNT_NOPOSIXBRL) == 0))
|
||||
posix_lck = true;
|
||||
|
||||
if (!lock && !unlock) {
|
||||
@ -2454,14 +2464,14 @@ int cifs_flock(struct file *file, int cmd, struct file_lock *fl)
|
||||
|
||||
int cifs_lock(struct file *file, int cmd, struct file_lock *flock)
|
||||
{
|
||||
int rc, xid;
|
||||
struct cifs_sb_info *cifs_sb = CIFS_SB(file);
|
||||
struct cifsFileInfo *cfile;
|
||||
int lock = 0, unlock = 0;
|
||||
bool wait_flag = false;
|
||||
bool posix_lck = false;
|
||||
struct cifs_sb_info *cifs_sb;
|
||||
struct cifs_tcon *tcon;
|
||||
struct cifsFileInfo *cfile;
|
||||
__u32 type;
|
||||
int rc, xid;
|
||||
|
||||
rc = -EACCES;
|
||||
xid = get_xid();
|
||||
@ -2476,12 +2486,11 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *flock)
|
||||
|
||||
cifs_read_flock(flock, &type, &lock, &unlock, &wait_flag,
|
||||
tcon->ses->server);
|
||||
cifs_sb = CIFS_FILE_SB(file);
|
||||
set_bit(CIFS_INO_CLOSE_ON_LOCK, &CIFS_I(d_inode(cfile->dentry))->flags);
|
||||
|
||||
if (cap_unix(tcon->ses) &&
|
||||
(CIFS_UNIX_FCNTL_CAP & le64_to_cpu(tcon->fsUnixInfo.Capability)) &&
|
||||
((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NOPOSIXBRL) == 0))
|
||||
((cifs_sb_flags(cifs_sb) & CIFS_MOUNT_NOPOSIXBRL) == 0))
|
||||
posix_lck = true;
|
||||
/*
|
||||
* BB add code here to normalize offset and length to account for
|
||||
@ -2531,11 +2540,11 @@ void cifs_write_subrequest_terminated(struct cifs_io_subrequest *wdata, ssize_t
|
||||
struct cifsFileInfo *find_readable_file(struct cifsInodeInfo *cifs_inode,
|
||||
bool fsuid_only)
|
||||
{
|
||||
struct cifs_sb_info *cifs_sb = CIFS_SB(cifs_inode);
|
||||
struct cifsFileInfo *open_file = NULL;
|
||||
struct cifs_sb_info *cifs_sb = CIFS_SB(cifs_inode->netfs.inode.i_sb);
|
||||
|
||||
/* only filter by fsuid on multiuser mounts */
|
||||
if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MULTIUSER))
|
||||
if (!(cifs_sb_flags(cifs_sb) & CIFS_MOUNT_MULTIUSER))
|
||||
fsuid_only = false;
|
||||
|
||||
spin_lock(&cifs_inode->open_file_lock);
|
||||
@ -2588,10 +2597,10 @@ cifs_get_writable_file(struct cifsInodeInfo *cifs_inode, int flags,
|
||||
return rc;
|
||||
}
|
||||
|
||||
cifs_sb = CIFS_SB(cifs_inode->netfs.inode.i_sb);
|
||||
cifs_sb = CIFS_SB(cifs_inode);
|
||||
|
||||
/* only filter by fsuid on multiuser mounts */
|
||||
if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MULTIUSER))
|
||||
if (!(cifs_sb_flags(cifs_sb) & CIFS_MOUNT_MULTIUSER))
|
||||
fsuid_only = false;
|
||||
|
||||
spin_lock(&cifs_inode->open_file_lock);
|
||||
@ -2786,7 +2795,7 @@ int cifs_fsync(struct file *file, loff_t start, loff_t end, int datasync)
|
||||
struct TCP_Server_Info *server;
|
||||
struct cifsFileInfo *smbfile = file->private_data;
|
||||
struct inode *inode = file_inode(file);
|
||||
struct cifs_sb_info *cifs_sb = CIFS_FILE_SB(file);
|
||||
struct cifs_sb_info *cifs_sb = CIFS_SB(file);
|
||||
|
||||
rc = file_write_and_wait_range(file, start, end);
|
||||
if (rc) {
|
||||
@ -2800,7 +2809,7 @@ int cifs_fsync(struct file *file, loff_t start, loff_t end, int datasync)
|
||||
file, datasync);
|
||||
|
||||
tcon = tlink_tcon(smbfile->tlink);
|
||||
if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NOSSYNC)) {
|
||||
if (!(cifs_sb_flags(cifs_sb) & CIFS_MOUNT_NOSSYNC)) {
|
||||
server = tcon->ses->server;
|
||||
if (server->ops->flush == NULL) {
|
||||
rc = -ENOSYS;
|
||||
@ -2852,7 +2861,7 @@ cifs_writev(struct kiocb *iocb, struct iov_iter *from)
|
||||
struct inode *inode = file->f_mapping->host;
|
||||
struct cifsInodeInfo *cinode = CIFS_I(inode);
|
||||
struct TCP_Server_Info *server = tlink_tcon(cfile->tlink)->ses->server;
|
||||
struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
|
||||
struct cifs_sb_info *cifs_sb = CIFS_SB(inode);
|
||||
ssize_t rc;
|
||||
|
||||
rc = netfs_start_io_write(inode);
|
||||
@ -2869,7 +2878,7 @@ cifs_writev(struct kiocb *iocb, struct iov_iter *from)
|
||||
if (rc <= 0)
|
||||
goto out;
|
||||
|
||||
if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NOPOSIXBRL) &&
|
||||
if ((cifs_sb_flags(cifs_sb) & CIFS_MOUNT_NOPOSIXBRL) &&
|
||||
(cifs_find_lock_conflict(cfile, iocb->ki_pos, iov_iter_count(from),
|
||||
server->vals->exclusive_lock_type, 0,
|
||||
NULL, CIFS_WRITE_OP))) {
|
||||
@ -2892,7 +2901,7 @@ cifs_strict_writev(struct kiocb *iocb, struct iov_iter *from)
|
||||
{
|
||||
struct inode *inode = file_inode(iocb->ki_filp);
|
||||
struct cifsInodeInfo *cinode = CIFS_I(inode);
|
||||
struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
|
||||
struct cifs_sb_info *cifs_sb = CIFS_SB(inode);
|
||||
struct cifsFileInfo *cfile = (struct cifsFileInfo *)
|
||||
iocb->ki_filp->private_data;
|
||||
struct cifs_tcon *tcon = tlink_tcon(cfile->tlink);
|
||||
@ -2905,7 +2914,7 @@ cifs_strict_writev(struct kiocb *iocb, struct iov_iter *from)
|
||||
if (CIFS_CACHE_WRITE(cinode)) {
|
||||
if (cap_unix(tcon->ses) &&
|
||||
(CIFS_UNIX_FCNTL_CAP & le64_to_cpu(tcon->fsUnixInfo.Capability)) &&
|
||||
((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NOPOSIXBRL) == 0)) {
|
||||
((cifs_sb_flags(cifs_sb) & CIFS_MOUNT_NOPOSIXBRL) == 0)) {
|
||||
written = netfs_file_write_iter(iocb, from);
|
||||
goto out;
|
||||
}
|
||||
@ -2930,7 +2939,7 @@ cifs_strict_writev(struct kiocb *iocb, struct iov_iter *from)
|
||||
cifs_zap_mapping(inode);
|
||||
cifs_dbg(FYI, "Set Oplock/Lease to NONE for inode=%p after write\n",
|
||||
inode);
|
||||
cinode->oplock = 0;
|
||||
cifs_reset_oplock(cinode);
|
||||
}
|
||||
out:
|
||||
cifs_put_writer(cinode);
|
||||
@ -2966,7 +2975,7 @@ ssize_t cifs_file_write_iter(struct kiocb *iocb, struct iov_iter *from)
|
||||
cifs_dbg(FYI,
|
||||
"Set no oplock for inode=%p after a write operation\n",
|
||||
inode);
|
||||
cinode->oplock = 0;
|
||||
cifs_reset_oplock(cinode);
|
||||
}
|
||||
return written;
|
||||
}
|
||||
@ -2993,7 +3002,7 @@ cifs_strict_readv(struct kiocb *iocb, struct iov_iter *to)
|
||||
{
|
||||
struct inode *inode = file_inode(iocb->ki_filp);
|
||||
struct cifsInodeInfo *cinode = CIFS_I(inode);
|
||||
struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
|
||||
struct cifs_sb_info *cifs_sb = CIFS_SB(inode);
|
||||
struct cifsFileInfo *cfile = (struct cifsFileInfo *)
|
||||
iocb->ki_filp->private_data;
|
||||
struct cifs_tcon *tcon = tlink_tcon(cfile->tlink);
|
||||
@ -3010,7 +3019,7 @@ cifs_strict_readv(struct kiocb *iocb, struct iov_iter *to)
|
||||
if (!CIFS_CACHE_READ(cinode))
|
||||
return netfs_unbuffered_read_iter(iocb, to);
|
||||
|
||||
if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NOPOSIXBRL) == 0) {
|
||||
if ((cifs_sb_flags(cifs_sb) & CIFS_MOUNT_NOPOSIXBRL) == 0) {
|
||||
if (iocb->ki_flags & IOCB_DIRECT)
|
||||
return netfs_unbuffered_read_iter(iocb, to);
|
||||
return netfs_buffered_read_iter(iocb, to);
|
||||
@ -3123,16 +3132,28 @@ static int is_inode_writable(struct cifsInodeInfo *cifs_inode)
|
||||
bool is_size_safe_to_change(struct cifsInodeInfo *cifsInode, __u64 end_of_file,
|
||||
bool from_readdir)
|
||||
{
|
||||
struct cifs_sb_info *cifs_sb;
|
||||
unsigned long tlw;
|
||||
|
||||
if (!cifsInode)
|
||||
return true;
|
||||
|
||||
cifs_sb = CIFS_SB(cifsInode);
|
||||
|
||||
if (is_inode_writable(cifsInode) ||
|
||||
((cifsInode->oplock & CIFS_CACHE_RW_FLG) != 0 && from_readdir)) {
|
||||
/* This inode is open for write at least once */
|
||||
struct cifs_sb_info *cifs_sb;
|
||||
|
||||
cifs_sb = CIFS_SB(cifsInode->netfs.inode.i_sb);
|
||||
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO) {
|
||||
/*
|
||||
* Readdir data is unreliable when we have writable handles or
|
||||
* an exclusive lease -- never allow it to change i_size, even
|
||||
* on direct-IO mounts where the server's directory metadata
|
||||
* can still lag behind the actual file state.
|
||||
*/
|
||||
if (from_readdir)
|
||||
return false;
|
||||
|
||||
if (cifs_sb_flags(cifs_sb) & CIFS_MOUNT_DIRECT_IO) {
|
||||
/* since no page cache to corrupt on directio
|
||||
we can change size safely */
|
||||
return true;
|
||||
@ -3142,8 +3163,40 @@ bool is_size_safe_to_change(struct cifsInodeInfo *cifsInode, __u64 end_of_file,
|
||||
return true;
|
||||
|
||||
return false;
|
||||
} else
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* No writable handles open. Check whether we are within the attribute
|
||||
* cache validity window of a recent local modification.
|
||||
*
|
||||
* For the close() path: _cifsFileInfo_put() stamps time_last_write
|
||||
* (via smp_store_release()) before releasing open_file_lock. That
|
||||
* spin_unlock() is a store-release that pairs with the spin_lock()
|
||||
* (load-acquire) in is_inode_writable() above, so if
|
||||
* is_inode_writable() returned false the smp_load_acquire() below is
|
||||
* guaranteed to observe any time_last_write update from a concurrent
|
||||
* close(), covering all close paths including background I/O.
|
||||
*
|
||||
* For the setattr/truncate paths: those callers use smp_store_release()
|
||||
* directly; the smp_load_acquire() below pairs with that store. There
|
||||
* is no shared lock between setattr and readdir, so this relies on
|
||||
* acquire-release semantics alone. The store propagation latency on
|
||||
* weakly-ordered architectures (nanoseconds) is negligible relative to
|
||||
* the acregmax window (seconds) and the readdir RPC round-trip
|
||||
* (milliseconds), making this a sound design choice in practice.
|
||||
*
|
||||
* time_last_write == 0 means the inode has never been written locally;
|
||||
* skip the window check to avoid false positives near boot time when
|
||||
* jiffies is still close to INITIAL_JIFFIES on 32-bit systems.
|
||||
*/
|
||||
if (from_readdir) {
|
||||
/* Pairs with smp_store_release() in _cifsFileInfo_put() and setattr. */
|
||||
tlw = smp_load_acquire(&cifsInode->time_last_write);
|
||||
if (tlw && time_before(jiffies, tlw + cifs_sb->ctx->acregmax))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void cifs_oplock_break(struct work_struct *work)
|
||||
@ -3154,9 +3207,11 @@ void cifs_oplock_break(struct work_struct *work)
|
||||
struct super_block *sb = inode->i_sb;
|
||||
struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
|
||||
struct cifsInodeInfo *cinode = CIFS_I(inode);
|
||||
bool cache_read, cache_write, cache_handle;
|
||||
struct cifs_tcon *tcon;
|
||||
struct TCP_Server_Info *server;
|
||||
struct tcon_link *tlink;
|
||||
unsigned int oplock;
|
||||
int rc = 0;
|
||||
bool purge_cache = false, oplock_break_cancelled;
|
||||
__u64 persistent_fid, volatile_fid;
|
||||
@ -3177,29 +3232,40 @@ void cifs_oplock_break(struct work_struct *work)
|
||||
tcon = tlink_tcon(tlink);
|
||||
server = tcon->ses->server;
|
||||
|
||||
server->ops->downgrade_oplock(server, cinode, cfile->oplock_level,
|
||||
cfile->oplock_epoch, &purge_cache);
|
||||
scoped_guard(spinlock, &cinode->open_file_lock) {
|
||||
unsigned int sbflags = cifs_sb_flags(cifs_sb);
|
||||
|
||||
if (!CIFS_CACHE_WRITE(cinode) && CIFS_CACHE_READ(cinode) &&
|
||||
cifs_has_mand_locks(cinode)) {
|
||||
server->ops->downgrade_oplock(server, cinode, cfile->oplock_level,
|
||||
cfile->oplock_epoch, &purge_cache);
|
||||
oplock = READ_ONCE(cinode->oplock);
|
||||
cache_read = (oplock & CIFS_CACHE_READ_FLG) ||
|
||||
(sbflags & CIFS_MOUNT_RO_CACHE);
|
||||
cache_write = (oplock & CIFS_CACHE_WRITE_FLG) ||
|
||||
(sbflags & CIFS_MOUNT_RW_CACHE);
|
||||
cache_handle = oplock & CIFS_CACHE_HANDLE_FLG;
|
||||
}
|
||||
|
||||
if (!cache_write && cache_read && cifs_has_mand_locks(cinode)) {
|
||||
cifs_dbg(FYI, "Reset oplock to None for inode=%p due to mand locks\n",
|
||||
inode);
|
||||
cinode->oplock = 0;
|
||||
cifs_reset_oplock(cinode);
|
||||
oplock = 0;
|
||||
cache_read = cache_write = cache_handle = false;
|
||||
}
|
||||
|
||||
if (S_ISREG(inode->i_mode)) {
|
||||
if (CIFS_CACHE_READ(cinode))
|
||||
if (cache_read)
|
||||
break_lease(inode, O_RDONLY);
|
||||
else
|
||||
break_lease(inode, O_WRONLY);
|
||||
rc = filemap_fdatawrite(inode->i_mapping);
|
||||
if (!CIFS_CACHE_READ(cinode) || purge_cache) {
|
||||
if (!cache_read || purge_cache) {
|
||||
rc = filemap_fdatawait(inode->i_mapping);
|
||||
mapping_set_error(inode->i_mapping, rc);
|
||||
cifs_zap_mapping(inode);
|
||||
}
|
||||
cifs_dbg(FYI, "Oplock flush inode %p rc %d\n", inode, rc);
|
||||
if (CIFS_CACHE_WRITE(cinode))
|
||||
if (cache_write)
|
||||
goto oplock_break_ack;
|
||||
}
|
||||
|
||||
@ -3214,7 +3280,7 @@ oplock_break_ack:
|
||||
* So, new open will not use cached handle.
|
||||
*/
|
||||
|
||||
if (!CIFS_CACHE_HANDLE(cinode) && !list_empty(&cinode->deferred_closes))
|
||||
if (!cache_handle && !list_empty(&cinode->deferred_closes))
|
||||
cifs_close_deferred_file(cinode);
|
||||
|
||||
persistent_fid = cfile->fid.persistent_fid;
|
||||
@ -3232,7 +3298,8 @@ oplock_break_ack:
|
||||
if (!oplock_break_cancelled && !list_empty(&cinode->openFileList)) {
|
||||
spin_unlock(&cinode->open_file_lock);
|
||||
rc = server->ops->oplock_response(tcon, persistent_fid,
|
||||
volatile_fid, net_fid, cinode);
|
||||
volatile_fid, net_fid,
|
||||
cinode, oplock);
|
||||
cifs_dbg(FYI, "Oplock release rc = %d\n", rc);
|
||||
} else
|
||||
spin_unlock(&cinode->open_file_lock);
|
||||
|
||||
@ -2071,161 +2071,160 @@ smb3_cleanup_fs_context(struct smb3_fs_context *ctx)
|
||||
kfree(ctx);
|
||||
}
|
||||
|
||||
void smb3_update_mnt_flags(struct cifs_sb_info *cifs_sb)
|
||||
unsigned int smb3_update_mnt_flags(struct cifs_sb_info *cifs_sb)
|
||||
{
|
||||
unsigned int sbflags = cifs_sb_flags(cifs_sb);
|
||||
struct smb3_fs_context *ctx = cifs_sb->ctx;
|
||||
|
||||
if (ctx->nodfs)
|
||||
cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_DFS;
|
||||
sbflags |= CIFS_MOUNT_NO_DFS;
|
||||
else
|
||||
cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_NO_DFS;
|
||||
sbflags &= ~CIFS_MOUNT_NO_DFS;
|
||||
|
||||
if (ctx->noperm)
|
||||
cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_PERM;
|
||||
sbflags |= CIFS_MOUNT_NO_PERM;
|
||||
else
|
||||
cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_NO_PERM;
|
||||
sbflags &= ~CIFS_MOUNT_NO_PERM;
|
||||
|
||||
if (ctx->setuids)
|
||||
cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_SET_UID;
|
||||
sbflags |= CIFS_MOUNT_SET_UID;
|
||||
else
|
||||
cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_SET_UID;
|
||||
sbflags &= ~CIFS_MOUNT_SET_UID;
|
||||
|
||||
if (ctx->setuidfromacl)
|
||||
cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_UID_FROM_ACL;
|
||||
sbflags |= CIFS_MOUNT_UID_FROM_ACL;
|
||||
else
|
||||
cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_UID_FROM_ACL;
|
||||
sbflags &= ~CIFS_MOUNT_UID_FROM_ACL;
|
||||
|
||||
if (ctx->server_ino)
|
||||
cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_SERVER_INUM;
|
||||
sbflags |= CIFS_MOUNT_SERVER_INUM;
|
||||
else
|
||||
cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_SERVER_INUM;
|
||||
sbflags &= ~CIFS_MOUNT_SERVER_INUM;
|
||||
|
||||
if (ctx->remap)
|
||||
cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MAP_SFM_CHR;
|
||||
sbflags |= CIFS_MOUNT_MAP_SFM_CHR;
|
||||
else
|
||||
cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_MAP_SFM_CHR;
|
||||
sbflags &= ~CIFS_MOUNT_MAP_SFM_CHR;
|
||||
|
||||
if (ctx->sfu_remap)
|
||||
cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MAP_SPECIAL_CHR;
|
||||
sbflags |= CIFS_MOUNT_MAP_SPECIAL_CHR;
|
||||
else
|
||||
cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_MAP_SPECIAL_CHR;
|
||||
sbflags &= ~CIFS_MOUNT_MAP_SPECIAL_CHR;
|
||||
|
||||
if (ctx->no_xattr)
|
||||
cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_XATTR;
|
||||
sbflags |= CIFS_MOUNT_NO_XATTR;
|
||||
else
|
||||
cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_NO_XATTR;
|
||||
sbflags &= ~CIFS_MOUNT_NO_XATTR;
|
||||
|
||||
if (ctx->sfu_emul)
|
||||
cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_UNX_EMUL;
|
||||
sbflags |= CIFS_MOUNT_UNX_EMUL;
|
||||
else
|
||||
cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_UNX_EMUL;
|
||||
sbflags &= ~CIFS_MOUNT_UNX_EMUL;
|
||||
|
||||
if (ctx->nobrl)
|
||||
cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_BRL;
|
||||
sbflags |= CIFS_MOUNT_NO_BRL;
|
||||
else
|
||||
cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_NO_BRL;
|
||||
sbflags &= ~CIFS_MOUNT_NO_BRL;
|
||||
|
||||
if (ctx->nohandlecache)
|
||||
cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_HANDLE_CACHE;
|
||||
sbflags |= CIFS_MOUNT_NO_HANDLE_CACHE;
|
||||
else
|
||||
cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_NO_HANDLE_CACHE;
|
||||
sbflags &= ~CIFS_MOUNT_NO_HANDLE_CACHE;
|
||||
|
||||
if (ctx->nostrictsync)
|
||||
cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NOSSYNC;
|
||||
sbflags |= CIFS_MOUNT_NOSSYNC;
|
||||
else
|
||||
cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_NOSSYNC;
|
||||
sbflags &= ~CIFS_MOUNT_NOSSYNC;
|
||||
|
||||
if (ctx->mand_lock)
|
||||
cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NOPOSIXBRL;
|
||||
sbflags |= CIFS_MOUNT_NOPOSIXBRL;
|
||||
else
|
||||
cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_NOPOSIXBRL;
|
||||
sbflags &= ~CIFS_MOUNT_NOPOSIXBRL;
|
||||
|
||||
if (ctx->rwpidforward)
|
||||
cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_RWPIDFORWARD;
|
||||
sbflags |= CIFS_MOUNT_RWPIDFORWARD;
|
||||
else
|
||||
cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_RWPIDFORWARD;
|
||||
sbflags &= ~CIFS_MOUNT_RWPIDFORWARD;
|
||||
|
||||
if (ctx->mode_ace)
|
||||
cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MODE_FROM_SID;
|
||||
sbflags |= CIFS_MOUNT_MODE_FROM_SID;
|
||||
else
|
||||
cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_MODE_FROM_SID;
|
||||
sbflags &= ~CIFS_MOUNT_MODE_FROM_SID;
|
||||
|
||||
if (ctx->cifs_acl)
|
||||
cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_CIFS_ACL;
|
||||
sbflags |= CIFS_MOUNT_CIFS_ACL;
|
||||
else
|
||||
cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_CIFS_ACL;
|
||||
sbflags &= ~CIFS_MOUNT_CIFS_ACL;
|
||||
|
||||
if (ctx->backupuid_specified)
|
||||
cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_CIFS_BACKUPUID;
|
||||
sbflags |= CIFS_MOUNT_CIFS_BACKUPUID;
|
||||
else
|
||||
cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_CIFS_BACKUPUID;
|
||||
sbflags &= ~CIFS_MOUNT_CIFS_BACKUPUID;
|
||||
|
||||
if (ctx->backupgid_specified)
|
||||
cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_CIFS_BACKUPGID;
|
||||
sbflags |= CIFS_MOUNT_CIFS_BACKUPGID;
|
||||
else
|
||||
cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_CIFS_BACKUPGID;
|
||||
sbflags &= ~CIFS_MOUNT_CIFS_BACKUPGID;
|
||||
|
||||
if (ctx->override_uid)
|
||||
cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_OVERR_UID;
|
||||
sbflags |= CIFS_MOUNT_OVERR_UID;
|
||||
else
|
||||
cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_OVERR_UID;
|
||||
sbflags &= ~CIFS_MOUNT_OVERR_UID;
|
||||
|
||||
if (ctx->override_gid)
|
||||
cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_OVERR_GID;
|
||||
sbflags |= CIFS_MOUNT_OVERR_GID;
|
||||
else
|
||||
cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_OVERR_GID;
|
||||
sbflags &= ~CIFS_MOUNT_OVERR_GID;
|
||||
|
||||
if (ctx->dynperm)
|
||||
cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DYNPERM;
|
||||
sbflags |= CIFS_MOUNT_DYNPERM;
|
||||
else
|
||||
cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_DYNPERM;
|
||||
sbflags &= ~CIFS_MOUNT_DYNPERM;
|
||||
|
||||
if (ctx->fsc)
|
||||
cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_FSCACHE;
|
||||
sbflags |= CIFS_MOUNT_FSCACHE;
|
||||
else
|
||||
cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_FSCACHE;
|
||||
sbflags &= ~CIFS_MOUNT_FSCACHE;
|
||||
|
||||
if (ctx->multiuser)
|
||||
cifs_sb->mnt_cifs_flags |= (CIFS_MOUNT_MULTIUSER |
|
||||
CIFS_MOUNT_NO_PERM);
|
||||
sbflags |= CIFS_MOUNT_MULTIUSER | CIFS_MOUNT_NO_PERM;
|
||||
else
|
||||
cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_MULTIUSER;
|
||||
sbflags &= ~CIFS_MOUNT_MULTIUSER;
|
||||
|
||||
|
||||
if (ctx->strict_io)
|
||||
cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_STRICT_IO;
|
||||
sbflags |= CIFS_MOUNT_STRICT_IO;
|
||||
else
|
||||
cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_STRICT_IO;
|
||||
sbflags &= ~CIFS_MOUNT_STRICT_IO;
|
||||
|
||||
if (ctx->direct_io)
|
||||
cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DIRECT_IO;
|
||||
sbflags |= CIFS_MOUNT_DIRECT_IO;
|
||||
else
|
||||
cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_DIRECT_IO;
|
||||
sbflags &= ~CIFS_MOUNT_DIRECT_IO;
|
||||
|
||||
if (ctx->mfsymlinks)
|
||||
cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MF_SYMLINKS;
|
||||
sbflags |= CIFS_MOUNT_MF_SYMLINKS;
|
||||
else
|
||||
cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_MF_SYMLINKS;
|
||||
if (ctx->mfsymlinks) {
|
||||
if (ctx->sfu_emul) {
|
||||
/*
|
||||
* Our SFU ("Services for Unix") emulation allows now
|
||||
* creating new and reading existing SFU symlinks.
|
||||
* Older Linux kernel versions were not able to neither
|
||||
* read existing nor create new SFU symlinks. But
|
||||
* creating and reading SFU style mknod and FIFOs was
|
||||
* supported for long time. When "mfsymlinks" and
|
||||
* "sfu" are both enabled at the same time, it allows
|
||||
* reading both types of symlinks, but will only create
|
||||
* them with mfsymlinks format. This allows better
|
||||
* Apple compatibility, compatibility with older Linux
|
||||
* kernel clients (probably better for Samba too)
|
||||
* while still recognizing old Windows style symlinks.
|
||||
*/
|
||||
cifs_dbg(VFS, "mount options mfsymlinks and sfu both enabled\n");
|
||||
}
|
||||
}
|
||||
cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_SHUTDOWN;
|
||||
sbflags &= ~CIFS_MOUNT_MF_SYMLINKS;
|
||||
|
||||
return;
|
||||
if (ctx->mfsymlinks && ctx->sfu_emul) {
|
||||
/*
|
||||
* Our SFU ("Services for Unix") emulation allows now
|
||||
* creating new and reading existing SFU symlinks.
|
||||
* Older Linux kernel versions were not able to neither
|
||||
* read existing nor create new SFU symlinks. But
|
||||
* creating and reading SFU style mknod and FIFOs was
|
||||
* supported for long time. When "mfsymlinks" and
|
||||
* "sfu" are both enabled at the same time, it allows
|
||||
* reading both types of symlinks, but will only create
|
||||
* them with mfsymlinks format. This allows better
|
||||
* Apple compatibility, compatibility with older Linux
|
||||
* kernel clients (probably better for Samba too)
|
||||
* while still recognizing old Windows style symlinks.
|
||||
*/
|
||||
cifs_dbg(VFS, "mount options mfsymlinks and sfu both enabled\n");
|
||||
}
|
||||
sbflags &= ~CIFS_MOUNT_SHUTDOWN;
|
||||
atomic_set(&cifs_sb->mnt_cifs_flags, sbflags);
|
||||
return sbflags;
|
||||
}
|
||||
|
||||
@ -372,7 +372,7 @@ static inline struct smb3_fs_context *smb3_fc2context(const struct fs_context *f
|
||||
|
||||
extern int smb3_fs_context_dup(struct smb3_fs_context *new_ctx, struct smb3_fs_context *ctx);
|
||||
extern int smb3_sync_session_ctx_passwords(struct cifs_sb_info *cifs_sb, struct cifs_ses *ses);
|
||||
extern void smb3_update_mnt_flags(struct cifs_sb_info *cifs_sb);
|
||||
unsigned int smb3_update_mnt_flags(struct cifs_sb_info *cifs_sb);
|
||||
|
||||
/*
|
||||
* max deferred close timeout (jiffies) - 2^30
|
||||
|
||||
@ -40,32 +40,33 @@ static void cifs_set_netfs_context(struct inode *inode)
|
||||
|
||||
static void cifs_set_ops(struct inode *inode)
|
||||
{
|
||||
struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
|
||||
struct cifs_sb_info *cifs_sb = CIFS_SB(inode);
|
||||
struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb);
|
||||
struct netfs_inode *ictx = netfs_inode(inode);
|
||||
unsigned int sbflags = cifs_sb_flags(cifs_sb);
|
||||
|
||||
switch (inode->i_mode & S_IFMT) {
|
||||
case S_IFREG:
|
||||
inode->i_op = &cifs_file_inode_ops;
|
||||
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO) {
|
||||
if (sbflags & CIFS_MOUNT_DIRECT_IO) {
|
||||
set_bit(NETFS_ICTX_UNBUFFERED, &ictx->flags);
|
||||
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL)
|
||||
if (sbflags & CIFS_MOUNT_NO_BRL)
|
||||
inode->i_fop = &cifs_file_direct_nobrl_ops;
|
||||
else
|
||||
inode->i_fop = &cifs_file_direct_ops;
|
||||
} else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_STRICT_IO) {
|
||||
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL)
|
||||
} else if (sbflags & CIFS_MOUNT_STRICT_IO) {
|
||||
if (sbflags & CIFS_MOUNT_NO_BRL)
|
||||
inode->i_fop = &cifs_file_strict_nobrl_ops;
|
||||
else
|
||||
inode->i_fop = &cifs_file_strict_ops;
|
||||
} else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL)
|
||||
} else if (sbflags & CIFS_MOUNT_NO_BRL)
|
||||
inode->i_fop = &cifs_file_nobrl_ops;
|
||||
else { /* not direct, send byte range locks */
|
||||
inode->i_fop = &cifs_file_ops;
|
||||
}
|
||||
|
||||
/* check if server can support readahead */
|
||||
if (cifs_sb_master_tcon(cifs_sb)->ses->server->max_read <
|
||||
PAGE_SIZE + MAX_CIFS_HDR_SIZE)
|
||||
if (tcon->ses->server->max_read < PAGE_SIZE + MAX_CIFS_HDR_SIZE)
|
||||
inode->i_data.a_ops = &cifs_addr_ops_smallbuf;
|
||||
else
|
||||
inode->i_data.a_ops = &cifs_addr_ops;
|
||||
@ -194,8 +195,8 @@ cifs_fattr_to_inode(struct inode *inode, struct cifs_fattr *fattr,
|
||||
inode->i_gid = fattr->cf_gid;
|
||||
|
||||
/* if dynperm is set, don't clobber existing mode */
|
||||
if (inode->i_state & I_NEW ||
|
||||
!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM))
|
||||
if ((inode->i_state & I_NEW) ||
|
||||
!(cifs_sb_flags(cifs_sb) & CIFS_MOUNT_DYNPERM))
|
||||
inode->i_mode = fattr->cf_mode;
|
||||
|
||||
cifs_i->cifsAttrs = fattr->cf_cifsattrs;
|
||||
@ -225,6 +226,8 @@ cifs_fattr_to_inode(struct inode *inode, struct cifs_fattr *fattr,
|
||||
* calculating num blocks.
|
||||
*/
|
||||
inode->i_blocks = (512 - 1 + fattr->cf_bytes) >> 9;
|
||||
} else if (from_readdir && i_size_read(inode) != fattr->cf_eof) {
|
||||
cifs_i->time = 0;
|
||||
}
|
||||
|
||||
if (S_ISLNK(fattr->cf_mode) && fattr->cf_symlink_target) {
|
||||
@ -248,10 +251,8 @@ cifs_fill_uniqueid(struct super_block *sb, struct cifs_fattr *fattr)
|
||||
{
|
||||
struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
|
||||
|
||||
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM)
|
||||
return;
|
||||
|
||||
fattr->cf_uniqueid = iunique(sb, ROOT_I);
|
||||
if (!(cifs_sb_flags(cifs_sb) & CIFS_MOUNT_SERVER_INUM))
|
||||
fattr->cf_uniqueid = iunique(sb, ROOT_I);
|
||||
}
|
||||
|
||||
/* Fill a cifs_fattr struct with info from FILE_UNIX_BASIC_INFO. */
|
||||
@ -259,6 +260,8 @@ void
|
||||
cifs_unix_basic_to_fattr(struct cifs_fattr *fattr, FILE_UNIX_BASIC_INFO *info,
|
||||
struct cifs_sb_info *cifs_sb)
|
||||
{
|
||||
unsigned int sbflags;
|
||||
|
||||
memset(fattr, 0, sizeof(*fattr));
|
||||
fattr->cf_uniqueid = le64_to_cpu(info->UniqueId);
|
||||
fattr->cf_bytes = le64_to_cpu(info->NumOfBytes);
|
||||
@ -317,8 +320,9 @@ cifs_unix_basic_to_fattr(struct cifs_fattr *fattr, FILE_UNIX_BASIC_INFO *info,
|
||||
break;
|
||||
}
|
||||
|
||||
sbflags = cifs_sb_flags(cifs_sb);
|
||||
fattr->cf_uid = cifs_sb->ctx->linux_uid;
|
||||
if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_UID)) {
|
||||
if (!(sbflags & CIFS_MOUNT_OVERR_UID)) {
|
||||
u64 id = le64_to_cpu(info->Uid);
|
||||
if (id < ((uid_t)-1)) {
|
||||
kuid_t uid = make_kuid(&init_user_ns, id);
|
||||
@ -328,7 +332,7 @@ cifs_unix_basic_to_fattr(struct cifs_fattr *fattr, FILE_UNIX_BASIC_INFO *info,
|
||||
}
|
||||
|
||||
fattr->cf_gid = cifs_sb->ctx->linux_gid;
|
||||
if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_GID)) {
|
||||
if (!(sbflags & CIFS_MOUNT_OVERR_GID)) {
|
||||
u64 id = le64_to_cpu(info->Gid);
|
||||
if (id < ((gid_t)-1)) {
|
||||
kgid_t gid = make_kgid(&init_user_ns, id);
|
||||
@ -382,7 +386,7 @@ static int update_inode_info(struct super_block *sb,
|
||||
*
|
||||
* If file type or uniqueid is different, return error.
|
||||
*/
|
||||
if (unlikely((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) &&
|
||||
if (unlikely((cifs_sb_flags(cifs_sb) & CIFS_MOUNT_SERVER_INUM) &&
|
||||
CIFS_I(*inode)->uniqueid != fattr->cf_uniqueid)) {
|
||||
CIFS_I(*inode)->time = 0; /* force reval */
|
||||
return -ESTALE;
|
||||
@ -468,7 +472,7 @@ static int cifs_get_unix_fattr(const unsigned char *full_path,
|
||||
cifs_fill_uniqueid(sb, fattr);
|
||||
|
||||
/* check for Minshall+French symlinks */
|
||||
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS) {
|
||||
if (cifs_sb_flags(cifs_sb) & CIFS_MOUNT_MF_SYMLINKS) {
|
||||
tmprc = check_mf_symlink(xid, tcon, cifs_sb, fattr, full_path);
|
||||
cifs_dbg(FYI, "check_mf_symlink: %d\n", tmprc);
|
||||
}
|
||||
@ -1081,7 +1085,7 @@ cifs_backup_query_path_info(int xid,
|
||||
else if ((tcon->ses->capabilities &
|
||||
tcon->ses->server->vals->cap_nt_find) == 0)
|
||||
info.info_level = SMB_FIND_FILE_INFO_STANDARD;
|
||||
else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM)
|
||||
else if (cifs_sb_flags(cifs_sb) & CIFS_MOUNT_SERVER_INUM)
|
||||
info.info_level = SMB_FIND_FILE_ID_FULL_DIR_INFO;
|
||||
else /* no srvino useful for fallback to some netapp */
|
||||
info.info_level = SMB_FIND_FILE_DIRECTORY_INFO;
|
||||
@ -1109,7 +1113,7 @@ static void cifs_set_fattr_ino(int xid, struct cifs_tcon *tcon, struct super_blo
|
||||
struct TCP_Server_Info *server = tcon->ses->server;
|
||||
int rc;
|
||||
|
||||
if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM)) {
|
||||
if (!(cifs_sb_flags(cifs_sb) & CIFS_MOUNT_SERVER_INUM)) {
|
||||
if (*inode)
|
||||
fattr->cf_uniqueid = CIFS_I(*inode)->uniqueid;
|
||||
else
|
||||
@ -1263,14 +1267,15 @@ static int cifs_get_fattr(struct cifs_open_info_data *data,
|
||||
struct inode **inode,
|
||||
const char *full_path)
|
||||
{
|
||||
struct cifs_open_info_data tmp_data = {};
|
||||
struct cifs_tcon *tcon;
|
||||
struct TCP_Server_Info *server;
|
||||
struct tcon_link *tlink;
|
||||
struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
|
||||
struct cifs_open_info_data tmp_data = {};
|
||||
void *smb1_backup_rsp_buf = NULL;
|
||||
int rc = 0;
|
||||
struct TCP_Server_Info *server;
|
||||
struct cifs_tcon *tcon;
|
||||
struct tcon_link *tlink;
|
||||
unsigned int sbflags;
|
||||
int tmprc = 0;
|
||||
int rc = 0;
|
||||
|
||||
tlink = cifs_sb_tlink(cifs_sb);
|
||||
if (IS_ERR(tlink))
|
||||
@ -1370,16 +1375,17 @@ static int cifs_get_fattr(struct cifs_open_info_data *data,
|
||||
#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY
|
||||
handle_mnt_opt:
|
||||
#endif /* CONFIG_CIFS_ALLOW_INSECURE_LEGACY */
|
||||
sbflags = cifs_sb_flags(cifs_sb);
|
||||
/* query for SFU type info if supported and needed */
|
||||
if ((fattr->cf_cifsattrs & ATTR_SYSTEM) &&
|
||||
(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL)) {
|
||||
(sbflags & CIFS_MOUNT_UNX_EMUL)) {
|
||||
tmprc = cifs_sfu_type(fattr, full_path, cifs_sb, xid);
|
||||
if (tmprc)
|
||||
cifs_dbg(FYI, "cifs_sfu_type failed: %d\n", tmprc);
|
||||
}
|
||||
|
||||
/* fill in 0777 bits from ACL */
|
||||
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MODE_FROM_SID) {
|
||||
if (sbflags & CIFS_MOUNT_MODE_FROM_SID) {
|
||||
rc = cifs_acl_to_fattr(cifs_sb, fattr, *inode,
|
||||
true, full_path, fid);
|
||||
if (rc == -EREMOTE)
|
||||
@ -1389,7 +1395,7 @@ handle_mnt_opt:
|
||||
__func__, rc);
|
||||
goto out;
|
||||
}
|
||||
} else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) {
|
||||
} else if (sbflags & CIFS_MOUNT_CIFS_ACL) {
|
||||
rc = cifs_acl_to_fattr(cifs_sb, fattr, *inode,
|
||||
false, full_path, fid);
|
||||
if (rc == -EREMOTE)
|
||||
@ -1399,7 +1405,7 @@ handle_mnt_opt:
|
||||
__func__, rc);
|
||||
goto out;
|
||||
}
|
||||
} else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL)
|
||||
} else if (sbflags & CIFS_MOUNT_UNX_EMUL)
|
||||
/* fill in remaining high mode bits e.g. SUID, VTX */
|
||||
cifs_sfu_mode(fattr, full_path, cifs_sb, xid);
|
||||
else if (!(tcon->posix_extensions))
|
||||
@ -1409,7 +1415,7 @@ handle_mnt_opt:
|
||||
|
||||
|
||||
/* check for Minshall+French symlinks */
|
||||
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS) {
|
||||
if (sbflags & CIFS_MOUNT_MF_SYMLINKS) {
|
||||
tmprc = check_mf_symlink(xid, tcon, cifs_sb, fattr, full_path);
|
||||
cifs_dbg(FYI, "check_mf_symlink: %d\n", tmprc);
|
||||
}
|
||||
@ -1509,7 +1515,7 @@ static int smb311_posix_get_fattr(struct cifs_open_info_data *data,
|
||||
* 3. Tweak fattr based on mount options
|
||||
*/
|
||||
/* check for Minshall+French symlinks */
|
||||
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS) {
|
||||
if (cifs_sb_flags(cifs_sb) & CIFS_MOUNT_MF_SYMLINKS) {
|
||||
tmprc = check_mf_symlink(xid, tcon, cifs_sb, fattr, full_path);
|
||||
cifs_dbg(FYI, "check_mf_symlink: %d\n", tmprc);
|
||||
}
|
||||
@ -1660,7 +1666,7 @@ struct inode *cifs_root_iget(struct super_block *sb)
|
||||
int len;
|
||||
int rc;
|
||||
|
||||
if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_USE_PREFIX_PATH)
|
||||
if ((cifs_sb_flags(cifs_sb) & CIFS_MOUNT_USE_PREFIX_PATH)
|
||||
&& cifs_sb->prepath) {
|
||||
len = strlen(cifs_sb->prepath);
|
||||
path = kzalloc(len + 2 /* leading sep + null */, GFP_KERNEL);
|
||||
@ -2098,8 +2104,9 @@ cifs_mkdir_qinfo(struct inode *parent, struct dentry *dentry, umode_t mode,
|
||||
const char *full_path, struct cifs_sb_info *cifs_sb,
|
||||
struct cifs_tcon *tcon, const unsigned int xid)
|
||||
{
|
||||
int rc = 0;
|
||||
struct inode *inode = NULL;
|
||||
unsigned int sbflags;
|
||||
int rc = 0;
|
||||
|
||||
if (tcon->posix_extensions) {
|
||||
rc = smb311_posix_get_inode_info(&inode, full_path,
|
||||
@ -2139,6 +2146,7 @@ cifs_mkdir_qinfo(struct inode *parent, struct dentry *dentry, umode_t mode,
|
||||
if (parent->i_mode & S_ISGID)
|
||||
mode |= S_ISGID;
|
||||
|
||||
sbflags = cifs_sb_flags(cifs_sb);
|
||||
#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY
|
||||
if (tcon->unix_ext) {
|
||||
struct cifs_unix_set_info_args args = {
|
||||
@ -2148,7 +2156,7 @@ cifs_mkdir_qinfo(struct inode *parent, struct dentry *dentry, umode_t mode,
|
||||
.mtime = NO_CHANGE_64,
|
||||
.device = 0,
|
||||
};
|
||||
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
|
||||
if (sbflags & CIFS_MOUNT_SET_UID) {
|
||||
args.uid = current_fsuid();
|
||||
if (parent->i_mode & S_ISGID)
|
||||
args.gid = parent->i_gid;
|
||||
@ -2166,14 +2174,14 @@ cifs_mkdir_qinfo(struct inode *parent, struct dentry *dentry, umode_t mode,
|
||||
{
|
||||
#endif /* CONFIG_CIFS_ALLOW_INSECURE_LEGACY */
|
||||
struct TCP_Server_Info *server = tcon->ses->server;
|
||||
if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) &&
|
||||
if (!(sbflags & CIFS_MOUNT_CIFS_ACL) &&
|
||||
(mode & S_IWUGO) == 0 && server->ops->mkdir_setinfo)
|
||||
server->ops->mkdir_setinfo(inode, full_path, cifs_sb,
|
||||
tcon, xid);
|
||||
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM)
|
||||
if (sbflags & CIFS_MOUNT_DYNPERM)
|
||||
inode->i_mode = (mode | S_IFDIR);
|
||||
|
||||
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
|
||||
if (sbflags & CIFS_MOUNT_SET_UID) {
|
||||
inode->i_uid = current_fsuid();
|
||||
if (inode->i_mode & S_ISGID)
|
||||
inode->i_gid = parent->i_gid;
|
||||
@ -2687,7 +2695,7 @@ cifs_dentry_needs_reval(struct dentry *dentry)
|
||||
{
|
||||
struct inode *inode = d_inode(dentry);
|
||||
struct cifsInodeInfo *cifs_i = CIFS_I(inode);
|
||||
struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
|
||||
struct cifs_sb_info *cifs_sb = CIFS_SB(inode);
|
||||
struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb);
|
||||
struct cached_fid *cfid = NULL;
|
||||
|
||||
@ -2728,7 +2736,7 @@ cifs_dentry_needs_reval(struct dentry *dentry)
|
||||
}
|
||||
|
||||
/* hardlinked files w/ noserverino get "special" treatment */
|
||||
if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) &&
|
||||
if (!(cifs_sb_flags(cifs_sb) & CIFS_MOUNT_SERVER_INUM) &&
|
||||
S_ISREG(inode->i_mode) && inode->i_nlink != 1)
|
||||
return true;
|
||||
|
||||
@ -2753,10 +2761,10 @@ cifs_wait_bit_killable(struct wait_bit_key *key, int mode)
|
||||
int
|
||||
cifs_revalidate_mapping(struct inode *inode)
|
||||
{
|
||||
int rc;
|
||||
struct cifsInodeInfo *cifs_inode = CIFS_I(inode);
|
||||
struct cifs_sb_info *cifs_sb = CIFS_SB(inode);
|
||||
unsigned long *flags = &cifs_inode->flags;
|
||||
struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
|
||||
int rc;
|
||||
|
||||
/* swapfiles are not supposed to be shared */
|
||||
if (IS_SWAPFILE(inode))
|
||||
@ -2769,7 +2777,7 @@ cifs_revalidate_mapping(struct inode *inode)
|
||||
|
||||
if (test_and_clear_bit(CIFS_INO_INVALID_MAPPING, flags)) {
|
||||
/* for cache=singleclient, do not invalidate */
|
||||
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_RW_CACHE)
|
||||
if (cifs_sb_flags(cifs_sb) & CIFS_MOUNT_RW_CACHE)
|
||||
goto skip_invalidate;
|
||||
|
||||
cifs_inode->netfs.zero_point = cifs_inode->netfs.remote_i_size;
|
||||
@ -2893,10 +2901,11 @@ int cifs_revalidate_dentry(struct dentry *dentry)
|
||||
int cifs_getattr(struct mnt_idmap *idmap, const struct path *path,
|
||||
struct kstat *stat, u32 request_mask, unsigned int flags)
|
||||
{
|
||||
struct dentry *dentry = path->dentry;
|
||||
struct cifs_sb_info *cifs_sb = CIFS_SB(dentry->d_sb);
|
||||
struct cifs_sb_info *cifs_sb = CIFS_SB(path->dentry);
|
||||
struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb);
|
||||
struct dentry *dentry = path->dentry;
|
||||
struct inode *inode = d_inode(dentry);
|
||||
unsigned int sbflags;
|
||||
int rc;
|
||||
|
||||
if (unlikely(cifs_forced_shutdown(CIFS_SB(inode->i_sb))))
|
||||
@ -2953,12 +2962,13 @@ int cifs_getattr(struct mnt_idmap *idmap, const struct path *path,
|
||||
* enabled, and the admin hasn't overridden them, set the ownership
|
||||
* to the fsuid/fsgid of the current process.
|
||||
*/
|
||||
if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MULTIUSER) &&
|
||||
!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) &&
|
||||
sbflags = cifs_sb_flags(cifs_sb);
|
||||
if ((sbflags & CIFS_MOUNT_MULTIUSER) &&
|
||||
!(sbflags & CIFS_MOUNT_CIFS_ACL) &&
|
||||
!tcon->unix_ext) {
|
||||
if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_UID))
|
||||
if (!(sbflags & CIFS_MOUNT_OVERR_UID))
|
||||
stat->uid = current_fsuid();
|
||||
if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_GID))
|
||||
if (!(sbflags & CIFS_MOUNT_OVERR_GID))
|
||||
stat->gid = current_fsgid();
|
||||
}
|
||||
return 0;
|
||||
@ -3103,7 +3113,7 @@ cifs_setattr_unix(struct dentry *direntry, struct iattr *attrs)
|
||||
void *page = alloc_dentry_path();
|
||||
struct inode *inode = d_inode(direntry);
|
||||
struct cifsInodeInfo *cifsInode = CIFS_I(inode);
|
||||
struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
|
||||
struct cifs_sb_info *cifs_sb = CIFS_SB(inode);
|
||||
struct tcon_link *tlink;
|
||||
struct cifs_tcon *pTcon;
|
||||
struct cifs_unix_set_info_args *args = NULL;
|
||||
@ -3114,7 +3124,7 @@ cifs_setattr_unix(struct dentry *direntry, struct iattr *attrs)
|
||||
|
||||
xid = get_xid();
|
||||
|
||||
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_PERM)
|
||||
if (cifs_sb_flags(cifs_sb) & CIFS_MOUNT_NO_PERM)
|
||||
attrs->ia_valid |= ATTR_FORCE;
|
||||
|
||||
rc = setattr_prepare(&nop_mnt_idmap, direntry, attrs);
|
||||
@ -3151,6 +3161,17 @@ cifs_setattr_unix(struct dentry *direntry, struct iattr *attrs)
|
||||
rc = 0;
|
||||
|
||||
if (attrs->ia_valid & ATTR_SIZE) {
|
||||
if (attrs->ia_size != i_size_read(inode)) {
|
||||
/* Stamp before RPC. On failure the stamp remains: restoring a
|
||||
* stale snapshot could silently erase a concurrent
|
||||
* _cifsFileInfo_put() close stamp. readdir is suppressed
|
||||
* until the stamp expires; stat() bypasses this via the
|
||||
* from_readdir=false path in is_size_safe_to_change() and
|
||||
* always returns an authoritative QUERY_INFO result.
|
||||
* Pairs with smp_load_acquire() in is_size_safe_to_change().
|
||||
*/
|
||||
smp_store_release(&cifsInode->time_last_write, jiffies);
|
||||
}
|
||||
rc = cifs_file_set_size(xid, direntry, full_path,
|
||||
open_file, attrs->ia_size);
|
||||
if (rc != 0)
|
||||
@ -3267,26 +3288,26 @@ out:
|
||||
static int
|
||||
cifs_setattr_nounix(struct dentry *direntry, struct iattr *attrs)
|
||||
{
|
||||
unsigned int xid;
|
||||
struct inode *inode = d_inode(direntry);
|
||||
struct cifsInodeInfo *cifsInode = CIFS_I(inode);
|
||||
struct cifs_sb_info *cifs_sb = CIFS_SB(inode);
|
||||
unsigned int sbflags = cifs_sb_flags(cifs_sb);
|
||||
struct cifsFileInfo *cfile = NULL;
|
||||
void *page = alloc_dentry_path();
|
||||
__u64 mode = NO_CHANGE_64;
|
||||
kuid_t uid = INVALID_UID;
|
||||
kgid_t gid = INVALID_GID;
|
||||
struct inode *inode = d_inode(direntry);
|
||||
struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
|
||||
struct cifsInodeInfo *cifsInode = CIFS_I(inode);
|
||||
struct cifsFileInfo *cfile = NULL;
|
||||
const char *full_path;
|
||||
void *page = alloc_dentry_path();
|
||||
int rc = -EACCES;
|
||||
__u32 dosattr = 0;
|
||||
__u64 mode = NO_CHANGE_64;
|
||||
bool posix = cifs_sb_master_tcon(cifs_sb)->posix_extensions;
|
||||
int rc = -EACCES;
|
||||
unsigned int xid;
|
||||
|
||||
xid = get_xid();
|
||||
|
||||
cifs_dbg(FYI, "setattr on file %pd attrs->ia_valid 0x%x\n",
|
||||
direntry, attrs->ia_valid);
|
||||
|
||||
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_PERM)
|
||||
if (sbflags & CIFS_MOUNT_NO_PERM)
|
||||
attrs->ia_valid |= ATTR_FORCE;
|
||||
|
||||
rc = setattr_prepare(&nop_mnt_idmap, direntry, attrs);
|
||||
@ -3329,6 +3350,17 @@ cifs_setattr_nounix(struct dentry *direntry, struct iattr *attrs)
|
||||
}
|
||||
|
||||
if (attrs->ia_valid & ATTR_SIZE) {
|
||||
if (attrs->ia_size != i_size_read(inode)) {
|
||||
/* Stamp before RPC. On failure the stamp remains: restoring a
|
||||
* stale snapshot could silently erase a concurrent
|
||||
* _cifsFileInfo_put() close stamp. readdir is suppressed
|
||||
* until the stamp expires; stat() bypasses this via the
|
||||
* from_readdir=false path in is_size_safe_to_change() and
|
||||
* always returns an authoritative QUERY_INFO result.
|
||||
* Pairs with smp_load_acquire() in is_size_safe_to_change().
|
||||
*/
|
||||
smp_store_release(&cifsInode->time_last_write, jiffies);
|
||||
}
|
||||
rc = cifs_file_set_size(xid, direntry, full_path,
|
||||
cfile, attrs->ia_size);
|
||||
if (rc != 0)
|
||||
@ -3347,8 +3379,7 @@ cifs_setattr_nounix(struct dentry *direntry, struct iattr *attrs)
|
||||
if (attrs->ia_valid & ATTR_GID)
|
||||
gid = attrs->ia_gid;
|
||||
|
||||
if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) ||
|
||||
(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MODE_FROM_SID)) {
|
||||
if (sbflags & (CIFS_MOUNT_CIFS_ACL | CIFS_MOUNT_MODE_FROM_SID)) {
|
||||
if (uid_valid(uid) || gid_valid(gid)) {
|
||||
mode = NO_CHANGE_64;
|
||||
rc = id_mode_to_cifs_acl(inode, full_path, &mode,
|
||||
@ -3359,9 +3390,9 @@ cifs_setattr_nounix(struct dentry *direntry, struct iattr *attrs)
|
||||
goto cifs_setattr_exit;
|
||||
}
|
||||
}
|
||||
} else
|
||||
if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID))
|
||||
} else if (!(sbflags & CIFS_MOUNT_SET_UID)) {
|
||||
attrs->ia_valid &= ~(ATTR_UID | ATTR_GID);
|
||||
}
|
||||
|
||||
/* skip mode change if it's just for clearing setuid/setgid */
|
||||
if (attrs->ia_valid & (ATTR_KILL_SUID|ATTR_KILL_SGID))
|
||||
@ -3370,9 +3401,8 @@ cifs_setattr_nounix(struct dentry *direntry, struct iattr *attrs)
|
||||
if (attrs->ia_valid & ATTR_MODE) {
|
||||
mode = attrs->ia_mode;
|
||||
rc = 0;
|
||||
if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) ||
|
||||
(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MODE_FROM_SID) ||
|
||||
posix) {
|
||||
if ((sbflags & (CIFS_MOUNT_CIFS_ACL | CIFS_MOUNT_MODE_FROM_SID)) ||
|
||||
cifs_sb_master_tcon(cifs_sb)->posix_extensions) {
|
||||
rc = id_mode_to_cifs_acl(inode, full_path, &mode,
|
||||
INVALID_UID, INVALID_GID);
|
||||
if (rc) {
|
||||
@ -3394,7 +3424,7 @@ cifs_setattr_nounix(struct dentry *direntry, struct iattr *attrs)
|
||||
dosattr = cifsInode->cifsAttrs | ATTR_READONLY;
|
||||
|
||||
/* fix up mode if we're not using dynperm */
|
||||
if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM) == 0)
|
||||
if ((sbflags & CIFS_MOUNT_DYNPERM) == 0)
|
||||
attrs->ia_mode = inode->i_mode & ~S_IWUGO;
|
||||
} else if ((mode & S_IWUGO) &&
|
||||
(cifsInode->cifsAttrs & ATTR_READONLY)) {
|
||||
@ -3405,7 +3435,7 @@ cifs_setattr_nounix(struct dentry *direntry, struct iattr *attrs)
|
||||
dosattr |= ATTR_NORMAL;
|
||||
|
||||
/* reset local inode permissions to normal */
|
||||
if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM)) {
|
||||
if (!(sbflags & CIFS_MOUNT_DYNPERM)) {
|
||||
attrs->ia_mode &= ~(S_IALLUGO);
|
||||
if (S_ISDIR(inode->i_mode))
|
||||
attrs->ia_mode |=
|
||||
@ -3414,7 +3444,7 @@ cifs_setattr_nounix(struct dentry *direntry, struct iattr *attrs)
|
||||
attrs->ia_mode |=
|
||||
cifs_sb->ctx->file_mode;
|
||||
}
|
||||
} else if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM)) {
|
||||
} else if (!(sbflags & CIFS_MOUNT_DYNPERM)) {
|
||||
/* ignore mode change - ATTR_READONLY hasn't changed */
|
||||
attrs->ia_valid &= ~ATTR_MODE;
|
||||
}
|
||||
|
||||
@ -217,7 +217,7 @@ 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;
|
||||
atomic_or(CIFS_MOUNT_SHUTDOWN, &sbi->mnt_cifs_flags);
|
||||
goto shutdown_good;
|
||||
default:
|
||||
rc = -EINVAL;
|
||||
|
||||
@ -570,14 +570,15 @@ int
|
||||
cifs_symlink(struct mnt_idmap *idmap, struct inode *inode,
|
||||
struct dentry *direntry, const char *symname)
|
||||
{
|
||||
int rc = -EOPNOTSUPP;
|
||||
unsigned int xid;
|
||||
struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
|
||||
struct cifs_sb_info *cifs_sb = CIFS_SB(inode);
|
||||
struct inode *newinode = NULL;
|
||||
struct tcon_link *tlink;
|
||||
struct cifs_tcon *pTcon;
|
||||
const char *full_path;
|
||||
int rc = -EOPNOTSUPP;
|
||||
unsigned int sbflags;
|
||||
unsigned int xid;
|
||||
void *page;
|
||||
struct inode *newinode = NULL;
|
||||
|
||||
if (unlikely(cifs_forced_shutdown(cifs_sb)))
|
||||
return smb_EIO(smb_eio_trace_forced_shutdown);
|
||||
@ -606,6 +607,7 @@ cifs_symlink(struct mnt_idmap *idmap, struct inode *inode,
|
||||
cifs_dbg(FYI, "symname is %s\n", symname);
|
||||
|
||||
/* BB what if DFS and this volume is on different share? BB */
|
||||
sbflags = cifs_sb_flags(cifs_sb);
|
||||
rc = -EOPNOTSUPP;
|
||||
switch (cifs_symlink_type(cifs_sb)) {
|
||||
case CIFS_SYMLINK_TYPE_UNIX:
|
||||
@ -620,14 +622,14 @@ cifs_symlink(struct mnt_idmap *idmap, struct inode *inode,
|
||||
break;
|
||||
|
||||
case CIFS_SYMLINK_TYPE_MFSYMLINKS:
|
||||
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS) {
|
||||
if (sbflags & CIFS_MOUNT_MF_SYMLINKS) {
|
||||
rc = create_mf_symlink(xid, pTcon, cifs_sb,
|
||||
full_path, symname);
|
||||
}
|
||||
break;
|
||||
|
||||
case CIFS_SYMLINK_TYPE_SFU:
|
||||
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) {
|
||||
if (sbflags & CIFS_MOUNT_UNX_EMUL) {
|
||||
rc = __cifs_sfu_make_node(xid, inode, direntry, pTcon,
|
||||
full_path, S_IFLNK,
|
||||
0, symname);
|
||||
|
||||
@ -567,13 +567,15 @@ dump_smb(void *buf, int smb_buf_length)
|
||||
void
|
||||
cifs_autodisable_serverino(struct cifs_sb_info *cifs_sb)
|
||||
{
|
||||
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) {
|
||||
unsigned int sbflags = cifs_sb_flags(cifs_sb);
|
||||
|
||||
if (sbflags & CIFS_MOUNT_SERVER_INUM) {
|
||||
struct cifs_tcon *tcon = NULL;
|
||||
|
||||
if (cifs_sb->master_tlink)
|
||||
tcon = cifs_sb_master_tcon(cifs_sb);
|
||||
|
||||
cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_SERVER_INUM;
|
||||
atomic_andnot(CIFS_MOUNT_SERVER_INUM, &cifs_sb->mnt_cifs_flags);
|
||||
cifs_sb->mnt_cifs_serverino_autodisabled = true;
|
||||
cifs_dbg(VFS, "Autodisabling the use of server inode numbers on %s\n",
|
||||
tcon ? tcon->tree_name : "new server");
|
||||
@ -674,11 +676,13 @@ void cifs_done_oplock_break(struct cifsInodeInfo *cinode)
|
||||
bool
|
||||
backup_cred(struct cifs_sb_info *cifs_sb)
|
||||
{
|
||||
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_BACKUPUID) {
|
||||
unsigned int sbflags = cifs_sb_flags(cifs_sb);
|
||||
|
||||
if (sbflags & CIFS_MOUNT_CIFS_BACKUPUID) {
|
||||
if (uid_eq(cifs_sb->ctx->backupuid, current_fsuid()))
|
||||
return true;
|
||||
}
|
||||
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_BACKUPGID) {
|
||||
if (sbflags & CIFS_MOUNT_CIFS_BACKUPGID) {
|
||||
if (in_group_p(cifs_sb->ctx->backupgid))
|
||||
return true;
|
||||
}
|
||||
@ -776,7 +780,7 @@ cifs_del_deferred_close(struct cifsFileInfo *cfile)
|
||||
void
|
||||
cifs_close_deferred_file(struct cifsInodeInfo *cifs_inode)
|
||||
{
|
||||
struct cifsFileInfo *cfile = NULL;
|
||||
struct cifsFileInfo *cfile = NULL, *failed_cfile = NULL;
|
||||
struct file_list *tmp_list, *tmp_next_list;
|
||||
LIST_HEAD(file_head);
|
||||
|
||||
@ -792,8 +796,10 @@ cifs_close_deferred_file(struct cifsInodeInfo *cifs_inode)
|
||||
spin_unlock(&cifs_inode->deferred_lock);
|
||||
|
||||
tmp_list = kmalloc(sizeof(struct file_list), GFP_ATOMIC);
|
||||
if (tmp_list == NULL)
|
||||
if (tmp_list == NULL) {
|
||||
failed_cfile = cfile;
|
||||
break;
|
||||
}
|
||||
tmp_list->cfile = cfile;
|
||||
list_add_tail(&tmp_list->list, &file_head);
|
||||
}
|
||||
@ -801,6 +807,9 @@ cifs_close_deferred_file(struct cifsInodeInfo *cifs_inode)
|
||||
}
|
||||
spin_unlock(&cifs_inode->open_file_lock);
|
||||
|
||||
if (failed_cfile)
|
||||
_cifsFileInfo_put(failed_cfile, false, false);
|
||||
|
||||
list_for_each_entry_safe(tmp_list, tmp_next_list, &file_head, list) {
|
||||
_cifsFileInfo_put(tmp_list->cfile, false, false);
|
||||
list_del(&tmp_list->list);
|
||||
@ -811,7 +820,7 @@ cifs_close_deferred_file(struct cifsInodeInfo *cifs_inode)
|
||||
void
|
||||
cifs_close_all_deferred_files(struct cifs_tcon *tcon)
|
||||
{
|
||||
struct cifsFileInfo *cfile;
|
||||
struct cifsFileInfo *cfile, *failed_cfile = NULL;
|
||||
struct file_list *tmp_list, *tmp_next_list;
|
||||
LIST_HEAD(file_head);
|
||||
|
||||
@ -824,8 +833,10 @@ cifs_close_all_deferred_files(struct cifs_tcon *tcon)
|
||||
spin_unlock(&CIFS_I(d_inode(cfile->dentry))->deferred_lock);
|
||||
|
||||
tmp_list = kmalloc(sizeof(struct file_list), GFP_ATOMIC);
|
||||
if (tmp_list == NULL)
|
||||
if (tmp_list == NULL) {
|
||||
failed_cfile = cfile;
|
||||
break;
|
||||
}
|
||||
tmp_list->cfile = cfile;
|
||||
list_add_tail(&tmp_list->list, &file_head);
|
||||
}
|
||||
@ -833,6 +844,9 @@ cifs_close_all_deferred_files(struct cifs_tcon *tcon)
|
||||
}
|
||||
spin_unlock(&tcon->open_file_lock);
|
||||
|
||||
if (failed_cfile)
|
||||
_cifsFileInfo_put(failed_cfile, true, false);
|
||||
|
||||
list_for_each_entry_safe(tmp_list, tmp_next_list, &file_head, list) {
|
||||
_cifsFileInfo_put(tmp_list->cfile, true, false);
|
||||
list_del(&tmp_list->list);
|
||||
@ -844,7 +858,7 @@ void cifs_close_deferred_file_under_dentry(struct cifs_tcon *tcon,
|
||||
struct dentry *dentry)
|
||||
{
|
||||
struct file_list *tmp_list, *tmp_next_list;
|
||||
struct cifsFileInfo *cfile;
|
||||
struct cifsFileInfo *cfile, *failed_cfile = NULL;
|
||||
LIST_HEAD(file_head);
|
||||
|
||||
spin_lock(&tcon->open_file_lock);
|
||||
@ -857,14 +871,19 @@ void cifs_close_deferred_file_under_dentry(struct cifs_tcon *tcon,
|
||||
spin_unlock(&CIFS_I(d_inode(cfile->dentry))->deferred_lock);
|
||||
|
||||
tmp_list = kmalloc(sizeof(struct file_list), GFP_ATOMIC);
|
||||
if (tmp_list == NULL)
|
||||
if (tmp_list == NULL) {
|
||||
failed_cfile = cfile;
|
||||
break;
|
||||
}
|
||||
tmp_list->cfile = cfile;
|
||||
list_add_tail(&tmp_list->list, &file_head);
|
||||
}
|
||||
}
|
||||
spin_unlock(&tcon->open_file_lock);
|
||||
|
||||
if (failed_cfile)
|
||||
_cifsFileInfo_put(failed_cfile, true, false);
|
||||
|
||||
list_for_each_entry_safe(tmp_list, tmp_next_list, &file_head, list) {
|
||||
_cifsFileInfo_put(tmp_list->cfile, true, false);
|
||||
list_del(&tmp_list->list);
|
||||
@ -1246,7 +1265,7 @@ int cifs_update_super_prepath(struct cifs_sb_info *cifs_sb, char *prefix)
|
||||
convert_delimiter(cifs_sb->prepath, CIFS_DIR_SEP(cifs_sb));
|
||||
}
|
||||
|
||||
cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_USE_PREFIX_PATH;
|
||||
atomic_or(CIFS_MOUNT_USE_PREFIX_PATH, &cifs_sb->mnt_cifs_flags);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1275,7 +1294,7 @@ int cifs_inval_name_dfs_link_error(const unsigned int xid,
|
||||
* look up or tcon is not DFS.
|
||||
*/
|
||||
if (strlen(full_path) < 2 || !cifs_sb ||
|
||||
(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_DFS) ||
|
||||
(cifs_sb_flags(cifs_sb) & CIFS_MOUNT_NO_DFS) ||
|
||||
!is_tcon_dfs(tcon))
|
||||
return 0;
|
||||
|
||||
|
||||
@ -121,7 +121,7 @@ retry:
|
||||
* want to clobber the existing one with the one that
|
||||
* the readdir code created.
|
||||
*/
|
||||
if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM))
|
||||
if (!(cifs_sb_flags(cifs_sb) & CIFS_MOUNT_SERVER_INUM))
|
||||
fattr->cf_uniqueid = CIFS_I(inode)->uniqueid;
|
||||
|
||||
/*
|
||||
@ -177,6 +177,7 @@ cifs_fill_common_info(struct cifs_fattr *fattr, struct cifs_sb_info *cifs_sb)
|
||||
struct cifs_open_info_data data = {
|
||||
.reparse = { .tag = fattr->cf_cifstag, },
|
||||
};
|
||||
unsigned int sbflags;
|
||||
|
||||
fattr->cf_uid = cifs_sb->ctx->linux_uid;
|
||||
fattr->cf_gid = cifs_sb->ctx->linux_gid;
|
||||
@ -215,12 +216,12 @@ out_reparse:
|
||||
* may look wrong since the inodes may not have timed out by the time
|
||||
* "ls" does a stat() call on them.
|
||||
*/
|
||||
if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) ||
|
||||
(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MODE_FROM_SID))
|
||||
sbflags = cifs_sb_flags(cifs_sb);
|
||||
if (sbflags & (CIFS_MOUNT_CIFS_ACL | CIFS_MOUNT_MODE_FROM_SID))
|
||||
fattr->cf_flags |= CIFS_FATTR_NEED_REVAL;
|
||||
|
||||
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL &&
|
||||
fattr->cf_cifsattrs & ATTR_SYSTEM) {
|
||||
if ((sbflags & CIFS_MOUNT_UNX_EMUL) &&
|
||||
(fattr->cf_cifsattrs & ATTR_SYSTEM)) {
|
||||
if (fattr->cf_eof == 0) {
|
||||
fattr->cf_mode &= ~S_IFMT;
|
||||
fattr->cf_mode |= S_IFIFO;
|
||||
@ -345,13 +346,14 @@ static int
|
||||
_initiate_cifs_search(const unsigned int xid, struct file *file,
|
||||
const char *full_path)
|
||||
{
|
||||
struct cifs_sb_info *cifs_sb = CIFS_SB(file);
|
||||
struct tcon_link *tlink = NULL;
|
||||
struct TCP_Server_Info *server;
|
||||
struct cifsFileInfo *cifsFile;
|
||||
struct cifs_tcon *tcon;
|
||||
unsigned int sbflags;
|
||||
__u16 search_flags;
|
||||
int rc = 0;
|
||||
struct cifsFileInfo *cifsFile;
|
||||
struct cifs_sb_info *cifs_sb = CIFS_FILE_SB(file);
|
||||
struct tcon_link *tlink = NULL;
|
||||
struct cifs_tcon *tcon;
|
||||
struct TCP_Server_Info *server;
|
||||
|
||||
if (file->private_data == NULL) {
|
||||
tlink = cifs_sb_tlink(cifs_sb);
|
||||
@ -385,6 +387,7 @@ _initiate_cifs_search(const unsigned int xid, struct file *file,
|
||||
cifs_dbg(FYI, "Full path: %s start at: %lld\n", full_path, file->f_pos);
|
||||
|
||||
ffirst_retry:
|
||||
sbflags = cifs_sb_flags(cifs_sb);
|
||||
/* test for Unix extensions */
|
||||
/* but now check for them on the share/mount not on the SMB session */
|
||||
/* if (cap_unix(tcon->ses) { */
|
||||
@ -395,7 +398,7 @@ ffirst_retry:
|
||||
else if ((tcon->ses->capabilities &
|
||||
tcon->ses->server->vals->cap_nt_find) == 0) {
|
||||
cifsFile->srch_inf.info_level = SMB_FIND_FILE_INFO_STANDARD;
|
||||
} else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) {
|
||||
} else if (sbflags & CIFS_MOUNT_SERVER_INUM) {
|
||||
cifsFile->srch_inf.info_level = SMB_FIND_FILE_ID_FULL_DIR_INFO;
|
||||
} else /* not srvinos - BB fixme add check for backlevel? */ {
|
||||
cifsFile->srch_inf.info_level = SMB_FIND_FILE_FULL_DIRECTORY_INFO;
|
||||
@ -411,8 +414,7 @@ ffirst_retry:
|
||||
|
||||
if (rc == 0) {
|
||||
cifsFile->invalidHandle = false;
|
||||
} else if ((rc == -EOPNOTSUPP) &&
|
||||
(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM)) {
|
||||
} else if (rc == -EOPNOTSUPP && (sbflags & CIFS_MOUNT_SERVER_INUM)) {
|
||||
cifs_autodisable_serverino(cifs_sb);
|
||||
goto ffirst_retry;
|
||||
}
|
||||
@ -690,7 +692,7 @@ find_cifs_entry(const unsigned int xid, struct cifs_tcon *tcon, loff_t pos,
|
||||
loff_t first_entry_in_buffer;
|
||||
loff_t index_to_find = pos;
|
||||
struct cifsFileInfo *cfile = file->private_data;
|
||||
struct cifs_sb_info *cifs_sb = CIFS_FILE_SB(file);
|
||||
struct cifs_sb_info *cifs_sb = CIFS_SB(file);
|
||||
struct TCP_Server_Info *server = tcon->ses->server;
|
||||
/* check if index in the buffer */
|
||||
|
||||
@ -955,6 +957,7 @@ static int cifs_filldir(char *find_entry, struct file *file,
|
||||
struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
|
||||
struct cifs_dirent de = { NULL, };
|
||||
struct cifs_fattr fattr;
|
||||
unsigned int sbflags;
|
||||
struct qstr name;
|
||||
int rc = 0;
|
||||
|
||||
@ -1019,15 +1022,15 @@ static int cifs_filldir(char *find_entry, struct file *file,
|
||||
break;
|
||||
}
|
||||
|
||||
if (de.ino && (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM)) {
|
||||
sbflags = cifs_sb_flags(cifs_sb);
|
||||
if (de.ino && (sbflags & CIFS_MOUNT_SERVER_INUM)) {
|
||||
fattr.cf_uniqueid = de.ino;
|
||||
} else {
|
||||
fattr.cf_uniqueid = iunique(sb, ROOT_I);
|
||||
cifs_autodisable_serverino(cifs_sb);
|
||||
}
|
||||
|
||||
if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS) &&
|
||||
couldbe_mf_symlink(&fattr))
|
||||
if ((sbflags & CIFS_MOUNT_MF_SYMLINKS) && couldbe_mf_symlink(&fattr))
|
||||
/*
|
||||
* trying to get the type and mode can be slow,
|
||||
* so just call those regular files for now, and mark
|
||||
@ -1058,7 +1061,7 @@ int cifs_readdir(struct file *file, struct dir_context *ctx)
|
||||
const char *full_path;
|
||||
void *page = alloc_dentry_path();
|
||||
struct cached_fid *cfid = NULL;
|
||||
struct cifs_sb_info *cifs_sb = CIFS_FILE_SB(file);
|
||||
struct cifs_sb_info *cifs_sb = CIFS_SB(file);
|
||||
|
||||
xid = get_xid();
|
||||
|
||||
|
||||
@ -55,17 +55,18 @@ static int create_native_symlink(const unsigned int xid, struct inode *inode,
|
||||
const char *full_path, const char *symname)
|
||||
{
|
||||
struct reparse_symlink_data_buffer *buf = NULL;
|
||||
struct cifs_open_info_data data = {};
|
||||
struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
|
||||
struct cifs_sb_info *cifs_sb = CIFS_SB(inode);
|
||||
const char *symroot = cifs_sb->ctx->symlinkroot;
|
||||
struct inode *new;
|
||||
struct kvec iov;
|
||||
__le16 *path = NULL;
|
||||
bool directory;
|
||||
char *symlink_target = NULL;
|
||||
char *sym = NULL;
|
||||
struct cifs_open_info_data data = {};
|
||||
char sep = CIFS_DIR_SEP(cifs_sb);
|
||||
char *symlink_target = NULL;
|
||||
u16 len, plen, poff, slen;
|
||||
unsigned int sbflags;
|
||||
__le16 *path = NULL;
|
||||
struct inode *new;
|
||||
char *sym = NULL;
|
||||
struct kvec iov;
|
||||
bool directory;
|
||||
int rc = 0;
|
||||
|
||||
if (strlen(symname) > REPARSE_SYM_PATH_MAX)
|
||||
@ -83,8 +84,8 @@ static int create_native_symlink(const unsigned int xid, struct inode *inode,
|
||||
.symlink_target = symlink_target,
|
||||
};
|
||||
|
||||
if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS) &&
|
||||
symroot && symname[0] == '/') {
|
||||
sbflags = cifs_sb_flags(cifs_sb);
|
||||
if (!(sbflags & CIFS_MOUNT_POSIX_PATHS) && symroot && symname[0] == '/') {
|
||||
/*
|
||||
* This is a request to create an absolute symlink on the server
|
||||
* which does not support POSIX paths, and expects symlink in
|
||||
@ -164,7 +165,7 @@ static int create_native_symlink(const unsigned int xid, struct inode *inode,
|
||||
* mask these characters in NT object prefix by '_' and then change
|
||||
* them back.
|
||||
*/
|
||||
if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS) && symname[0] == '/')
|
||||
if (!(sbflags & CIFS_MOUNT_POSIX_PATHS) && symname[0] == '/')
|
||||
sym[0] = sym[1] = sym[2] = sym[5] = '_';
|
||||
|
||||
path = cifs_convert_path_to_utf16(sym, cifs_sb);
|
||||
@ -173,7 +174,7 @@ static int create_native_symlink(const unsigned int xid, struct inode *inode,
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS) && symname[0] == '/') {
|
||||
if (!(sbflags & CIFS_MOUNT_POSIX_PATHS) && symname[0] == '/') {
|
||||
sym[0] = '\\';
|
||||
sym[1] = sym[2] = '?';
|
||||
sym[5] = ':';
|
||||
@ -197,7 +198,7 @@ static int create_native_symlink(const unsigned int xid, struct inode *inode,
|
||||
slen = 2 * UniStrnlen((wchar_t *)path, REPARSE_SYM_PATH_MAX);
|
||||
poff = 0;
|
||||
plen = slen;
|
||||
if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS) && symname[0] == '/') {
|
||||
if (!(sbflags & CIFS_MOUNT_POSIX_PATHS) && symname[0] == '/') {
|
||||
/*
|
||||
* For absolute NT symlinks skip leading "\\??\\" in PrintName as
|
||||
* PrintName is user visible location in DOS/Win32 format (not in NT format).
|
||||
@ -824,7 +825,7 @@ int smb2_parse_native_symlink(char **target, const char *buf, unsigned int len,
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS) &&
|
||||
if (!(cifs_sb_flags(cifs_sb) & CIFS_MOUNT_POSIX_PATHS) &&
|
||||
symroot && !relative) {
|
||||
/*
|
||||
* This is an absolute symlink from the server which does not
|
||||
|
||||
@ -32,7 +32,7 @@ static inline kuid_t wsl_make_kuid(struct cifs_sb_info *cifs_sb,
|
||||
{
|
||||
u32 uid = le32_to_cpu(*(__le32 *)ptr);
|
||||
|
||||
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_UID)
|
||||
if (cifs_sb_flags(cifs_sb) & CIFS_MOUNT_OVERR_UID)
|
||||
return cifs_sb->ctx->linux_uid;
|
||||
return make_kuid(current_user_ns(), uid);
|
||||
}
|
||||
@ -42,7 +42,7 @@ static inline kgid_t wsl_make_kgid(struct cifs_sb_info *cifs_sb,
|
||||
{
|
||||
u32 gid = le32_to_cpu(*(__le32 *)ptr);
|
||||
|
||||
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_GID)
|
||||
if (cifs_sb_flags(cifs_sb) & CIFS_MOUNT_OVERR_GID)
|
||||
return cifs_sb->ctx->linux_gid;
|
||||
return make_kgid(current_user_ns(), gid);
|
||||
}
|
||||
|
||||
@ -399,11 +399,13 @@ coalesce_t2(char *second_buf, struct smb_hdr *target_hdr, unsigned int *pdu_len)
|
||||
}
|
||||
put_bcc(byte_count, target_hdr);
|
||||
|
||||
byte_count = *pdu_len;
|
||||
byte_count += total_in_src;
|
||||
/* use smbCalcSize() rather than *pdu_len: the demux loop resets
|
||||
* *pdu_len to each secondary's pdu_length, making it unreliable.
|
||||
*/
|
||||
byte_count = smbCalcSize(target_hdr);
|
||||
/* don't allow buffer to overflow */
|
||||
if (byte_count > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE) {
|
||||
cifs_dbg(FYI, "coalesced BCC exceeds buffer size (%u)\n",
|
||||
cifs_dbg(FYI, "coalesced size exceeds buffer size (%u)\n",
|
||||
byte_count);
|
||||
return -ENOBUFS;
|
||||
}
|
||||
@ -428,6 +430,7 @@ cifs_downgrade_oplock(struct TCP_Server_Info *server,
|
||||
struct cifsInodeInfo *cinode, __u32 oplock,
|
||||
__u16 epoch, bool *purge_cache)
|
||||
{
|
||||
lockdep_assert_held(&cinode->open_file_lock);
|
||||
cifs_set_oplock_level(cinode, oplock);
|
||||
}
|
||||
|
||||
@ -958,6 +961,9 @@ static void
|
||||
cifs_set_fid(struct cifsFileInfo *cfile, struct cifs_fid *fid, __u32 oplock)
|
||||
{
|
||||
struct cifsInodeInfo *cinode = CIFS_I(d_inode(cfile->dentry));
|
||||
|
||||
lockdep_assert_held(&cinode->open_file_lock);
|
||||
|
||||
cfile->fid.netfid = fid->netfid;
|
||||
cifs_set_oplock_level(cinode, oplock);
|
||||
cinode->can_cache_brlcks = CIFS_CACHE_WRITE(cinode);
|
||||
@ -1203,12 +1209,16 @@ cifs_close_dir(const unsigned int xid, struct cifs_tcon *tcon,
|
||||
return CIFSFindClose(xid, tcon, fid->netfid);
|
||||
}
|
||||
|
||||
static int
|
||||
cifs_oplock_response(struct cifs_tcon *tcon, __u64 persistent_fid,
|
||||
__u64 volatile_fid, __u16 net_fid, struct cifsInodeInfo *cinode)
|
||||
static int cifs_oplock_response(struct cifs_tcon *tcon, __u64 persistent_fid,
|
||||
__u64 volatile_fid, __u16 net_fid,
|
||||
struct cifsInodeInfo *cinode, unsigned int oplock)
|
||||
{
|
||||
unsigned int sbflags = cifs_sb_flags(CIFS_SB(cinode));
|
||||
__u8 op;
|
||||
|
||||
op = !!((oplock & CIFS_CACHE_READ_FLG) || (sbflags & CIFS_MOUNT_RO_CACHE));
|
||||
return CIFSSMBLock(0, tcon, net_fid, current->tgid, 0, 0, 0, 0,
|
||||
LOCKING_ANDX_OPLOCK_RELEASE, false, CIFS_CACHE_READ(cinode) ? 1 : 0);
|
||||
LOCKING_ANDX_OPLOCK_RELEASE, false, op);
|
||||
}
|
||||
|
||||
static int
|
||||
@ -1338,7 +1348,8 @@ cifs_make_node(unsigned int xid, struct inode *inode,
|
||||
struct dentry *dentry, struct cifs_tcon *tcon,
|
||||
const char *full_path, umode_t mode, dev_t dev)
|
||||
{
|
||||
struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
|
||||
struct cifs_sb_info *cifs_sb = CIFS_SB(inode);
|
||||
unsigned int sbflags = cifs_sb_flags(cifs_sb);
|
||||
struct inode *newinode = NULL;
|
||||
int rc;
|
||||
|
||||
@ -1354,7 +1365,7 @@ cifs_make_node(unsigned int xid, struct inode *inode,
|
||||
.mtime = NO_CHANGE_64,
|
||||
.device = dev,
|
||||
};
|
||||
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
|
||||
if (sbflags & CIFS_MOUNT_SET_UID) {
|
||||
args.uid = current_fsuid();
|
||||
args.gid = current_fsgid();
|
||||
} else {
|
||||
@ -1373,7 +1384,7 @@ cifs_make_node(unsigned int xid, struct inode *inode,
|
||||
if (rc == 0)
|
||||
d_instantiate(dentry, newinode);
|
||||
return rc;
|
||||
} else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) {
|
||||
} else if (sbflags & CIFS_MOUNT_UNX_EMUL) {
|
||||
/*
|
||||
* Check if mounted with mount parm 'sfu' mount parm.
|
||||
* SFU emulation should work with all servers
|
||||
|
||||
@ -74,7 +74,7 @@ int smb2_fix_symlink_target_type(char **target, bool directory, struct cifs_sb_i
|
||||
* POSIX server does not distinguish between symlinks to file and
|
||||
* symlink directory. So nothing is needed to fix on the client side.
|
||||
*/
|
||||
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS)
|
||||
if (cifs_sb_flags(cifs_sb) & CIFS_MOUNT_POSIX_PATHS)
|
||||
return 0;
|
||||
|
||||
if (!*target)
|
||||
|
||||
@ -240,7 +240,8 @@ smb2_check_message(char *buf, unsigned int pdu_len, unsigned int len,
|
||||
if (len != calc_len) {
|
||||
/* create failed on symlink */
|
||||
if (command == SMB2_CREATE_HE &&
|
||||
shdr->Status == STATUS_STOPPED_ON_SYMLINK)
|
||||
shdr->Status == STATUS_STOPPED_ON_SYMLINK &&
|
||||
len > calc_len)
|
||||
return 0;
|
||||
/* Windows 7 server returns 24 bytes more */
|
||||
if (calc_len + 24 == len && command == SMB2_OPLOCK_BREAK_HE)
|
||||
@ -454,17 +455,8 @@ calc_size_exit:
|
||||
__le16 *
|
||||
cifs_convert_path_to_utf16(const char *from, struct cifs_sb_info *cifs_sb)
|
||||
{
|
||||
int len;
|
||||
const char *start_of_path;
|
||||
__le16 *to;
|
||||
int map_type;
|
||||
|
||||
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SFM_CHR)
|
||||
map_type = SFM_MAP_UNI_RSVD;
|
||||
else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR)
|
||||
map_type = SFU_MAP_UNI_RSVD;
|
||||
else
|
||||
map_type = NO_MAP_UNI_RSVD;
|
||||
int len;
|
||||
|
||||
/* Windows doesn't allow paths beginning with \ */
|
||||
if (from[0] == '\\')
|
||||
@ -478,21 +470,20 @@ cifs_convert_path_to_utf16(const char *from, struct cifs_sb_info *cifs_sb)
|
||||
} else
|
||||
start_of_path = from;
|
||||
|
||||
to = cifs_strndup_to_utf16(start_of_path, PATH_MAX, &len,
|
||||
cifs_sb->local_nls, map_type);
|
||||
return to;
|
||||
return cifs_strndup_to_utf16(start_of_path, PATH_MAX, &len,
|
||||
cifs_sb->local_nls, cifs_remap(cifs_sb));
|
||||
}
|
||||
|
||||
__le32
|
||||
smb2_get_lease_state(struct cifsInodeInfo *cinode)
|
||||
__le32 smb2_get_lease_state(struct cifsInodeInfo *cinode, unsigned int oplock)
|
||||
{
|
||||
unsigned int sbflags = cifs_sb_flags(CIFS_SB(cinode));
|
||||
__le32 lease = 0;
|
||||
|
||||
if (CIFS_CACHE_WRITE(cinode))
|
||||
if ((oplock & CIFS_CACHE_WRITE_FLG) || (sbflags & CIFS_MOUNT_RW_CACHE))
|
||||
lease |= SMB2_LEASE_WRITE_CACHING_LE;
|
||||
if (CIFS_CACHE_HANDLE(cinode))
|
||||
if (oplock & CIFS_CACHE_HANDLE_FLG)
|
||||
lease |= SMB2_LEASE_HANDLE_CACHING_LE;
|
||||
if (CIFS_CACHE_READ(cinode))
|
||||
if ((oplock & CIFS_CACHE_READ_FLG) || (sbflags & CIFS_MOUNT_RO_CACHE))
|
||||
lease |= SMB2_LEASE_READ_CACHING_LE;
|
||||
return lease;
|
||||
}
|
||||
|
||||
@ -987,7 +987,7 @@ smb2_is_path_accessible(const unsigned int xid, struct cifs_tcon *tcon,
|
||||
rc = -EREMOTE;
|
||||
}
|
||||
if (rc == -EREMOTE && IS_ENABLED(CONFIG_CIFS_DFS_UPCALL) &&
|
||||
(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_DFS))
|
||||
(cifs_sb_flags(cifs_sb) & CIFS_MOUNT_NO_DFS))
|
||||
rc = -EOPNOTSUPP;
|
||||
goto out;
|
||||
}
|
||||
@ -1461,6 +1461,8 @@ smb2_set_fid(struct cifsFileInfo *cfile, struct cifs_fid *fid, __u32 oplock)
|
||||
struct cifsInodeInfo *cinode = CIFS_I(d_inode(cfile->dentry));
|
||||
struct TCP_Server_Info *server = tlink_tcon(cfile->tlink)->ses->server;
|
||||
|
||||
lockdep_assert_held(&cinode->open_file_lock);
|
||||
|
||||
cfile->fid.persistent_fid = fid->persistent_fid;
|
||||
cfile->fid.volatile_fid = fid->volatile_fid;
|
||||
cfile->fid.access = fid->access;
|
||||
@ -2686,16 +2688,19 @@ smb2_is_network_name_deleted(char *buf, struct TCP_Server_Info *server)
|
||||
return false;
|
||||
}
|
||||
|
||||
static int
|
||||
smb2_oplock_response(struct cifs_tcon *tcon, __u64 persistent_fid,
|
||||
__u64 volatile_fid, __u16 net_fid, struct cifsInodeInfo *cinode)
|
||||
static int smb2_oplock_response(struct cifs_tcon *tcon, __u64 persistent_fid,
|
||||
__u64 volatile_fid, __u16 net_fid,
|
||||
struct cifsInodeInfo *cinode, unsigned int oplock)
|
||||
{
|
||||
unsigned int sbflags = cifs_sb_flags(CIFS_SB(cinode));
|
||||
__u8 op;
|
||||
|
||||
if (tcon->ses->server->capabilities & SMB2_GLOBAL_CAP_LEASING)
|
||||
return SMB2_lease_break(0, tcon, cinode->lease_key,
|
||||
smb2_get_lease_state(cinode));
|
||||
smb2_get_lease_state(cinode, oplock));
|
||||
|
||||
return SMB2_oplock_break(0, tcon, persistent_fid, volatile_fid,
|
||||
CIFS_CACHE_READ(cinode) ? 1 : 0);
|
||||
op = !!((oplock & CIFS_CACHE_READ_FLG) || (sbflags & CIFS_MOUNT_RO_CACHE));
|
||||
return SMB2_oplock_break(0, tcon, persistent_fid, volatile_fid, op);
|
||||
}
|
||||
|
||||
void
|
||||
@ -3559,6 +3564,7 @@ static int smb3_simple_fallocate_range(unsigned int xid,
|
||||
struct file_allocated_range_buffer in_data, *out_data = NULL, *tmp_data;
|
||||
u32 out_data_len;
|
||||
char *buf = NULL;
|
||||
u64 range_start, range_len, range_end;
|
||||
loff_t l;
|
||||
int rc;
|
||||
|
||||
@ -3595,13 +3601,21 @@ static int smb3_simple_fallocate_range(unsigned int xid,
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (off < le64_to_cpu(tmp_data->file_offset)) {
|
||||
range_start = le64_to_cpu(tmp_data->file_offset);
|
||||
range_len = le64_to_cpu(tmp_data->length);
|
||||
if (check_add_overflow(range_start, range_len, &range_end) ||
|
||||
range_end > S64_MAX) {
|
||||
rc = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (off < range_start) {
|
||||
/*
|
||||
* We are at a hole. Write until the end of the region
|
||||
* or until the next allocated data,
|
||||
* whichever comes next.
|
||||
*/
|
||||
l = le64_to_cpu(tmp_data->file_offset) - off;
|
||||
l = range_start - off;
|
||||
if (len < l)
|
||||
l = len;
|
||||
rc = smb3_simple_fallocate_write_range(xid, tcon,
|
||||
@ -3618,11 +3632,13 @@ static int smb3_simple_fallocate_range(unsigned int xid,
|
||||
* until the end of the data or the end of the region
|
||||
* we are supposed to fallocate, whichever comes first.
|
||||
*/
|
||||
l = le64_to_cpu(tmp_data->length);
|
||||
if (len < l)
|
||||
l = len;
|
||||
off += l;
|
||||
len -= l;
|
||||
if (off < range_end) {
|
||||
l = range_end - off;
|
||||
if (len < l)
|
||||
l = len;
|
||||
off += l;
|
||||
len -= l;
|
||||
}
|
||||
|
||||
tmp_data = &tmp_data[1];
|
||||
out_data_len -= sizeof(struct file_allocated_range_buffer);
|
||||
@ -4053,6 +4069,7 @@ smb2_downgrade_oplock(struct TCP_Server_Info *server,
|
||||
struct cifsInodeInfo *cinode, __u32 oplock,
|
||||
__u16 epoch, bool *purge_cache)
|
||||
{
|
||||
lockdep_assert_held(&cinode->open_file_lock);
|
||||
server->ops->set_oplock_level(cinode, oplock, 0, NULL);
|
||||
}
|
||||
|
||||
@ -4093,19 +4110,19 @@ smb2_set_oplock_level(struct cifsInodeInfo *cinode, __u32 oplock,
|
||||
if (oplock == SMB2_OPLOCK_LEVEL_NOCHANGE)
|
||||
return;
|
||||
if (oplock == SMB2_OPLOCK_LEVEL_BATCH) {
|
||||
cinode->oplock = CIFS_CACHE_RHW_FLG;
|
||||
WRITE_ONCE(cinode->oplock, CIFS_CACHE_RHW_FLG);
|
||||
cifs_dbg(FYI, "Batch Oplock granted on inode %p\n",
|
||||
&cinode->netfs.inode);
|
||||
} else if (oplock == SMB2_OPLOCK_LEVEL_EXCLUSIVE) {
|
||||
cinode->oplock = CIFS_CACHE_RW_FLG;
|
||||
WRITE_ONCE(cinode->oplock, CIFS_CACHE_RW_FLG);
|
||||
cifs_dbg(FYI, "Exclusive Oplock granted on inode %p\n",
|
||||
&cinode->netfs.inode);
|
||||
} else if (oplock == SMB2_OPLOCK_LEVEL_II) {
|
||||
cinode->oplock = CIFS_CACHE_READ_FLG;
|
||||
WRITE_ONCE(cinode->oplock, CIFS_CACHE_READ_FLG);
|
||||
cifs_dbg(FYI, "Level II Oplock granted on inode %p\n",
|
||||
&cinode->netfs.inode);
|
||||
} else
|
||||
cinode->oplock = 0;
|
||||
WRITE_ONCE(cinode->oplock, 0);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -4140,7 +4157,7 @@ smb21_set_oplock_level(struct cifsInodeInfo *cinode, __u32 oplock,
|
||||
if (!new_oplock)
|
||||
strscpy(message, "None");
|
||||
|
||||
cinode->oplock = new_oplock;
|
||||
WRITE_ONCE(cinode->oplock, new_oplock);
|
||||
cifs_dbg(FYI, "%s Lease granted on inode %p\n", message,
|
||||
&cinode->netfs.inode);
|
||||
}
|
||||
@ -4149,30 +4166,32 @@ static void
|
||||
smb3_set_oplock_level(struct cifsInodeInfo *cinode, __u32 oplock,
|
||||
__u16 epoch, bool *purge_cache)
|
||||
{
|
||||
unsigned int old_oplock = cinode->oplock;
|
||||
unsigned int old_oplock = READ_ONCE(cinode->oplock);
|
||||
unsigned int new_oplock;
|
||||
|
||||
smb21_set_oplock_level(cinode, oplock, epoch, purge_cache);
|
||||
new_oplock = READ_ONCE(cinode->oplock);
|
||||
|
||||
if (purge_cache) {
|
||||
*purge_cache = false;
|
||||
if (old_oplock == CIFS_CACHE_READ_FLG) {
|
||||
if (cinode->oplock == CIFS_CACHE_READ_FLG &&
|
||||
if (new_oplock == CIFS_CACHE_READ_FLG &&
|
||||
(epoch - cinode->epoch > 0))
|
||||
*purge_cache = true;
|
||||
else if (cinode->oplock == CIFS_CACHE_RH_FLG &&
|
||||
else if (new_oplock == CIFS_CACHE_RH_FLG &&
|
||||
(epoch - cinode->epoch > 1))
|
||||
*purge_cache = true;
|
||||
else if (cinode->oplock == CIFS_CACHE_RHW_FLG &&
|
||||
else if (new_oplock == CIFS_CACHE_RHW_FLG &&
|
||||
(epoch - cinode->epoch > 1))
|
||||
*purge_cache = true;
|
||||
else if (cinode->oplock == 0 &&
|
||||
else if (new_oplock == 0 &&
|
||||
(epoch - cinode->epoch > 0))
|
||||
*purge_cache = true;
|
||||
} else if (old_oplock == CIFS_CACHE_RH_FLG) {
|
||||
if (cinode->oplock == CIFS_CACHE_RH_FLG &&
|
||||
if (new_oplock == CIFS_CACHE_RH_FLG &&
|
||||
(epoch - cinode->epoch > 0))
|
||||
*purge_cache = true;
|
||||
else if (cinode->oplock == CIFS_CACHE_RHW_FLG &&
|
||||
else if (new_oplock == CIFS_CACHE_RHW_FLG &&
|
||||
(epoch - cinode->epoch > 1))
|
||||
*purge_cache = true;
|
||||
}
|
||||
@ -5325,7 +5344,7 @@ static int smb2_make_node(unsigned int xid, struct inode *inode,
|
||||
struct dentry *dentry, struct cifs_tcon *tcon,
|
||||
const char *full_path, umode_t mode, dev_t dev)
|
||||
{
|
||||
struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
|
||||
unsigned int sbflags = cifs_sb_flags(CIFS_SB(inode));
|
||||
int rc = -EOPNOTSUPP;
|
||||
|
||||
/*
|
||||
@ -5334,7 +5353,7 @@ static int smb2_make_node(unsigned int xid, struct inode *inode,
|
||||
* supports block and char device, socket & fifo,
|
||||
* and was used by default in earlier versions of Windows
|
||||
*/
|
||||
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) {
|
||||
if (sbflags & CIFS_MOUNT_UNX_EMUL) {
|
||||
rc = cifs_sfu_make_node(xid, inode, dentry, tcon,
|
||||
full_path, mode, dev);
|
||||
} else if (CIFS_REPARSE_SUPPORT(tcon)) {
|
||||
|
||||
@ -3182,22 +3182,19 @@ SMB2_open_init(struct cifs_tcon *tcon, struct TCP_Server_Info *server,
|
||||
}
|
||||
|
||||
if ((oparms->disposition != FILE_OPEN) && (oparms->cifs_sb)) {
|
||||
unsigned int sbflags = cifs_sb_flags(oparms->cifs_sb);
|
||||
bool set_mode;
|
||||
bool set_owner;
|
||||
|
||||
if ((oparms->cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MODE_FROM_SID) &&
|
||||
(oparms->mode != ACL_NO_MODE))
|
||||
if ((sbflags & CIFS_MOUNT_MODE_FROM_SID) &&
|
||||
oparms->mode != ACL_NO_MODE) {
|
||||
set_mode = true;
|
||||
else {
|
||||
} else {
|
||||
set_mode = false;
|
||||
oparms->mode = ACL_NO_MODE;
|
||||
}
|
||||
|
||||
if (oparms->cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UID_FROM_ACL)
|
||||
set_owner = true;
|
||||
else
|
||||
set_owner = false;
|
||||
|
||||
set_owner = sbflags & CIFS_MOUNT_UID_FROM_ACL;
|
||||
if (set_owner | set_mode) {
|
||||
cifs_dbg(FYI, "add sd with mode 0x%x\n", oparms->mode);
|
||||
rc = add_sd_context(iov, &n_iov, oparms->mode, set_owner);
|
||||
@ -3272,6 +3269,8 @@ SMB2_open(const unsigned int xid, struct cifs_open_parms *oparms, __le16 *path,
|
||||
|
||||
replay_again:
|
||||
/* reinitialize for possible replay */
|
||||
resp_buftype = CIFS_NO_BUFFER;
|
||||
memset(&rsp_iov, 0, sizeof(rsp_iov));
|
||||
flags = 0;
|
||||
server = cifs_pick_channel(ses);
|
||||
oparms->replay = !!(retries);
|
||||
@ -3902,6 +3901,8 @@ query_info(const unsigned int xid, struct cifs_tcon *tcon,
|
||||
|
||||
replay_again:
|
||||
/* reinitialize for possible replay */
|
||||
resp_buftype = CIFS_NO_BUFFER;
|
||||
memset(&rsp_iov, 0, sizeof(rsp_iov));
|
||||
flags = 0;
|
||||
allocated = false;
|
||||
server = cifs_pick_channel(ses);
|
||||
|
||||
@ -41,7 +41,7 @@ extern struct mid_q_entry *smb2_setup_async_request(
|
||||
struct TCP_Server_Info *server, struct smb_rqst *rqst);
|
||||
extern struct cifs_tcon *smb2_find_smb_tcon(struct TCP_Server_Info *server,
|
||||
__u64 ses_id, __u32 tid);
|
||||
extern __le32 smb2_get_lease_state(struct cifsInodeInfo *cinode);
|
||||
__le32 smb2_get_lease_state(struct cifsInodeInfo *cinode, unsigned int oplock);
|
||||
extern bool smb2_is_valid_oplock_break(char *buffer,
|
||||
struct TCP_Server_Info *srv);
|
||||
extern int smb3_handle_read_data(struct TCP_Server_Info *server,
|
||||
|
||||
@ -150,7 +150,7 @@ static int cifs_xattr_set(const struct xattr_handler *handler,
|
||||
break;
|
||||
}
|
||||
|
||||
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR)
|
||||
if (cifs_sb_flags(cifs_sb) & CIFS_MOUNT_NO_XATTR)
|
||||
goto out;
|
||||
|
||||
if (pTcon->ses->server->ops->set_EA) {
|
||||
@ -310,7 +310,7 @@ static int cifs_xattr_get(const struct xattr_handler *handler,
|
||||
break;
|
||||
}
|
||||
|
||||
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR)
|
||||
if (cifs_sb_flags(cifs_sb) & CIFS_MOUNT_NO_XATTR)
|
||||
goto out;
|
||||
|
||||
if (pTcon->ses->server->ops->query_all_EAs)
|
||||
@ -399,7 +399,7 @@ ssize_t cifs_listxattr(struct dentry *direntry, char *data, size_t buf_size)
|
||||
if (unlikely(cifs_forced_shutdown(cifs_sb)))
|
||||
return smb_EIO(smb_eio_trace_forced_shutdown);
|
||||
|
||||
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR)
|
||||
if (cifs_sb_flags(cifs_sb) & CIFS_MOUNT_NO_XATTR)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
tlink = cifs_sb_tlink(cifs_sb);
|
||||
|
||||
@ -1686,8 +1686,9 @@ static struct udf_vds_record *handle_partition_descriptor(
|
||||
return &(data->part_descs_loc[i].rec);
|
||||
if (data->num_part_descs >= data->size_part_descs) {
|
||||
struct part_desc_seq_scan_data *new_loc;
|
||||
unsigned int new_size = ALIGN(partnum, PART_DESC_ALLOC_STEP);
|
||||
unsigned int new_size;
|
||||
|
||||
new_size = data->num_part_descs + PART_DESC_ALLOC_STEP;
|
||||
new_loc = kcalloc(new_size, sizeof(*new_loc), GFP_KERNEL);
|
||||
if (!new_loc)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
@ -1697,6 +1698,7 @@ static struct udf_vds_record *handle_partition_descriptor(
|
||||
data->part_descs_loc = new_loc;
|
||||
data->size_part_descs = new_size;
|
||||
}
|
||||
data->part_descs_loc[data->num_part_descs].partnum = partnum;
|
||||
return &(data->part_descs_loc[data->num_part_descs++].rec);
|
||||
}
|
||||
|
||||
|
||||
@ -959,6 +959,16 @@ xmi_can_exchange_reflink_flags(
|
||||
{
|
||||
struct xfs_mount *mp = req->ip1->i_mount;
|
||||
|
||||
/*
|
||||
* The INO1_WRITTEN optimization can skip exchanging hole and
|
||||
* unwritten mappings, which means we cannot guarantee that all
|
||||
* shared extents actually moved to the other file. Clearing the
|
||||
* reflink flag of an inode that still holds shared extents breaks
|
||||
* the CoW write path, so refuse to exchange the flags in that case.
|
||||
*/
|
||||
if (req->flags & XFS_EXCHMAPS_INO1_WRITTEN)
|
||||
return false;
|
||||
|
||||
if (hweight32(reflink_state) != 1)
|
||||
return false;
|
||||
if (req->startoff1 != 0 || req->startoff2 != 0)
|
||||
|
||||
@ -25,7 +25,9 @@ void psi_memstall_leave(unsigned long *flags);
|
||||
int psi_show(struct seq_file *s, struct psi_group *group, enum psi_res res);
|
||||
struct psi_trigger *psi_trigger_create(struct psi_group *group, char *buf,
|
||||
enum psi_res res, struct file *file,
|
||||
struct kernfs_open_file *of);
|
||||
struct kernfs_open_file *of,
|
||||
bool *need_rtpoll_worker);
|
||||
int psi_trigger_create_rtpoll_worker(struct psi_group *group);
|
||||
void psi_trigger_destroy(struct psi_trigger *t);
|
||||
|
||||
__poll_t psi_trigger_poll(void **trigger_ptr, struct file *file,
|
||||
|
||||
@ -1,2 +1,2 @@
|
||||
sbat,1,SBAT Version,sbat,1,https://github.com/rhboot/shim/blob/main/SBAT.md
|
||||
kernel.almalinux,1,AlmaLinux,kernel-core,6.12.0-211.47.1.el10.x86_64,mailto:security@almalinux.org
|
||||
kernel.almalinux,1,AlmaLinux,kernel-core,6.12.0-211.49.1.el10.x86_64,mailto:security@almalinux.org
|
||||
|
||||
@ -3842,33 +3842,62 @@ static int cgroup_cpu_pressure_show(struct seq_file *seq, void *v)
|
||||
static ssize_t pressure_write(struct kernfs_open_file *of, char *buf,
|
||||
size_t nbytes, enum psi_res res)
|
||||
{
|
||||
struct cgroup_file_ctx *ctx = of->priv;
|
||||
struct cgroup_file_ctx *ctx;
|
||||
struct psi_trigger *new;
|
||||
struct cgroup *cgrp;
|
||||
struct psi_group *psi;
|
||||
bool need_rtpoll_worker;
|
||||
ssize_t ret = 0;
|
||||
|
||||
cgrp = cgroup_kn_lock_live(of->kn, false);
|
||||
if (!cgrp)
|
||||
return -ENODEV;
|
||||
|
||||
cgroup_get(cgrp);
|
||||
cgroup_kn_unlock(of->kn);
|
||||
ctx = of->priv;
|
||||
if (!ctx) {
|
||||
ret = -ENODEV;
|
||||
goto out_unlock;
|
||||
}
|
||||
|
||||
/* Allow only one trigger per file descriptor */
|
||||
if (ctx->psi.trigger) {
|
||||
cgroup_put(cgrp);
|
||||
return -EBUSY;
|
||||
ret = -EBUSY;
|
||||
goto out_unlock;
|
||||
}
|
||||
|
||||
psi = cgroup_psi(cgrp);
|
||||
new = psi_trigger_create(psi, buf, res, of->file, of);
|
||||
new = psi_trigger_create(psi, buf, res, of->file, of,
|
||||
&need_rtpoll_worker);
|
||||
if (IS_ERR(new)) {
|
||||
cgroup_put(cgrp);
|
||||
return PTR_ERR(new);
|
||||
ret = PTR_ERR(new);
|
||||
goto out_unlock;
|
||||
}
|
||||
|
||||
/*
|
||||
* The worker fork must run with neither cgroup_mutex nor the file's
|
||||
* kernfs active reference held. The latter is broken since
|
||||
* cgroup_kn_lock_live(). @of->priv may be released while unlocked, so
|
||||
* recheck before publishing @new.
|
||||
*/
|
||||
if (need_rtpoll_worker) {
|
||||
cgroup_unlock();
|
||||
ret = psi_trigger_create_rtpoll_worker(psi);
|
||||
cgroup_lock();
|
||||
|
||||
if (!ret && !of->priv)
|
||||
ret = -ENODEV;
|
||||
if (ret) {
|
||||
psi_trigger_destroy(new);
|
||||
goto out_unlock;
|
||||
}
|
||||
}
|
||||
|
||||
smp_store_release(&ctx->psi.trigger, new);
|
||||
cgroup_put(cgrp);
|
||||
|
||||
out_unlock:
|
||||
cgroup_kn_unlock(of->kn);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return nbytes;
|
||||
}
|
||||
|
||||
@ -203,19 +203,16 @@ static void __exit_signal(struct task_struct *tsk)
|
||||
write_sequnlock(&sig->stats_lock);
|
||||
|
||||
/*
|
||||
* Do this under ->siglock, we can race with another thread
|
||||
* doing sigqueue_free() if we have SIGQUEUE_PREALLOC signals.
|
||||
* Ensure that all preceeding state is visible. Pairs with
|
||||
* the smp_acquire__after_ctrl_dep() in the sighand == NULL
|
||||
* path of lock_task_sighand().
|
||||
*/
|
||||
flush_sigqueue(&tsk->pending);
|
||||
tsk->sighand = NULL;
|
||||
smp_store_release(&tsk->sighand, NULL);
|
||||
spin_unlock(&sighand->siglock);
|
||||
|
||||
__cleanup_sighand(sighand);
|
||||
clear_tsk_thread_flag(tsk, TIF_SIGPENDING);
|
||||
if (group_dead) {
|
||||
flush_sigqueue(&sig->shared_pending);
|
||||
if (group_dead)
|
||||
tty_kref_put(tty);
|
||||
}
|
||||
}
|
||||
|
||||
static void delayed_put_task_struct(struct rcu_head *rhp)
|
||||
@ -282,6 +279,16 @@ repeat:
|
||||
proc_flush_pid(thread_pid);
|
||||
put_pid(thread_pid);
|
||||
release_thread(p);
|
||||
/*
|
||||
* This task was already removed from the process/thread/pid lists
|
||||
* and lock_task_sighand(p) can't succeed. Nobody else can touch
|
||||
* ->pending or, if group dead, signal->shared_pending. We can call
|
||||
* flush_sigqueue() lockless.
|
||||
*/
|
||||
flush_sigqueue(&p->pending);
|
||||
if (thread_group_leader(p))
|
||||
flush_sigqueue(&p->signal->shared_pending);
|
||||
|
||||
put_task_struct_rcu_user(p);
|
||||
|
||||
p = leader;
|
||||
|
||||
@ -1292,9 +1292,44 @@ int psi_show(struct seq_file *m, struct psi_group *group, enum psi_res res)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Create @group's rtpoll worker after psi_trigger_create() reported the need
|
||||
* for one. kthread creation depends on the whole fork path and we don't want
|
||||
* all of that nested inside cgroup_mutex, so the caller must drop it and any
|
||||
* other lock that forks can wait behind. If two callers race, the loser stops
|
||||
* its never-woken kthread.
|
||||
*/
|
||||
int psi_trigger_create_rtpoll_worker(struct psi_group *group)
|
||||
{
|
||||
struct task_struct *task;
|
||||
|
||||
task = kthread_create(psi_rtpoll_worker, group, "psimon");
|
||||
if (IS_ERR(task))
|
||||
return PTR_ERR(task);
|
||||
|
||||
scoped_guard(mutex, &group->rtpoll_trigger_lock) {
|
||||
if (!rcu_access_pointer(group->rtpoll_task)) {
|
||||
atomic_set(&group->rtpoll_wakeup, 0);
|
||||
wake_up_process(task);
|
||||
rcu_assign_pointer(group->rtpoll_task, task);
|
||||
|
||||
/*
|
||||
* Poll once to catch up on scheduling attempts dropped
|
||||
* while there was no rtpoll worker.
|
||||
*/
|
||||
psi_schedule_rtpoll_work(group, 1, true);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
kthread_stop(task);
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct psi_trigger *psi_trigger_create(struct psi_group *group, char *buf,
|
||||
enum psi_res res, struct file *file,
|
||||
struct kernfs_open_file *of)
|
||||
struct kernfs_open_file *of,
|
||||
bool *need_rtpoll_worker)
|
||||
{
|
||||
struct psi_trigger *t;
|
||||
enum psi_states state;
|
||||
@ -1302,6 +1337,8 @@ struct psi_trigger *psi_trigger_create(struct psi_group *group, char *buf,
|
||||
bool privileged;
|
||||
u32 window_us;
|
||||
|
||||
*need_rtpoll_worker = false;
|
||||
|
||||
if (static_branch_likely(&psi_disabled))
|
||||
return ERR_PTR(-EOPNOTSUPP);
|
||||
|
||||
@ -1362,26 +1399,14 @@ struct psi_trigger *psi_trigger_create(struct psi_group *group, char *buf,
|
||||
if (privileged) {
|
||||
mutex_lock(&group->rtpoll_trigger_lock);
|
||||
|
||||
if (!rcu_access_pointer(group->rtpoll_task)) {
|
||||
struct task_struct *task;
|
||||
|
||||
task = kthread_create(psi_rtpoll_worker, group, "psimon");
|
||||
if (IS_ERR(task)) {
|
||||
kfree(t);
|
||||
mutex_unlock(&group->rtpoll_trigger_lock);
|
||||
return ERR_CAST(task);
|
||||
}
|
||||
atomic_set(&group->rtpoll_wakeup, 0);
|
||||
wake_up_process(task);
|
||||
rcu_assign_pointer(group->rtpoll_task, task);
|
||||
}
|
||||
|
||||
list_add(&t->node, &group->rtpoll_triggers);
|
||||
group->rtpoll_min_period = min(group->rtpoll_min_period,
|
||||
div_u64(t->win.size, UPDATES_PER_WINDOW));
|
||||
group->rtpoll_nr_triggers[t->state]++;
|
||||
group->rtpoll_states |= (1 << t->state);
|
||||
|
||||
*need_rtpoll_worker = !rcu_access_pointer(group->rtpoll_task);
|
||||
|
||||
mutex_unlock(&group->rtpoll_trigger_lock);
|
||||
} else {
|
||||
mutex_lock(&group->avgs_lock);
|
||||
@ -1541,6 +1566,8 @@ static ssize_t psi_write(struct file *file, const char __user *user_buf,
|
||||
size_t buf_size;
|
||||
struct seq_file *seq;
|
||||
struct psi_trigger *new;
|
||||
bool need_rtpoll_worker;
|
||||
int ret;
|
||||
|
||||
if (static_branch_likely(&psi_disabled))
|
||||
return -EOPNOTSUPP;
|
||||
@ -1565,12 +1592,22 @@ static ssize_t psi_write(struct file *file, const char __user *user_buf,
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
new = psi_trigger_create(&psi_system, buf, res, file, NULL);
|
||||
new = psi_trigger_create(&psi_system, buf, res, file, NULL,
|
||||
&need_rtpoll_worker);
|
||||
if (IS_ERR(new)) {
|
||||
mutex_unlock(&seq->lock);
|
||||
return PTR_ERR(new);
|
||||
}
|
||||
|
||||
if (need_rtpoll_worker) {
|
||||
ret = psi_trigger_create_rtpoll_worker(&psi_system);
|
||||
if (ret) {
|
||||
psi_trigger_destroy(new);
|
||||
mutex_unlock(&seq->lock);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
smp_store_release(&seq->private, new);
|
||||
mutex_unlock(&seq->lock);
|
||||
|
||||
|
||||
@ -1362,8 +1362,16 @@ struct sighand_struct *__lock_task_sighand(struct task_struct *tsk,
|
||||
rcu_read_lock();
|
||||
for (;;) {
|
||||
sighand = rcu_dereference(tsk->sighand);
|
||||
if (unlikely(sighand == NULL))
|
||||
if (unlikely(sighand == NULL)) {
|
||||
/*
|
||||
* Pairs with the smp_store_release() in
|
||||
* __exit_signal(). It ensures that all state
|
||||
* modifications to the task preceeding the store are
|
||||
* visible to the callers of lock_task_sighand().
|
||||
*/
|
||||
smp_acquire__after_ctrl_dep();
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* This sighand can be already freed and even reused, but
|
||||
|
||||
@ -461,6 +461,109 @@ static void disarm_timer(struct k_itimer *timer, struct task_struct *p)
|
||||
trigger_base_recalc_expires(timer, p);
|
||||
}
|
||||
|
||||
/*
|
||||
* Lookup the task via timer->it.cpu.pid and attempt to lock the task's sighand.
|
||||
*
|
||||
* This can race with the reaping of the task:
|
||||
*
|
||||
* CPU0 CPU1
|
||||
*
|
||||
* // Finds task
|
||||
* p = pid_task(pid, pid_type); __exit_signal(p)
|
||||
* lock(p, sighand);
|
||||
* posix_cpu_timers*_exit();
|
||||
* sighand = lock_task_sighand(p); unhash_task(p);
|
||||
* p->sighand = NULL;
|
||||
* unlock(sighand);
|
||||
*
|
||||
* In this case sighand is NULL, which means the task and the associated timer
|
||||
* queue cannot be longer accessed safely.
|
||||
*
|
||||
* __exit_signal() invokes posix_cpu_timers_exit() and if the thread group is
|
||||
* dead it also invokes posix_cpu_timers_group_exit(). These functions delete
|
||||
* all pending timers from the related timer queues. The POSIX timers (k_itimer)
|
||||
* themself are still accessible, but not longer connected to the task.
|
||||
*
|
||||
* exec() works slightly differently. The task which exec()'s terminates all
|
||||
* other threads in the thread group and runs __exit_signal() on them. As the
|
||||
* thread group is not dead they only clean up the per task timers via
|
||||
* posix_cpu_timers_exit().
|
||||
*
|
||||
* As the TGID on exec() stays the same per process timers stay queued, if they
|
||||
* are armed. This works without a problem when exec() is done by the thread
|
||||
* group leader. If a non-leader thread exec()'s this can end up in the
|
||||
* following scenario:
|
||||
*
|
||||
* CPU0 CPU1
|
||||
* // Returns old leader
|
||||
* p = pid_task(pid, pid_type); de_thread()
|
||||
* switch_leader()
|
||||
* release_task(old leader)
|
||||
* __exit_signal()
|
||||
* old_leader->sighand = NULL;
|
||||
* // Returns NULL
|
||||
* sighand = lock_task_sighand(p)
|
||||
*
|
||||
* That's problematic for several functions:
|
||||
*
|
||||
* - posix_cpu_timer_del(): If the timer is still enqueued on the task the
|
||||
* underlying k_itimer will be freed which results in a UAF in
|
||||
* run_posix_cpu_timers() or on timerqueue related add/delete operations.
|
||||
* If the timer is not enqueued, the failure is harmless
|
||||
*
|
||||
* - posix_cpu_timer_set(): Independent of the enqueued state that results in a
|
||||
* transient failure which is user space visible (-ESRCH) for regular posix
|
||||
* timers. But for the use case in do_cpu_nanosleep() it's the same UAF
|
||||
* problem just that the timer is allocated on the stack.
|
||||
*
|
||||
* - posix_cpu_timer_rearm(): Timer is not enqueued at that point, but this
|
||||
* silently ignores the rearm request, which is a functional problem as the
|
||||
* timer wont expire anymore.
|
||||
*/
|
||||
static struct task_struct *timer_lock_sighand(struct k_itimer *timer, unsigned long *flags)
|
||||
{
|
||||
enum pid_type type = clock_pid_type(timer->it_clock);
|
||||
struct cpu_timer *ctmr = &timer->it.cpu;
|
||||
|
||||
guard(rcu)();
|
||||
|
||||
for (;;) {
|
||||
struct task_struct *t = pid_task(timer->it.cpu.pid, type);
|
||||
|
||||
/* Fail if the task cannot be found. */
|
||||
if (!t)
|
||||
break;
|
||||
|
||||
/* Try to lock the task's sighand */
|
||||
if (lock_task_sighand(t, flags))
|
||||
return t;
|
||||
|
||||
/*
|
||||
* The next PID lookup might either fail or return the new
|
||||
* leader. This is correct for both exit() and exec().
|
||||
*/
|
||||
}
|
||||
|
||||
/*
|
||||
* If the timer is still enqueued, warn. There is nothing safe to do
|
||||
* here as there might be two timers in there which are removed in
|
||||
* parallel and that will cause more damage than good. This should never
|
||||
* happen!
|
||||
*
|
||||
* Ensure that the stores to the timer and timerqueue are visible:
|
||||
*
|
||||
* __exit_signal()
|
||||
* posix_cpu_timers*_exit()
|
||||
* write_seqlock(seqlock)
|
||||
* smp_wmb(); <-------
|
||||
* __unhash_process() | !pid_task()
|
||||
* ----> smp_rmb();
|
||||
* WARN_ON_ONCE(...)
|
||||
*/
|
||||
smp_rmb();
|
||||
WARN_ON_ONCE(ctmr->head || timerqueue_node_queued(&ctmr->node));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Clean up a CPU-clock timer that is about to be destroyed.
|
||||
@ -470,29 +573,13 @@ static void disarm_timer(struct k_itimer *timer, struct task_struct *p)
|
||||
*/
|
||||
static int posix_cpu_timer_del(struct k_itimer *timer)
|
||||
{
|
||||
struct cpu_timer *ctmr = &timer->it.cpu;
|
||||
struct sighand_struct *sighand;
|
||||
struct task_struct *p;
|
||||
unsigned long flags;
|
||||
int ret = 0;
|
||||
|
||||
rcu_read_lock();
|
||||
p = cpu_timer_task_rcu(timer);
|
||||
if (!p)
|
||||
goto out;
|
||||
p = timer_lock_sighand(timer, &flags);
|
||||
|
||||
/*
|
||||
* Protect against sighand release/switch in exit/exec and process/
|
||||
* thread timer list entry concurrent read/writes.
|
||||
*/
|
||||
sighand = lock_task_sighand(p, &flags);
|
||||
if (unlikely(sighand == NULL)) {
|
||||
/*
|
||||
* This raced with the reaping of the task. The exit cleanup
|
||||
* should have removed this timer from the timer queue.
|
||||
*/
|
||||
WARN_ON_ONCE(ctmr->head || timerqueue_node_queued(&ctmr->node));
|
||||
} else {
|
||||
if (likely(p)) {
|
||||
if (timer->it.cpu.firing) {
|
||||
/*
|
||||
* Prevent signal delivery. The timer cannot be dequeued
|
||||
@ -508,11 +595,8 @@ static int posix_cpu_timer_del(struct k_itimer *timer)
|
||||
unlock_task_sighand(p, &flags);
|
||||
}
|
||||
|
||||
out:
|
||||
rcu_read_unlock();
|
||||
|
||||
if (!ret) {
|
||||
put_pid(ctmr->pid);
|
||||
put_pid(timer->it.cpu.pid);
|
||||
timer->it_status = POSIX_TIMER_DISARMED;
|
||||
}
|
||||
return ret;
|
||||
@ -626,21 +710,17 @@ static int posix_cpu_timer_set(struct k_itimer *timer, int timer_flags,
|
||||
clockid_t clkid = CPUCLOCK_WHICH(timer->it_clock);
|
||||
struct cpu_timer *ctmr = &timer->it.cpu;
|
||||
u64 old_expires, new_expires, now;
|
||||
struct sighand_struct *sighand;
|
||||
struct task_struct *p;
|
||||
unsigned long flags;
|
||||
int ret = 0;
|
||||
|
||||
rcu_read_lock();
|
||||
p = cpu_timer_task_rcu(timer);
|
||||
if (!p) {
|
||||
/*
|
||||
* If p has just been reaped, we can no
|
||||
* longer get any information about it at all.
|
||||
*/
|
||||
rcu_read_unlock();
|
||||
p = timer_lock_sighand(timer, &flags);
|
||||
/*
|
||||
* If p has just been reaped, we can no longer get any information about
|
||||
* it at all.
|
||||
*/
|
||||
if (!p)
|
||||
return -ESRCH;
|
||||
}
|
||||
|
||||
/*
|
||||
* Use the to_ktime conversion because that clamps the maximum
|
||||
@ -648,20 +728,6 @@ static int posix_cpu_timer_set(struct k_itimer *timer, int timer_flags,
|
||||
*/
|
||||
new_expires = ktime_to_ns(timespec64_to_ktime(new->it_value));
|
||||
|
||||
/*
|
||||
* Protect against sighand release/switch in exit/exec and p->cpu_timers
|
||||
* and p->signal->cpu_timers read/write in arm_timer()
|
||||
*/
|
||||
sighand = lock_task_sighand(p, &flags);
|
||||
/*
|
||||
* If p has just been reaped, we can no
|
||||
* longer get any information about it at all.
|
||||
*/
|
||||
if (unlikely(sighand == NULL)) {
|
||||
rcu_read_unlock();
|
||||
return -ESRCH;
|
||||
}
|
||||
|
||||
/* Retrieve the current expiry time before disarming the timer */
|
||||
old_expires = cpu_timer_getexpires(ctmr);
|
||||
|
||||
@ -698,7 +764,7 @@ static int posix_cpu_timer_set(struct k_itimer *timer, int timer_flags,
|
||||
/* Retry if the timer expiry is running concurrently */
|
||||
if (unlikely(ret)) {
|
||||
unlock_task_sighand(p, &flags);
|
||||
goto out;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Convert relative expiry time to absolute */
|
||||
@ -733,8 +799,6 @@ static int posix_cpu_timer_set(struct k_itimer *timer, int timer_flags,
|
||||
*/
|
||||
if (!sigev_none && new_expires && now >= new_expires)
|
||||
cpu_timer_fire(timer);
|
||||
out:
|
||||
rcu_read_unlock();
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -1016,19 +1080,12 @@ static void posix_cpu_timer_rearm(struct k_itimer *timer)
|
||||
{
|
||||
clockid_t clkid = CPUCLOCK_WHICH(timer->it_clock);
|
||||
struct task_struct *p;
|
||||
struct sighand_struct *sighand;
|
||||
unsigned long flags;
|
||||
u64 now;
|
||||
|
||||
rcu_read_lock();
|
||||
p = cpu_timer_task_rcu(timer);
|
||||
if (!p)
|
||||
goto out;
|
||||
|
||||
/* Protect timer list r/w in arm_timer() */
|
||||
sighand = lock_task_sighand(p, &flags);
|
||||
if (unlikely(sighand == NULL))
|
||||
goto out;
|
||||
p = timer_lock_sighand(timer, &flags);
|
||||
if (unlikely(!p))
|
||||
return;
|
||||
|
||||
/*
|
||||
* Fetch the current sample and update the timer's expiry time.
|
||||
@ -1045,8 +1102,6 @@ static void posix_cpu_timer_rearm(struct k_itimer *timer)
|
||||
*/
|
||||
arm_timer(timer, p);
|
||||
unlock_task_sighand(p, &flags);
|
||||
out:
|
||||
rcu_read_unlock();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1504,6 +1559,7 @@ static int do_cpu_nanosleep(const clockid_t which_clock, int flags,
|
||||
spin_lock_irq(&timer.it_lock);
|
||||
error = posix_cpu_timer_set(&timer, flags, &it, NULL);
|
||||
if (error) {
|
||||
posix_cpu_timer_del(&timer);
|
||||
spin_unlock_irq(&timer.it_lock);
|
||||
return error;
|
||||
}
|
||||
|
||||
12
mm/memfd.c
12
mm/memfd.c
@ -246,6 +246,12 @@ static int memfd_add_seals(struct file *file, unsigned int seals)
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
/*
|
||||
* SEAL_EXEC implies SEAL_WRITE, making W^X from the start.
|
||||
*/
|
||||
if (seals & F_SEAL_EXEC && inode->i_mode & 0111)
|
||||
seals |= F_SEAL_SHRINK|F_SEAL_GROW|F_SEAL_WRITE|F_SEAL_FUTURE_WRITE;
|
||||
|
||||
if ((seals & F_SEAL_WRITE) && !(*file_seals & F_SEAL_WRITE)) {
|
||||
error = mapping_deny_writable(file->f_mapping);
|
||||
if (error)
|
||||
@ -258,12 +264,6 @@ static int memfd_add_seals(struct file *file, unsigned int seals)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* SEAL_EXEC implys SEAL_WRITE, making W^X from the start.
|
||||
*/
|
||||
if (seals & F_SEAL_EXEC && inode->i_mode & 0111)
|
||||
seals |= F_SEAL_SHRINK|F_SEAL_GROW|F_SEAL_WRITE|F_SEAL_FUTURE_WRITE;
|
||||
|
||||
*file_seals |= seals;
|
||||
error = 0;
|
||||
|
||||
|
||||
@ -247,6 +247,21 @@ tcpmss_tg6(struct sk_buff *skb, const struct xt_action_param *par)
|
||||
}
|
||||
#endif
|
||||
|
||||
static int tcpmss_tg4_check_hooks(const struct xt_tgchk_param *par)
|
||||
{
|
||||
const struct xt_tcpmss_info *info = par->targinfo;
|
||||
|
||||
if (info->mss == XT_TCPMSS_CLAMP_PMTU &&
|
||||
(par->hook_mask & ~((1 << NF_INET_FORWARD) |
|
||||
(1 << NF_INET_LOCAL_OUT) |
|
||||
(1 << NF_INET_POST_ROUTING))) != 0) {
|
||||
pr_info_ratelimited("path-MTU clamping only supported in FORWARD, OUTPUT and POSTROUTING hooks\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Must specify -p tcp --syn */
|
||||
static inline bool find_syn_match(const struct xt_entry_match *m)
|
||||
{
|
||||
@ -262,17 +277,9 @@ static inline bool find_syn_match(const struct xt_entry_match *m)
|
||||
|
||||
static int tcpmss_tg4_check(const struct xt_tgchk_param *par)
|
||||
{
|
||||
const struct xt_tcpmss_info *info = par->targinfo;
|
||||
const struct ipt_entry *e = par->entryinfo;
|
||||
const struct xt_entry_match *ematch;
|
||||
|
||||
if (info->mss == XT_TCPMSS_CLAMP_PMTU &&
|
||||
(par->hook_mask & ~((1 << NF_INET_FORWARD) |
|
||||
(1 << NF_INET_LOCAL_OUT) |
|
||||
(1 << NF_INET_POST_ROUTING))) != 0) {
|
||||
pr_info_ratelimited("path-MTU clamping only supported in FORWARD, OUTPUT and POSTROUTING hooks\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
if (par->nft_compat)
|
||||
return 0;
|
||||
|
||||
@ -286,17 +293,9 @@ static int tcpmss_tg4_check(const struct xt_tgchk_param *par)
|
||||
#if IS_ENABLED(CONFIG_IP6_NF_IPTABLES)
|
||||
static int tcpmss_tg6_check(const struct xt_tgchk_param *par)
|
||||
{
|
||||
const struct xt_tcpmss_info *info = par->targinfo;
|
||||
const struct ip6t_entry *e = par->entryinfo;
|
||||
const struct xt_entry_match *ematch;
|
||||
|
||||
if (info->mss == XT_TCPMSS_CLAMP_PMTU &&
|
||||
(par->hook_mask & ~((1 << NF_INET_FORWARD) |
|
||||
(1 << NF_INET_LOCAL_OUT) |
|
||||
(1 << NF_INET_POST_ROUTING))) != 0) {
|
||||
pr_info_ratelimited("path-MTU clamping only supported in FORWARD, OUTPUT and POSTROUTING hooks\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
if (par->nft_compat)
|
||||
return 0;
|
||||
|
||||
@ -312,6 +311,7 @@ static struct xt_target tcpmss_tg_reg[] __read_mostly = {
|
||||
{
|
||||
.family = NFPROTO_IPV4,
|
||||
.name = "TCPMSS",
|
||||
.check_hooks = tcpmss_tg4_check_hooks,
|
||||
.checkentry = tcpmss_tg4_check,
|
||||
.target = tcpmss_tg4,
|
||||
.targetsize = sizeof(struct xt_tcpmss_info),
|
||||
@ -322,6 +322,7 @@ static struct xt_target tcpmss_tg_reg[] __read_mostly = {
|
||||
{
|
||||
.family = NFPROTO_IPV6,
|
||||
.name = "TCPMSS",
|
||||
.check_hooks = tcpmss_tg4_check_hooks,
|
||||
.checkentry = tcpmss_tg6_check,
|
||||
.target = tcpmss_tg6,
|
||||
.targetsize = sizeof(struct xt_tcpmss_info),
|
||||
|
||||
@ -1,3 +1,142 @@
|
||||
* Wed Aug 19 2026 CKI KWF Bot <cki-ci-bot+kwf-gitlab-com@redhat.com> [6.12.0-211.49.1.el10_2]
|
||||
- udf: fix partition descriptor append bookkeeping (CKI Backport Bot) [RHEL-179570] {CVE-2026-45991}
|
||||
- cifs: fix time_last_write stamp placement in setattr/truncate paths (Paulo Alcantara) [RHEL-235459]
|
||||
- cifs: consolidate time_last_write stamp into _cifsFileInfo_put() (Paulo Alcantara) [RHEL-235459]
|
||||
- cifs: fix cifsFileInfo leak on kmalloc failure in deferred close drain paths (Paulo Alcantara) [RHEL-235459]
|
||||
- cifs: prevent readdir from changing file size due to stale directory metadata (Paulo Alcantara) [RHEL-235459]
|
||||
- smb: client: fix dir separator in SMB1 UNIX mounts (Paulo Alcantara) [RHEL-235459]
|
||||
- smb: client: fix sbflags initialization (Paulo Alcantara) [RHEL-235459]
|
||||
- smb: client: use atomic_t for mnt_cifs_flags (Paulo Alcantara) [RHEL-235459]
|
||||
- smb: client: fix data corruption due to racy lease checks (Paulo Alcantara) [RHEL-235459]
|
||||
- crypto: pcrypt - Fix handling of MAY_BACKLOG requests (Ricardo Robaina) [RHEL-226717] {CVE-2026-43493}
|
||||
- smb: client: fix SMB1 TRANS2 multi-response truncation in SendReceive() (Paulo Alcantara) [RHEL-235812]
|
||||
- smb/client: handle overlapping allocated ranges in fallocate (CKI Backport Bot) [RHEL-236210] {CVE-2026-68388}
|
||||
- posix-cpu-timers: Prevent UAF caused by non-leader exec() race (Waiman Long) [RHEL-227850] {CVE-2026-64560}
|
||||
- posix-cpu-timers: Fix pid refcount leak in do_cpu_nanosleep() error path (Waiman Long) [RHEL-227850] {CVE-2026-64370}
|
||||
- exit: kill the pointless __exit_signal()->clear_tsk_thread_flag(TIF_SIGPENDING) (Waiman Long) [RHEL-227850]
|
||||
- exit: change the release_task() paths to call flush_sigqueue() lockless (Waiman Long) [RHEL-227850]
|
||||
- smb: client: fix double-free in SMB2_open() replay (CKI Backport Bot) [RHEL-234551] {CVE-2026-64382}
|
||||
- smb: client: mask server-provided mode to 07777 in modefromsid (CKI Backport Bot) [RHEL-234530] {CVE-2026-64379}
|
||||
- smb: client: fix query_info() replay double-free (CKI Backport Bot) [RHEL-234129] {CVE-2026-64386}
|
||||
- smb/client: fix out-of-bounds read in symlink_data() (CKI Backport Bot) [RHEL-229066] {CVE-2026-46185}
|
||||
- blk-mq: reinsert cached request to the list (CKI Backport Bot) [RHEL-213153] {CVE-2026-64017}
|
||||
- blk-mq: pop cached request if it is usable (CKI Backport Bot) [RHEL-213153] {CVE-2026-64017}
|
||||
Resolves: RHEL-179570, RHEL-213153, RHEL-226717, RHEL-227850, RHEL-229066, RHEL-234129, RHEL-234530, RHEL-234551, RHEL-235459, RHEL-235812, RHEL-236210
|
||||
|
||||
* Mon Aug 17 2026 CKI KWF Bot <cki-ci-bot+kwf-gitlab-com@redhat.com> [6.12.0-211.48.1.el10_2]
|
||||
- scsi: target: iscsi: Fix CRC overread and double-free in iscsit_handle_text_cmd() (Maurizio Lombardi) [RHEL-213217] {CVE-2026-63888}
|
||||
- drm/i915: Fix potential UAF in TTM object purge (CKI Backport Bot) [RHEL-222740] {CVE-2026-63884}
|
||||
- drm/amd/display: Validate payload length and link_index in dc_process_dmub_aux_transfer_async (CKI Backport Bot) [RHEL-222567] {CVE-2026-64219}
|
||||
- drm/amd/display: Use krealloc_array() in dal_vector_reserve() (CKI Backport Bot) [RHEL-222667] {CVE-2026-53329}
|
||||
- drm/amdgpu: fix amdgpu_hmm_range_get_pages (Mika Penttilä) [RHEL-222625] {CVE-2026-63879}
|
||||
- drm/amdkfd: Fix out-of-bounds write in kfd_event_page_set() (CKI Backport Bot) [RHEL-221336] {CVE-2026-43206}
|
||||
- drm/i915/gem: Fix phys BO pread/pwrite with offset (CKI Backport Bot) [RHEL-222753] {CVE-2026-53356}
|
||||
- drm/amdkfd: Fix watch_id bounds checking in debug address watch v2 (CKI Backport Bot) [RHEL-222721] {CVE-2026-45878}
|
||||
- drm/amdkfd: Fix buffer overflow in SDMA queue checkpoint/restore on GFX11 (CKI Backport Bot) [RHEL-222701] {CVE-2026-53143}
|
||||
- drm/amd/display: Clamp VBIOS HDMI retimer register count to array size (CKI Backport Bot) [RHEL-222685] {CVE-2026-53136}
|
||||
- drm/amdgpu: zero-initialize GART table on allocation (CKI Backport Bot) [RHEL-222646] {CVE-2026-53374}
|
||||
- drm/amdgpu: Refactor amdgpu_gem_va_ioctl for Handling Last Fence Update and Timeline Management v7 (CKI Backport Bot) [RHEL-221380] {CVE-2026-43237}
|
||||
- drm/amdgpu: Refactor amdgpu_gem_va_ioctl for Handling Last Fence Update and Timeline Management v4 (CKI Backport Bot) [RHEL-221380] {CVE-2026-43237}
|
||||
- sched/psi: Create the psimon kthread outside of cgroup_mutex (CKI Backport Bot) [RHEL-232560] {CVE-2026-52991}
|
||||
- sched/psi: fix race between file release and pressure write (CKI Backport Bot) [RHEL-232560] {CVE-2026-52991}
|
||||
- scsi: target: Fix hexadecimal CHAP_I handling (CKI Backport Bot) [RHEL-231667] {CVE-2026-63886}
|
||||
- scsi: target: iscsi: Validate CHAP_R length before base64 decode (CKI Backport Bot) [RHEL-231667] {CVE-2026-63886}
|
||||
- memfd: deny writeable mappings when implying SEAL_WRITE (Luiz Capitulino) [RHEL-228531] {CVE-2026-63952}
|
||||
- mm/memfd: fix spelling in memfd_add_seals() (Luiz Capitulino) [RHEL-228531]
|
||||
- vhost: reset the vring metadata cache on vring reconfiguration (CKI Backport Bot) [RHEL-224545]
|
||||
- xfs: fix exchange-range reflink flag clearing issue with INO1_WRITTEN (Lukas Herbolt) [RHEL-223954]
|
||||
Resolves: RHEL-213217, RHEL-221336, RHEL-221380, RHEL-222567, RHEL-222625, RHEL-222646, RHEL-222667, RHEL-222685, RHEL-222701, RHEL-222721, RHEL-222740, RHEL-222753, RHEL-223954, RHEL-224545, RHEL-228531, RHEL-231667, RHEL-232560
|
||||
|
||||
* Wed Aug 12 2026 CKI KWF Bot <cki-ci-bot+kwf-gitlab-com@redhat.com> [6.12.0-211.47.1.el10_2]
|
||||
- scsi: target: iscsi: Bound iscsi_encode_text_output() appends to rsp_buf (Maurizio Lombardi) [RHEL-213198] {CVE-2026-63887}
|
||||
- perf/aux: Fix page UAF in map_range() (CKI Backport Bot) [RHEL-218475] {CVE-2026-64300}
|
||||
- net/sched: act_api: use RCU with deferred freeing for action lifecycle (CKI Backport Bot) [RHEL-218188] {CVE-2026-53264}
|
||||
- KVM: SVM: make svm_flush_tlb_gva do a full asid flush if NPT enabled (Paolo Bonzini) [RHEL-214436]
|
||||
- KVM: x86: hyper-v: Validate all GVAs during PV TLB flush (Paolo Bonzini) [RHEL-214436]
|
||||
- KVM: x86/mmu: Ensure hugepage is in by slot before checking max mapping level (Aidan Wallace) [RHEL-213472] {CVE-2026-63807}
|
||||
- KVM: nVMX: Hide shadow VMCS right after VMCLEAR (Aidan Wallace) [RHEL-213472]
|
||||
- KVM: x86: Check for invalid/obsolete root *after* making MMU pages available (Aidan Wallace) [RHEL-213472]
|
||||
- KVM: nVMX: Put vmcs12 pages if nested VM-Enter fails due to invalid guest state (Aidan Wallace) [RHEL-213472]
|
||||
- accel/ivpu: Fix signed integer truncation in IPC receive (CKI Backport Bot) [RHEL-190054] {CVE-2026-53202}
|
||||
- netfilter: nf_conntrack_expect: store master_tuple in expectation (Florian Westphal) [RHEL-185311]
|
||||
- selftests: netfilter: nft_concat_range.sh: add check for flush+reload bug (Florian Westphal) [RHEL-185311]
|
||||
- selftests: netfilter: nft_concat_range.sh: add check for overlap detection bug (Florian Westphal) [RHEL-185311]
|
||||
- selftests: netfilter: nft_concat_range.sh: add check for double-create bug (Florian Westphal) [RHEL-185311]
|
||||
- netfilter: ctnetlink: use nf_ct_exp_net() in expectation dump (Florian Westphal) [RHEL-185311]
|
||||
- netfilter: nf_dup_netdev: add nf_dev_xmit_recursion*() helpers and use them (Florian Westphal) [RHEL-185311]
|
||||
- netfilter: nft_fib: fix stale stack leak via the OIFNAME register (Florian Westphal) [RHEL-185311]
|
||||
- netfilter: nft_exthdr: fix register tracking for F_PRESENT flag (Florian Westphal) [RHEL-185311]
|
||||
- netfilter: nf_log: validate MAC header was set before dumping it (Florian Westphal) [RHEL-185311]
|
||||
- netfilter: nf_conntrack: destroy stale expectfn expectations on unregister (Florian Westphal) [RHEL-185311]
|
||||
- netfilter: revalidate bridge ports (Florian Westphal) [RHEL-185311]
|
||||
- netfilter: nft_ct: bail out on template ct in get eval (Florian Westphal) [RHEL-185311]
|
||||
- netfilter: nft_tunnel: fix use-after-free on object destroy (Florian Westphal) [RHEL-185311]
|
||||
- netfilter: conntrack_irc: fix possible out-of-bounds read (Florian Westphal) [RHEL-185311]
|
||||
- netfilter: synproxy: add mutex to guard hook reference counting (Florian Westphal) [RHEL-185311]
|
||||
- netfilter: disable payload mangling in userns (Florian Westphal) [RHEL-185311]
|
||||
- netfilter: nf_conntrack_gre: fix gre keymap list corruption (Florian Westphal) [RHEL-185311]
|
||||
- netfilter: synproxy: refresh tcphdr after skb_ensure_writable (Florian Westphal) [RHEL-185311]
|
||||
- netfilter: conntrack: tcp: do not force CLOSE on invalid-seq RST without direction check (Florian Westphal) [RHEL-185311]
|
||||
- netfilter: nf_queue: hold bridge skb->dev while queued (Florian Westphal) [RHEL-185311]
|
||||
- netfilter: br_netfilter: Reallocate headroom if necessary in neigh_hh_bridge() (Florian Westphal) [RHEL-185311]
|
||||
- netfilter: ip6t_hbh: reject oversized option lists (Florian Westphal) [RHEL-185311]
|
||||
- netfilter: nf_conntrack_helper: fix possible null deref during error log (Florian Westphal) [RHEL-185311]
|
||||
- netfilter: nft_ct: fix missing expect put in obj eval (Florian Westphal) [RHEL-185311]
|
||||
- netfilter: nf_conntrack_sip: get helper before allocating expectation (Florian Westphal) [RHEL-185311]
|
||||
- netfilter: ctnetlink: check tuple and mask in expectations created via nfqueue (Florian Westphal) [RHEL-185311]
|
||||
- netfilter: nf_conntrack_expect: restore helper propagation via expectation (Florian Westphal) [RHEL-185311]
|
||||
- netfilter: nf_tables: fix netdev hook allocation memleak with dormant tables (Florian Westphal) [RHEL-185311]
|
||||
- netfilter: xt_CT: fix usersize for v1 and v2 revision (Florian Westphal) [RHEL-185311]
|
||||
- netfilter: nft_compat: run xt_check_hooks_{match,target}() from .validate (Florian Westphal) [RHEL-185311]
|
||||
- netfilter: x_tables: add .check_hooks to matches and targets (Florian Westphal) [RHEL-185311]
|
||||
- netfilter: xtables: restrict several matches to inet family (Florian Westphal) [RHEL-185311]
|
||||
- netfilter: nft_fwd_netdev: use recursion counter in neigh egress path (Florian Westphal) [RHEL-185311]
|
||||
- netfilter: nft_fwd_netdev: add device and headroom validate with neigh forwarding (Florian Westphal) [RHEL-185311]
|
||||
- netfilter: replace skb_try_make_writable() by skb_ensure_writable() (Florian Westphal) [RHEL-185311]
|
||||
- netfilter: nf_conntrack_sip: don't use simple_strtoul (Florian Westphal) [RHEL-185311]
|
||||
- netfilter: xt_policy: fix strict mode inbound policy matching (Florian Westphal) [RHEL-185311]
|
||||
- netfilter: nf_tables: add hook transactions for device deletions (Florian Westphal) [RHEL-185311]
|
||||
- netfilter: nf_tables: join hook list via splice_list_rcu() in commit phase (Florian Westphal) [RHEL-185311]
|
||||
- rculist: add list_splice_rcu() for private lists (Florian Westphal) [RHEL-185311]
|
||||
- netfilter: nf_tables: use list_del_rcu for netlink hooks (Florian Westphal) [RHEL-185311] {CVE-2026-46324}
|
||||
- netfilter: nfnetlink_osf: fix potential NULL dereference in ttl check (Florian Westphal) [RHEL-185311]
|
||||
- netfilter: nfnetlink_osf: fix out-of-bounds read on option matching (Florian Westphal) [RHEL-185311]
|
||||
- netfilter: nat: use kfree_rcu to release ops (Florian Westphal) [RHEL-185311]
|
||||
- netfilter: conntrack: remove sprintf usage (Florian Westphal) [RHEL-185311]
|
||||
- netfilter: nfnetlink_osf: fix divide-by-zero in OSF_WSS_MODULO (Florian Westphal) [RHEL-185311] {CVE-2026-45841}
|
||||
- nfnetlink_osf: validate individual option lengths in fingerprints (Florian Westphal) [RHEL-185311] {CVE-2026-23397}
|
||||
- netfilter: nft_osf: restrict it to ipv4 (Florian Westphal) [RHEL-185311]
|
||||
- netfilter: nft_ct: fix use-after-free in timeout object destroy (Florian Westphal) [RHEL-185311] {CVE-2026-31665}
|
||||
- netfilter: xt_multiport: validate range encoding in checkentry (Florian Westphal) [RHEL-185311] {CVE-2026-31681}
|
||||
- netfilter: nfnetlink_log: initialize nfgenmsg in NLMSG_DONE terminator (Florian Westphal) [RHEL-185311] {CVE-2026-43085}
|
||||
- netfilter: nf_tables: reject immediate NF_QUEUE verdict (Florian Westphal) [RHEL-185311] {CVE-2026-43024}
|
||||
- netfilter: x_tables: restrict xt_check_match/xt_check_target extensions for NFPROTO_ARP (Florian Westphal) [RHEL-185311] {CVE-2026-31424}
|
||||
- netfilter: ctnetlink: ignore explicit helper on new expectations (Florian Westphal) [RHEL-185311] {CVE-2026-43025}
|
||||
- netfilter: ctnetlink: zero expect NAT fields when CTA_EXPECT_NAT absent (Florian Westphal) [RHEL-185311] {CVE-2026-43026}
|
||||
- netfilter: ipset: use nla_strcmp for IPSET_ATTR_NAME attr (Florian Westphal) [RHEL-185311]
|
||||
- netfilter: x_tables: ensure names are nul-terminated (Florian Westphal) [RHEL-185311] {CVE-2026-43028}
|
||||
- netfilter: nfnetlink_log: account for netlink header size (Florian Westphal) [RHEL-185311] {CVE-2026-31416}
|
||||
- netfilter: ctnetlink: use netlink policy range checks (Florian Westphal) [RHEL-185311] {CVE-2026-31495}
|
||||
- netfilter: ip6t_rt: reject oversized addrnr in rt_mt6_check() (Florian Westphal) [RHEL-185311] {CVE-2026-31674}
|
||||
- netfilter: nf_conntrack_expect: store netns and zone in expectation (Florian Westphal) [RHEL-185311]
|
||||
- netfilter: nf_conntrack_expect: use expect->helper (Florian Westphal) [RHEL-185311]
|
||||
- netfilter: nf_conntrack_expect: honor expectation helper field (Florian Westphal) [RHEL-185311]
|
||||
- netfilter: nfnetlink_log: fix uninitialized padding leak in NFULA_PAYLOAD (Florian Westphal) [RHEL-185311] {CVE-2026-31428}
|
||||
- netfilter: nft_set_pipapo_avx2: don't return non-matching entry on expiry (Florian Westphal) [RHEL-185311] {CVE-2026-43114}
|
||||
- nf_tables: nft_dynset: fix possible stateful expression memleak in error path (Florian Westphal) [RHEL-185311] {CVE-2026-23399}
|
||||
- netfilter: nf_conntrack_h323: fix OOB read in decode_int() CONS case (Florian Westphal) [RHEL-185311] {CVE-2026-23456}
|
||||
- netfilter: nf_conntrack_sip: fix Content-Length u32 truncation in sip_help_tcp() (Florian Westphal) [RHEL-185311] {CVE-2026-23457}
|
||||
- netfilter: conntrack: add missing netlink policy validations (Florian Westphal) [RHEL-185311] {CVE-2026-31407}
|
||||
- netfilter: ctnetlink: fix use-after-free in ctnetlink_dump_exp_ct() (Florian Westphal) [RHEL-185311] {CVE-2026-23458}
|
||||
- netfilter: nfnetlink_queue: fix entry leak in bridge verdict error path (Florian Westphal) [RHEL-185311] {CVE-2026-43451}
|
||||
- netfilter: nft_set_pipapo: fix stack out-of-bounds read in pipapo_drop() (Florian Westphal) [RHEL-185311] {CVE-2026-43453}
|
||||
- netfilter: nf_tables: unconditionally bump set->nelems before insertion (Florian Westphal) [RHEL-185311] {CVE-2026-23272}
|
||||
- netfilter: nf_conntrack_h323: fix OOB read in decode_choice() (Florian Westphal) [RHEL-185311] {CVE-2026-43233}
|
||||
- netfilter: nft_set_hash: fix get operation on big endian (Florian Westphal) [RHEL-185311]
|
||||
- netfilter: nf_tables: always walk all pending catchall elements (Florian Westphal) [RHEL-185311] {CVE-2026-23278}
|
||||
- netfilter: nft_set_pipapo: split gc into unlink and reclaim phase (Florian Westphal) [RHEL-185311] {CVE-2026-23351}
|
||||
Resolves: RHEL-185311, RHEL-190054, RHEL-213198, RHEL-213472, RHEL-214436, RHEL-218188, RHEL-218475
|
||||
|
||||
* Mon Aug 10 2026 CKI KWF Bot <cki-ci-bot+kwf-gitlab-com@redhat.com> [6.12.0-211.46.1.el10_2]
|
||||
- mm/slab: do not limit zeroing to orig_size when only red zoning is enabled (Rafael Aquini) [RHEL-223405] {CVE-2026-64368}
|
||||
Resolves: RHEL-223405
|
||||
|
||||
@ -1,2 +1,2 @@
|
||||
sbat,1,SBAT Version,sbat,1,https://github.com/rhboot/shim/blob/main/SBAT.md
|
||||
kernel-uki-virt-addons.almalinux,1,AlmaLinux,kernel-uki-virt-addons,6.12.0-211.47.1.el10.x86_64,mailto:security@almalinux.org
|
||||
kernel-uki-virt-addons.almalinux,1,AlmaLinux,kernel-uki-virt-addons,6.12.0-211.49.1.el10.x86_64,mailto:security@almalinux.org
|
||||
|
||||
2
uki.sbat
2
uki.sbat
@ -1,2 +1,2 @@
|
||||
sbat,1,SBAT Version,sbat,1,https://github.com/rhboot/shim/blob/main/SBAT.md
|
||||
kernel-uki-virt.almalinux,1,AlmaLinux,kernel-uki-virt,6.12.0-211.47.1.el10.x86_64,mailto:security@almalinux.org
|
||||
kernel-uki-virt.almalinux,1,AlmaLinux,kernel-uki-virt,6.12.0-211.49.1.el10.x86_64,mailto:security@almalinux.org
|
||||
|
||||
Loading…
Reference in New Issue
Block a user