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

* 'bugfixes' of git://git.linux-nfs.org/projects/trondmy/nfs-2.6:
NFS: Don't clobber the attribute type in nfs_update_inode()
NFS: Fix a umount race
NFS: Fix an Oops when truncating a file
NFS: Ensure that we handle NFS4ERR_STALE_STATEID correctly
NFSv4.1: Don't call nfs4_schedule_state_recovery() unnecessarily
NFSv4: Don't allow posix locking against servers that don't support it
NFSv4: Ensure that the NFSv4 locking can recover from stateid errors
NFS: Avoid warnings when CONFIG_NFS_V4=n
NFS: Make nfs_commitdata_release static
NFS: Try to commit unstable writes in nfs_release_page()
NFS: Fix a reference leak in nfs_wb_cancel_page()

+93 -32
+2
fs/nfs/file.c
··· 486 { 487 dfprintk(PAGECACHE, "NFS: release_page(%p)\n", page); 488 489 /* If PagePrivate() is set, then the page is not freeable */ 490 if (PagePrivate(page)) 491 return 0;
··· 486 { 487 dfprintk(PAGECACHE, "NFS: release_page(%p)\n", page); 488 489 + if (gfp & __GFP_WAIT) 490 + nfs_wb_page(page->mapping->host, page); 491 /* If PagePrivate() is set, then the page is not freeable */ 492 if (PagePrivate(page)) 493 return 0;
+3 -1
fs/nfs/inode.c
··· 1261 1262 if (fattr->valid & NFS_ATTR_FATTR_MODE) { 1263 if ((inode->i_mode & S_IALLUGO) != (fattr->mode & S_IALLUGO)) { 1264 invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL; 1265 - inode->i_mode = fattr->mode; 1266 } 1267 } else if (server->caps & NFS_CAP_MODE) 1268 invalid |= save_cache_validity & (NFS_INO_INVALID_ATTR
··· 1261 1262 if (fattr->valid & NFS_ATTR_FATTR_MODE) { 1263 if ((inode->i_mode & S_IALLUGO) != (fattr->mode & S_IALLUGO)) { 1264 + umode_t newmode = inode->i_mode & S_IFMT; 1265 + newmode |= fattr->mode & S_IALLUGO; 1266 + inode->i_mode = newmode; 1267 invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL; 1268 } 1269 } else if (server->caps & NFS_CAP_MODE) 1270 invalid |= save_cache_validity & (NFS_INO_INVALID_ATTR
+2
fs/nfs/nfs4_fs.h
··· 146 NFS_O_RDWR_STATE, /* OPEN stateid has read/write state */ 147 NFS_STATE_RECLAIM_REBOOT, /* OPEN stateid server rebooted */ 148 NFS_STATE_RECLAIM_NOGRACE, /* OPEN stateid needs to recover state */ 149 }; 150 151 struct nfs4_state { ··· 278 extern void nfs4_schedule_state_recovery(struct nfs_client *); 279 extern void nfs4_schedule_state_manager(struct nfs_client *); 280 extern int nfs4_state_mark_reclaim_nograce(struct nfs_client *clp, struct nfs4_state *state); 281 extern void nfs41_handle_sequence_flag_errors(struct nfs_client *clp, u32 flags); 282 extern void nfs4_put_lock_state(struct nfs4_lock_state *lsp); 283 extern int nfs4_set_lock_state(struct nfs4_state *state, struct file_lock *fl);
··· 146 NFS_O_RDWR_STATE, /* OPEN stateid has read/write state */ 147 NFS_STATE_RECLAIM_REBOOT, /* OPEN stateid server rebooted */ 148 NFS_STATE_RECLAIM_NOGRACE, /* OPEN stateid needs to recover state */ 149 + NFS_STATE_POSIX_LOCKS, /* Posix locks are supported */ 150 }; 151 152 struct nfs4_state { ··· 277 extern void nfs4_schedule_state_recovery(struct nfs_client *); 278 extern void nfs4_schedule_state_manager(struct nfs_client *); 279 extern int nfs4_state_mark_reclaim_nograce(struct nfs_client *clp, struct nfs4_state *state); 280 + extern int nfs4_state_mark_reclaim_reboot(struct nfs_client *clp, struct nfs4_state *state); 281 extern void nfs41_handle_sequence_flag_errors(struct nfs_client *clp, u32 flags); 282 extern void nfs4_put_lock_state(struct nfs4_lock_state *lsp); 283 extern int nfs4_set_lock_state(struct nfs4_state *state, struct file_lock *fl);
+58 -20
fs/nfs/nfs4proc.c
··· 249 if (state == NULL) 250 break; 251 nfs4_state_mark_reclaim_nograce(clp, state); 252 - case -NFS4ERR_STALE_CLIENTID: 253 case -NFS4ERR_STALE_STATEID: 254 - case -NFS4ERR_EXPIRED: 255 - nfs4_schedule_state_recovery(clp); 256 - ret = nfs4_wait_clnt_recover(clp); 257 - if (ret == 0) 258 - exception->retry = 1; 259 - #if !defined(CONFIG_NFS_V4_1) 260 - break; 261 - #else /* !defined(CONFIG_NFS_V4_1) */ 262 - if (!nfs4_has_session(server->nfs_client)) 263 break; 264 - /* FALLTHROUGH */ 265 case -NFS4ERR_BADSESSION: 266 case -NFS4ERR_BADSLOT: 267 case -NFS4ERR_BAD_HIGH_SLOT: ··· 270 nfs4_schedule_state_recovery(clp); 271 exception->retry = 1; 272 break; 273 - #endif /* !defined(CONFIG_NFS_V4_1) */ 274 case -NFS4ERR_FILE_OPEN: 275 if (exception->timeout > HZ) { 276 /* We have retried a decent amount, time to ··· 289 } 290 /* We failed to handle the error */ 291 return nfs4_map_errors(ret); 292 } 293 294 ··· 1660 status = PTR_ERR(state); 1661 if (IS_ERR(state)) 1662 goto err_opendata_put; 1663 nfs4_opendata_put(opendata); 1664 nfs4_put_state_owner(sp); 1665 *res = state; ··· 3426 if (state == NULL) 3427 break; 3428 nfs4_state_mark_reclaim_nograce(clp, state); 3429 - case -NFS4ERR_STALE_CLIENTID: 3430 case -NFS4ERR_STALE_STATEID: 3431 case -NFS4ERR_EXPIRED: 3432 - rpc_sleep_on(&clp->cl_rpcwaitq, task, NULL); 3433 - nfs4_schedule_state_recovery(clp); 3434 - if (test_bit(NFS4CLNT_MANAGER_RUNNING, &clp->cl_state) == 0) 3435 - rpc_wake_up_queued_task(&clp->cl_rpcwaitq, task); 3436 - task->tk_status = 0; 3437 - return -EAGAIN; 3438 #if defined(CONFIG_NFS_V4_1) 3439 case -NFS4ERR_BADSESSION: 3440 case -NFS4ERR_BADSLOT: ··· 3461 } 3462 task->tk_status = nfs4_map_errors(task->tk_status); 3463 return 0; 3464 } 3465 3466 static int ··· 4098 .rpc_release = nfs4_lock_release, 4099 }; 4100 4101 static int _nfs4_do_setlk(struct nfs4_state *state, int cmd, struct file_lock *fl, int recovery_type) 4102 { 4103 struct nfs4_lockdata *data; ··· 4158 ret = nfs4_wait_for_completion_rpc_task(task); 4159 if (ret == 0) { 4160 ret = data->rpc_status; 4161 } else 4162 data->cancelled = 1; 4163 rpc_put_task(task); ··· 4216 { 4217 struct nfs_inode *nfsi = NFS_I(state->inode); 4218 unsigned char fl_flags = request->fl_flags; 4219 - int status; 4220 4221 /* Is this a delegated open? */ 4222 status = nfs4_set_lock_state(state, request); 4223 if (status != 0)
··· 249 if (state == NULL) 250 break; 251 nfs4_state_mark_reclaim_nograce(clp, state); 252 + goto do_state_recovery; 253 case -NFS4ERR_STALE_STATEID: 254 + if (state == NULL) 255 break; 256 + nfs4_state_mark_reclaim_reboot(clp, state); 257 + case -NFS4ERR_STALE_CLIENTID: 258 + case -NFS4ERR_EXPIRED: 259 + goto do_state_recovery; 260 + #if defined(CONFIG_NFS_V4_1) 261 case -NFS4ERR_BADSESSION: 262 case -NFS4ERR_BADSLOT: 263 case -NFS4ERR_BAD_HIGH_SLOT: ··· 274 nfs4_schedule_state_recovery(clp); 275 exception->retry = 1; 276 break; 277 + #endif /* defined(CONFIG_NFS_V4_1) */ 278 case -NFS4ERR_FILE_OPEN: 279 if (exception->timeout > HZ) { 280 /* We have retried a decent amount, time to ··· 293 } 294 /* We failed to handle the error */ 295 return nfs4_map_errors(ret); 296 + do_state_recovery: 297 + nfs4_schedule_state_recovery(clp); 298 + ret = nfs4_wait_clnt_recover(clp); 299 + if (ret == 0) 300 + exception->retry = 1; 301 + return ret; 302 } 303 304 ··· 1658 status = PTR_ERR(state); 1659 if (IS_ERR(state)) 1660 goto err_opendata_put; 1661 + if ((opendata->o_res.rflags & NFS4_OPEN_RESULT_LOCKTYPE_POSIX) != 0) 1662 + set_bit(NFS_STATE_POSIX_LOCKS, &state->flags); 1663 nfs4_opendata_put(opendata); 1664 nfs4_put_state_owner(sp); 1665 *res = state; ··· 3422 if (state == NULL) 3423 break; 3424 nfs4_state_mark_reclaim_nograce(clp, state); 3425 + goto do_state_recovery; 3426 case -NFS4ERR_STALE_STATEID: 3427 + if (state == NULL) 3428 + break; 3429 + nfs4_state_mark_reclaim_reboot(clp, state); 3430 + case -NFS4ERR_STALE_CLIENTID: 3431 case -NFS4ERR_EXPIRED: 3432 + goto do_state_recovery; 3433 #if defined(CONFIG_NFS_V4_1) 3434 case -NFS4ERR_BADSESSION: 3435 case -NFS4ERR_BADSLOT: ··· 3458 } 3459 task->tk_status = nfs4_map_errors(task->tk_status); 3460 return 0; 3461 + do_state_recovery: 3462 + rpc_sleep_on(&clp->cl_rpcwaitq, task, NULL); 3463 + nfs4_schedule_state_recovery(clp); 3464 + if (test_bit(NFS4CLNT_MANAGER_RUNNING, &clp->cl_state) == 0) 3465 + rpc_wake_up_queued_task(&clp->cl_rpcwaitq, task); 3466 + task->tk_status = 0; 3467 + return -EAGAIN; 3468 } 3469 3470 static int ··· 4088 .rpc_release = nfs4_lock_release, 4089 }; 4090 4091 + static void nfs4_handle_setlk_error(struct nfs_server *server, struct nfs4_lock_state *lsp, int new_lock_owner, int error) 4092 + { 4093 + struct nfs_client *clp = server->nfs_client; 4094 + struct nfs4_state *state = lsp->ls_state; 4095 + 4096 + switch (error) { 4097 + case -NFS4ERR_ADMIN_REVOKED: 4098 + case -NFS4ERR_BAD_STATEID: 4099 + case -NFS4ERR_EXPIRED: 4100 + if (new_lock_owner != 0 || 4101 + (lsp->ls_flags & NFS_LOCK_INITIALIZED) != 0) 4102 + nfs4_state_mark_reclaim_nograce(clp, state); 4103 + lsp->ls_seqid.flags &= ~NFS_SEQID_CONFIRMED; 4104 + break; 4105 + case -NFS4ERR_STALE_STATEID: 4106 + if (new_lock_owner != 0 || 4107 + (lsp->ls_flags & NFS_LOCK_INITIALIZED) != 0) 4108 + nfs4_state_mark_reclaim_reboot(clp, state); 4109 + lsp->ls_seqid.flags &= ~NFS_SEQID_CONFIRMED; 4110 + }; 4111 + } 4112 + 4113 static int _nfs4_do_setlk(struct nfs4_state *state, int cmd, struct file_lock *fl, int recovery_type) 4114 { 4115 struct nfs4_lockdata *data; ··· 4126 ret = nfs4_wait_for_completion_rpc_task(task); 4127 if (ret == 0) { 4128 ret = data->rpc_status; 4129 + if (ret) 4130 + nfs4_handle_setlk_error(data->server, data->lsp, 4131 + data->arg.new_lock_owner, ret); 4132 } else 4133 data->cancelled = 1; 4134 rpc_put_task(task); ··· 4181 { 4182 struct nfs_inode *nfsi = NFS_I(state->inode); 4183 unsigned char fl_flags = request->fl_flags; 4184 + int status = -ENOLCK; 4185 4186 + if ((fl_flags & FL_POSIX) && 4187 + !test_bit(NFS_STATE_POSIX_LOCKS, &state->flags)) 4188 + goto out; 4189 /* Is this a delegated open? */ 4190 status = nfs4_set_lock_state(state, request); 4191 if (status != 0)
+1 -1
fs/nfs/nfs4state.c
··· 901 nfs4_schedule_state_manager(clp); 902 } 903 904 - static int nfs4_state_mark_reclaim_reboot(struct nfs_client *clp, struct nfs4_state *state) 905 { 906 907 set_bit(NFS_STATE_RECLAIM_REBOOT, &state->flags);
··· 901 nfs4_schedule_state_manager(clp); 902 } 903 904 + int nfs4_state_mark_reclaim_reboot(struct nfs_client *clp, struct nfs4_state *state) 905 { 906 907 set_bit(NFS_STATE_RECLAIM_REBOOT, &state->flags);
+9 -8
fs/nfs/pagelist.c
··· 176 kref_put(&req->wb_kref, nfs_free_request); 177 } 178 179 /** 180 * nfs_wait_on_request - Wait for a request to complete. 181 * @req: request to wait upon. ··· 192 int 193 nfs_wait_on_request(struct nfs_page *req) 194 { 195 - int ret = 0; 196 - 197 - if (!test_bit(PG_BUSY, &req->wb_flags)) 198 - goto out; 199 - ret = out_of_line_wait_on_bit(&req->wb_flags, PG_BUSY, 200 - nfs_wait_bit_killable, TASK_KILLABLE); 201 - out: 202 - return ret; 203 } 204 205 /**
··· 176 kref_put(&req->wb_kref, nfs_free_request); 177 } 178 179 + static int nfs_wait_bit_uninterruptible(void *word) 180 + { 181 + io_schedule(); 182 + return 0; 183 + } 184 + 185 /** 186 * nfs_wait_on_request - Wait for a request to complete. 187 * @req: request to wait upon. ··· 186 int 187 nfs_wait_on_request(struct nfs_page *req) 188 { 189 + return wait_on_bit(&req->wb_flags, PG_BUSY, 190 + nfs_wait_bit_uninterruptible, 191 + TASK_UNINTERRUPTIBLE); 192 } 193 194 /**
+14 -1
fs/nfs/super.c
··· 243 static int nfs_get_sb(struct file_system_type *, int, const char *, void *, struct vfsmount *); 244 static int nfs_xdev_get_sb(struct file_system_type *fs_type, 245 int flags, const char *dev_name, void *raw_data, struct vfsmount *mnt); 246 static void nfs_kill_super(struct super_block *); 247 static int nfs_remount(struct super_block *sb, int *flags, char *raw_data); 248 ··· 267 .alloc_inode = nfs_alloc_inode, 268 .destroy_inode = nfs_destroy_inode, 269 .write_inode = nfs_write_inode, 270 .statfs = nfs_statfs, 271 .clear_inode = nfs_clear_inode, 272 .umount_begin = nfs_umount_begin, ··· 337 .alloc_inode = nfs_alloc_inode, 338 .destroy_inode = nfs_destroy_inode, 339 .write_inode = nfs_write_inode, 340 .statfs = nfs_statfs, 341 .clear_inode = nfs4_clear_inode, 342 .umount_begin = nfs_umount_begin, ··· 2261 } 2262 2263 /* 2264 * Destroy an NFS2/3 superblock 2265 */ 2266 static void nfs_kill_super(struct super_block *s) ··· 2279 struct nfs_server *server = NFS_SB(s); 2280 2281 kill_anon_super(s); 2282 - bdi_unregister(&server->backing_dev_info); 2283 nfs_fscache_release_super_cookie(s); 2284 nfs_free_server(server); 2285 }
··· 243 static int nfs_get_sb(struct file_system_type *, int, const char *, void *, struct vfsmount *); 244 static int nfs_xdev_get_sb(struct file_system_type *fs_type, 245 int flags, const char *dev_name, void *raw_data, struct vfsmount *mnt); 246 + static void nfs_put_super(struct super_block *); 247 static void nfs_kill_super(struct super_block *); 248 static int nfs_remount(struct super_block *sb, int *flags, char *raw_data); 249 ··· 266 .alloc_inode = nfs_alloc_inode, 267 .destroy_inode = nfs_destroy_inode, 268 .write_inode = nfs_write_inode, 269 + .put_super = nfs_put_super, 270 .statfs = nfs_statfs, 271 .clear_inode = nfs_clear_inode, 272 .umount_begin = nfs_umount_begin, ··· 335 .alloc_inode = nfs_alloc_inode, 336 .destroy_inode = nfs_destroy_inode, 337 .write_inode = nfs_write_inode, 338 + .put_super = nfs_put_super, 339 .statfs = nfs_statfs, 340 .clear_inode = nfs4_clear_inode, 341 .umount_begin = nfs_umount_begin, ··· 2258 } 2259 2260 /* 2261 + * Ensure that we unregister the bdi before kill_anon_super 2262 + * releases the device name 2263 + */ 2264 + static void nfs_put_super(struct super_block *s) 2265 + { 2266 + struct nfs_server *server = NFS_SB(s); 2267 + 2268 + bdi_unregister(&server->backing_dev_info); 2269 + } 2270 + 2271 + /* 2272 * Destroy an NFS2/3 superblock 2273 */ 2274 static void nfs_kill_super(struct super_block *s) ··· 2265 struct nfs_server *server = NFS_SB(s); 2266 2267 kill_anon_super(s); 2268 nfs_fscache_release_super_cookie(s); 2269 nfs_free_server(server); 2270 }
+2
fs/nfs/sysctl.c
··· 15 16 #include "callback.h" 17 18 static const int nfs_set_port_min = 0; 19 static const int nfs_set_port_max = 65535; 20 static struct ctl_table_header *nfs_callback_sysctl_table; 21 22 static ctl_table nfs_cb_sysctls[] = {
··· 15 16 #include "callback.h" 17 18 + #ifdef CONFIG_NFS_V4 19 static const int nfs_set_port_min = 0; 20 static const int nfs_set_port_max = 65535; 21 + #endif 22 static struct ctl_table_header *nfs_callback_sysctl_table; 23 24 static ctl_table nfs_cb_sysctls[] = {
+2 -1
fs/nfs/write.c
··· 1233 1234 1235 #if defined(CONFIG_NFS_V3) || defined(CONFIG_NFS_V4) 1236 - void nfs_commitdata_release(void *data) 1237 { 1238 struct nfs_write_data *wdata = data; 1239 ··· 1541 break; 1542 } 1543 ret = nfs_wait_on_request(req); 1544 if (ret < 0) 1545 goto out; 1546 }
··· 1233 1234 1235 #if defined(CONFIG_NFS_V3) || defined(CONFIG_NFS_V4) 1236 + static void nfs_commitdata_release(void *data) 1237 { 1238 struct nfs_write_data *wdata = data; 1239 ··· 1541 break; 1542 } 1543 ret = nfs_wait_on_request(req); 1544 + nfs_release_request(req); 1545 if (ret < 0) 1546 goto out; 1547 }