Skip to content

Commit

Permalink
cifs: add refcounting to cifs_readdata structures
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Jeff Layton authored and Steve French committed May 17, 2012
1 parent 8d5ce4d commit 6993f74
Show file tree
Hide file tree
Showing 3 changed files with 19 additions and 7 deletions.
2 changes: 2 additions & 0 deletions fs/cifs/cifsproto.h
Original file line number Diff line number Diff line change
Expand Up @@ -464,6 +464,7 @@ extern int SMBencrypt(unsigned char *passwd, const unsigned char *c8,

/* asynchronous read support */
struct cifs_readdata {
struct kref refcount;
struct cifsFileInfo *cfile;
struct address_space *mapping;
__u64 offset;
Expand All @@ -478,6 +479,7 @@ struct cifs_readdata {
struct kvec iov[1];
};

void cifs_readdata_release(struct kref *refcount);
int cifs_async_readv(struct cifs_readdata *rdata);

/* asynchronous write support */
Expand Down
3 changes: 3 additions & 0 deletions fs/cifs/cifssmb.c
Original file line number Diff line number Diff line change
Expand Up @@ -1635,12 +1635,15 @@ cifs_async_readv(struct cifs_readdata *rdata)
rdata->iov[0].iov_base = smb;
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,
cifs_readv_receive, cifs_readv_callback,
rdata, false);

if (rc == 0)
cifs_stats_inc(&tcon->num_reads);
else
kref_put(&rdata->refcount, cifs_readdata_release);

cifs_small_buf_release(smb);
return rc;
Expand Down
21 changes: 14 additions & 7 deletions fs/cifs/file.c
Original file line number Diff line number Diff line change
Expand Up @@ -2347,16 +2347,22 @@ cifs_readdata_alloc(unsigned int nr_vecs, work_func_t complete)
rdata = kzalloc(sizeof(*rdata) +
sizeof(struct kvec) * nr_vecs, GFP_KERNEL);
if (rdata != NULL) {
kref_init(&rdata->refcount);
INIT_WORK(&rdata->work, complete);
INIT_LIST_HEAD(&rdata->pages);
}
return rdata;
}

static void
cifs_readdata_free(struct cifs_readdata *rdata)
void
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);
}

Expand Down Expand Up @@ -2651,7 +2657,7 @@ cifs_readv_complete(struct work_struct *work)

page_cache_release(page);
}
cifs_readdata_free(rdata);
kref_put(&rdata->refcount, cifs_readdata_release);
}

static int
Expand Down Expand Up @@ -2837,9 +2843,8 @@ static int cifs_readpages(struct file *file, struct address_space *mapping,
}

spin_lock(&cifs_file_list_lock);
cifsFileInfo_get(open_file);
spin_unlock(&cifs_file_list_lock);
rdata->cfile = open_file;
rdata->cfile = cifsFileInfo_get(open_file);
rdata->mapping = mapping;
rdata->offset = offset;
rdata->bytes = bytes;
Expand All @@ -2864,9 +2869,11 @@ static int cifs_readpages(struct file *file, struct address_space *mapping,
unlock_page(page);
page_cache_release(page);
}
cifs_readdata_free(rdata);
kref_put(&rdata->refcount, cifs_readdata_release);
break;
}

kref_put(&rdata->refcount, cifs_readdata_release);
}

return rc;
Expand Down

0 comments on commit 6993f74

Please sign in to comment.