Commit 14c43f76 authored by David Quigley's avatar David Quigley Committed by Trond Myklebust

NFS: Add label lifecycle management

This patch adds the lifecycle management for the security label structure
introduced in an earlier patch. The label is not used yet but allocations and
freeing of the structure is handled.
Signed-off-by: default avatarMatthew N. Dodd <Matthew.Dodd@sparta.com>
Signed-off-by: default avatarMiguel Rodel Felipe <Rodel_FM@dsi.a-star.edu.sg>
Signed-off-by: default avatarPhua Eu Gene <PHUA_Eu_Gene@dsi.a-star.edu.sg>
Signed-off-by: default avatarKhin Mi Mi Aung <Mi_Mi_AUNG@dsi.a-star.edu.sg>
Signed-off-by: default avatarSteve Dickson <steved@redhat.com>
Signed-off-by: default avatarTrond Myklebust <Trond.Myklebust@netapp.com>
parent 1775fd3e
...@@ -585,10 +585,16 @@ int nfs_readdir_xdr_to_array(nfs_readdir_descriptor_t *desc, struct page *page, ...@@ -585,10 +585,16 @@ int nfs_readdir_xdr_to_array(nfs_readdir_descriptor_t *desc, struct page *page,
if (entry.fh == NULL || entry.fattr == NULL) if (entry.fh == NULL || entry.fattr == NULL)
goto out; goto out;
entry.label = nfs4_label_alloc(NFS_SERVER(inode), GFP_NOWAIT);
if (IS_ERR(entry.label)) {
status = PTR_ERR(entry.label);
goto out;
}
array = nfs_readdir_get_array(page); array = nfs_readdir_get_array(page);
if (IS_ERR(array)) { if (IS_ERR(array)) {
status = PTR_ERR(array); status = PTR_ERR(array);
goto out; goto out_label_free;
} }
memset(array, 0, sizeof(struct nfs_cache_array)); memset(array, 0, sizeof(struct nfs_cache_array));
array->eof_index = -1; array->eof_index = -1;
...@@ -614,6 +620,8 @@ int nfs_readdir_xdr_to_array(nfs_readdir_descriptor_t *desc, struct page *page, ...@@ -614,6 +620,8 @@ int nfs_readdir_xdr_to_array(nfs_readdir_descriptor_t *desc, struct page *page,
nfs_readdir_free_large_page(pages_ptr, pages, array_size); nfs_readdir_free_large_page(pages_ptr, pages, array_size);
out_release_array: out_release_array:
nfs_readdir_release_array(page); nfs_readdir_release_array(page);
out_label_free:
nfs4_label_free(entry.label);
out: out:
nfs_free_fattr(entry.fattr); nfs_free_fattr(entry.fattr);
nfs_free_fhandle(entry.fh); nfs_free_fhandle(entry.fh);
...@@ -1083,6 +1091,10 @@ static int nfs_lookup_revalidate(struct dentry *dentry, unsigned int flags) ...@@ -1083,6 +1091,10 @@ static int nfs_lookup_revalidate(struct dentry *dentry, unsigned int flags)
if (fhandle == NULL || fattr == NULL) if (fhandle == NULL || fattr == NULL)
goto out_error; goto out_error;
label = nfs4_label_alloc(NFS_SERVER(inode), GFP_NOWAIT);
if (IS_ERR(label))
goto out_error;
error = NFS_PROTO(dir)->lookup(dir, &dentry->d_name, fhandle, fattr, label); error = NFS_PROTO(dir)->lookup(dir, &dentry->d_name, fhandle, fattr, label);
if (error) if (error)
goto out_bad; goto out_bad;
...@@ -1093,6 +1105,8 @@ static int nfs_lookup_revalidate(struct dentry *dentry, unsigned int flags) ...@@ -1093,6 +1105,8 @@ static int nfs_lookup_revalidate(struct dentry *dentry, unsigned int flags)
nfs_free_fattr(fattr); nfs_free_fattr(fattr);
nfs_free_fhandle(fhandle); nfs_free_fhandle(fhandle);
nfs4_label_free(label);
out_set_verifier: out_set_verifier:
nfs_set_verifier(dentry, nfs_save_change_attribute(dir)); nfs_set_verifier(dentry, nfs_save_change_attribute(dir));
out_valid: out_valid:
...@@ -1109,6 +1123,7 @@ static int nfs_lookup_revalidate(struct dentry *dentry, unsigned int flags) ...@@ -1109,6 +1123,7 @@ static int nfs_lookup_revalidate(struct dentry *dentry, unsigned int flags)
out_bad: out_bad:
nfs_free_fattr(fattr); nfs_free_fattr(fattr);
nfs_free_fhandle(fhandle); nfs_free_fhandle(fhandle);
nfs4_label_free(label);
nfs_mark_for_revalidate(dir); nfs_mark_for_revalidate(dir);
if (inode && S_ISDIR(inode->i_mode)) { if (inode && S_ISDIR(inode->i_mode)) {
/* Purge readdir caches. */ /* Purge readdir caches. */
...@@ -1129,6 +1144,7 @@ static int nfs_lookup_revalidate(struct dentry *dentry, unsigned int flags) ...@@ -1129,6 +1144,7 @@ static int nfs_lookup_revalidate(struct dentry *dentry, unsigned int flags)
out_error: out_error:
nfs_free_fattr(fattr); nfs_free_fattr(fattr);
nfs_free_fhandle(fhandle); nfs_free_fhandle(fhandle);
nfs4_label_free(label);
dput(parent); dput(parent);
dfprintk(LOOKUPCACHE, "NFS: %s(%s/%s) lookup returned error %d\n", dfprintk(LOOKUPCACHE, "NFS: %s(%s/%s) lookup returned error %d\n",
__func__, dentry->d_parent->d_name.name, __func__, dentry->d_parent->d_name.name,
...@@ -1284,6 +1300,10 @@ struct dentry *nfs_lookup(struct inode *dir, struct dentry * dentry, unsigned in ...@@ -1284,6 +1300,10 @@ struct dentry *nfs_lookup(struct inode *dir, struct dentry * dentry, unsigned in
if (fhandle == NULL || fattr == NULL) if (fhandle == NULL || fattr == NULL)
goto out; goto out;
label = nfs4_label_alloc(NFS_SERVER(dir), GFP_NOWAIT);
if (IS_ERR(label))
goto out;
parent = dentry->d_parent; parent = dentry->d_parent;
/* Protect against concurrent sillydeletes */ /* Protect against concurrent sillydeletes */
nfs_block_sillyrename(parent); nfs_block_sillyrename(parent);
...@@ -1312,6 +1332,7 @@ struct dentry *nfs_lookup(struct inode *dir, struct dentry * dentry, unsigned in ...@@ -1312,6 +1332,7 @@ struct dentry *nfs_lookup(struct inode *dir, struct dentry * dentry, unsigned in
nfs_set_verifier(dentry, nfs_save_change_attribute(dir)); nfs_set_verifier(dentry, nfs_save_change_attribute(dir));
out_unblock_sillyrename: out_unblock_sillyrename:
nfs_unblock_sillyrename(parent); nfs_unblock_sillyrename(parent);
nfs4_label_free(label);
out: out:
nfs_free_fattr(fattr); nfs_free_fattr(fattr);
nfs_free_fhandle(fhandle); nfs_free_fhandle(fhandle);
......
...@@ -836,6 +836,13 @@ __nfs_revalidate_inode(struct nfs_server *server, struct inode *inode) ...@@ -836,6 +836,13 @@ __nfs_revalidate_inode(struct nfs_server *server, struct inode *inode)
goto out; goto out;
nfs_inc_stats(inode, NFSIOS_INODEREVALIDATE); nfs_inc_stats(inode, NFSIOS_INODEREVALIDATE);
label = nfs4_label_alloc(NFS_SERVER(inode), GFP_KERNEL);
if (IS_ERR(label)) {
status = PTR_ERR(label);
goto out;
}
status = NFS_PROTO(inode)->getattr(server, NFS_FH(inode), fattr, label); status = NFS_PROTO(inode)->getattr(server, NFS_FH(inode), fattr, label);
if (status != 0) { if (status != 0) {
dfprintk(PAGECACHE, "nfs_revalidate_inode: (%s/%Ld) getattr failed, error=%d\n", dfprintk(PAGECACHE, "nfs_revalidate_inode: (%s/%Ld) getattr failed, error=%d\n",
...@@ -846,7 +853,7 @@ __nfs_revalidate_inode(struct nfs_server *server, struct inode *inode) ...@@ -846,7 +853,7 @@ __nfs_revalidate_inode(struct nfs_server *server, struct inode *inode)
if (!S_ISDIR(inode->i_mode)) if (!S_ISDIR(inode->i_mode))
set_bit(NFS_INO_STALE, &NFS_I(inode)->flags); set_bit(NFS_INO_STALE, &NFS_I(inode)->flags);
} }
goto out; goto err_out;
} }
status = nfs_refresh_inode(inode, fattr); status = nfs_refresh_inode(inode, fattr);
...@@ -854,7 +861,7 @@ __nfs_revalidate_inode(struct nfs_server *server, struct inode *inode) ...@@ -854,7 +861,7 @@ __nfs_revalidate_inode(struct nfs_server *server, struct inode *inode)
dfprintk(PAGECACHE, "nfs_revalidate_inode: (%s/%Ld) refresh failed, error=%d\n", dfprintk(PAGECACHE, "nfs_revalidate_inode: (%s/%Ld) refresh failed, error=%d\n",
inode->i_sb->s_id, inode->i_sb->s_id,
(long long)NFS_FILEID(inode), status); (long long)NFS_FILEID(inode), status);
goto out; goto err_out;
} }
if (nfsi->cache_validity & NFS_INO_INVALID_ACL) if (nfsi->cache_validity & NFS_INO_INVALID_ACL)
...@@ -864,7 +871,9 @@ __nfs_revalidate_inode(struct nfs_server *server, struct inode *inode) ...@@ -864,7 +871,9 @@ __nfs_revalidate_inode(struct nfs_server *server, struct inode *inode)
inode->i_sb->s_id, inode->i_sb->s_id,
(long long)NFS_FILEID(inode)); (long long)NFS_FILEID(inode));
out: err_out:
nfs4_label_free(label);
out:
nfs_free_fattr(fattr); nfs_free_fattr(fattr);
return status; return status;
} }
......
...@@ -833,9 +833,14 @@ static struct nfs4_opendata *nfs4_opendata_alloc(struct dentry *dentry, ...@@ -833,9 +833,14 @@ static struct nfs4_opendata *nfs4_opendata_alloc(struct dentry *dentry,
p = kzalloc(sizeof(*p), gfp_mask); p = kzalloc(sizeof(*p), gfp_mask);
if (p == NULL) if (p == NULL)
goto err; goto err;
p->f_label = nfs4_label_alloc(server, gfp_mask);
if (IS_ERR(p->f_label))
goto err_free_p;
p->o_arg.seqid = nfs_alloc_seqid(&sp->so_seqid, gfp_mask); p->o_arg.seqid = nfs_alloc_seqid(&sp->so_seqid, gfp_mask);
if (p->o_arg.seqid == NULL) if (p->o_arg.seqid == NULL)
goto err_free; goto err_free_label;
nfs_sb_active(dentry->d_sb); nfs_sb_active(dentry->d_sb);
p->dentry = dget(dentry); p->dentry = dget(dentry);
p->dir = parent; p->dir = parent;
...@@ -889,7 +894,10 @@ static struct nfs4_opendata *nfs4_opendata_alloc(struct dentry *dentry, ...@@ -889,7 +894,10 @@ static struct nfs4_opendata *nfs4_opendata_alloc(struct dentry *dentry,
nfs4_init_opendata_res(p); nfs4_init_opendata_res(p);
kref_init(&p->kref); kref_init(&p->kref);
return p; return p;
err_free:
err_free_label:
nfs4_label_free(p->f_label);
err_free_p:
kfree(p); kfree(p);
err: err:
dput(parent); dput(parent);
...@@ -906,6 +914,9 @@ static void nfs4_opendata_free(struct kref *kref) ...@@ -906,6 +914,9 @@ static void nfs4_opendata_free(struct kref *kref)
if (p->state != NULL) if (p->state != NULL)
nfs4_put_open_state(p->state); nfs4_put_open_state(p->state);
nfs4_put_state_owner(p->owner); nfs4_put_state_owner(p->owner);
nfs4_label_free(p->f_label);
dput(p->dir); dput(p->dir);
dput(p->dentry); dput(p->dentry);
nfs_sb_deactive(sb); nfs_sb_deactive(sb);
...@@ -2020,10 +2031,18 @@ static int _nfs4_do_open(struct inode *dir, ...@@ -2020,10 +2031,18 @@ static int _nfs4_do_open(struct inode *dir,
if (opendata == NULL) if (opendata == NULL)
goto err_put_state_owner; goto err_put_state_owner;
if (label) {
olabel = nfs4_label_alloc(server, GFP_KERNEL);
if (IS_ERR(olabel)) {
status = PTR_ERR(olabel);
goto err_opendata_put;
}
}
if (ctx_th && server->attr_bitmask[2] & FATTR4_WORD2_MDSTHRESHOLD) { if (ctx_th && server->attr_bitmask[2] & FATTR4_WORD2_MDSTHRESHOLD) {
opendata->f_attr.mdsthreshold = pnfs_mdsthreshold_alloc(); opendata->f_attr.mdsthreshold = pnfs_mdsthreshold_alloc();
if (!opendata->f_attr.mdsthreshold) if (!opendata->f_attr.mdsthreshold)
goto err_opendata_put; goto err_free_label;
opendata->o_arg.open_bitmap = &nfs4_pnfs_open_bitmap[0]; opendata->o_arg.open_bitmap = &nfs4_pnfs_open_bitmap[0];
} }
if (dentry->d_inode != NULL) if (dentry->d_inode != NULL)
...@@ -2031,7 +2050,7 @@ static int _nfs4_do_open(struct inode *dir, ...@@ -2031,7 +2050,7 @@ static int _nfs4_do_open(struct inode *dir,
status = _nfs4_open_and_get_state(opendata, fmode, flags, &state); status = _nfs4_open_and_get_state(opendata, fmode, flags, &state);
if (status != 0) if (status != 0)
goto err_opendata_put; goto err_free_label;
if ((opendata->o_arg.open_flags & O_EXCL) && if ((opendata->o_arg.open_flags & O_EXCL) &&
(opendata->o_arg.createmode != NFS4_CREATE_GUARDED)) { (opendata->o_arg.createmode != NFS4_CREATE_GUARDED)) {
...@@ -2053,10 +2072,14 @@ static int _nfs4_do_open(struct inode *dir, ...@@ -2053,10 +2072,14 @@ static int _nfs4_do_open(struct inode *dir,
kfree(opendata->f_attr.mdsthreshold); kfree(opendata->f_attr.mdsthreshold);
opendata->f_attr.mdsthreshold = NULL; opendata->f_attr.mdsthreshold = NULL;
nfs4_label_free(olabel);
nfs4_opendata_put(opendata); nfs4_opendata_put(opendata);
nfs4_put_state_owner(sp); nfs4_put_state_owner(sp);
*res = state; *res = state;
return 0; return 0;
err_free_label:
nfs4_label_free(olabel);
err_opendata_put: err_opendata_put:
kfree(opendata->f_attr.mdsthreshold); kfree(opendata->f_attr.mdsthreshold);
nfs4_opendata_put(opendata); nfs4_opendata_put(opendata);
...@@ -2670,16 +2693,23 @@ static int nfs4_proc_get_root(struct nfs_server *server, struct nfs_fh *mntfh, ...@@ -2670,16 +2693,23 @@ static int nfs4_proc_get_root(struct nfs_server *server, struct nfs_fh *mntfh,
return error; return error;
} }
label = nfs4_label_alloc(server, GFP_KERNEL);
if (IS_ERR(label))
return PTR_ERR(label);
error = nfs4_proc_getattr(server, mntfh, fattr, label); error = nfs4_proc_getattr(server, mntfh, fattr, label);
if (error < 0) { if (error < 0) {
dprintk("nfs4_get_root: getattr error = %d\n", -error); dprintk("nfs4_get_root: getattr error = %d\n", -error);
return error; goto err_free_label;
} }
if (fattr->valid & NFS_ATTR_FATTR_FSID && if (fattr->valid & NFS_ATTR_FATTR_FSID &&
!nfs_fsid_equal(&server->fsid, &fattr->fsid)) !nfs_fsid_equal(&server->fsid, &fattr->fsid))
memcpy(&server->fsid, &fattr->fsid, sizeof(server->fsid)); memcpy(&server->fsid, &fattr->fsid, sizeof(server->fsid));
err_free_label:
nfs4_label_free(label);
return error; return error;
} }
...@@ -2785,6 +2815,7 @@ nfs4_proc_setattr(struct dentry *dentry, struct nfs_fattr *fattr, ...@@ -2785,6 +2815,7 @@ nfs4_proc_setattr(struct dentry *dentry, struct nfs_fattr *fattr,
struct inode *inode = dentry->d_inode; struct inode *inode = dentry->d_inode;
struct rpc_cred *cred = NULL; struct rpc_cred *cred = NULL;
struct nfs4_state *state = NULL; struct nfs4_state *state = NULL;
struct nfs4_label *label = NULL;
int status; int status;
if (pnfs_ld_layoutret_on_setattr(inode)) if (pnfs_ld_layoutret_on_setattr(inode))
...@@ -2811,9 +2842,15 @@ nfs4_proc_setattr(struct dentry *dentry, struct nfs_fattr *fattr, ...@@ -2811,9 +2842,15 @@ nfs4_proc_setattr(struct dentry *dentry, struct nfs_fattr *fattr,
} }
} }
status = nfs4_do_setattr(inode, cred, fattr, sattr, state, NULL, NULL); label = nfs4_label_alloc(NFS_SERVER(inode), GFP_KERNEL);
if (IS_ERR(label))
return PTR_ERR(label);
status = nfs4_do_setattr(inode, cred, fattr, sattr, state, NULL, label);
if (status == 0) if (status == 0)
nfs_setattr_update_inode(inode, sattr); nfs_setattr_update_inode(inode, sattr);
nfs4_label_free(label);
return status; return status;
} }
...@@ -3240,11 +3277,21 @@ static int _nfs4_proc_link(struct inode *inode, struct inode *dir, struct qstr * ...@@ -3240,11 +3277,21 @@ static int _nfs4_proc_link(struct inode *inode, struct inode *dir, struct qstr *
if (res.fattr == NULL) if (res.fattr == NULL)
goto out; goto out;
res.label = nfs4_label_alloc(server, GFP_KERNEL);
if (IS_ERR(res.label)) {
status = PTR_ERR(res.label);
goto out;
}
status = nfs4_call_sync(server->client, server, &msg, &arg.seq_args, &res.seq_res, 1); status = nfs4_call_sync(server->client, server, &msg, &arg.seq_args, &res.seq_res, 1);
if (!status) { if (!status) {
update_changeattr(dir, &res.cinfo); update_changeattr(dir, &res.cinfo);
nfs_post_op_update_inode(inode, res.fattr); nfs_post_op_update_inode(inode, res.fattr);
} }
nfs4_label_free(res.label);
out: out:
nfs_free_fattr(res.fattr); nfs_free_fattr(res.fattr);
return status; return status;
...@@ -3280,6 +3327,10 @@ static struct nfs4_createdata *nfs4_alloc_createdata(struct inode *dir, ...@@ -3280,6 +3327,10 @@ static struct nfs4_createdata *nfs4_alloc_createdata(struct inode *dir,
if (data != NULL) { if (data != NULL) {
struct nfs_server *server = NFS_SERVER(dir); struct nfs_server *server = NFS_SERVER(dir);
data->label = nfs4_label_alloc(server, GFP_KERNEL);
if (IS_ERR(data->label))
goto out_free;
data->msg.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_CREATE]; data->msg.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_CREATE];
data->msg.rpc_argp = &data->arg; data->msg.rpc_argp = &data->arg;
data->msg.rpc_resp = &data->res; data->msg.rpc_resp = &data->res;
...@@ -3296,6 +3347,9 @@ static struct nfs4_createdata *nfs4_alloc_createdata(struct inode *dir, ...@@ -3296,6 +3347,9 @@ static struct nfs4_createdata *nfs4_alloc_createdata(struct inode *dir,
nfs_fattr_init(data->res.fattr); nfs_fattr_init(data->res.fattr);
} }
return data; return data;
out_free:
kfree(data);
return NULL;
} }
static int nfs4_do_create(struct inode *dir, struct dentry *dentry, struct nfs4_createdata *data) static int nfs4_do_create(struct inode *dir, struct dentry *dentry, struct nfs4_createdata *data)
...@@ -3311,6 +3365,7 @@ static int nfs4_do_create(struct inode *dir, struct dentry *dentry, struct nfs4_ ...@@ -3311,6 +3365,7 @@ static int nfs4_do_create(struct inode *dir, struct dentry *dentry, struct nfs4_
static void nfs4_free_createdata(struct nfs4_createdata *data) static void nfs4_free_createdata(struct nfs4_createdata *data)
{ {
nfs4_label_free(data->label);
kfree(data); kfree(data);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment