mirror of https://gitee.com/openkylin/linux.git
NFSv4: Ensure that we track the NFSv4 lock state in read/write requests.
This patch fixes bugzilla entry 14501: https://bugzilla.kernel.org/show_bug.cgi?id=14501 Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
This commit is contained in:
parent
1f0e890dba
commit
f11ac8db5d
|
@ -69,6 +69,7 @@ struct nfs_direct_req {
|
||||||
|
|
||||||
/* I/O parameters */
|
/* I/O parameters */
|
||||||
struct nfs_open_context *ctx; /* file open context info */
|
struct nfs_open_context *ctx; /* file open context info */
|
||||||
|
struct nfs_lock_context *l_ctx; /* Lock context info */
|
||||||
struct kiocb * iocb; /* controlling i/o request */
|
struct kiocb * iocb; /* controlling i/o request */
|
||||||
struct inode * inode; /* target file of i/o */
|
struct inode * inode; /* target file of i/o */
|
||||||
|
|
||||||
|
@ -160,6 +161,7 @@ static inline struct nfs_direct_req *nfs_direct_req_alloc(void)
|
||||||
INIT_LIST_HEAD(&dreq->rewrite_list);
|
INIT_LIST_HEAD(&dreq->rewrite_list);
|
||||||
dreq->iocb = NULL;
|
dreq->iocb = NULL;
|
||||||
dreq->ctx = NULL;
|
dreq->ctx = NULL;
|
||||||
|
dreq->l_ctx = NULL;
|
||||||
spin_lock_init(&dreq->lock);
|
spin_lock_init(&dreq->lock);
|
||||||
atomic_set(&dreq->io_count, 0);
|
atomic_set(&dreq->io_count, 0);
|
||||||
dreq->count = 0;
|
dreq->count = 0;
|
||||||
|
@ -173,6 +175,8 @@ static void nfs_direct_req_free(struct kref *kref)
|
||||||
{
|
{
|
||||||
struct nfs_direct_req *dreq = container_of(kref, struct nfs_direct_req, kref);
|
struct nfs_direct_req *dreq = container_of(kref, struct nfs_direct_req, kref);
|
||||||
|
|
||||||
|
if (dreq->l_ctx != NULL)
|
||||||
|
nfs_put_lock_context(dreq->l_ctx);
|
||||||
if (dreq->ctx != NULL)
|
if (dreq->ctx != NULL)
|
||||||
put_nfs_open_context(dreq->ctx);
|
put_nfs_open_context(dreq->ctx);
|
||||||
kmem_cache_free(nfs_direct_cachep, dreq);
|
kmem_cache_free(nfs_direct_cachep, dreq);
|
||||||
|
@ -336,6 +340,7 @@ static ssize_t nfs_direct_read_schedule_segment(struct nfs_direct_req *dreq,
|
||||||
data->cred = msg.rpc_cred;
|
data->cred = msg.rpc_cred;
|
||||||
data->args.fh = NFS_FH(inode);
|
data->args.fh = NFS_FH(inode);
|
||||||
data->args.context = ctx;
|
data->args.context = ctx;
|
||||||
|
data->args.lock_context = dreq->l_ctx;
|
||||||
data->args.offset = pos;
|
data->args.offset = pos;
|
||||||
data->args.pgbase = pgbase;
|
data->args.pgbase = pgbase;
|
||||||
data->args.pages = data->pagevec;
|
data->args.pages = data->pagevec;
|
||||||
|
@ -416,24 +421,28 @@ static ssize_t nfs_direct_read_schedule_iovec(struct nfs_direct_req *dreq,
|
||||||
static ssize_t nfs_direct_read(struct kiocb *iocb, const struct iovec *iov,
|
static ssize_t nfs_direct_read(struct kiocb *iocb, const struct iovec *iov,
|
||||||
unsigned long nr_segs, loff_t pos)
|
unsigned long nr_segs, loff_t pos)
|
||||||
{
|
{
|
||||||
ssize_t result = 0;
|
ssize_t result = -ENOMEM;
|
||||||
struct inode *inode = iocb->ki_filp->f_mapping->host;
|
struct inode *inode = iocb->ki_filp->f_mapping->host;
|
||||||
struct nfs_direct_req *dreq;
|
struct nfs_direct_req *dreq;
|
||||||
|
|
||||||
dreq = nfs_direct_req_alloc();
|
dreq = nfs_direct_req_alloc();
|
||||||
if (!dreq)
|
if (dreq == NULL)
|
||||||
return -ENOMEM;
|
goto out;
|
||||||
|
|
||||||
dreq->inode = inode;
|
dreq->inode = inode;
|
||||||
dreq->ctx = get_nfs_open_context(nfs_file_open_context(iocb->ki_filp));
|
dreq->ctx = get_nfs_open_context(nfs_file_open_context(iocb->ki_filp));
|
||||||
|
dreq->l_ctx = nfs_get_lock_context(dreq->ctx);
|
||||||
|
if (dreq->l_ctx == NULL)
|
||||||
|
goto out_release;
|
||||||
if (!is_sync_kiocb(iocb))
|
if (!is_sync_kiocb(iocb))
|
||||||
dreq->iocb = iocb;
|
dreq->iocb = iocb;
|
||||||
|
|
||||||
result = nfs_direct_read_schedule_iovec(dreq, iov, nr_segs, pos);
|
result = nfs_direct_read_schedule_iovec(dreq, iov, nr_segs, pos);
|
||||||
if (!result)
|
if (!result)
|
||||||
result = nfs_direct_wait(dreq);
|
result = nfs_direct_wait(dreq);
|
||||||
|
out_release:
|
||||||
nfs_direct_req_release(dreq);
|
nfs_direct_req_release(dreq);
|
||||||
|
out:
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -574,6 +583,7 @@ static void nfs_direct_commit_schedule(struct nfs_direct_req *dreq)
|
||||||
data->args.offset = 0;
|
data->args.offset = 0;
|
||||||
data->args.count = 0;
|
data->args.count = 0;
|
||||||
data->args.context = dreq->ctx;
|
data->args.context = dreq->ctx;
|
||||||
|
data->args.lock_context = dreq->l_ctx;
|
||||||
data->res.count = 0;
|
data->res.count = 0;
|
||||||
data->res.fattr = &data->fattr;
|
data->res.fattr = &data->fattr;
|
||||||
data->res.verf = &data->verf;
|
data->res.verf = &data->verf;
|
||||||
|
@ -761,6 +771,7 @@ static ssize_t nfs_direct_write_schedule_segment(struct nfs_direct_req *dreq,
|
||||||
data->cred = msg.rpc_cred;
|
data->cred = msg.rpc_cred;
|
||||||
data->args.fh = NFS_FH(inode);
|
data->args.fh = NFS_FH(inode);
|
||||||
data->args.context = ctx;
|
data->args.context = ctx;
|
||||||
|
data->args.lock_context = dreq->l_ctx;
|
||||||
data->args.offset = pos;
|
data->args.offset = pos;
|
||||||
data->args.pgbase = pgbase;
|
data->args.pgbase = pgbase;
|
||||||
data->args.pages = data->pagevec;
|
data->args.pages = data->pagevec;
|
||||||
|
@ -845,7 +856,7 @@ static ssize_t nfs_direct_write(struct kiocb *iocb, const struct iovec *iov,
|
||||||
unsigned long nr_segs, loff_t pos,
|
unsigned long nr_segs, loff_t pos,
|
||||||
size_t count)
|
size_t count)
|
||||||
{
|
{
|
||||||
ssize_t result = 0;
|
ssize_t result = -ENOMEM;
|
||||||
struct inode *inode = iocb->ki_filp->f_mapping->host;
|
struct inode *inode = iocb->ki_filp->f_mapping->host;
|
||||||
struct nfs_direct_req *dreq;
|
struct nfs_direct_req *dreq;
|
||||||
size_t wsize = NFS_SERVER(inode)->wsize;
|
size_t wsize = NFS_SERVER(inode)->wsize;
|
||||||
|
@ -853,7 +864,7 @@ static ssize_t nfs_direct_write(struct kiocb *iocb, const struct iovec *iov,
|
||||||
|
|
||||||
dreq = nfs_direct_req_alloc();
|
dreq = nfs_direct_req_alloc();
|
||||||
if (!dreq)
|
if (!dreq)
|
||||||
return -ENOMEM;
|
goto out;
|
||||||
nfs_alloc_commit_data(dreq);
|
nfs_alloc_commit_data(dreq);
|
||||||
|
|
||||||
if (dreq->commit_data == NULL || count < wsize)
|
if (dreq->commit_data == NULL || count < wsize)
|
||||||
|
@ -861,14 +872,18 @@ static ssize_t nfs_direct_write(struct kiocb *iocb, const struct iovec *iov,
|
||||||
|
|
||||||
dreq->inode = inode;
|
dreq->inode = inode;
|
||||||
dreq->ctx = get_nfs_open_context(nfs_file_open_context(iocb->ki_filp));
|
dreq->ctx = get_nfs_open_context(nfs_file_open_context(iocb->ki_filp));
|
||||||
|
dreq->l_ctx = nfs_get_lock_context(dreq->ctx);
|
||||||
|
if (dreq->l_ctx != NULL)
|
||||||
|
goto out_release;
|
||||||
if (!is_sync_kiocb(iocb))
|
if (!is_sync_kiocb(iocb))
|
||||||
dreq->iocb = iocb;
|
dreq->iocb = iocb;
|
||||||
|
|
||||||
result = nfs_direct_write_schedule_iovec(dreq, iov, nr_segs, pos, sync);
|
result = nfs_direct_write_schedule_iovec(dreq, iov, nr_segs, pos, sync);
|
||||||
if (!result)
|
if (!result)
|
||||||
result = nfs_direct_wait(dreq);
|
result = nfs_direct_wait(dreq);
|
||||||
|
out_release:
|
||||||
nfs_direct_req_release(dreq);
|
nfs_direct_req_release(dreq);
|
||||||
|
out:
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -530,6 +530,68 @@ int nfs_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat)
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void nfs_init_lock_context(struct nfs_lock_context *l_ctx)
|
||||||
|
{
|
||||||
|
atomic_set(&l_ctx->count, 1);
|
||||||
|
l_ctx->lockowner = current->files;
|
||||||
|
l_ctx->pid = current->tgid;
|
||||||
|
INIT_LIST_HEAD(&l_ctx->list);
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct nfs_lock_context *__nfs_find_lock_context(struct nfs_open_context *ctx)
|
||||||
|
{
|
||||||
|
struct nfs_lock_context *pos;
|
||||||
|
|
||||||
|
list_for_each_entry(pos, &ctx->lock_context.list, list) {
|
||||||
|
if (pos->lockowner != current->files)
|
||||||
|
continue;
|
||||||
|
if (pos->pid != current->tgid)
|
||||||
|
continue;
|
||||||
|
atomic_inc(&pos->count);
|
||||||
|
return pos;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct nfs_lock_context *nfs_get_lock_context(struct nfs_open_context *ctx)
|
||||||
|
{
|
||||||
|
struct nfs_lock_context *res, *new = NULL;
|
||||||
|
struct inode *inode = ctx->path.dentry->d_inode;
|
||||||
|
|
||||||
|
spin_lock(&inode->i_lock);
|
||||||
|
res = __nfs_find_lock_context(ctx);
|
||||||
|
if (res == NULL) {
|
||||||
|
spin_unlock(&inode->i_lock);
|
||||||
|
new = kmalloc(sizeof(*new), GFP_KERNEL);
|
||||||
|
if (new == NULL)
|
||||||
|
return NULL;
|
||||||
|
nfs_init_lock_context(new);
|
||||||
|
spin_lock(&inode->i_lock);
|
||||||
|
res = __nfs_find_lock_context(ctx);
|
||||||
|
if (res == NULL) {
|
||||||
|
list_add_tail(&new->list, &ctx->lock_context.list);
|
||||||
|
new->open_context = ctx;
|
||||||
|
res = new;
|
||||||
|
new = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
spin_unlock(&inode->i_lock);
|
||||||
|
kfree(new);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
void nfs_put_lock_context(struct nfs_lock_context *l_ctx)
|
||||||
|
{
|
||||||
|
struct nfs_open_context *ctx = l_ctx->open_context;
|
||||||
|
struct inode *inode = ctx->path.dentry->d_inode;
|
||||||
|
|
||||||
|
if (!atomic_dec_and_lock(&l_ctx->count, &inode->i_lock))
|
||||||
|
return;
|
||||||
|
list_del(&l_ctx->list);
|
||||||
|
spin_unlock(&inode->i_lock);
|
||||||
|
kfree(l_ctx);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* nfs_close_context - Common close_context() routine NFSv2/v3
|
* nfs_close_context - Common close_context() routine NFSv2/v3
|
||||||
* @ctx: pointer to context
|
* @ctx: pointer to context
|
||||||
|
@ -566,11 +628,11 @@ static struct nfs_open_context *alloc_nfs_open_context(struct path *path, struct
|
||||||
path_get(&ctx->path);
|
path_get(&ctx->path);
|
||||||
ctx->cred = get_rpccred(cred);
|
ctx->cred = get_rpccred(cred);
|
||||||
ctx->state = NULL;
|
ctx->state = NULL;
|
||||||
ctx->lockowner = current->files;
|
|
||||||
ctx->flags = 0;
|
ctx->flags = 0;
|
||||||
ctx->error = 0;
|
ctx->error = 0;
|
||||||
ctx->dir_cookie = 0;
|
ctx->dir_cookie = 0;
|
||||||
atomic_set(&ctx->count, 1);
|
nfs_init_lock_context(&ctx->lock_context);
|
||||||
|
ctx->lock_context.open_context = ctx;
|
||||||
}
|
}
|
||||||
return ctx;
|
return ctx;
|
||||||
}
|
}
|
||||||
|
@ -578,7 +640,7 @@ static struct nfs_open_context *alloc_nfs_open_context(struct path *path, struct
|
||||||
struct nfs_open_context *get_nfs_open_context(struct nfs_open_context *ctx)
|
struct nfs_open_context *get_nfs_open_context(struct nfs_open_context *ctx)
|
||||||
{
|
{
|
||||||
if (ctx != NULL)
|
if (ctx != NULL)
|
||||||
atomic_inc(&ctx->count);
|
atomic_inc(&ctx->lock_context.count);
|
||||||
return ctx;
|
return ctx;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -586,7 +648,7 @@ static void __put_nfs_open_context(struct nfs_open_context *ctx, int is_sync)
|
||||||
{
|
{
|
||||||
struct inode *inode = ctx->path.dentry->d_inode;
|
struct inode *inode = ctx->path.dentry->d_inode;
|
||||||
|
|
||||||
if (!atomic_dec_and_lock(&ctx->count, &inode->i_lock))
|
if (!atomic_dec_and_lock(&ctx->lock_context.count, &inode->i_lock))
|
||||||
return;
|
return;
|
||||||
list_del(&ctx->list);
|
list_del(&ctx->list);
|
||||||
spin_unlock(&inode->i_lock);
|
spin_unlock(&inode->i_lock);
|
||||||
|
|
|
@ -1324,14 +1324,14 @@ static void encode_putrootfh(struct xdr_stream *xdr, struct compound_hdr *hdr)
|
||||||
hdr->replen += decode_putrootfh_maxsz;
|
hdr->replen += decode_putrootfh_maxsz;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void encode_stateid(struct xdr_stream *xdr, const struct nfs_open_context *ctx)
|
static void encode_stateid(struct xdr_stream *xdr, const struct nfs_open_context *ctx, const struct nfs_lock_context *l_ctx)
|
||||||
{
|
{
|
||||||
nfs4_stateid stateid;
|
nfs4_stateid stateid;
|
||||||
__be32 *p;
|
__be32 *p;
|
||||||
|
|
||||||
p = reserve_space(xdr, NFS4_STATEID_SIZE);
|
p = reserve_space(xdr, NFS4_STATEID_SIZE);
|
||||||
if (ctx->state != NULL) {
|
if (ctx->state != NULL) {
|
||||||
nfs4_copy_stateid(&stateid, ctx->state, ctx->lockowner);
|
nfs4_copy_stateid(&stateid, ctx->state, l_ctx->lockowner);
|
||||||
xdr_encode_opaque_fixed(p, stateid.data, NFS4_STATEID_SIZE);
|
xdr_encode_opaque_fixed(p, stateid.data, NFS4_STATEID_SIZE);
|
||||||
} else
|
} else
|
||||||
xdr_encode_opaque_fixed(p, zero_stateid.data, NFS4_STATEID_SIZE);
|
xdr_encode_opaque_fixed(p, zero_stateid.data, NFS4_STATEID_SIZE);
|
||||||
|
@ -1344,7 +1344,7 @@ static void encode_read(struct xdr_stream *xdr, const struct nfs_readargs *args,
|
||||||
p = reserve_space(xdr, 4);
|
p = reserve_space(xdr, 4);
|
||||||
*p = cpu_to_be32(OP_READ);
|
*p = cpu_to_be32(OP_READ);
|
||||||
|
|
||||||
encode_stateid(xdr, args->context);
|
encode_stateid(xdr, args->context, args->lock_context);
|
||||||
|
|
||||||
p = reserve_space(xdr, 12);
|
p = reserve_space(xdr, 12);
|
||||||
p = xdr_encode_hyper(p, args->offset);
|
p = xdr_encode_hyper(p, args->offset);
|
||||||
|
@ -1523,7 +1523,7 @@ static void encode_write(struct xdr_stream *xdr, const struct nfs_writeargs *arg
|
||||||
p = reserve_space(xdr, 4);
|
p = reserve_space(xdr, 4);
|
||||||
*p = cpu_to_be32(OP_WRITE);
|
*p = cpu_to_be32(OP_WRITE);
|
||||||
|
|
||||||
encode_stateid(xdr, args->context);
|
encode_stateid(xdr, args->context, args->lock_context);
|
||||||
|
|
||||||
p = reserve_space(xdr, 16);
|
p = reserve_space(xdr, 16);
|
||||||
p = xdr_encode_hyper(p, args->offset);
|
p = xdr_encode_hyper(p, args->offset);
|
||||||
|
|
|
@ -79,6 +79,7 @@ nfs_create_request(struct nfs_open_context *ctx, struct inode *inode,
|
||||||
req->wb_pgbase = offset;
|
req->wb_pgbase = offset;
|
||||||
req->wb_bytes = count;
|
req->wb_bytes = count;
|
||||||
req->wb_context = get_nfs_open_context(ctx);
|
req->wb_context = get_nfs_open_context(ctx);
|
||||||
|
req->wb_lock_context = nfs_get_lock_context(ctx);
|
||||||
kref_init(&req->wb_kref);
|
kref_init(&req->wb_kref);
|
||||||
return req;
|
return req;
|
||||||
}
|
}
|
||||||
|
@ -141,11 +142,16 @@ void nfs_clear_request(struct nfs_page *req)
|
||||||
{
|
{
|
||||||
struct page *page = req->wb_page;
|
struct page *page = req->wb_page;
|
||||||
struct nfs_open_context *ctx = req->wb_context;
|
struct nfs_open_context *ctx = req->wb_context;
|
||||||
|
struct nfs_lock_context *l_ctx = req->wb_lock_context;
|
||||||
|
|
||||||
if (page != NULL) {
|
if (page != NULL) {
|
||||||
page_cache_release(page);
|
page_cache_release(page);
|
||||||
req->wb_page = NULL;
|
req->wb_page = NULL;
|
||||||
}
|
}
|
||||||
|
if (l_ctx != NULL) {
|
||||||
|
nfs_put_lock_context(l_ctx);
|
||||||
|
req->wb_lock_context = NULL;
|
||||||
|
}
|
||||||
if (ctx != NULL) {
|
if (ctx != NULL) {
|
||||||
put_nfs_open_context(ctx);
|
put_nfs_open_context(ctx);
|
||||||
req->wb_context = NULL;
|
req->wb_context = NULL;
|
||||||
|
@ -235,7 +241,7 @@ static int nfs_can_coalesce_requests(struct nfs_page *prev,
|
||||||
{
|
{
|
||||||
if (req->wb_context->cred != prev->wb_context->cred)
|
if (req->wb_context->cred != prev->wb_context->cred)
|
||||||
return 0;
|
return 0;
|
||||||
if (req->wb_context->lockowner != prev->wb_context->lockowner)
|
if (req->wb_lock_context->lockowner != prev->wb_lock_context->lockowner)
|
||||||
return 0;
|
return 0;
|
||||||
if (req->wb_context->state != prev->wb_context->state)
|
if (req->wb_context->state != prev->wb_context->state)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -190,6 +190,7 @@ static int nfs_read_rpcsetup(struct nfs_page *req, struct nfs_read_data *data,
|
||||||
data->args.pages = data->pagevec;
|
data->args.pages = data->pagevec;
|
||||||
data->args.count = count;
|
data->args.count = count;
|
||||||
data->args.context = get_nfs_open_context(req->wb_context);
|
data->args.context = get_nfs_open_context(req->wb_context);
|
||||||
|
data->args.lock_context = req->wb_lock_context;
|
||||||
|
|
||||||
data->res.fattr = &data->fattr;
|
data->res.fattr = &data->fattr;
|
||||||
data->res.count = count;
|
data->res.count = count;
|
||||||
|
|
|
@ -689,7 +689,9 @@ int nfs_flush_incompatible(struct file *file, struct page *page)
|
||||||
req = nfs_page_find_request(page);
|
req = nfs_page_find_request(page);
|
||||||
if (req == NULL)
|
if (req == NULL)
|
||||||
return 0;
|
return 0;
|
||||||
do_flush = req->wb_page != page || req->wb_context != ctx;
|
do_flush = req->wb_page != page || req->wb_context != ctx ||
|
||||||
|
req->wb_lock_context->lockowner != current->files ||
|
||||||
|
req->wb_lock_context->pid != current->tgid;
|
||||||
nfs_release_request(req);
|
nfs_release_request(req);
|
||||||
if (!do_flush)
|
if (!do_flush)
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -813,6 +815,7 @@ static int nfs_write_rpcsetup(struct nfs_page *req,
|
||||||
data->args.pages = data->pagevec;
|
data->args.pages = data->pagevec;
|
||||||
data->args.count = count;
|
data->args.count = count;
|
||||||
data->args.context = get_nfs_open_context(req->wb_context);
|
data->args.context = get_nfs_open_context(req->wb_context);
|
||||||
|
data->args.lock_context = req->wb_lock_context;
|
||||||
data->args.stable = NFS_UNSTABLE;
|
data->args.stable = NFS_UNSTABLE;
|
||||||
if (how & FLUSH_STABLE) {
|
if (how & FLUSH_STABLE) {
|
||||||
data->args.stable = NFS_DATA_SYNC;
|
data->args.stable = NFS_DATA_SYNC;
|
||||||
|
|
|
@ -72,13 +72,20 @@ struct nfs_access_entry {
|
||||||
int mask;
|
int mask;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct nfs_lock_context {
|
||||||
|
atomic_t count;
|
||||||
|
struct list_head list;
|
||||||
|
struct nfs_open_context *open_context;
|
||||||
|
fl_owner_t lockowner;
|
||||||
|
pid_t pid;
|
||||||
|
};
|
||||||
|
|
||||||
struct nfs4_state;
|
struct nfs4_state;
|
||||||
struct nfs_open_context {
|
struct nfs_open_context {
|
||||||
atomic_t count;
|
struct nfs_lock_context lock_context;
|
||||||
struct path path;
|
struct path path;
|
||||||
struct rpc_cred *cred;
|
struct rpc_cred *cred;
|
||||||
struct nfs4_state *state;
|
struct nfs4_state *state;
|
||||||
fl_owner_t lockowner;
|
|
||||||
fmode_t mode;
|
fmode_t mode;
|
||||||
|
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
@ -353,6 +360,8 @@ extern void nfs_setattr_update_inode(struct inode *inode, struct iattr *attr);
|
||||||
extern struct nfs_open_context *get_nfs_open_context(struct nfs_open_context *ctx);
|
extern struct nfs_open_context *get_nfs_open_context(struct nfs_open_context *ctx);
|
||||||
extern void put_nfs_open_context(struct nfs_open_context *ctx);
|
extern void put_nfs_open_context(struct nfs_open_context *ctx);
|
||||||
extern struct nfs_open_context *nfs_find_open_context(struct inode *inode, struct rpc_cred *cred, fmode_t mode);
|
extern struct nfs_open_context *nfs_find_open_context(struct inode *inode, struct rpc_cred *cred, fmode_t mode);
|
||||||
|
extern struct nfs_lock_context *nfs_get_lock_context(struct nfs_open_context *ctx);
|
||||||
|
extern void nfs_put_lock_context(struct nfs_lock_context *l_ctx);
|
||||||
extern u64 nfs_compat_user_ino64(u64 fileid);
|
extern u64 nfs_compat_user_ino64(u64 fileid);
|
||||||
extern void nfs_fattr_init(struct nfs_fattr *fattr);
|
extern void nfs_fattr_init(struct nfs_fattr *fattr);
|
||||||
|
|
||||||
|
|
|
@ -39,6 +39,7 @@ struct nfs_page {
|
||||||
struct list_head wb_list; /* Defines state of page: */
|
struct list_head wb_list; /* Defines state of page: */
|
||||||
struct page *wb_page; /* page to read in/write out */
|
struct page *wb_page; /* page to read in/write out */
|
||||||
struct nfs_open_context *wb_context; /* File state context info */
|
struct nfs_open_context *wb_context; /* File state context info */
|
||||||
|
struct nfs_lock_context *wb_lock_context; /* lock context info */
|
||||||
atomic_t wb_complete; /* i/os we're waiting for */
|
atomic_t wb_complete; /* i/os we're waiting for */
|
||||||
pgoff_t wb_index; /* Offset >> PAGE_CACHE_SHIFT */
|
pgoff_t wb_index; /* Offset >> PAGE_CACHE_SHIFT */
|
||||||
unsigned int wb_offset, /* Offset & ~PAGE_CACHE_MASK */
|
unsigned int wb_offset, /* Offset & ~PAGE_CACHE_MASK */
|
||||||
|
|
|
@ -334,6 +334,7 @@ struct nfs4_delegreturnres {
|
||||||
struct nfs_readargs {
|
struct nfs_readargs {
|
||||||
struct nfs_fh * fh;
|
struct nfs_fh * fh;
|
||||||
struct nfs_open_context *context;
|
struct nfs_open_context *context;
|
||||||
|
struct nfs_lock_context *lock_context;
|
||||||
__u64 offset;
|
__u64 offset;
|
||||||
__u32 count;
|
__u32 count;
|
||||||
unsigned int pgbase;
|
unsigned int pgbase;
|
||||||
|
@ -354,6 +355,7 @@ struct nfs_readres {
|
||||||
struct nfs_writeargs {
|
struct nfs_writeargs {
|
||||||
struct nfs_fh * fh;
|
struct nfs_fh * fh;
|
||||||
struct nfs_open_context *context;
|
struct nfs_open_context *context;
|
||||||
|
struct nfs_lock_context *lock_context;
|
||||||
__u64 offset;
|
__u64 offset;
|
||||||
__u32 count;
|
__u32 count;
|
||||||
enum nfs3_stable_how stable;
|
enum nfs3_stable_how stable;
|
||||||
|
|
Loading…
Reference in New Issue