aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs/nfs4proc.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/nfs/nfs4proc.c')
-rw-r--r--fs/nfs/nfs4proc.c85
1 files changed, 36 insertions, 49 deletions
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index 4b90e17555a9..cb99fd90a9ac 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -62,10 +62,8 @@ struct nfs4_opendata;
62static int _nfs4_proc_open(struct nfs4_opendata *data); 62static int _nfs4_proc_open(struct nfs4_opendata *data);
63static int nfs4_do_fsinfo(struct nfs_server *, struct nfs_fh *, struct nfs_fsinfo *); 63static int nfs4_do_fsinfo(struct nfs_server *, struct nfs_fh *, struct nfs_fsinfo *);
64static int nfs4_async_handle_error(struct rpc_task *, const struct nfs_server *); 64static int nfs4_async_handle_error(struct rpc_task *, const struct nfs_server *);
65static int _nfs4_proc_access(struct inode *inode, struct nfs_access_entry *entry);
66static int nfs4_handle_exception(const struct nfs_server *server, int errorcode, struct nfs4_exception *exception); 65static int nfs4_handle_exception(const struct nfs_server *server, int errorcode, struct nfs4_exception *exception);
67static int nfs4_wait_clnt_recover(struct rpc_clnt *clnt, struct nfs_client *clp); 66static int nfs4_wait_clnt_recover(struct rpc_clnt *clnt, struct nfs_client *clp);
68static int _nfs4_do_access(struct inode *inode, struct rpc_cred *cred, int openflags);
69static int _nfs4_proc_lookup(struct inode *dir, const struct qstr *name, struct nfs_fh *fhandle, struct nfs_fattr *fattr); 67static int _nfs4_proc_lookup(struct inode *dir, const struct qstr *name, struct nfs_fh *fhandle, struct nfs_fattr *fattr);
70static int _nfs4_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle, struct nfs_fattr *fattr); 68static int _nfs4_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle, struct nfs_fattr *fattr);
71 69
@@ -177,7 +175,7 @@ static void nfs4_setup_readdir(u64 cookie, __be32 *verifier, struct dentry *dent
177 *p++ = xdr_one; /* bitmap length */ 175 *p++ = xdr_one; /* bitmap length */
178 *p++ = htonl(FATTR4_WORD0_FILEID); /* bitmap */ 176 *p++ = htonl(FATTR4_WORD0_FILEID); /* bitmap */
179 *p++ = htonl(8); /* attribute buffer length */ 177 *p++ = htonl(8); /* attribute buffer length */
180 p = xdr_encode_hyper(p, dentry->d_inode->i_ino); 178 p = xdr_encode_hyper(p, NFS_FILEID(dentry->d_inode));
181 } 179 }
182 180
183 *p++ = xdr_one; /* next */ 181 *p++ = xdr_one; /* next */
@@ -189,7 +187,7 @@ static void nfs4_setup_readdir(u64 cookie, __be32 *verifier, struct dentry *dent
189 *p++ = xdr_one; /* bitmap length */ 187 *p++ = xdr_one; /* bitmap length */
190 *p++ = htonl(FATTR4_WORD0_FILEID); /* bitmap */ 188 *p++ = htonl(FATTR4_WORD0_FILEID); /* bitmap */
191 *p++ = htonl(8); /* attribute buffer length */ 189 *p++ = htonl(8); /* attribute buffer length */
192 p = xdr_encode_hyper(p, dentry->d_parent->d_inode->i_ino); 190 p = xdr_encode_hyper(p, NFS_FILEID(dentry->d_parent->d_inode));
193 191
194 readdir->pgbase = (char *)p - (char *)start; 192 readdir->pgbase = (char *)p - (char *)start;
195 readdir->count -= readdir->pgbase; 193 readdir->count -= readdir->pgbase;
@@ -211,8 +209,9 @@ static void update_changeattr(struct inode *dir, struct nfs4_change_info *cinfo)
211 209
212 spin_lock(&dir->i_lock); 210 spin_lock(&dir->i_lock);
213 nfsi->cache_validity |= NFS_INO_INVALID_ATTR|NFS_INO_REVAL_PAGECACHE|NFS_INO_INVALID_DATA; 211 nfsi->cache_validity |= NFS_INO_INVALID_ATTR|NFS_INO_REVAL_PAGECACHE|NFS_INO_INVALID_DATA;
214 if (cinfo->before == nfsi->change_attr && cinfo->atomic) 212 if (!cinfo->atomic || cinfo->before != nfsi->change_attr)
215 nfsi->change_attr = cinfo->after; 213 nfsi->cache_change_attribute = jiffies;
214 nfsi->change_attr = cinfo->after;
216 spin_unlock(&dir->i_lock); 215 spin_unlock(&dir->i_lock);
217} 216}
218 217
@@ -454,7 +453,7 @@ static struct nfs4_state *nfs4_try_open_cached(struct nfs4_opendata *opendata)
454 memcpy(stateid.data, delegation->stateid.data, sizeof(stateid.data)); 453 memcpy(stateid.data, delegation->stateid.data, sizeof(stateid.data));
455 rcu_read_unlock(); 454 rcu_read_unlock();
456 lock_kernel(); 455 lock_kernel();
457 ret = _nfs4_do_access(state->inode, state->owner->so_cred, open_mode); 456 ret = nfs_may_open(state->inode, state->owner->so_cred, open_mode);
458 unlock_kernel(); 457 unlock_kernel();
459 if (ret != 0) 458 if (ret != 0)
460 goto out; 459 goto out;
@@ -948,36 +947,6 @@ static int _nfs4_proc_open(struct nfs4_opendata *data)
948 return 0; 947 return 0;
949} 948}
950 949
951static int _nfs4_do_access(struct inode *inode, struct rpc_cred *cred, int openflags)
952{
953 struct nfs_access_entry cache;
954 int mask = 0;
955 int status;
956
957 if (openflags & FMODE_READ)
958 mask |= MAY_READ;
959 if (openflags & FMODE_WRITE)
960 mask |= MAY_WRITE;
961 if (openflags & FMODE_EXEC)
962 mask |= MAY_EXEC;
963 status = nfs_access_get_cached(inode, cred, &cache);
964 if (status == 0)
965 goto out;
966
967 /* Be clever: ask server to check for all possible rights */
968 cache.mask = MAY_EXEC | MAY_WRITE | MAY_READ;
969 cache.cred = cred;
970 cache.jiffies = jiffies;
971 status = _nfs4_proc_access(inode, &cache);
972 if (status != 0)
973 return status;
974 nfs_access_add_cache(inode, &cache);
975out:
976 if ((cache.mask & mask) == mask)
977 return 0;
978 return -EACCES;
979}
980
981static int nfs4_recover_expired_lease(struct nfs_server *server) 950static int nfs4_recover_expired_lease(struct nfs_server *server)
982{ 951{
983 struct nfs_client *clp = server->nfs_client; 952 struct nfs_client *clp = server->nfs_client;
@@ -1381,7 +1350,7 @@ static int nfs4_intent_set_file(struct nameidata *nd, struct path *path, struct
1381 1350
1382 /* If the open_intent is for execute, we have an extra check to make */ 1351 /* If the open_intent is for execute, we have an extra check to make */
1383 if (nd->intent.open.flags & FMODE_EXEC) { 1352 if (nd->intent.open.flags & FMODE_EXEC) {
1384 ret = _nfs4_do_access(state->inode, 1353 ret = nfs_may_open(state->inode,
1385 state->owner->so_cred, 1354 state->owner->so_cred,
1386 nd->intent.open.flags); 1355 nd->intent.open.flags);
1387 if (ret < 0) 1356 if (ret < 0)
@@ -1390,7 +1359,7 @@ static int nfs4_intent_set_file(struct nameidata *nd, struct path *path, struct
1390 filp = lookup_instantiate_filp(nd, path->dentry, NULL); 1359 filp = lookup_instantiate_filp(nd, path->dentry, NULL);
1391 if (!IS_ERR(filp)) { 1360 if (!IS_ERR(filp)) {
1392 struct nfs_open_context *ctx; 1361 struct nfs_open_context *ctx;
1393 ctx = (struct nfs_open_context *)filp->private_data; 1362 ctx = nfs_file_open_context(filp);
1394 ctx->state = state; 1363 ctx->state = state;
1395 return 0; 1364 return 0;
1396 } 1365 }
@@ -1428,13 +1397,16 @@ nfs4_atomic_open(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
1428 state = nfs4_do_open(dir, &path, nd->intent.open.flags, &attr, cred); 1397 state = nfs4_do_open(dir, &path, nd->intent.open.flags, &attr, cred);
1429 put_rpccred(cred); 1398 put_rpccred(cred);
1430 if (IS_ERR(state)) { 1399 if (IS_ERR(state)) {
1431 if (PTR_ERR(state) == -ENOENT) 1400 if (PTR_ERR(state) == -ENOENT) {
1432 d_add(dentry, NULL); 1401 d_add(dentry, NULL);
1402 nfs_set_verifier(dentry, nfs_save_change_attribute(dir));
1403 }
1433 return (struct dentry *)state; 1404 return (struct dentry *)state;
1434 } 1405 }
1435 res = d_add_unique(dentry, igrab(state->inode)); 1406 res = d_add_unique(dentry, igrab(state->inode));
1436 if (res != NULL) 1407 if (res != NULL)
1437 path.dentry = res; 1408 path.dentry = res;
1409 nfs_set_verifier(path.dentry, nfs_save_change_attribute(dir));
1438 nfs4_intent_set_file(nd, &path, state); 1410 nfs4_intent_set_file(nd, &path, state);
1439 return res; 1411 return res;
1440} 1412}
@@ -1468,6 +1440,7 @@ nfs4_open_revalidate(struct inode *dir, struct dentry *dentry, int openflags, st
1468 } 1440 }
1469 } 1441 }
1470 if (state->inode == dentry->d_inode) { 1442 if (state->inode == dentry->d_inode) {
1443 nfs_set_verifier(dentry, nfs_save_change_attribute(dir));
1471 nfs4_intent_set_file(nd, &path, state); 1444 nfs4_intent_set_file(nd, &path, state);
1472 return 1; 1445 return 1;
1473 } 1446 }
@@ -1757,10 +1730,16 @@ static int nfs4_proc_lookup(struct inode *dir, struct qstr *name, struct nfs_fh
1757 1730
1758static int _nfs4_proc_access(struct inode *inode, struct nfs_access_entry *entry) 1731static int _nfs4_proc_access(struct inode *inode, struct nfs_access_entry *entry)
1759{ 1732{
1733 struct nfs_server *server = NFS_SERVER(inode);
1734 struct nfs_fattr fattr;
1760 struct nfs4_accessargs args = { 1735 struct nfs4_accessargs args = {
1761 .fh = NFS_FH(inode), 1736 .fh = NFS_FH(inode),
1737 .bitmask = server->attr_bitmask,
1738 };
1739 struct nfs4_accessres res = {
1740 .server = server,
1741 .fattr = &fattr,
1762 }; 1742 };
1763 struct nfs4_accessres res = { 0 };
1764 struct rpc_message msg = { 1743 struct rpc_message msg = {
1765 .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_ACCESS], 1744 .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_ACCESS],
1766 .rpc_argp = &args, 1745 .rpc_argp = &args,
@@ -1786,6 +1765,7 @@ static int _nfs4_proc_access(struct inode *inode, struct nfs_access_entry *entry
1786 if (mode & MAY_EXEC) 1765 if (mode & MAY_EXEC)
1787 args.access |= NFS4_ACCESS_EXECUTE; 1766 args.access |= NFS4_ACCESS_EXECUTE;
1788 } 1767 }
1768 nfs_fattr_init(&fattr);
1789 status = rpc_call_sync(NFS_CLIENT(inode), &msg, 0); 1769 status = rpc_call_sync(NFS_CLIENT(inode), &msg, 0);
1790 if (!status) { 1770 if (!status) {
1791 entry->mask = 0; 1771 entry->mask = 0;
@@ -1795,6 +1775,7 @@ static int _nfs4_proc_access(struct inode *inode, struct nfs_access_entry *entry
1795 entry->mask |= MAY_WRITE; 1775 entry->mask |= MAY_WRITE;
1796 if (res.access & (NFS4_ACCESS_LOOKUP|NFS4_ACCESS_EXECUTE)) 1776 if (res.access & (NFS4_ACCESS_LOOKUP|NFS4_ACCESS_EXECUTE))
1797 entry->mask |= MAY_EXEC; 1777 entry->mask |= MAY_EXEC;
1778 nfs_refresh_inode(inode, &fattr);
1798 } 1779 }
1799 return status; 1780 return status;
1800} 1781}
@@ -1900,11 +1881,13 @@ nfs4_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr,
1900 } 1881 }
1901 state = nfs4_do_open(dir, &path, flags, sattr, cred); 1882 state = nfs4_do_open(dir, &path, flags, sattr, cred);
1902 put_rpccred(cred); 1883 put_rpccred(cred);
1884 d_drop(dentry);
1903 if (IS_ERR(state)) { 1885 if (IS_ERR(state)) {
1904 status = PTR_ERR(state); 1886 status = PTR_ERR(state);
1905 goto out; 1887 goto out;
1906 } 1888 }
1907 d_instantiate(dentry, igrab(state->inode)); 1889 d_add(dentry, igrab(state->inode));
1890 nfs_set_verifier(dentry, nfs_save_change_attribute(dir));
1908 if (flags & O_EXCL) { 1891 if (flags & O_EXCL) {
1909 struct nfs_fattr fattr; 1892 struct nfs_fattr fattr;
1910 status = nfs4_do_setattr(state->inode, &fattr, sattr, state); 1893 status = nfs4_do_setattr(state->inode, &fattr, sattr, state);
@@ -2218,6 +2201,9 @@ static int _nfs4_proc_readdir(struct dentry *dentry, struct rpc_cred *cred,
2218 status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0); 2201 status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0);
2219 if (status == 0) 2202 if (status == 0)
2220 memcpy(NFS_COOKIEVERF(dir), res.verifier.data, NFS4_VERIFIER_SIZE); 2203 memcpy(NFS_COOKIEVERF(dir), res.verifier.data, NFS4_VERIFIER_SIZE);
2204
2205 nfs_invalidate_atime(dir);
2206
2221 dprintk("%s: returns %d\n", __FUNCTION__, status); 2207 dprintk("%s: returns %d\n", __FUNCTION__, status);
2222 return status; 2208 return status;
2223} 2209}
@@ -2414,6 +2400,8 @@ static int nfs4_read_done(struct rpc_task *task, struct nfs_read_data *data)
2414 rpc_restart_call(task); 2400 rpc_restart_call(task);
2415 return -EAGAIN; 2401 return -EAGAIN;
2416 } 2402 }
2403
2404 nfs_invalidate_atime(data->inode);
2417 if (task->tk_status > 0) 2405 if (task->tk_status > 0)
2418 renew_lease(server, data->timestamp); 2406 renew_lease(server, data->timestamp);
2419 return 0; 2407 return 0;
@@ -2443,7 +2431,7 @@ static int nfs4_write_done(struct rpc_task *task, struct nfs_write_data *data)
2443 } 2431 }
2444 if (task->tk_status >= 0) { 2432 if (task->tk_status >= 0) {
2445 renew_lease(NFS_SERVER(inode), data->timestamp); 2433 renew_lease(NFS_SERVER(inode), data->timestamp);
2446 nfs_post_op_update_inode(inode, data->res.fattr); 2434 nfs_post_op_update_inode_force_wcc(inode, data->res.fattr);
2447 } 2435 }
2448 return 0; 2436 return 0;
2449} 2437}
@@ -2485,8 +2473,7 @@ static int nfs4_commit_done(struct rpc_task *task, struct nfs_write_data *data)
2485 rpc_restart_call(task); 2473 rpc_restart_call(task);
2486 return -EAGAIN; 2474 return -EAGAIN;
2487 } 2475 }
2488 if (task->tk_status >= 0) 2476 nfs_refresh_inode(inode, data->res.fattr);
2489 nfs_post_op_update_inode(inode, data->res.fattr);
2490 return 0; 2477 return 0;
2491} 2478}
2492 2479
@@ -3056,7 +3043,7 @@ static int _nfs4_proc_delegreturn(struct inode *inode, struct rpc_cred *cred, co
3056 if (status == 0) { 3043 if (status == 0) {
3057 status = data->rpc_status; 3044 status = data->rpc_status;
3058 if (status == 0) 3045 if (status == 0)
3059 nfs_post_op_update_inode(inode, &data->fattr); 3046 nfs_refresh_inode(inode, &data->fattr);
3060 } 3047 }
3061 rpc_put_task(task); 3048 rpc_put_task(task);
3062 return status; 3049 return status;
@@ -3303,7 +3290,7 @@ static int nfs4_proc_unlck(struct nfs4_state *state, int cmd, struct file_lock *
3303 status = -ENOMEM; 3290 status = -ENOMEM;
3304 if (seqid == NULL) 3291 if (seqid == NULL)
3305 goto out; 3292 goto out;
3306 task = nfs4_do_unlck(request, request->fl_file->private_data, lsp, seqid); 3293 task = nfs4_do_unlck(request, nfs_file_open_context(request->fl_file), lsp, seqid);
3307 status = PTR_ERR(task); 3294 status = PTR_ERR(task);
3308 if (IS_ERR(task)) 3295 if (IS_ERR(task))
3309 goto out; 3296 goto out;
@@ -3447,7 +3434,7 @@ static int _nfs4_do_setlk(struct nfs4_state *state, int cmd, struct file_lock *f
3447 int ret; 3434 int ret;
3448 3435
3449 dprintk("%s: begin!\n", __FUNCTION__); 3436 dprintk("%s: begin!\n", __FUNCTION__);
3450 data = nfs4_alloc_lockdata(fl, fl->fl_file->private_data, 3437 data = nfs4_alloc_lockdata(fl, nfs_file_open_context(fl->fl_file),
3451 fl->fl_u.nfs4_fl.owner); 3438 fl->fl_u.nfs4_fl.owner);
3452 if (data == NULL) 3439 if (data == NULL)
3453 return -ENOMEM; 3440 return -ENOMEM;
@@ -3573,7 +3560,7 @@ nfs4_proc_lock(struct file *filp, int cmd, struct file_lock *request)
3573 int status; 3560 int status;
3574 3561
3575 /* verify open state */ 3562 /* verify open state */
3576 ctx = (struct nfs_open_context *)filp->private_data; 3563 ctx = nfs_file_open_context(filp);
3577 state = ctx->state; 3564 state = ctx->state;
3578 3565
3579 if (request->fl_start < 0 || request->fl_end < 0) 3566 if (request->fl_start < 0 || request->fl_end < 0)