Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge tag 'nfs-for-3.8-2' of git://git.linux-nfs.org/projects/trondmy/linux-nfs

Pull NFS client bugfixes from Trond Myklebust:

- Fix a permissions problem when opening NFSv4 files that only have the
exec bit set.

- Fix a couple of typos in pNFS (inverted logic), and the mount parsing
(missing pointer dereference).

- Work around a series of deadlock issues due to workqueues using
struct work_struct pointer address comparisons in the re-entrancy
tests. Ensure that we don't free struct work_struct prematurely if
our work function involves waiting for completion of other work items
(e.g. by calling rpc_shutdown_client).

- Revert the part of commit 168e4b3 that is causing unnecessary
warnings to be issued in the nfsd callback code.

* tag 'nfs-for-3.8-2' of git://git.linux-nfs.org/projects/trondmy/linux-nfs:
nfs: avoid dereferencing null pointer in initiate_bulk_draining
SUNRPC: Partial revert of commit 168e4b39d1afb79a7e3ea6c3bb246b4c82c6bdb9
NFS: Ensure that we free the rpc_task after read and write cleanups are done
SUNRPC: Ensure that we free the rpc_task after cleanups are done
nfs: fix null checking in nfs_get_option_str()
pnfs: Increase the refcount when LAYOUTGET fails the first time
NFS: Fix access to suid/sgid executables

+61 -31
+1 -1
fs/nfs/callback_proc.c
··· 206 206 207 207 list_for_each_entry(lo, &server->layouts, plh_layouts) { 208 208 ino = igrab(lo->plh_inode); 209 - if (ino) 209 + if (!ino) 210 210 continue; 211 211 spin_lock(&ino->i_lock); 212 212 /* Is this layout in the process of being freed? */
+10 -6
fs/nfs/dir.c
··· 2153 2153 { 2154 2154 int mask = 0; 2155 2155 2156 - if ((openflags & O_ACCMODE) != O_WRONLY) 2157 - mask |= MAY_READ; 2158 - if ((openflags & O_ACCMODE) != O_RDONLY) 2159 - mask |= MAY_WRITE; 2160 - if (openflags & __FMODE_EXEC) 2161 - mask |= MAY_EXEC; 2156 + if (openflags & __FMODE_EXEC) { 2157 + /* ONLY check exec rights */ 2158 + mask = MAY_EXEC; 2159 + } else { 2160 + if ((openflags & O_ACCMODE) != O_WRONLY) 2161 + mask |= MAY_READ; 2162 + if ((openflags & O_ACCMODE) != O_RDONLY) 2163 + mask |= MAY_WRITE; 2164 + } 2165 + 2162 2166 return mask; 2163 2167 } 2164 2168
+11 -7
fs/nfs/nfs4proc.c
··· 1626 1626 1627 1627 static int nfs4_opendata_access(struct rpc_cred *cred, 1628 1628 struct nfs4_opendata *opendata, 1629 - struct nfs4_state *state, fmode_t fmode) 1629 + struct nfs4_state *state, fmode_t fmode, 1630 + int openflags) 1630 1631 { 1631 1632 struct nfs_access_entry cache; 1632 1633 u32 mask; ··· 1639 1638 1640 1639 mask = 0; 1641 1640 /* don't check MAY_WRITE - a newly created file may not have 1642 - * write mode bits, but POSIX allows the creating process to write */ 1643 - if (fmode & FMODE_READ) 1644 - mask |= MAY_READ; 1645 - if (fmode & FMODE_EXEC) 1646 - mask |= MAY_EXEC; 1641 + * write mode bits, but POSIX allows the creating process to write. 1642 + * use openflags to check for exec, because fmode won't 1643 + * always have FMODE_EXEC set when file open for exec. */ 1644 + if (openflags & __FMODE_EXEC) { 1645 + /* ONLY check for exec rights */ 1646 + mask = MAY_EXEC; 1647 + } else if (fmode & FMODE_READ) 1648 + mask = MAY_READ; 1647 1649 1648 1650 cache.cred = cred; 1649 1651 cache.jiffies = jiffies; ··· 1900 1896 if (server->caps & NFS_CAP_POSIX_LOCK) 1901 1897 set_bit(NFS_STATE_POSIX_LOCKS, &state->flags); 1902 1898 1903 - status = nfs4_opendata_access(cred, opendata, state, fmode); 1899 + status = nfs4_opendata_access(cred, opendata, state, fmode, flags); 1904 1900 if (status != 0) 1905 1901 goto err_opendata_put; 1906 1902
+1 -1
fs/nfs/pnfs.c
··· 254 254 pnfs_layout_set_fail_bit(struct pnfs_layout_hdr *lo, int fail_bit) 255 255 { 256 256 lo->plh_retry_timestamp = jiffies; 257 - if (test_and_set_bit(fail_bit, &lo->plh_flags)) 257 + if (!test_and_set_bit(fail_bit, &lo->plh_flags)) 258 258 atomic_inc(&lo->plh_refcount); 259 259 } 260 260
+7 -3
fs/nfs/read.c
··· 91 91 put_nfs_open_context(rdata->args.context); 92 92 if (rdata->pages.pagevec != rdata->pages.page_array) 93 93 kfree(rdata->pages.pagevec); 94 - if (rdata != &read_header->rpc_data) 95 - kfree(rdata); 96 - else 94 + if (rdata == &read_header->rpc_data) { 97 95 rdata->header = NULL; 96 + rdata = NULL; 97 + } 98 98 if (atomic_dec_and_test(&hdr->refcnt)) 99 99 hdr->completion_ops->completion(hdr); 100 + /* Note: we only free the rpc_task after callbacks are done. 101 + * See the comment in rpc_free_task() for why 102 + */ 103 + kfree(rdata); 100 104 } 101 105 EXPORT_SYMBOL_GPL(nfs_readdata_release); 102 106
+1 -1
fs/nfs/super.c
··· 1152 1152 { 1153 1153 kfree(*option); 1154 1154 *option = match_strdup(args); 1155 - return !option; 1155 + return !*option; 1156 1156 } 1157 1157 1158 1158 static int nfs_get_option_ul(substring_t args[], unsigned long *option)
+7 -3
fs/nfs/write.c
··· 126 126 put_nfs_open_context(wdata->args.context); 127 127 if (wdata->pages.pagevec != wdata->pages.page_array) 128 128 kfree(wdata->pages.pagevec); 129 - if (wdata != &write_header->rpc_data) 130 - kfree(wdata); 131 - else 129 + if (wdata == &write_header->rpc_data) { 132 130 wdata->header = NULL; 131 + wdata = NULL; 132 + } 133 133 if (atomic_dec_and_test(&hdr->refcnt)) 134 134 hdr->completion_ops->completion(hdr); 135 + /* Note: we only free the rpc_task after callbacks are done. 136 + * See the comment in rpc_free_task() for why 137 + */ 138 + kfree(wdata); 135 139 } 136 140 EXPORT_SYMBOL_GPL(nfs_writedata_release); 137 141
-5
net/sunrpc/clnt.c
··· 610 610 */ 611 611 void rpc_shutdown_client(struct rpc_clnt *clnt) 612 612 { 613 - /* 614 - * To avoid deadlock, never call rpc_shutdown_client from a 615 - * workqueue context! 616 - */ 617 - WARN_ON_ONCE(current->flags & PF_WQ_WORKER); 618 613 might_sleep(); 619 614 620 615 dprintk_rcu("RPC: shutting down %s client for %s\n",
+23 -4
net/sunrpc/sched.c
··· 934 934 return task; 935 935 } 936 936 937 + /* 938 + * rpc_free_task - release rpc task and perform cleanups 939 + * 940 + * Note that we free up the rpc_task _after_ rpc_release_calldata() 941 + * in order to work around a workqueue dependency issue. 942 + * 943 + * Tejun Heo states: 944 + * "Workqueue currently considers two work items to be the same if they're 945 + * on the same address and won't execute them concurrently - ie. it 946 + * makes a work item which is queued again while being executed wait 947 + * for the previous execution to complete. 948 + * 949 + * If a work function frees the work item, and then waits for an event 950 + * which should be performed by another work item and *that* work item 951 + * recycles the freed work item, it can create a false dependency loop. 952 + * There really is no reliable way to detect this short of verifying 953 + * every memory free." 954 + * 955 + */ 937 956 static void rpc_free_task(struct rpc_task *task) 938 957 { 939 - const struct rpc_call_ops *tk_ops = task->tk_ops; 940 - void *calldata = task->tk_calldata; 958 + unsigned short tk_flags = task->tk_flags; 941 959 942 - if (task->tk_flags & RPC_TASK_DYNAMIC) { 960 + rpc_release_calldata(task->tk_ops, task->tk_calldata); 961 + 962 + if (tk_flags & RPC_TASK_DYNAMIC) { 943 963 dprintk("RPC: %5u freeing task\n", task->tk_pid); 944 964 mempool_free(task, rpc_task_mempool); 945 965 } 946 - rpc_release_calldata(tk_ops, calldata); 947 966 } 948 967 949 968 static void rpc_async_release(struct work_struct *work)