diff options
Diffstat (limited to 'fs/nfs')
-rw-r--r-- | fs/nfs/callback.c | 3 | ||||
-rw-r--r-- | fs/nfs/callback_xdr.c | 6 | ||||
-rw-r--r-- | fs/nfs/delegation.c | 2 | ||||
-rw-r--r-- | fs/nfs/dir.c | 5 | ||||
-rw-r--r-- | fs/nfs/file.c | 4 | ||||
-rw-r--r-- | fs/nfs/idmap.c | 2 | ||||
-rw-r--r-- | fs/nfs/inode.c | 7 | ||||
-rw-r--r-- | fs/nfs/internal.h | 3 | ||||
-rw-r--r-- | fs/nfs/nfs4state.c | 2 | ||||
-rw-r--r-- | fs/nfs/read.c | 5 | ||||
-rw-r--r-- | fs/nfs/super.c | 68 | ||||
-rw-r--r-- | fs/nfs/write.c | 10 |
12 files changed, 99 insertions, 18 deletions
diff --git a/fs/nfs/callback.c b/fs/nfs/callback.c index ecc06c619494..66648dd92d97 100644 --- a/fs/nfs/callback.c +++ b/fs/nfs/callback.c | |||
@@ -93,6 +93,7 @@ static void nfs_callback_svc(struct svc_rqst *rqstp) | |||
93 | svc_process(rqstp); | 93 | svc_process(rqstp); |
94 | } | 94 | } |
95 | 95 | ||
96 | flush_signals(current); | ||
96 | svc_exit_thread(rqstp); | 97 | svc_exit_thread(rqstp); |
97 | nfs_callback_info.pid = 0; | 98 | nfs_callback_info.pid = 0; |
98 | complete(&nfs_callback_info.stopped); | 99 | complete(&nfs_callback_info.stopped); |
@@ -171,7 +172,7 @@ void nfs_callback_down(void) | |||
171 | static int nfs_callback_authenticate(struct svc_rqst *rqstp) | 172 | static int nfs_callback_authenticate(struct svc_rqst *rqstp) |
172 | { | 173 | { |
173 | struct nfs_client *clp; | 174 | struct nfs_client *clp; |
174 | char buf[RPC_MAX_ADDRBUFLEN]; | 175 | RPC_IFDEBUG(char buf[RPC_MAX_ADDRBUFLEN]); |
175 | 176 | ||
176 | /* Don't talk to strangers */ | 177 | /* Don't talk to strangers */ |
177 | clp = nfs_find_client(svc_addr(rqstp), 4); | 178 | clp = nfs_find_client(svc_addr(rqstp), 4); |
diff --git a/fs/nfs/callback_xdr.c b/fs/nfs/callback_xdr.c index c63eb720b68b..13619d24f023 100644 --- a/fs/nfs/callback_xdr.c +++ b/fs/nfs/callback_xdr.c | |||
@@ -254,7 +254,7 @@ static __be32 encode_attr_change(struct xdr_stream *xdr, const uint32_t *bitmap, | |||
254 | if (!(bitmap[0] & FATTR4_WORD0_CHANGE)) | 254 | if (!(bitmap[0] & FATTR4_WORD0_CHANGE)) |
255 | return 0; | 255 | return 0; |
256 | p = xdr_reserve_space(xdr, 8); | 256 | p = xdr_reserve_space(xdr, 8); |
257 | if (unlikely(p == 0)) | 257 | if (unlikely(!p)) |
258 | return htonl(NFS4ERR_RESOURCE); | 258 | return htonl(NFS4ERR_RESOURCE); |
259 | p = xdr_encode_hyper(p, change); | 259 | p = xdr_encode_hyper(p, change); |
260 | return 0; | 260 | return 0; |
@@ -267,7 +267,7 @@ static __be32 encode_attr_size(struct xdr_stream *xdr, const uint32_t *bitmap, u | |||
267 | if (!(bitmap[0] & FATTR4_WORD0_SIZE)) | 267 | if (!(bitmap[0] & FATTR4_WORD0_SIZE)) |
268 | return 0; | 268 | return 0; |
269 | p = xdr_reserve_space(xdr, 8); | 269 | p = xdr_reserve_space(xdr, 8); |
270 | if (unlikely(p == 0)) | 270 | if (unlikely(!p)) |
271 | return htonl(NFS4ERR_RESOURCE); | 271 | return htonl(NFS4ERR_RESOURCE); |
272 | p = xdr_encode_hyper(p, size); | 272 | p = xdr_encode_hyper(p, size); |
273 | return 0; | 273 | return 0; |
@@ -278,7 +278,7 @@ static __be32 encode_attr_time(struct xdr_stream *xdr, const struct timespec *ti | |||
278 | __be32 *p; | 278 | __be32 *p; |
279 | 279 | ||
280 | p = xdr_reserve_space(xdr, 12); | 280 | p = xdr_reserve_space(xdr, 12); |
281 | if (unlikely(p == 0)) | 281 | if (unlikely(!p)) |
282 | return htonl(NFS4ERR_RESOURCE); | 282 | return htonl(NFS4ERR_RESOURCE); |
283 | p = xdr_encode_hyper(p, time->tv_sec); | 283 | p = xdr_encode_hyper(p, time->tv_sec); |
284 | *p = htonl(time->tv_nsec); | 284 | *p = htonl(time->tv_nsec); |
diff --git a/fs/nfs/delegation.c b/fs/nfs/delegation.c index b9eadd18ba70..00a5e4405e16 100644 --- a/fs/nfs/delegation.c +++ b/fs/nfs/delegation.c | |||
@@ -49,7 +49,7 @@ static int nfs_delegation_claim_locks(struct nfs_open_context *ctx, struct nfs4_ | |||
49 | struct file_lock *fl; | 49 | struct file_lock *fl; |
50 | int status; | 50 | int status; |
51 | 51 | ||
52 | for (fl = inode->i_flock; fl != 0; fl = fl->fl_next) { | 52 | for (fl = inode->i_flock; fl != NULL; fl = fl->fl_next) { |
53 | if (!(fl->fl_flags & (FL_POSIX|FL_FLOCK))) | 53 | if (!(fl->fl_flags & (FL_POSIX|FL_FLOCK))) |
54 | continue; | 54 | continue; |
55 | if (nfs_file_open_context(fl->fl_file) != ctx) | 55 | if (nfs_file_open_context(fl->fl_file) != ctx) |
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c index ae04892a5e5d..d9e30ac2798d 100644 --- a/fs/nfs/dir.c +++ b/fs/nfs/dir.c | |||
@@ -710,6 +710,8 @@ int nfs_lookup_verify_inode(struct inode *inode, struct nameidata *nd) | |||
710 | { | 710 | { |
711 | struct nfs_server *server = NFS_SERVER(inode); | 711 | struct nfs_server *server = NFS_SERVER(inode); |
712 | 712 | ||
713 | if (test_bit(NFS_INO_MOUNTPOINT, &NFS_I(inode)->flags)) | ||
714 | return 0; | ||
713 | if (nd != NULL) { | 715 | if (nd != NULL) { |
714 | /* VFS wants an on-the-wire revalidation */ | 716 | /* VFS wants an on-the-wire revalidation */ |
715 | if (nd->flags & LOOKUP_REVAL) | 717 | if (nd->flags & LOOKUP_REVAL) |
@@ -965,7 +967,8 @@ static int is_atomic_open(struct inode *dir, struct nameidata *nd) | |||
965 | if (nd->flags & LOOKUP_DIRECTORY) | 967 | if (nd->flags & LOOKUP_DIRECTORY) |
966 | return 0; | 968 | return 0; |
967 | /* Are we trying to write to a read only partition? */ | 969 | /* Are we trying to write to a read only partition? */ |
968 | if (IS_RDONLY(dir) && (nd->intent.open.flags & (O_CREAT|O_TRUNC|FMODE_WRITE))) | 970 | if (__mnt_is_readonly(nd->path.mnt) && |
971 | (nd->intent.open.flags & (O_CREAT|O_TRUNC|FMODE_WRITE))) | ||
969 | return 0; | 972 | return 0; |
970 | return 1; | 973 | return 1; |
971 | } | 974 | } |
diff --git a/fs/nfs/file.c b/fs/nfs/file.c index ef57a5ae5904..5d2e9d9a4e28 100644 --- a/fs/nfs/file.c +++ b/fs/nfs/file.c | |||
@@ -64,7 +64,11 @@ const struct file_operations nfs_file_operations = { | |||
64 | .write = do_sync_write, | 64 | .write = do_sync_write, |
65 | .aio_read = nfs_file_read, | 65 | .aio_read = nfs_file_read, |
66 | .aio_write = nfs_file_write, | 66 | .aio_write = nfs_file_write, |
67 | #ifdef CONFIG_MMU | ||
67 | .mmap = nfs_file_mmap, | 68 | .mmap = nfs_file_mmap, |
69 | #else | ||
70 | .mmap = generic_file_mmap, | ||
71 | #endif | ||
68 | .open = nfs_file_open, | 72 | .open = nfs_file_open, |
69 | .flush = nfs_file_flush, | 73 | .flush = nfs_file_flush, |
70 | .release = nfs_file_release, | 74 | .release = nfs_file_release, |
diff --git a/fs/nfs/idmap.c b/fs/nfs/idmap.c index 8ae5dba2d4e5..86147b0ab2cf 100644 --- a/fs/nfs/idmap.c +++ b/fs/nfs/idmap.c | |||
@@ -309,7 +309,7 @@ nfs_idmap_name(struct idmap *idmap, struct idmap_hashtable *h, | |||
309 | mutex_lock(&idmap->idmap_im_lock); | 309 | mutex_lock(&idmap->idmap_im_lock); |
310 | 310 | ||
311 | he = idmap_lookup_id(h, id); | 311 | he = idmap_lookup_id(h, id); |
312 | if (he != 0) { | 312 | if (he) { |
313 | memcpy(name, he->ih_name, he->ih_namelen); | 313 | memcpy(name, he->ih_name, he->ih_namelen); |
314 | ret = he->ih_namelen; | 314 | ret = he->ih_namelen; |
315 | goto out; | 315 | goto out; |
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c index 966a8850aa30..6f88d7c77ac9 100644 --- a/fs/nfs/inode.c +++ b/fs/nfs/inode.c | |||
@@ -299,6 +299,7 @@ nfs_fhget(struct super_block *sb, struct nfs_fh *fh, struct nfs_fattr *fattr) | |||
299 | else | 299 | else |
300 | inode->i_op = &nfs_mountpoint_inode_operations; | 300 | inode->i_op = &nfs_mountpoint_inode_operations; |
301 | inode->i_fop = NULL; | 301 | inode->i_fop = NULL; |
302 | set_bit(NFS_INO_MOUNTPOINT, &nfsi->flags); | ||
302 | } | 303 | } |
303 | } else if (S_ISLNK(inode->i_mode)) | 304 | } else if (S_ISLNK(inode->i_mode)) |
304 | inode->i_op = &nfs_symlink_inode_operations; | 305 | inode->i_op = &nfs_symlink_inode_operations; |
@@ -505,6 +506,7 @@ static struct nfs_open_context *alloc_nfs_open_context(struct vfsmount *mnt, str | |||
505 | ctx->cred = get_rpccred(cred); | 506 | ctx->cred = get_rpccred(cred); |
506 | ctx->state = NULL; | 507 | ctx->state = NULL; |
507 | ctx->lockowner = current->files; | 508 | ctx->lockowner = current->files; |
509 | ctx->flags = 0; | ||
508 | ctx->error = 0; | 510 | ctx->error = 0; |
509 | ctx->dir_cookie = 0; | 511 | ctx->dir_cookie = 0; |
510 | atomic_set(&ctx->count, 1); | 512 | atomic_set(&ctx->count, 1); |
@@ -1003,8 +1005,9 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr) | |||
1003 | 1005 | ||
1004 | server = NFS_SERVER(inode); | 1006 | server = NFS_SERVER(inode); |
1005 | /* Update the fsid? */ | 1007 | /* Update the fsid? */ |
1006 | if (S_ISDIR(inode->i_mode) | 1008 | if (S_ISDIR(inode->i_mode) && |
1007 | && !nfs_fsid_equal(&server->fsid, &fattr->fsid)) | 1009 | !nfs_fsid_equal(&server->fsid, &fattr->fsid) && |
1010 | !test_bit(NFS_INO_MOUNTPOINT, &nfsi->flags)) | ||
1008 | server->fsid = fattr->fsid; | 1011 | server->fsid = fattr->fsid; |
1009 | 1012 | ||
1010 | /* | 1013 | /* |
diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h index 0f5619611b8d..931992763e68 100644 --- a/fs/nfs/internal.h +++ b/fs/nfs/internal.h | |||
@@ -3,6 +3,7 @@ | |||
3 | */ | 3 | */ |
4 | 4 | ||
5 | #include <linux/mount.h> | 5 | #include <linux/mount.h> |
6 | #include <linux/security.h> | ||
6 | 7 | ||
7 | struct nfs_string; | 8 | struct nfs_string; |
8 | 9 | ||
@@ -57,6 +58,8 @@ struct nfs_parsed_mount_data { | |||
57 | char *export_path; | 58 | char *export_path; |
58 | int protocol; | 59 | int protocol; |
59 | } nfs_server; | 60 | } nfs_server; |
61 | |||
62 | struct security_mnt_opts lsm_opts; | ||
60 | }; | 63 | }; |
61 | 64 | ||
62 | /* client.c */ | 65 | /* client.c */ |
diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c index 6233eb5e98c1..b962397004c1 100644 --- a/fs/nfs/nfs4state.c +++ b/fs/nfs/nfs4state.c | |||
@@ -785,7 +785,7 @@ static int nfs4_reclaim_locks(struct nfs4_state_recovery_ops *ops, struct nfs4_s | |||
785 | struct file_lock *fl; | 785 | struct file_lock *fl; |
786 | int status = 0; | 786 | int status = 0; |
787 | 787 | ||
788 | for (fl = inode->i_flock; fl != 0; fl = fl->fl_next) { | 788 | for (fl = inode->i_flock; fl != NULL; fl = fl->fl_next) { |
789 | if (!(fl->fl_flags & (FL_POSIX|FL_FLOCK))) | 789 | if (!(fl->fl_flags & (FL_POSIX|FL_FLOCK))) |
790 | continue; | 790 | continue; |
791 | if (nfs_file_open_context(fl->fl_file)->state != state) | 791 | if (nfs_file_open_context(fl->fl_file)->state != state) |
diff --git a/fs/nfs/read.c b/fs/nfs/read.c index 3d7d9631e125..5a70be589bbe 100644 --- a/fs/nfs/read.c +++ b/fs/nfs/read.c | |||
@@ -533,7 +533,10 @@ readpage_async_filler(void *data, struct page *page) | |||
533 | 533 | ||
534 | if (len < PAGE_CACHE_SIZE) | 534 | if (len < PAGE_CACHE_SIZE) |
535 | zero_user_segment(page, len, PAGE_CACHE_SIZE); | 535 | zero_user_segment(page, len, PAGE_CACHE_SIZE); |
536 | nfs_pageio_add_request(desc->pgio, new); | 536 | if (!nfs_pageio_add_request(desc->pgio, new)) { |
537 | error = desc->pgio->pg_error; | ||
538 | goto out_unlock; | ||
539 | } | ||
537 | return 0; | 540 | return 0; |
538 | out_error: | 541 | out_error: |
539 | error = PTR_ERR(new); | 542 | error = PTR_ERR(new); |
diff --git a/fs/nfs/super.c b/fs/nfs/super.c index 1fb381843650..f9219024f31a 100644 --- a/fs/nfs/super.c +++ b/fs/nfs/super.c | |||
@@ -589,8 +589,6 @@ static void nfs_umount_begin(struct vfsmount *vfsmnt, int flags) | |||
589 | struct nfs_server *server = NFS_SB(vfsmnt->mnt_sb); | 589 | struct nfs_server *server = NFS_SB(vfsmnt->mnt_sb); |
590 | struct rpc_clnt *rpc; | 590 | struct rpc_clnt *rpc; |
591 | 591 | ||
592 | shrink_submounts(vfsmnt, &nfs_automount_list); | ||
593 | |||
594 | if (!(flags & MNT_FORCE)) | 592 | if (!(flags & MNT_FORCE)) |
595 | return; | 593 | return; |
596 | /* -EIO all pending I/O */ | 594 | /* -EIO all pending I/O */ |
@@ -632,7 +630,7 @@ static int nfs_verify_server_address(struct sockaddr *addr) | |||
632 | switch (addr->sa_family) { | 630 | switch (addr->sa_family) { |
633 | case AF_INET: { | 631 | case AF_INET: { |
634 | struct sockaddr_in *sa = (struct sockaddr_in *)addr; | 632 | struct sockaddr_in *sa = (struct sockaddr_in *)addr; |
635 | return sa->sin_addr.s_addr != INADDR_ANY; | 633 | return sa->sin_addr.s_addr != htonl(INADDR_ANY); |
636 | } | 634 | } |
637 | case AF_INET6: { | 635 | case AF_INET6: { |
638 | struct in6_addr *sa = &((struct sockaddr_in6 *)addr)->sin6_addr; | 636 | struct in6_addr *sa = &((struct sockaddr_in6 *)addr)->sin6_addr; |
@@ -684,8 +682,9 @@ static void nfs_parse_server_address(char *value, | |||
684 | static int nfs_parse_mount_options(char *raw, | 682 | static int nfs_parse_mount_options(char *raw, |
685 | struct nfs_parsed_mount_data *mnt) | 683 | struct nfs_parsed_mount_data *mnt) |
686 | { | 684 | { |
687 | char *p, *string; | 685 | char *p, *string, *secdata; |
688 | unsigned short port = 0; | 686 | unsigned short port = 0; |
687 | int rc; | ||
689 | 688 | ||
690 | if (!raw) { | 689 | if (!raw) { |
691 | dfprintk(MOUNT, "NFS: mount options string was NULL.\n"); | 690 | dfprintk(MOUNT, "NFS: mount options string was NULL.\n"); |
@@ -693,6 +692,20 @@ static int nfs_parse_mount_options(char *raw, | |||
693 | } | 692 | } |
694 | dfprintk(MOUNT, "NFS: nfs mount opts='%s'\n", raw); | 693 | dfprintk(MOUNT, "NFS: nfs mount opts='%s'\n", raw); |
695 | 694 | ||
695 | secdata = alloc_secdata(); | ||
696 | if (!secdata) | ||
697 | goto out_nomem; | ||
698 | |||
699 | rc = security_sb_copy_data(raw, secdata); | ||
700 | if (rc) | ||
701 | goto out_security_failure; | ||
702 | |||
703 | rc = security_sb_parse_opts_str(secdata, &mnt->lsm_opts); | ||
704 | if (rc) | ||
705 | goto out_security_failure; | ||
706 | |||
707 | free_secdata(secdata); | ||
708 | |||
696 | while ((p = strsep(&raw, ",")) != NULL) { | 709 | while ((p = strsep(&raw, ",")) != NULL) { |
697 | substring_t args[MAX_OPT_ARGS]; | 710 | substring_t args[MAX_OPT_ARGS]; |
698 | int option, token; | 711 | int option, token; |
@@ -1042,7 +1055,10 @@ static int nfs_parse_mount_options(char *raw, | |||
1042 | out_nomem: | 1055 | out_nomem: |
1043 | printk(KERN_INFO "NFS: not enough memory to parse option\n"); | 1056 | printk(KERN_INFO "NFS: not enough memory to parse option\n"); |
1044 | return 0; | 1057 | return 0; |
1045 | 1058 | out_security_failure: | |
1059 | free_secdata(secdata); | ||
1060 | printk(KERN_INFO "NFS: security options invalid: %d\n", rc); | ||
1061 | return 0; | ||
1046 | out_unrec_vers: | 1062 | out_unrec_vers: |
1047 | printk(KERN_INFO "NFS: unrecognized NFS version number\n"); | 1063 | printk(KERN_INFO "NFS: unrecognized NFS version number\n"); |
1048 | return 0; | 1064 | return 0; |
@@ -1214,6 +1230,33 @@ static int nfs_validate_mount_data(void *options, | |||
1214 | args->namlen = data->namlen; | 1230 | args->namlen = data->namlen; |
1215 | args->bsize = data->bsize; | 1231 | args->bsize = data->bsize; |
1216 | args->auth_flavors[0] = data->pseudoflavor; | 1232 | args->auth_flavors[0] = data->pseudoflavor; |
1233 | |||
1234 | /* | ||
1235 | * The legacy version 6 binary mount data from userspace has a | ||
1236 | * field used only to transport selinux information into the | ||
1237 | * the kernel. To continue to support that functionality we | ||
1238 | * have a touch of selinux knowledge here in the NFS code. The | ||
1239 | * userspace code converted context=blah to just blah so we are | ||
1240 | * converting back to the full string selinux understands. | ||
1241 | */ | ||
1242 | if (data->context[0]){ | ||
1243 | #ifdef CONFIG_SECURITY_SELINUX | ||
1244 | int rc; | ||
1245 | char *opts_str = kmalloc(sizeof(data->context) + 8, GFP_KERNEL); | ||
1246 | if (!opts_str) | ||
1247 | return -ENOMEM; | ||
1248 | strcpy(opts_str, "context="); | ||
1249 | data->context[NFS_MAX_CONTEXT_LEN] = '\0'; | ||
1250 | strcat(opts_str, &data->context[0]); | ||
1251 | rc = security_sb_parse_opts_str(opts_str, &args->lsm_opts); | ||
1252 | kfree(opts_str); | ||
1253 | if (rc) | ||
1254 | return rc; | ||
1255 | #else | ||
1256 | return -EINVAL; | ||
1257 | #endif | ||
1258 | } | ||
1259 | |||
1217 | break; | 1260 | break; |
1218 | default: { | 1261 | default: { |
1219 | unsigned int len; | 1262 | unsigned int len; |
@@ -1476,6 +1519,8 @@ static int nfs_get_sb(struct file_system_type *fs_type, | |||
1476 | }; | 1519 | }; |
1477 | int error; | 1520 | int error; |
1478 | 1521 | ||
1522 | security_init_mnt_opts(&data.lsm_opts); | ||
1523 | |||
1479 | /* Validate the mount data */ | 1524 | /* Validate the mount data */ |
1480 | error = nfs_validate_mount_data(raw_data, &data, &mntfh, dev_name); | 1525 | error = nfs_validate_mount_data(raw_data, &data, &mntfh, dev_name); |
1481 | if (error < 0) | 1526 | if (error < 0) |
@@ -1515,6 +1560,10 @@ static int nfs_get_sb(struct file_system_type *fs_type, | |||
1515 | goto error_splat_super; | 1560 | goto error_splat_super; |
1516 | } | 1561 | } |
1517 | 1562 | ||
1563 | error = security_sb_set_mnt_opts(s, &data.lsm_opts); | ||
1564 | if (error) | ||
1565 | goto error_splat_root; | ||
1566 | |||
1518 | s->s_flags |= MS_ACTIVE; | 1567 | s->s_flags |= MS_ACTIVE; |
1519 | mnt->mnt_sb = s; | 1568 | mnt->mnt_sb = s; |
1520 | mnt->mnt_root = mntroot; | 1569 | mnt->mnt_root = mntroot; |
@@ -1523,12 +1572,15 @@ static int nfs_get_sb(struct file_system_type *fs_type, | |||
1523 | out: | 1572 | out: |
1524 | kfree(data.nfs_server.hostname); | 1573 | kfree(data.nfs_server.hostname); |
1525 | kfree(data.mount_server.hostname); | 1574 | kfree(data.mount_server.hostname); |
1575 | security_free_mnt_opts(&data.lsm_opts); | ||
1526 | return error; | 1576 | return error; |
1527 | 1577 | ||
1528 | out_err_nosb: | 1578 | out_err_nosb: |
1529 | nfs_free_server(server); | 1579 | nfs_free_server(server); |
1530 | goto out; | 1580 | goto out; |
1531 | 1581 | ||
1582 | error_splat_root: | ||
1583 | dput(mntroot); | ||
1532 | error_splat_super: | 1584 | error_splat_super: |
1533 | up_write(&s->s_umount); | 1585 | up_write(&s->s_umount); |
1534 | deactivate_super(s); | 1586 | deactivate_super(s); |
@@ -1608,6 +1660,9 @@ static int nfs_xdev_get_sb(struct file_system_type *fs_type, int flags, | |||
1608 | mnt->mnt_sb = s; | 1660 | mnt->mnt_sb = s; |
1609 | mnt->mnt_root = mntroot; | 1661 | mnt->mnt_root = mntroot; |
1610 | 1662 | ||
1663 | /* clone any lsm security options from the parent to the new sb */ | ||
1664 | security_sb_clone_mnt_opts(data->sb, s); | ||
1665 | |||
1611 | dprintk("<-- nfs_xdev_get_sb() = 0\n"); | 1666 | dprintk("<-- nfs_xdev_get_sb() = 0\n"); |
1612 | return 0; | 1667 | return 0; |
1613 | 1668 | ||
@@ -1850,6 +1905,8 @@ static int nfs4_get_sb(struct file_system_type *fs_type, | |||
1850 | }; | 1905 | }; |
1851 | int error; | 1906 | int error; |
1852 | 1907 | ||
1908 | security_init_mnt_opts(&data.lsm_opts); | ||
1909 | |||
1853 | /* Validate the mount data */ | 1910 | /* Validate the mount data */ |
1854 | error = nfs4_validate_mount_data(raw_data, &data, dev_name); | 1911 | error = nfs4_validate_mount_data(raw_data, &data, dev_name); |
1855 | if (error < 0) | 1912 | if (error < 0) |
@@ -1898,6 +1955,7 @@ out: | |||
1898 | kfree(data.client_address); | 1955 | kfree(data.client_address); |
1899 | kfree(data.nfs_server.export_path); | 1956 | kfree(data.nfs_server.export_path); |
1900 | kfree(data.nfs_server.hostname); | 1957 | kfree(data.nfs_server.hostname); |
1958 | security_free_mnt_opts(&data.lsm_opts); | ||
1901 | return error; | 1959 | return error; |
1902 | 1960 | ||
1903 | out_free: | 1961 | out_free: |
diff --git a/fs/nfs/write.c b/fs/nfs/write.c index f55c437124a2..bed63416a55b 100644 --- a/fs/nfs/write.c +++ b/fs/nfs/write.c | |||
@@ -39,6 +39,7 @@ static struct nfs_page * nfs_update_request(struct nfs_open_context*, | |||
39 | unsigned int, unsigned int); | 39 | unsigned int, unsigned int); |
40 | static void nfs_pageio_init_write(struct nfs_pageio_descriptor *desc, | 40 | static void nfs_pageio_init_write(struct nfs_pageio_descriptor *desc, |
41 | struct inode *inode, int ioflags); | 41 | struct inode *inode, int ioflags); |
42 | static void nfs_redirty_request(struct nfs_page *req); | ||
42 | static const struct rpc_call_ops nfs_write_partial_ops; | 43 | static const struct rpc_call_ops nfs_write_partial_ops; |
43 | static const struct rpc_call_ops nfs_write_full_ops; | 44 | static const struct rpc_call_ops nfs_write_full_ops; |
44 | static const struct rpc_call_ops nfs_commit_ops; | 45 | static const struct rpc_call_ops nfs_commit_ops; |
@@ -288,7 +289,12 @@ static int nfs_page_async_flush(struct nfs_pageio_descriptor *pgio, | |||
288 | BUG(); | 289 | BUG(); |
289 | } | 290 | } |
290 | spin_unlock(&inode->i_lock); | 291 | spin_unlock(&inode->i_lock); |
291 | nfs_pageio_add_request(pgio, req); | 292 | if (!nfs_pageio_add_request(pgio, req)) { |
293 | nfs_redirty_request(req); | ||
294 | nfs_end_page_writeback(page); | ||
295 | nfs_clear_page_tag_locked(req); | ||
296 | return pgio->pg_error; | ||
297 | } | ||
292 | return 0; | 298 | return 0; |
293 | } | 299 | } |
294 | 300 | ||
@@ -734,7 +740,7 @@ int nfs_updatepage(struct file *file, struct page *page, | |||
734 | */ | 740 | */ |
735 | if (nfs_write_pageuptodate(page, inode) && | 741 | if (nfs_write_pageuptodate(page, inode) && |
736 | inode->i_flock == NULL && | 742 | inode->i_flock == NULL && |
737 | !(file->f_mode & O_SYNC)) { | 743 | !(file->f_flags & O_SYNC)) { |
738 | count = max(count + offset, nfs_page_length(page)); | 744 | count = max(count + offset, nfs_page_length(page)); |
739 | offset = 0; | 745 | offset = 0; |
740 | } | 746 | } |