Skip to content

Commit

Permalink
NFS: Add label lifecycle management
Browse files Browse the repository at this point in the history
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: Matthew N. Dodd <Matthew.Dodd@sparta.com>
Signed-off-by: Miguel Rodel Felipe <Rodel_FM@dsi.a-star.edu.sg>
Signed-off-by: Phua Eu Gene <PHUA_Eu_Gene@dsi.a-star.edu.sg>
Signed-off-by: Khin Mi Mi Aung <Mi_Mi_AUNG@dsi.a-star.edu.sg>
Signed-off-by: Steve Dickson <steved@redhat.com>
Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
  • Loading branch information
David Quigley authored and Trond Myklebust committed Jun 8, 2013
1 parent 1775fd3 commit 14c43f7
Show file tree
Hide file tree
Showing 3 changed files with 96 additions and 11 deletions.
23 changes: 22 additions & 1 deletion fs/nfs/dir.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
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);
if (IS_ERR(array)) {
status = PTR_ERR(array);
goto out;
goto out_label_free;
}
memset(array, 0, sizeof(struct nfs_cache_array));
array->eof_index = -1;
Expand All @@ -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);
out_release_array:
nfs_readdir_release_array(page);
out_label_free:
nfs4_label_free(entry.label);
out:
nfs_free_fattr(entry.fattr);
nfs_free_fhandle(entry.fh);
Expand Down Expand Up @@ -1083,6 +1091,10 @@ static int nfs_lookup_revalidate(struct dentry *dentry, unsigned int flags)
if (fhandle == NULL || fattr == NULL)
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);
if (error)
goto out_bad;
Expand All @@ -1093,6 +1105,8 @@ static int nfs_lookup_revalidate(struct dentry *dentry, unsigned int flags)

nfs_free_fattr(fattr);
nfs_free_fhandle(fhandle);
nfs4_label_free(label);

out_set_verifier:
nfs_set_verifier(dentry, nfs_save_change_attribute(dir));
out_valid:
Expand All @@ -1109,6 +1123,7 @@ static int nfs_lookup_revalidate(struct dentry *dentry, unsigned int flags)
out_bad:
nfs_free_fattr(fattr);
nfs_free_fhandle(fhandle);
nfs4_label_free(label);
nfs_mark_for_revalidate(dir);
if (inode && S_ISDIR(inode->i_mode)) {
/* Purge readdir caches. */
Expand All @@ -1129,6 +1144,7 @@ static int nfs_lookup_revalidate(struct dentry *dentry, unsigned int flags)
out_error:
nfs_free_fattr(fattr);
nfs_free_fhandle(fhandle);
nfs4_label_free(label);
dput(parent);
dfprintk(LOOKUPCACHE, "NFS: %s(%s/%s) lookup returned error %d\n",
__func__, dentry->d_parent->d_name.name,
Expand Down Expand Up @@ -1284,6 +1300,10 @@ struct dentry *nfs_lookup(struct inode *dir, struct dentry * dentry, unsigned in
if (fhandle == NULL || fattr == NULL)
goto out;

label = nfs4_label_alloc(NFS_SERVER(dir), GFP_NOWAIT);
if (IS_ERR(label))
goto out;

parent = dentry->d_parent;
/* Protect against concurrent sillydeletes */
nfs_block_sillyrename(parent);
Expand Down Expand Up @@ -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));
out_unblock_sillyrename:
nfs_unblock_sillyrename(parent);
nfs4_label_free(label);
out:
nfs_free_fattr(fattr);
nfs_free_fhandle(fhandle);
Expand Down
15 changes: 12 additions & 3 deletions fs/nfs/inode.c
Original file line number Diff line number Diff line change
Expand Up @@ -836,6 +836,13 @@ __nfs_revalidate_inode(struct nfs_server *server, struct inode *inode)
goto out;

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);
if (status != 0) {
dfprintk(PAGECACHE, "nfs_revalidate_inode: (%s/%Ld) getattr failed, error=%d\n",
Expand All @@ -846,15 +853,15 @@ __nfs_revalidate_inode(struct nfs_server *server, struct inode *inode)
if (!S_ISDIR(inode->i_mode))
set_bit(NFS_INO_STALE, &NFS_I(inode)->flags);
}
goto out;
goto err_out;
}

status = nfs_refresh_inode(inode, fattr);
if (status) {
dfprintk(PAGECACHE, "nfs_revalidate_inode: (%s/%Ld) refresh failed, error=%d\n",
inode->i_sb->s_id,
(long long)NFS_FILEID(inode), status);
goto out;
goto err_out;
}

if (nfsi->cache_validity & NFS_INO_INVALID_ACL)
Expand All @@ -864,7 +871,9 @@ __nfs_revalidate_inode(struct nfs_server *server, struct inode *inode)
inode->i_sb->s_id,
(long long)NFS_FILEID(inode));

out:
err_out:
nfs4_label_free(label);
out:
nfs_free_fattr(fattr);
return status;
}
Expand Down
69 changes: 62 additions & 7 deletions fs/nfs/nfs4proc.c
Original file line number Diff line number Diff line change
Expand Up @@ -833,9 +833,14 @@ static struct nfs4_opendata *nfs4_opendata_alloc(struct dentry *dentry,
p = kzalloc(sizeof(*p), gfp_mask);
if (p == NULL)
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);
if (p->o_arg.seqid == NULL)
goto err_free;
goto err_free_label;
nfs_sb_active(dentry->d_sb);
p->dentry = dget(dentry);
p->dir = parent;
Expand Down Expand Up @@ -889,7 +894,10 @@ static struct nfs4_opendata *nfs4_opendata_alloc(struct dentry *dentry,
nfs4_init_opendata_res(p);
kref_init(&p->kref);
return p;
err_free:

err_free_label:
nfs4_label_free(p->f_label);
err_free_p:
kfree(p);
err:
dput(parent);
Expand All @@ -906,6 +914,9 @@ static void nfs4_opendata_free(struct kref *kref)
if (p->state != NULL)
nfs4_put_open_state(p->state);
nfs4_put_state_owner(p->owner);

nfs4_label_free(p->f_label);

dput(p->dir);
dput(p->dentry);
nfs_sb_deactive(sb);
Expand Down Expand Up @@ -2020,18 +2031,26 @@ static int _nfs4_do_open(struct inode *dir,
if (opendata == NULL)
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) {
opendata->f_attr.mdsthreshold = pnfs_mdsthreshold_alloc();
if (!opendata->f_attr.mdsthreshold)
goto err_opendata_put;
goto err_free_label;
opendata->o_arg.open_bitmap = &nfs4_pnfs_open_bitmap[0];
}
if (dentry->d_inode != NULL)
opendata->state = nfs4_get_open_state(dentry->d_inode, sp);

status = _nfs4_open_and_get_state(opendata, fmode, flags, &state);
if (status != 0)
goto err_opendata_put;
goto err_free_label;

if ((opendata->o_arg.open_flags & O_EXCL) &&
(opendata->o_arg.createmode != NFS4_CREATE_GUARDED)) {
Expand All @@ -2053,10 +2072,14 @@ static int _nfs4_do_open(struct inode *dir,
kfree(opendata->f_attr.mdsthreshold);
opendata->f_attr.mdsthreshold = NULL;

nfs4_label_free(olabel);

nfs4_opendata_put(opendata);
nfs4_put_state_owner(sp);
*res = state;
return 0;
err_free_label:
nfs4_label_free(olabel);
err_opendata_put:
kfree(opendata->f_attr.mdsthreshold);
nfs4_opendata_put(opendata);
Expand Down Expand Up @@ -2670,16 +2693,23 @@ static int nfs4_proc_get_root(struct nfs_server *server, struct nfs_fh *mntfh,
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);
if (error < 0) {
dprintk("nfs4_get_root: getattr error = %d\n", -error);
return error;
goto err_free_label;
}

if (fattr->valid & NFS_ATTR_FATTR_FSID &&
!nfs_fsid_equal(&server->fsid, &fattr->fsid))
memcpy(&server->fsid, &fattr->fsid, sizeof(server->fsid));

err_free_label:
nfs4_label_free(label);

return error;
}

Expand Down Expand Up @@ -2785,6 +2815,7 @@ nfs4_proc_setattr(struct dentry *dentry, struct nfs_fattr *fattr,
struct inode *inode = dentry->d_inode;
struct rpc_cred *cred = NULL;
struct nfs4_state *state = NULL;
struct nfs4_label *label = NULL;
int status;

if (pnfs_ld_layoutret_on_setattr(inode))
Expand All @@ -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)
nfs_setattr_update_inode(inode, sattr);

nfs4_label_free(label);
return status;
}

Expand Down Expand Up @@ -3193,7 +3230,7 @@ static int _nfs4_proc_rename(struct inode *old_dir, struct qstr *old_name,
.rpc_resp = &res,
};
int status = -ENOMEM;

status = nfs4_call_sync(server->client, server, &msg, &arg.seq_args, &res.seq_res, 1);
if (!status) {
update_changeattr(old_dir, &res.old_cinfo);
Expand Down Expand Up @@ -3240,11 +3277,21 @@ static int _nfs4_proc_link(struct inode *inode, struct inode *dir, struct qstr *
if (res.fattr == NULL)
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);
if (!status) {
update_changeattr(dir, &res.cinfo);
nfs_post_op_update_inode(inode, res.fattr);
}


nfs4_label_free(res.label);

out:
nfs_free_fattr(res.fattr);
return status;
Expand Down Expand Up @@ -3280,6 +3327,10 @@ static struct nfs4_createdata *nfs4_alloc_createdata(struct inode *dir,
if (data != NULL) {
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_argp = &data->arg;
data->msg.rpc_resp = &data->res;
Expand All @@ -3296,6 +3347,9 @@ static struct nfs4_createdata *nfs4_alloc_createdata(struct inode *dir,
nfs_fattr_init(data->res.fattr);
}
return data;
out_free:
kfree(data);
return NULL;
}

static int nfs4_do_create(struct inode *dir, struct dentry *dentry, struct nfs4_createdata *data)
Expand All @@ -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)
{
nfs4_label_free(data->label);
kfree(data);
}

Expand Down

0 comments on commit 14c43f7

Please sign in to comment.