mirror of
https://github.com/torvalds/linux.git
synced 2024-11-26 14:12:06 +00:00
cifs: add refcounting to cifs_readdata structures
This isn't strictly necessary for the async readpages code, but the uncached version will need to be able to collect the replies after issuing the calls. Add a kref to cifs_readdata and use change the code to take and put references appropriately. Signed-off-by: Jeff Layton <jlayton@redhat.com>
This commit is contained in:
parent
8d5ce4d23c
commit
6993f74a5b
@ -464,6 +464,7 @@ extern int SMBencrypt(unsigned char *passwd, const unsigned char *c8,
|
|||||||
|
|
||||||
/* asynchronous read support */
|
/* asynchronous read support */
|
||||||
struct cifs_readdata {
|
struct cifs_readdata {
|
||||||
|
struct kref refcount;
|
||||||
struct cifsFileInfo *cfile;
|
struct cifsFileInfo *cfile;
|
||||||
struct address_space *mapping;
|
struct address_space *mapping;
|
||||||
__u64 offset;
|
__u64 offset;
|
||||||
@ -478,6 +479,7 @@ struct cifs_readdata {
|
|||||||
struct kvec iov[1];
|
struct kvec iov[1];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
void cifs_readdata_release(struct kref *refcount);
|
||||||
int cifs_async_readv(struct cifs_readdata *rdata);
|
int cifs_async_readv(struct cifs_readdata *rdata);
|
||||||
|
|
||||||
/* asynchronous write support */
|
/* asynchronous write support */
|
||||||
|
@ -1635,12 +1635,15 @@ cifs_async_readv(struct cifs_readdata *rdata)
|
|||||||
rdata->iov[0].iov_base = smb;
|
rdata->iov[0].iov_base = smb;
|
||||||
rdata->iov[0].iov_len = be32_to_cpu(smb->hdr.smb_buf_length) + 4;
|
rdata->iov[0].iov_len = be32_to_cpu(smb->hdr.smb_buf_length) + 4;
|
||||||
|
|
||||||
|
kref_get(&rdata->refcount);
|
||||||
rc = cifs_call_async(tcon->ses->server, rdata->iov, 1,
|
rc = cifs_call_async(tcon->ses->server, rdata->iov, 1,
|
||||||
cifs_readv_receive, cifs_readv_callback,
|
cifs_readv_receive, cifs_readv_callback,
|
||||||
rdata, false);
|
rdata, false);
|
||||||
|
|
||||||
if (rc == 0)
|
if (rc == 0)
|
||||||
cifs_stats_inc(&tcon->num_reads);
|
cifs_stats_inc(&tcon->num_reads);
|
||||||
|
else
|
||||||
|
kref_put(&rdata->refcount, cifs_readdata_release);
|
||||||
|
|
||||||
cifs_small_buf_release(smb);
|
cifs_small_buf_release(smb);
|
||||||
return rc;
|
return rc;
|
||||||
|
@ -2347,16 +2347,22 @@ cifs_readdata_alloc(unsigned int nr_vecs, work_func_t complete)
|
|||||||
rdata = kzalloc(sizeof(*rdata) +
|
rdata = kzalloc(sizeof(*rdata) +
|
||||||
sizeof(struct kvec) * nr_vecs, GFP_KERNEL);
|
sizeof(struct kvec) * nr_vecs, GFP_KERNEL);
|
||||||
if (rdata != NULL) {
|
if (rdata != NULL) {
|
||||||
|
kref_init(&rdata->refcount);
|
||||||
INIT_WORK(&rdata->work, complete);
|
INIT_WORK(&rdata->work, complete);
|
||||||
INIT_LIST_HEAD(&rdata->pages);
|
INIT_LIST_HEAD(&rdata->pages);
|
||||||
}
|
}
|
||||||
return rdata;
|
return rdata;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
void
|
||||||
cifs_readdata_free(struct cifs_readdata *rdata)
|
cifs_readdata_release(struct kref *refcount)
|
||||||
{
|
{
|
||||||
cifsFileInfo_put(rdata->cfile);
|
struct cifs_readdata *rdata = container_of(refcount,
|
||||||
|
struct cifs_readdata, refcount);
|
||||||
|
|
||||||
|
if (rdata->cfile)
|
||||||
|
cifsFileInfo_put(rdata->cfile);
|
||||||
|
|
||||||
kfree(rdata);
|
kfree(rdata);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2651,7 +2657,7 @@ cifs_readv_complete(struct work_struct *work)
|
|||||||
|
|
||||||
page_cache_release(page);
|
page_cache_release(page);
|
||||||
}
|
}
|
||||||
cifs_readdata_free(rdata);
|
kref_put(&rdata->refcount, cifs_readdata_release);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
@ -2837,9 +2843,8 @@ static int cifs_readpages(struct file *file, struct address_space *mapping,
|
|||||||
}
|
}
|
||||||
|
|
||||||
spin_lock(&cifs_file_list_lock);
|
spin_lock(&cifs_file_list_lock);
|
||||||
cifsFileInfo_get(open_file);
|
|
||||||
spin_unlock(&cifs_file_list_lock);
|
spin_unlock(&cifs_file_list_lock);
|
||||||
rdata->cfile = open_file;
|
rdata->cfile = cifsFileInfo_get(open_file);
|
||||||
rdata->mapping = mapping;
|
rdata->mapping = mapping;
|
||||||
rdata->offset = offset;
|
rdata->offset = offset;
|
||||||
rdata->bytes = bytes;
|
rdata->bytes = bytes;
|
||||||
@ -2864,9 +2869,11 @@ static int cifs_readpages(struct file *file, struct address_space *mapping,
|
|||||||
unlock_page(page);
|
unlock_page(page);
|
||||||
page_cache_release(page);
|
page_cache_release(page);
|
||||||
}
|
}
|
||||||
cifs_readdata_free(rdata);
|
kref_put(&rdata->refcount, cifs_readdata_release);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
kref_put(&rdata->refcount, cifs_readdata_release);
|
||||||
}
|
}
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
|
Loading…
Reference in New Issue
Block a user