Commit 62786b9e authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'hotfixes' of git://git.linux-nfs.org/projects/trondmy/nfs-2.6

* 'hotfixes' of git://git.linux-nfs.org/projects/trondmy/nfs-2.6:
  NFS: nfs_updatepage(): don't mark page as dirty if an error occurred
  NFS: Fix filehandle size comparisons in the mount code
  NFS: Reduce the NFS mount code stack usage.
parents 27f4837c 03fa9e84
...@@ -130,10 +130,11 @@ static int xdr_decode_fhstatus3(struct rpc_rqst *req, __be32 *p, ...@@ -130,10 +130,11 @@ static int xdr_decode_fhstatus3(struct rpc_rqst *req, __be32 *p,
struct mnt_fhstatus *res) struct mnt_fhstatus *res)
{ {
struct nfs_fh *fh = res->fh; struct nfs_fh *fh = res->fh;
unsigned size;
if ((res->status = ntohl(*p++)) == 0) { if ((res->status = ntohl(*p++)) == 0) {
int size = ntohl(*p++); size = ntohl(*p++);
if (size <= NFS3_FHSIZE) { if (size <= NFS3_FHSIZE && size != 0) {
fh->size = size; fh->size = size;
memcpy(fh->data, p, size); memcpy(fh->data, p, size);
} else } else
......
...@@ -1216,8 +1216,6 @@ static int nfs_validate_mount_data(void *options, ...@@ -1216,8 +1216,6 @@ static int nfs_validate_mount_data(void *options,
{ {
struct nfs_mount_data *data = (struct nfs_mount_data *)options; struct nfs_mount_data *data = (struct nfs_mount_data *)options;
memset(args, 0, sizeof(*args));
if (data == NULL) if (data == NULL)
goto out_no_data; goto out_no_data;
...@@ -1251,13 +1249,13 @@ static int nfs_validate_mount_data(void *options, ...@@ -1251,13 +1249,13 @@ static int nfs_validate_mount_data(void *options,
case 5: case 5:
memset(data->context, 0, sizeof(data->context)); memset(data->context, 0, sizeof(data->context));
case 6: case 6:
if (data->flags & NFS_MOUNT_VER3) if (data->flags & NFS_MOUNT_VER3) {
if (data->root.size > NFS3_FHSIZE || data->root.size == 0)
goto out_invalid_fh;
mntfh->size = data->root.size; mntfh->size = data->root.size;
else } else
mntfh->size = NFS2_FHSIZE; mntfh->size = NFS2_FHSIZE;
if (mntfh->size > sizeof(mntfh->data))
goto out_invalid_fh;
memcpy(mntfh->data, data->root.data, mntfh->size); memcpy(mntfh->data, data->root.data, mntfh->size);
if (mntfh->size < sizeof(mntfh->data)) if (mntfh->size < sizeof(mntfh->data))
...@@ -1585,24 +1583,29 @@ static int nfs_get_sb(struct file_system_type *fs_type, ...@@ -1585,24 +1583,29 @@ static int nfs_get_sb(struct file_system_type *fs_type,
{ {
struct nfs_server *server = NULL; struct nfs_server *server = NULL;
struct super_block *s; struct super_block *s;
struct nfs_fh mntfh; struct nfs_parsed_mount_data *data;
struct nfs_parsed_mount_data data; struct nfs_fh *mntfh;
struct dentry *mntroot; struct dentry *mntroot;
int (*compare_super)(struct super_block *, void *) = nfs_compare_super; int (*compare_super)(struct super_block *, void *) = nfs_compare_super;
struct nfs_sb_mountdata sb_mntdata = { struct nfs_sb_mountdata sb_mntdata = {
.mntflags = flags, .mntflags = flags,
}; };
int error; int error = -ENOMEM;
data = kzalloc(sizeof(*data), GFP_KERNEL);
mntfh = kzalloc(sizeof(*mntfh), GFP_KERNEL);
if (data == NULL || mntfh == NULL)
goto out_free_fh;
security_init_mnt_opts(&data.lsm_opts); security_init_mnt_opts(&data->lsm_opts);
/* Validate the mount data */ /* Validate the mount data */
error = nfs_validate_mount_data(raw_data, &data, &mntfh, dev_name); error = nfs_validate_mount_data(raw_data, data, mntfh, dev_name);
if (error < 0) if (error < 0)
goto out; goto out;
/* Get a volume representation */ /* Get a volume representation */
server = nfs_create_server(&data, &mntfh); server = nfs_create_server(data, mntfh);
if (IS_ERR(server)) { if (IS_ERR(server)) {
error = PTR_ERR(server); error = PTR_ERR(server);
goto out; goto out;
...@@ -1630,16 +1633,16 @@ static int nfs_get_sb(struct file_system_type *fs_type, ...@@ -1630,16 +1633,16 @@ static int nfs_get_sb(struct file_system_type *fs_type,
if (!s->s_root) { if (!s->s_root) {
/* initial superblock/root creation */ /* initial superblock/root creation */
nfs_fill_super(s, &data); nfs_fill_super(s, data);
} }
mntroot = nfs_get_root(s, &mntfh); mntroot = nfs_get_root(s, mntfh);
if (IS_ERR(mntroot)) { if (IS_ERR(mntroot)) {
error = PTR_ERR(mntroot); error = PTR_ERR(mntroot);
goto error_splat_super; goto error_splat_super;
} }
error = security_sb_set_mnt_opts(s, &data.lsm_opts); error = security_sb_set_mnt_opts(s, &data->lsm_opts);
if (error) if (error)
goto error_splat_root; goto error_splat_root;
...@@ -1649,9 +1652,12 @@ static int nfs_get_sb(struct file_system_type *fs_type, ...@@ -1649,9 +1652,12 @@ static int nfs_get_sb(struct file_system_type *fs_type,
error = 0; error = 0;
out: out:
kfree(data.nfs_server.hostname); kfree(data->nfs_server.hostname);
kfree(data.mount_server.hostname); kfree(data->mount_server.hostname);
security_free_mnt_opts(&data.lsm_opts); security_free_mnt_opts(&data->lsm_opts);
out_free_fh:
kfree(mntfh);
kfree(data);
return error; return error;
out_err_nosb: out_err_nosb:
...@@ -1800,8 +1806,6 @@ static int nfs4_validate_mount_data(void *options, ...@@ -1800,8 +1806,6 @@ static int nfs4_validate_mount_data(void *options,
struct nfs4_mount_data *data = (struct nfs4_mount_data *)options; struct nfs4_mount_data *data = (struct nfs4_mount_data *)options;
char *c; char *c;
memset(args, 0, sizeof(*args));
if (data == NULL) if (data == NULL)
goto out_no_data; goto out_no_data;
...@@ -1959,26 +1963,31 @@ out_no_client_address: ...@@ -1959,26 +1963,31 @@ out_no_client_address:
static int nfs4_get_sb(struct file_system_type *fs_type, static int nfs4_get_sb(struct file_system_type *fs_type,
int flags, const char *dev_name, void *raw_data, struct vfsmount *mnt) int flags, const char *dev_name, void *raw_data, struct vfsmount *mnt)
{ {
struct nfs_parsed_mount_data data; struct nfs_parsed_mount_data *data;
struct super_block *s; struct super_block *s;
struct nfs_server *server; struct nfs_server *server;
struct nfs_fh mntfh; struct nfs_fh *mntfh;
struct dentry *mntroot; struct dentry *mntroot;
int (*compare_super)(struct super_block *, void *) = nfs_compare_super; int (*compare_super)(struct super_block *, void *) = nfs_compare_super;
struct nfs_sb_mountdata sb_mntdata = { struct nfs_sb_mountdata sb_mntdata = {
.mntflags = flags, .mntflags = flags,
}; };
int error; int error = -ENOMEM;
data = kzalloc(sizeof(*data), GFP_KERNEL);
mntfh = kzalloc(sizeof(*mntfh), GFP_KERNEL);
if (data == NULL || mntfh == NULL)
goto out_free_fh;
security_init_mnt_opts(&data.lsm_opts); security_init_mnt_opts(&data->lsm_opts);
/* Validate the mount data */ /* Validate the mount data */
error = nfs4_validate_mount_data(raw_data, &data, dev_name); error = nfs4_validate_mount_data(raw_data, data, dev_name);
if (error < 0) if (error < 0)
goto out; goto out;
/* Get a volume representation */ /* Get a volume representation */
server = nfs4_create_server(&data, &mntfh); server = nfs4_create_server(data, mntfh);
if (IS_ERR(server)) { if (IS_ERR(server)) {
error = PTR_ERR(server); error = PTR_ERR(server);
goto out; goto out;
...@@ -2009,13 +2018,13 @@ static int nfs4_get_sb(struct file_system_type *fs_type, ...@@ -2009,13 +2018,13 @@ static int nfs4_get_sb(struct file_system_type *fs_type,
nfs4_fill_super(s); nfs4_fill_super(s);
} }
mntroot = nfs4_get_root(s, &mntfh); mntroot = nfs4_get_root(s, mntfh);
if (IS_ERR(mntroot)) { if (IS_ERR(mntroot)) {
error = PTR_ERR(mntroot); error = PTR_ERR(mntroot);
goto error_splat_super; goto error_splat_super;
} }
error = security_sb_set_mnt_opts(s, &data.lsm_opts); error = security_sb_set_mnt_opts(s, &data->lsm_opts);
if (error) if (error)
goto error_splat_root; goto error_splat_root;
...@@ -2025,10 +2034,13 @@ static int nfs4_get_sb(struct file_system_type *fs_type, ...@@ -2025,10 +2034,13 @@ static int nfs4_get_sb(struct file_system_type *fs_type,
error = 0; error = 0;
out: out:
kfree(data.client_address); kfree(data->client_address);
kfree(data.nfs_server.export_path); kfree(data->nfs_server.export_path);
kfree(data.nfs_server.hostname); kfree(data->nfs_server.hostname);
security_free_mnt_opts(&data.lsm_opts); security_free_mnt_opts(&data->lsm_opts);
out_free_fh:
kfree(mntfh);
kfree(data);
return error; return error;
out_free: out_free:
......
...@@ -739,12 +739,13 @@ int nfs_updatepage(struct file *file, struct page *page, ...@@ -739,12 +739,13 @@ int nfs_updatepage(struct file *file, struct page *page,
} }
status = nfs_writepage_setup(ctx, page, offset, count); status = nfs_writepage_setup(ctx, page, offset, count);
if (status < 0)
nfs_set_pageerror(page);
else
__set_page_dirty_nobuffers(page); __set_page_dirty_nobuffers(page);
dprintk("NFS: nfs_updatepage returns %d (isize %Ld)\n", dprintk("NFS: nfs_updatepage returns %d (isize %Ld)\n",
status, (long long)i_size_read(inode)); status, (long long)i_size_read(inode));
if (status < 0)
nfs_set_pageerror(page);
return status; return status;
} }
......
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