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.c429
1 files changed, 339 insertions, 90 deletions
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index 1d5cb3e80c3e..1b76f80aedb9 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -48,6 +48,7 @@
48#include <linux/smp_lock.h> 48#include <linux/smp_lock.h>
49#include <linux/namei.h> 49#include <linux/namei.h>
50 50
51#include "nfs4_fs.h"
51#include "delegation.h" 52#include "delegation.h"
52 53
53#define NFSDBG_FACILITY NFSDBG_PROC 54#define NFSDBG_FACILITY NFSDBG_PROC
@@ -62,8 +63,6 @@ static int nfs4_handle_exception(struct nfs_server *server, int errorcode, struc
62extern u32 *nfs4_decode_dirent(u32 *p, struct nfs_entry *entry, int plus); 63extern u32 *nfs4_decode_dirent(u32 *p, struct nfs_entry *entry, int plus);
63extern struct rpc_procinfo nfs4_procedures[]; 64extern struct rpc_procinfo nfs4_procedures[];
64 65
65extern nfs4_stateid zero_stateid;
66
67/* Prevent leaks of NFSv4 errors into userland */ 66/* Prevent leaks of NFSv4 errors into userland */
68int nfs4_map_errors(int err) 67int nfs4_map_errors(int err)
69{ 68{
@@ -104,7 +103,7 @@ const u32 nfs4_statfs_bitmap[2] = {
104 | FATTR4_WORD1_SPACE_TOTAL 103 | FATTR4_WORD1_SPACE_TOTAL
105}; 104};
106 105
107u32 nfs4_pathconf_bitmap[2] = { 106const u32 nfs4_pathconf_bitmap[2] = {
108 FATTR4_WORD0_MAXLINK 107 FATTR4_WORD0_MAXLINK
109 | FATTR4_WORD0_MAXNAME, 108 | FATTR4_WORD0_MAXNAME,
110 0 109 0
@@ -124,7 +123,7 @@ static void nfs4_setup_readdir(u64 cookie, u32 *verifier, struct dentry *dentry,
124 123
125 BUG_ON(readdir->count < 80); 124 BUG_ON(readdir->count < 80);
126 if (cookie > 2) { 125 if (cookie > 2) {
127 readdir->cookie = (cookie > 2) ? cookie : 0; 126 readdir->cookie = cookie;
128 memcpy(&readdir->verifier, verifier, sizeof(readdir->verifier)); 127 memcpy(&readdir->verifier, verifier, sizeof(readdir->verifier));
129 return; 128 return;
130 } 129 }
@@ -270,14 +269,9 @@ static int nfs4_open_reclaim(struct nfs4_state_owner *sp, struct nfs4_state *sta
270 int err; 269 int err;
271 do { 270 do {
272 err = _nfs4_open_reclaim(sp, state); 271 err = _nfs4_open_reclaim(sp, state);
273 switch (err) { 272 if (err != -NFS4ERR_DELAY)
274 case 0: 273 break;
275 case -NFS4ERR_STALE_CLIENTID: 274 nfs4_handle_exception(server, err, &exception);
276 case -NFS4ERR_STALE_STATEID:
277 case -NFS4ERR_EXPIRED:
278 return err;
279 }
280 err = nfs4_handle_exception(server, err, &exception);
281 } while (exception.retry); 275 } while (exception.retry);
282 return err; 276 return err;
283} 277}
@@ -509,6 +503,20 @@ out_stale:
509 goto out_nodeleg; 503 goto out_nodeleg;
510} 504}
511 505
506static inline int nfs4_do_open_expired(struct nfs4_state_owner *sp, struct nfs4_state *state, struct dentry *dentry)
507{
508 struct nfs_server *server = NFS_SERVER(dentry->d_inode);
509 struct nfs4_exception exception = { };
510 int err;
511
512 do {
513 err = _nfs4_open_expired(sp, state, dentry);
514 if (err == -NFS4ERR_DELAY)
515 nfs4_handle_exception(server, err, &exception);
516 } while (exception.retry);
517 return err;
518}
519
512static int nfs4_open_expired(struct nfs4_state_owner *sp, struct nfs4_state *state) 520static int nfs4_open_expired(struct nfs4_state_owner *sp, struct nfs4_state *state)
513{ 521{
514 struct nfs_inode *nfsi = NFS_I(state->inode); 522 struct nfs_inode *nfsi = NFS_I(state->inode);
@@ -521,7 +529,7 @@ static int nfs4_open_expired(struct nfs4_state_owner *sp, struct nfs4_state *sta
521 continue; 529 continue;
522 get_nfs_open_context(ctx); 530 get_nfs_open_context(ctx);
523 spin_unlock(&state->inode->i_lock); 531 spin_unlock(&state->inode->i_lock);
524 status = _nfs4_open_expired(sp, state, ctx->dentry); 532 status = nfs4_do_open_expired(sp, state, ctx->dentry);
525 put_nfs_open_context(ctx); 533 put_nfs_open_context(ctx);
526 return status; 534 return status;
527 } 535 }
@@ -748,11 +756,10 @@ static int _nfs4_do_setattr(struct nfs_server *server, struct nfs_fattr *fattr,
748 756
749 fattr->valid = 0; 757 fattr->valid = 0;
750 758
751 if (state != NULL) 759 if (state != NULL) {
752 msg.rpc_cred = state->owner->so_cred; 760 msg.rpc_cred = state->owner->so_cred;
753 if (sattr->ia_valid & ATTR_SIZE) 761 nfs4_copy_stateid(&arg.stateid, state, current->files);
754 nfs4_copy_stateid(&arg.stateid, state, NULL); 762 } else
755 else
756 memcpy(&arg.stateid, &zero_stateid, sizeof(arg.stateid)); 763 memcpy(&arg.stateid, &zero_stateid, sizeof(arg.stateid));
757 764
758 return rpc_call_sync(server->client, &msg, 0); 765 return rpc_call_sync(server->client, &msg, 0);
@@ -1116,47 +1123,31 @@ static int
1116nfs4_proc_setattr(struct dentry *dentry, struct nfs_fattr *fattr, 1123nfs4_proc_setattr(struct dentry *dentry, struct nfs_fattr *fattr,
1117 struct iattr *sattr) 1124 struct iattr *sattr)
1118{ 1125{
1119 struct inode * inode = dentry->d_inode; 1126 struct rpc_cred *cred;
1120 int size_change = sattr->ia_valid & ATTR_SIZE; 1127 struct inode *inode = dentry->d_inode;
1121 struct nfs4_state *state = NULL; 1128 struct nfs4_state *state;
1122 int need_iput = 0;
1123 int status; 1129 int status;
1124 1130
1125 fattr->valid = 0; 1131 fattr->valid = 0;
1126 1132
1127 if (size_change) { 1133 cred = rpcauth_lookupcred(NFS_SERVER(inode)->client->cl_auth, 0);
1128 struct rpc_cred *cred = rpcauth_lookupcred(NFS_SERVER(inode)->client->cl_auth, 0); 1134 if (IS_ERR(cred))
1129 if (IS_ERR(cred)) 1135 return PTR_ERR(cred);
1130 return PTR_ERR(cred); 1136 /* Search for an existing WRITE delegation first */
1137 state = nfs4_open_delegated(inode, FMODE_WRITE, cred);
1138 if (!IS_ERR(state)) {
1139 /* NB: nfs4_open_delegated() bumps the inode->i_count */
1140 iput(inode);
1141 } else {
1142 /* Search for an existing open(O_WRITE) stateid */
1131 state = nfs4_find_state(inode, cred, FMODE_WRITE); 1143 state = nfs4_find_state(inode, cred, FMODE_WRITE);
1132 if (state == NULL) {
1133 state = nfs4_open_delegated(dentry->d_inode,
1134 FMODE_WRITE, cred);
1135 if (IS_ERR(state))
1136 state = nfs4_do_open(dentry->d_parent->d_inode,
1137 dentry, FMODE_WRITE,
1138 NULL, cred);
1139 need_iput = 1;
1140 }
1141 put_rpccred(cred);
1142 if (IS_ERR(state))
1143 return PTR_ERR(state);
1144
1145 if (state->inode != inode) {
1146 printk(KERN_WARNING "nfs: raced in setattr (%p != %p), returning -EIO\n", inode, state->inode);
1147 status = -EIO;
1148 goto out;
1149 }
1150 } 1144 }
1145
1151 status = nfs4_do_setattr(NFS_SERVER(inode), fattr, 1146 status = nfs4_do_setattr(NFS_SERVER(inode), fattr,
1152 NFS_FH(inode), sattr, state); 1147 NFS_FH(inode), sattr, state);
1153out: 1148 if (state != NULL)
1154 if (state) {
1155 inode = state->inode;
1156 nfs4_close_state(state, FMODE_WRITE); 1149 nfs4_close_state(state, FMODE_WRITE);
1157 if (need_iput) 1150 put_rpccred(cred);
1158 iput(inode);
1159 }
1160 return status; 1151 return status;
1161} 1152}
1162 1153
@@ -1731,6 +1722,10 @@ static int _nfs4_proc_readdir(struct dentry *dentry, struct rpc_cred *cred,
1731 }; 1722 };
1732 int status; 1723 int status;
1733 1724
1725 dprintk("%s: dentry = %s/%s, cookie = %Lu\n", __FUNCTION__,
1726 dentry->d_parent->d_name.name,
1727 dentry->d_name.name,
1728 (unsigned long long)cookie);
1734 lock_kernel(); 1729 lock_kernel();
1735 nfs4_setup_readdir(cookie, NFS_COOKIEVERF(dir), dentry, &args); 1730 nfs4_setup_readdir(cookie, NFS_COOKIEVERF(dir), dentry, &args);
1736 res.pgbase = args.pgbase; 1731 res.pgbase = args.pgbase;
@@ -1738,6 +1733,7 @@ static int _nfs4_proc_readdir(struct dentry *dentry, struct rpc_cred *cred,
1738 if (status == 0) 1733 if (status == 0)
1739 memcpy(NFS_COOKIEVERF(dir), res.verifier.data, NFS4_VERIFIER_SIZE); 1734 memcpy(NFS_COOKIEVERF(dir), res.verifier.data, NFS4_VERIFIER_SIZE);
1740 unlock_kernel(); 1735 unlock_kernel();
1736 dprintk("%s: returns %d\n", __FUNCTION__, status);
1741 return status; 1737 return status;
1742} 1738}
1743 1739
@@ -2163,6 +2159,193 @@ nfs4_proc_file_release(struct inode *inode, struct file *filp)
2163 return 0; 2159 return 0;
2164} 2160}
2165 2161
2162static inline int nfs4_server_supports_acls(struct nfs_server *server)
2163{
2164 return (server->caps & NFS_CAP_ACLS)
2165 && (server->acl_bitmask & ACL4_SUPPORT_ALLOW_ACL)
2166 && (server->acl_bitmask & ACL4_SUPPORT_DENY_ACL);
2167}
2168
2169/* Assuming that XATTR_SIZE_MAX is a multiple of PAGE_CACHE_SIZE, and that
2170 * it's OK to put sizeof(void) * (XATTR_SIZE_MAX/PAGE_CACHE_SIZE) bytes on
2171 * the stack.
2172 */
2173#define NFS4ACL_MAXPAGES (XATTR_SIZE_MAX >> PAGE_CACHE_SHIFT)
2174
2175static void buf_to_pages(const void *buf, size_t buflen,
2176 struct page **pages, unsigned int *pgbase)
2177{
2178 const void *p = buf;
2179
2180 *pgbase = offset_in_page(buf);
2181 p -= *pgbase;
2182 while (p < buf + buflen) {
2183 *(pages++) = virt_to_page(p);
2184 p += PAGE_CACHE_SIZE;
2185 }
2186}
2187
2188struct nfs4_cached_acl {
2189 int cached;
2190 size_t len;
2191 char data[0];
2192};
2193
2194static void nfs4_set_cached_acl(struct inode *inode, struct nfs4_cached_acl *acl)
2195{
2196 struct nfs_inode *nfsi = NFS_I(inode);
2197
2198 spin_lock(&inode->i_lock);
2199 kfree(nfsi->nfs4_acl);
2200 nfsi->nfs4_acl = acl;
2201 spin_unlock(&inode->i_lock);
2202}
2203
2204static void nfs4_zap_acl_attr(struct inode *inode)
2205{
2206 nfs4_set_cached_acl(inode, NULL);
2207}
2208
2209static inline ssize_t nfs4_read_cached_acl(struct inode *inode, char *buf, size_t buflen)
2210{
2211 struct nfs_inode *nfsi = NFS_I(inode);
2212 struct nfs4_cached_acl *acl;
2213 int ret = -ENOENT;
2214
2215 spin_lock(&inode->i_lock);
2216 acl = nfsi->nfs4_acl;
2217 if (acl == NULL)
2218 goto out;
2219 if (buf == NULL) /* user is just asking for length */
2220 goto out_len;
2221 if (acl->cached == 0)
2222 goto out;
2223 ret = -ERANGE; /* see getxattr(2) man page */
2224 if (acl->len > buflen)
2225 goto out;
2226 memcpy(buf, acl->data, acl->len);
2227out_len:
2228 ret = acl->len;
2229out:
2230 spin_unlock(&inode->i_lock);
2231 return ret;
2232}
2233
2234static void nfs4_write_cached_acl(struct inode *inode, const char *buf, size_t acl_len)
2235{
2236 struct nfs4_cached_acl *acl;
2237
2238 if (buf && acl_len <= PAGE_SIZE) {
2239 acl = kmalloc(sizeof(*acl) + acl_len, GFP_KERNEL);
2240 if (acl == NULL)
2241 goto out;
2242 acl->cached = 1;
2243 memcpy(acl->data, buf, acl_len);
2244 } else {
2245 acl = kmalloc(sizeof(*acl), GFP_KERNEL);
2246 if (acl == NULL)
2247 goto out;
2248 acl->cached = 0;
2249 }
2250 acl->len = acl_len;
2251out:
2252 nfs4_set_cached_acl(inode, acl);
2253}
2254
2255static inline ssize_t nfs4_get_acl_uncached(struct inode *inode, void *buf, size_t buflen)
2256{
2257 struct page *pages[NFS4ACL_MAXPAGES];
2258 struct nfs_getaclargs args = {
2259 .fh = NFS_FH(inode),
2260 .acl_pages = pages,
2261 .acl_len = buflen,
2262 };
2263 size_t resp_len = buflen;
2264 void *resp_buf;
2265 struct rpc_message msg = {
2266 .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_GETACL],
2267 .rpc_argp = &args,
2268 .rpc_resp = &resp_len,
2269 };
2270 struct page *localpage = NULL;
2271 int ret;
2272
2273 if (buflen < PAGE_SIZE) {
2274 /* As long as we're doing a round trip to the server anyway,
2275 * let's be prepared for a page of acl data. */
2276 localpage = alloc_page(GFP_KERNEL);
2277 resp_buf = page_address(localpage);
2278 if (localpage == NULL)
2279 return -ENOMEM;
2280 args.acl_pages[0] = localpage;
2281 args.acl_pgbase = 0;
2282 args.acl_len = PAGE_SIZE;
2283 } else {
2284 resp_buf = buf;
2285 buf_to_pages(buf, buflen, args.acl_pages, &args.acl_pgbase);
2286 }
2287 ret = rpc_call_sync(NFS_CLIENT(inode), &msg, 0);
2288 if (ret)
2289 goto out_free;
2290 if (resp_len > args.acl_len)
2291 nfs4_write_cached_acl(inode, NULL, resp_len);
2292 else
2293 nfs4_write_cached_acl(inode, resp_buf, resp_len);
2294 if (buf) {
2295 ret = -ERANGE;
2296 if (resp_len > buflen)
2297 goto out_free;
2298 if (localpage)
2299 memcpy(buf, resp_buf, resp_len);
2300 }
2301 ret = resp_len;
2302out_free:
2303 if (localpage)
2304 __free_page(localpage);
2305 return ret;
2306}
2307
2308static ssize_t nfs4_proc_get_acl(struct inode *inode, void *buf, size_t buflen)
2309{
2310 struct nfs_server *server = NFS_SERVER(inode);
2311 int ret;
2312
2313 if (!nfs4_server_supports_acls(server))
2314 return -EOPNOTSUPP;
2315 ret = nfs_revalidate_inode(server, inode);
2316 if (ret < 0)
2317 return ret;
2318 ret = nfs4_read_cached_acl(inode, buf, buflen);
2319 if (ret != -ENOENT)
2320 return ret;
2321 return nfs4_get_acl_uncached(inode, buf, buflen);
2322}
2323
2324static int nfs4_proc_set_acl(struct inode *inode, const void *buf, size_t buflen)
2325{
2326 struct nfs_server *server = NFS_SERVER(inode);
2327 struct page *pages[NFS4ACL_MAXPAGES];
2328 struct nfs_setaclargs arg = {
2329 .fh = NFS_FH(inode),
2330 .acl_pages = pages,
2331 .acl_len = buflen,
2332 };
2333 struct rpc_message msg = {
2334 .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_SETACL],
2335 .rpc_argp = &arg,
2336 .rpc_resp = NULL,
2337 };
2338 int ret;
2339
2340 if (!nfs4_server_supports_acls(server))
2341 return -EOPNOTSUPP;
2342 buf_to_pages(buf, buflen, arg.acl_pages, &arg.acl_pgbase);
2343 ret = rpc_call_sync(NFS_SERVER(inode)->client, &msg, 0);
2344 if (ret == 0)
2345 nfs4_write_cached_acl(inode, buf, buflen);
2346 return ret;
2347}
2348
2166static int 2349static int
2167nfs4_async_handle_error(struct rpc_task *task, struct nfs_server *server) 2350nfs4_async_handle_error(struct rpc_task *task, struct nfs_server *server)
2168{ 2351{
@@ -2448,14 +2631,11 @@ static int _nfs4_proc_getlk(struct nfs4_state *state, int cmd, struct file_lock
2448 down_read(&clp->cl_sem); 2631 down_read(&clp->cl_sem);
2449 nlo.clientid = clp->cl_clientid; 2632 nlo.clientid = clp->cl_clientid;
2450 down(&state->lock_sema); 2633 down(&state->lock_sema);
2451 lsp = nfs4_find_lock_state(state, request->fl_owner); 2634 status = nfs4_set_lock_state(state, request);
2452 if (lsp) 2635 if (status != 0)
2453 nlo.id = lsp->ls_id; 2636 goto out;
2454 else { 2637 lsp = request->fl_u.nfs4_fl.owner;
2455 spin_lock(&clp->cl_lock); 2638 nlo.id = lsp->ls_id;
2456 nlo.id = nfs4_alloc_lockowner_id(clp);
2457 spin_unlock(&clp->cl_lock);
2458 }
2459 arg.u.lockt = &nlo; 2639 arg.u.lockt = &nlo;
2460 status = rpc_call_sync(server->client, &msg, 0); 2640 status = rpc_call_sync(server->client, &msg, 0);
2461 if (!status) { 2641 if (!status) {
@@ -2476,8 +2656,7 @@ static int _nfs4_proc_getlk(struct nfs4_state *state, int cmd, struct file_lock
2476 request->fl_pid = 0; 2656 request->fl_pid = 0;
2477 status = 0; 2657 status = 0;
2478 } 2658 }
2479 if (lsp) 2659out:
2480 nfs4_put_lock_state(lsp);
2481 up(&state->lock_sema); 2660 up(&state->lock_sema);
2482 up_read(&clp->cl_sem); 2661 up_read(&clp->cl_sem);
2483 return status; 2662 return status;
@@ -2537,28 +2716,26 @@ static int _nfs4_proc_unlck(struct nfs4_state *state, int cmd, struct file_lock
2537 }; 2716 };
2538 struct nfs4_lock_state *lsp; 2717 struct nfs4_lock_state *lsp;
2539 struct nfs_locku_opargs luargs; 2718 struct nfs_locku_opargs luargs;
2540 int status = 0; 2719 int status;
2541 2720
2542 down_read(&clp->cl_sem); 2721 down_read(&clp->cl_sem);
2543 down(&state->lock_sema); 2722 down(&state->lock_sema);
2544 lsp = nfs4_find_lock_state(state, request->fl_owner); 2723 status = nfs4_set_lock_state(state, request);
2545 if (!lsp) 2724 if (status != 0)
2546 goto out; 2725 goto out;
2726 lsp = request->fl_u.nfs4_fl.owner;
2547 /* We might have lost the locks! */ 2727 /* We might have lost the locks! */
2548 if ((lsp->ls_flags & NFS_LOCK_INITIALIZED) != 0) { 2728 if ((lsp->ls_flags & NFS_LOCK_INITIALIZED) == 0)
2549 luargs.seqid = lsp->ls_seqid; 2729 goto out;
2550 memcpy(&luargs.stateid, &lsp->ls_stateid, sizeof(luargs.stateid)); 2730 luargs.seqid = lsp->ls_seqid;
2551 arg.u.locku = &luargs; 2731 memcpy(&luargs.stateid, &lsp->ls_stateid, sizeof(luargs.stateid));
2552 status = rpc_call_sync(server->client, &msg, RPC_TASK_NOINTR); 2732 arg.u.locku = &luargs;
2553 nfs4_increment_lock_seqid(status, lsp); 2733 status = rpc_call_sync(server->client, &msg, RPC_TASK_NOINTR);
2554 } 2734 nfs4_increment_lock_seqid(status, lsp);
2555 2735
2556 if (status == 0) { 2736 if (status == 0)
2557 memcpy(&lsp->ls_stateid, &res.u.stateid, 2737 memcpy(&lsp->ls_stateid, &res.u.stateid,
2558 sizeof(lsp->ls_stateid)); 2738 sizeof(lsp->ls_stateid));
2559 nfs4_notify_unlck(state, request, lsp);
2560 }
2561 nfs4_put_lock_state(lsp);
2562out: 2739out:
2563 up(&state->lock_sema); 2740 up(&state->lock_sema);
2564 if (status == 0) 2741 if (status == 0)
@@ -2584,7 +2761,7 @@ static int _nfs4_do_setlk(struct nfs4_state *state, int cmd, struct file_lock *r
2584{ 2761{
2585 struct inode *inode = state->inode; 2762 struct inode *inode = state->inode;
2586 struct nfs_server *server = NFS_SERVER(inode); 2763 struct nfs_server *server = NFS_SERVER(inode);
2587 struct nfs4_lock_state *lsp; 2764 struct nfs4_lock_state *lsp = request->fl_u.nfs4_fl.owner;
2588 struct nfs_lockargs arg = { 2765 struct nfs_lockargs arg = {
2589 .fh = NFS_FH(inode), 2766 .fh = NFS_FH(inode),
2590 .type = nfs4_lck_type(cmd, request), 2767 .type = nfs4_lck_type(cmd, request),
@@ -2606,9 +2783,6 @@ static int _nfs4_do_setlk(struct nfs4_state *state, int cmd, struct file_lock *r
2606 }; 2783 };
2607 int status; 2784 int status;
2608 2785
2609 lsp = nfs4_get_lock_state(state, request->fl_owner);
2610 if (lsp == NULL)
2611 return -ENOMEM;
2612 if (!(lsp->ls_flags & NFS_LOCK_INITIALIZED)) { 2786 if (!(lsp->ls_flags & NFS_LOCK_INITIALIZED)) {
2613 struct nfs4_state_owner *owner = state->owner; 2787 struct nfs4_state_owner *owner = state->owner;
2614 struct nfs_open_to_lock otl = { 2788 struct nfs_open_to_lock otl = {
@@ -2630,38 +2804,57 @@ static int _nfs4_do_setlk(struct nfs4_state *state, int cmd, struct file_lock *r
2630 * seqid mutating errors */ 2804 * seqid mutating errors */
2631 nfs4_increment_seqid(status, owner); 2805 nfs4_increment_seqid(status, owner);
2632 up(&owner->so_sema); 2806 up(&owner->so_sema);
2807 if (status == 0) {
2808 lsp->ls_flags |= NFS_LOCK_INITIALIZED;
2809 lsp->ls_seqid++;
2810 }
2633 } else { 2811 } else {
2634 struct nfs_exist_lock el = { 2812 struct nfs_exist_lock el = {
2635 .seqid = lsp->ls_seqid, 2813 .seqid = lsp->ls_seqid,
2636 }; 2814 };
2637 memcpy(&el.stateid, &lsp->ls_stateid, sizeof(el.stateid)); 2815 memcpy(&el.stateid, &lsp->ls_stateid, sizeof(el.stateid));
2638 largs.u.exist_lock = &el; 2816 largs.u.exist_lock = &el;
2639 largs.new_lock_owner = 0;
2640 arg.u.lock = &largs; 2817 arg.u.lock = &largs;
2641 status = rpc_call_sync(server->client, &msg, RPC_TASK_NOINTR); 2818 status = rpc_call_sync(server->client, &msg, RPC_TASK_NOINTR);
2819 /* increment seqid on success, and * seqid mutating errors*/
2820 nfs4_increment_lock_seqid(status, lsp);
2642 } 2821 }
2643 /* increment seqid on success, and * seqid mutating errors*/
2644 nfs4_increment_lock_seqid(status, lsp);
2645 /* save the returned stateid. */ 2822 /* save the returned stateid. */
2646 if (status == 0) { 2823 if (status == 0)
2647 memcpy(&lsp->ls_stateid, &res.u.stateid, sizeof(nfs4_stateid)); 2824 memcpy(&lsp->ls_stateid, &res.u.stateid, sizeof(nfs4_stateid));
2648 lsp->ls_flags |= NFS_LOCK_INITIALIZED; 2825 else if (status == -NFS4ERR_DENIED)
2649 if (!reclaim)
2650 nfs4_notify_setlk(state, request, lsp);
2651 } else if (status == -NFS4ERR_DENIED)
2652 status = -EAGAIN; 2826 status = -EAGAIN;
2653 nfs4_put_lock_state(lsp);
2654 return status; 2827 return status;
2655} 2828}
2656 2829
2657static int nfs4_lock_reclaim(struct nfs4_state *state, struct file_lock *request) 2830static int nfs4_lock_reclaim(struct nfs4_state *state, struct file_lock *request)
2658{ 2831{
2659 return _nfs4_do_setlk(state, F_SETLK, request, 1); 2832 struct nfs_server *server = NFS_SERVER(state->inode);
2833 struct nfs4_exception exception = { };
2834 int err;
2835
2836 do {
2837 err = _nfs4_do_setlk(state, F_SETLK, request, 1);
2838 if (err != -NFS4ERR_DELAY)
2839 break;
2840 nfs4_handle_exception(server, err, &exception);
2841 } while (exception.retry);
2842 return err;
2660} 2843}
2661 2844
2662static int nfs4_lock_expired(struct nfs4_state *state, struct file_lock *request) 2845static int nfs4_lock_expired(struct nfs4_state *state, struct file_lock *request)
2663{ 2846{
2664 return _nfs4_do_setlk(state, F_SETLK, request, 0); 2847 struct nfs_server *server = NFS_SERVER(state->inode);
2848 struct nfs4_exception exception = { };
2849 int err;
2850
2851 do {
2852 err = _nfs4_do_setlk(state, F_SETLK, request, 0);
2853 if (err != -NFS4ERR_DELAY)
2854 break;
2855 nfs4_handle_exception(server, err, &exception);
2856 } while (exception.retry);
2857 return err;
2665} 2858}
2666 2859
2667static int _nfs4_proc_setlk(struct nfs4_state *state, int cmd, struct file_lock *request) 2860static int _nfs4_proc_setlk(struct nfs4_state *state, int cmd, struct file_lock *request)
@@ -2671,7 +2864,9 @@ static int _nfs4_proc_setlk(struct nfs4_state *state, int cmd, struct file_lock
2671 2864
2672 down_read(&clp->cl_sem); 2865 down_read(&clp->cl_sem);
2673 down(&state->lock_sema); 2866 down(&state->lock_sema);
2674 status = _nfs4_do_setlk(state, cmd, request, 0); 2867 status = nfs4_set_lock_state(state, request);
2868 if (status == 0)
2869 status = _nfs4_do_setlk(state, cmd, request, 0);
2675 up(&state->lock_sema); 2870 up(&state->lock_sema);
2676 if (status == 0) { 2871 if (status == 0) {
2677 /* Note: we always want to sleep here! */ 2872 /* Note: we always want to sleep here! */
@@ -2729,10 +2924,53 @@ nfs4_proc_lock(struct file *filp, int cmd, struct file_lock *request)
2729 if (signalled()) 2924 if (signalled())
2730 break; 2925 break;
2731 } while(status < 0); 2926 } while(status < 0);
2732
2733 return status; 2927 return status;
2734} 2928}
2735 2929
2930
2931#define XATTR_NAME_NFSV4_ACL "system.nfs4_acl"
2932
2933int nfs4_setxattr(struct dentry *dentry, const char *key, const void *buf,
2934 size_t buflen, int flags)
2935{
2936 struct inode *inode = dentry->d_inode;
2937
2938 if (strcmp(key, XATTR_NAME_NFSV4_ACL) != 0)
2939 return -EOPNOTSUPP;
2940
2941 if (!S_ISREG(inode->i_mode) &&
2942 (!S_ISDIR(inode->i_mode) || inode->i_mode & S_ISVTX))
2943 return -EPERM;
2944
2945 return nfs4_proc_set_acl(inode, buf, buflen);
2946}
2947
2948/* The getxattr man page suggests returning -ENODATA for unknown attributes,
2949 * and that's what we'll do for e.g. user attributes that haven't been set.
2950 * But we'll follow ext2/ext3's lead by returning -EOPNOTSUPP for unsupported
2951 * attributes in kernel-managed attribute namespaces. */
2952ssize_t nfs4_getxattr(struct dentry *dentry, const char *key, void *buf,
2953 size_t buflen)
2954{
2955 struct inode *inode = dentry->d_inode;
2956
2957 if (strcmp(key, XATTR_NAME_NFSV4_ACL) != 0)
2958 return -EOPNOTSUPP;
2959
2960 return nfs4_proc_get_acl(inode, buf, buflen);
2961}
2962
2963ssize_t nfs4_listxattr(struct dentry *dentry, char *buf, size_t buflen)
2964{
2965 size_t len = strlen(XATTR_NAME_NFSV4_ACL) + 1;
2966
2967 if (buf && buflen < len)
2968 return -ERANGE;
2969 if (buf)
2970 memcpy(buf, XATTR_NAME_NFSV4_ACL, len);
2971 return len;
2972}
2973
2736struct nfs4_state_recovery_ops nfs4_reboot_recovery_ops = { 2974struct nfs4_state_recovery_ops nfs4_reboot_recovery_ops = {
2737 .recover_open = nfs4_open_reclaim, 2975 .recover_open = nfs4_open_reclaim,
2738 .recover_lock = nfs4_lock_reclaim, 2976 .recover_lock = nfs4_lock_reclaim,
@@ -2743,10 +2981,20 @@ struct nfs4_state_recovery_ops nfs4_network_partition_recovery_ops = {
2743 .recover_lock = nfs4_lock_expired, 2981 .recover_lock = nfs4_lock_expired,
2744}; 2982};
2745 2983
2984static struct inode_operations nfs4_file_inode_operations = {
2985 .permission = nfs_permission,
2986 .getattr = nfs_getattr,
2987 .setattr = nfs_setattr,
2988 .getxattr = nfs4_getxattr,
2989 .setxattr = nfs4_setxattr,
2990 .listxattr = nfs4_listxattr,
2991};
2992
2746struct nfs_rpc_ops nfs_v4_clientops = { 2993struct nfs_rpc_ops nfs_v4_clientops = {
2747 .version = 4, /* protocol version */ 2994 .version = 4, /* protocol version */
2748 .dentry_ops = &nfs4_dentry_operations, 2995 .dentry_ops = &nfs4_dentry_operations,
2749 .dir_inode_ops = &nfs4_dir_inode_operations, 2996 .dir_inode_ops = &nfs4_dir_inode_operations,
2997 .file_inode_ops = &nfs4_file_inode_operations,
2750 .getroot = nfs4_proc_get_root, 2998 .getroot = nfs4_proc_get_root,
2751 .getattr = nfs4_proc_getattr, 2999 .getattr = nfs4_proc_getattr,
2752 .setattr = nfs4_proc_setattr, 3000 .setattr = nfs4_proc_setattr,
@@ -2777,6 +3025,7 @@ struct nfs_rpc_ops nfs_v4_clientops = {
2777 .file_open = nfs4_proc_file_open, 3025 .file_open = nfs4_proc_file_open,
2778 .file_release = nfs4_proc_file_release, 3026 .file_release = nfs4_proc_file_release,
2779 .lock = nfs4_proc_lock, 3027 .lock = nfs4_proc_lock,
3028 .clear_acl_cache = nfs4_zap_acl_attr,
2780}; 3029};
2781 3030
2782/* 3031/*