aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
Diffstat (limited to 'fs')
-rw-r--r--fs/lockd/svclock.c2
-rw-r--r--fs/lockd/svcsubs.c69
-rw-r--r--fs/locks.c32
-rw-r--r--fs/nfsd/nfs4state.c3
-rw-r--r--fs/nfsd/nfs4xdr.c14
-rw-r--r--fs/nfsd/nfsctl.c65
6 files changed, 144 insertions, 41 deletions
diff --git a/fs/lockd/svclock.c b/fs/lockd/svclock.c
index 1f122c1940af..4d81553d2948 100644
--- a/fs/lockd/svclock.c
+++ b/fs/lockd/svclock.c
@@ -632,7 +632,7 @@ nlmsvc_update_deferred_block(struct nlm_block *block, struct file_lock *conf,
632 block->b_flags |= B_TIMED_OUT; 632 block->b_flags |= B_TIMED_OUT;
633 if (conf) { 633 if (conf) {
634 if (block->b_fl) 634 if (block->b_fl)
635 locks_copy_lock(block->b_fl, conf); 635 __locks_copy_lock(block->b_fl, conf);
636 } 636 }
637} 637}
638 638
diff --git a/fs/lockd/svcsubs.c b/fs/lockd/svcsubs.c
index dbbefbcd6712..d1c48b539df8 100644
--- a/fs/lockd/svcsubs.c
+++ b/fs/lockd/svcsubs.c
@@ -18,6 +18,8 @@
18#include <linux/lockd/lockd.h> 18#include <linux/lockd/lockd.h>
19#include <linux/lockd/share.h> 19#include <linux/lockd/share.h>
20#include <linux/lockd/sm_inter.h> 20#include <linux/lockd/sm_inter.h>
21#include <linux/module.h>
22#include <linux/mount.h>
21 23
22#define NLMDBG_FACILITY NLMDBG_SVCSUBS 24#define NLMDBG_FACILITY NLMDBG_SVCSUBS
23 25
@@ -194,6 +196,12 @@ again:
194 return 0; 196 return 0;
195} 197}
196 198
199static int
200nlmsvc_always_match(void *dummy1, struct nlm_host *dummy2)
201{
202 return 1;
203}
204
197/* 205/*
198 * Inspect a single file 206 * Inspect a single file
199 */ 207 */
@@ -230,7 +238,8 @@ nlm_file_inuse(struct nlm_file *file)
230 * Loop over all files in the file table. 238 * Loop over all files in the file table.
231 */ 239 */
232static int 240static int
233nlm_traverse_files(struct nlm_host *host, nlm_host_match_fn_t match) 241nlm_traverse_files(void *data, nlm_host_match_fn_t match,
242 int (*is_failover_file)(void *data, struct nlm_file *file))
234{ 243{
235 struct hlist_node *pos, *next; 244 struct hlist_node *pos, *next;
236 struct nlm_file *file; 245 struct nlm_file *file;
@@ -239,12 +248,14 @@ nlm_traverse_files(struct nlm_host *host, nlm_host_match_fn_t match)
239 mutex_lock(&nlm_file_mutex); 248 mutex_lock(&nlm_file_mutex);
240 for (i = 0; i < FILE_NRHASH; i++) { 249 for (i = 0; i < FILE_NRHASH; i++) {
241 hlist_for_each_entry_safe(file, pos, next, &nlm_files[i], f_list) { 250 hlist_for_each_entry_safe(file, pos, next, &nlm_files[i], f_list) {
251 if (is_failover_file && !is_failover_file(data, file))
252 continue;
242 file->f_count++; 253 file->f_count++;
243 mutex_unlock(&nlm_file_mutex); 254 mutex_unlock(&nlm_file_mutex);
244 255
245 /* Traverse locks, blocks and shares of this file 256 /* Traverse locks, blocks and shares of this file
246 * and update file->f_locks count */ 257 * and update file->f_locks count */
247 if (nlm_inspect_file(host, file, match)) 258 if (nlm_inspect_file(data, file, match))
248 ret = 1; 259 ret = 1;
249 260
250 mutex_lock(&nlm_file_mutex); 261 mutex_lock(&nlm_file_mutex);
@@ -303,21 +314,27 @@ nlm_release_file(struct nlm_file *file)
303 * Used by nlmsvc_invalidate_all 314 * Used by nlmsvc_invalidate_all
304 */ 315 */
305static int 316static int
306nlmsvc_mark_host(struct nlm_host *host, struct nlm_host *dummy) 317nlmsvc_mark_host(void *data, struct nlm_host *dummy)
307{ 318{
319 struct nlm_host *host = data;
320
308 host->h_inuse = 1; 321 host->h_inuse = 1;
309 return 0; 322 return 0;
310} 323}
311 324
312static int 325static int
313nlmsvc_same_host(struct nlm_host *host, struct nlm_host *other) 326nlmsvc_same_host(void *data, struct nlm_host *other)
314{ 327{
328 struct nlm_host *host = data;
329
315 return host == other; 330 return host == other;
316} 331}
317 332
318static int 333static int
319nlmsvc_is_client(struct nlm_host *host, struct nlm_host *dummy) 334nlmsvc_is_client(void *data, struct nlm_host *dummy)
320{ 335{
336 struct nlm_host *host = data;
337
321 if (host->h_server) { 338 if (host->h_server) {
322 /* we are destroying locks even though the client 339 /* we are destroying locks even though the client
323 * hasn't asked us too, so don't unmonitor the 340 * hasn't asked us too, so don't unmonitor the
@@ -337,7 +354,7 @@ void
337nlmsvc_mark_resources(void) 354nlmsvc_mark_resources(void)
338{ 355{
339 dprintk("lockd: nlmsvc_mark_resources\n"); 356 dprintk("lockd: nlmsvc_mark_resources\n");
340 nlm_traverse_files(NULL, nlmsvc_mark_host); 357 nlm_traverse_files(NULL, nlmsvc_mark_host, NULL);
341} 358}
342 359
343/* 360/*
@@ -348,7 +365,7 @@ nlmsvc_free_host_resources(struct nlm_host *host)
348{ 365{
349 dprintk("lockd: nlmsvc_free_host_resources\n"); 366 dprintk("lockd: nlmsvc_free_host_resources\n");
350 367
351 if (nlm_traverse_files(host, nlmsvc_same_host)) { 368 if (nlm_traverse_files(host, nlmsvc_same_host, NULL)) {
352 printk(KERN_WARNING 369 printk(KERN_WARNING
353 "lockd: couldn't remove all locks held by %s\n", 370 "lockd: couldn't remove all locks held by %s\n",
354 host->h_name); 371 host->h_name);
@@ -368,5 +385,41 @@ nlmsvc_invalidate_all(void)
368 * turn, which is about as inefficient as it gets. 385 * turn, which is about as inefficient as it gets.
369 * Now we just do it once in nlm_traverse_files. 386 * Now we just do it once in nlm_traverse_files.
370 */ 387 */
371 nlm_traverse_files(NULL, nlmsvc_is_client); 388 nlm_traverse_files(NULL, nlmsvc_is_client, NULL);
389}
390
391static int
392nlmsvc_match_sb(void *datap, struct nlm_file *file)
393{
394 struct super_block *sb = datap;
395
396 return sb == file->f_file->f_path.mnt->mnt_sb;
397}
398
399int
400nlmsvc_unlock_all_by_sb(struct super_block *sb)
401{
402 int ret;
403
404 ret = nlm_traverse_files(sb, nlmsvc_always_match, nlmsvc_match_sb);
405 return ret ? -EIO : 0;
406}
407EXPORT_SYMBOL_GPL(nlmsvc_unlock_all_by_sb);
408
409static int
410nlmsvc_match_ip(void *datap, struct nlm_host *host)
411{
412 __be32 *server_addr = datap;
413
414 return host->h_saddr.sin_addr.s_addr == *server_addr;
415}
416
417int
418nlmsvc_unlock_all_by_ip(__be32 server_addr)
419{
420 int ret;
421 ret = nlm_traverse_files(&server_addr, nlmsvc_match_ip, NULL);
422 return ret ? -EIO : 0;
423
372} 424}
425EXPORT_SYMBOL_GPL(nlmsvc_unlock_all_by_ip);
diff --git a/fs/locks.c b/fs/locks.c
index 592faadbcec1..e1ea2fe03681 100644
--- a/fs/locks.c
+++ b/fs/locks.c
@@ -224,7 +224,7 @@ static void locks_copy_private(struct file_lock *new, struct file_lock *fl)
224/* 224/*
225 * Initialize a new lock from an existing file_lock structure. 225 * Initialize a new lock from an existing file_lock structure.
226 */ 226 */
227static void __locks_copy_lock(struct file_lock *new, const struct file_lock *fl) 227void __locks_copy_lock(struct file_lock *new, const struct file_lock *fl)
228{ 228{
229 new->fl_owner = fl->fl_owner; 229 new->fl_owner = fl->fl_owner;
230 new->fl_pid = fl->fl_pid; 230 new->fl_pid = fl->fl_pid;
@@ -833,7 +833,7 @@ static int __posix_lock_file(struct inode *inode, struct file_lock *request, str
833 if (!posix_locks_conflict(request, fl)) 833 if (!posix_locks_conflict(request, fl))
834 continue; 834 continue;
835 if (conflock) 835 if (conflock)
836 locks_copy_lock(conflock, fl); 836 __locks_copy_lock(conflock, fl);
837 error = -EAGAIN; 837 error = -EAGAIN;
838 if (!(request->fl_flags & FL_SLEEP)) 838 if (!(request->fl_flags & FL_SLEEP))
839 goto out; 839 goto out;
@@ -1367,18 +1367,20 @@ int generic_setlease(struct file *filp, long arg, struct file_lock **flp)
1367 1367
1368 lease = *flp; 1368 lease = *flp;
1369 1369
1370 error = -EAGAIN; 1370 if (arg != F_UNLCK) {
1371 if ((arg == F_RDLCK) && (atomic_read(&inode->i_writecount) > 0)) 1371 error = -ENOMEM;
1372 goto out; 1372 new_fl = locks_alloc_lock();
1373 if ((arg == F_WRLCK) 1373 if (new_fl == NULL)
1374 && ((atomic_read(&dentry->d_count) > 1) 1374 goto out;
1375 || (atomic_read(&inode->i_count) > 1)))
1376 goto out;
1377 1375
1378 error = -ENOMEM; 1376 error = -EAGAIN;
1379 new_fl = locks_alloc_lock(); 1377 if ((arg == F_RDLCK) && (atomic_read(&inode->i_writecount) > 0))
1380 if (new_fl == NULL) 1378 goto out;
1381 goto out; 1379 if ((arg == F_WRLCK)
1380 && ((atomic_read(&dentry->d_count) > 1)
1381 || (atomic_read(&inode->i_count) > 1)))
1382 goto out;
1383 }
1382 1384
1383 /* 1385 /*
1384 * At this point, we know that if there is an exclusive 1386 * At this point, we know that if there is an exclusive
@@ -1404,6 +1406,7 @@ int generic_setlease(struct file *filp, long arg, struct file_lock **flp)
1404 rdlease_count++; 1406 rdlease_count++;
1405 } 1407 }
1406 1408
1409 error = -EAGAIN;
1407 if ((arg == F_RDLCK && (wrlease_count > 0)) || 1410 if ((arg == F_RDLCK && (wrlease_count > 0)) ||
1408 (arg == F_WRLCK && ((rdlease_count + wrlease_count) > 0))) 1411 (arg == F_WRLCK && ((rdlease_count + wrlease_count) > 0)))
1409 goto out; 1412 goto out;
@@ -1490,8 +1493,7 @@ EXPORT_SYMBOL_GPL(vfs_setlease);
1490int fcntl_setlease(unsigned int fd, struct file *filp, long arg) 1493int fcntl_setlease(unsigned int fd, struct file *filp, long arg)
1491{ 1494{
1492 struct file_lock fl, *flp = &fl; 1495 struct file_lock fl, *flp = &fl;
1493 struct dentry *dentry = filp->f_path.dentry; 1496 struct inode *inode = filp->f_path.dentry->d_inode;
1494 struct inode *inode = dentry->d_inode;
1495 int error; 1497 int error;
1496 1498
1497 locks_init_lock(&fl); 1499 locks_init_lock(&fl);
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
index 55dfdd71f1b0..8799b8708188 100644
--- a/fs/nfsd/nfs4state.c
+++ b/fs/nfsd/nfs4state.c
@@ -2712,9 +2712,6 @@ nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
2712 * Note: locks.c uses the BKL to protect the inode's lock list. 2712 * Note: locks.c uses the BKL to protect the inode's lock list.
2713 */ 2713 */
2714 2714
2715 /* XXX?: Just to divert the locks_release_private at the start of
2716 * locks_copy_lock: */
2717 locks_init_lock(&conflock);
2718 err = vfs_lock_file(filp, cmd, &file_lock, &conflock); 2715 err = vfs_lock_file(filp, cmd, &file_lock, &conflock);
2719 switch (-err) { 2716 switch (-err) {
2720 case 0: /* success! */ 2717 case 0: /* success! */
diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
index 1ba7ad981935..c513bbdf2d36 100644
--- a/fs/nfsd/nfs4xdr.c
+++ b/fs/nfsd/nfs4xdr.c
@@ -376,20 +376,6 @@ nfsd4_decode_fattr(struct nfsd4_compoundargs *argp, u32 *bmval, struct iattr *ia
376 goto xdr_error; 376 goto xdr_error;
377 } 377 }
378 } 378 }
379 if (bmval[1] & FATTR4_WORD1_TIME_METADATA) {
380 /* We require the high 32 bits of 'seconds' to be 0, and we ignore
381 all 32 bits of 'nseconds'. */
382 READ_BUF(12);
383 len += 12;
384 READ32(dummy32);
385 if (dummy32)
386 return nfserr_inval;
387 READ32(iattr->ia_ctime.tv_sec);
388 READ32(iattr->ia_ctime.tv_nsec);
389 if (iattr->ia_ctime.tv_nsec >= (u32)1000000000)
390 return nfserr_inval;
391 iattr->ia_valid |= ATTR_CTIME;
392 }
393 if (bmval[1] & FATTR4_WORD1_TIME_MODIFY_SET) { 379 if (bmval[1] & FATTR4_WORD1_TIME_MODIFY_SET) {
394 READ_BUF(4); 380 READ_BUF(4);
395 len += 4; 381 len += 4;
diff --git a/fs/nfsd/nfsctl.c b/fs/nfsd/nfsctl.c
index 613bcb8171a5..42f3820ee8f5 100644
--- a/fs/nfsd/nfsctl.c
+++ b/fs/nfsd/nfsctl.c
@@ -22,6 +22,7 @@
22#include <linux/seq_file.h> 22#include <linux/seq_file.h>
23#include <linux/pagemap.h> 23#include <linux/pagemap.h>
24#include <linux/init.h> 24#include <linux/init.h>
25#include <linux/inet.h>
25#include <linux/string.h> 26#include <linux/string.h>
26#include <linux/smp_lock.h> 27#include <linux/smp_lock.h>
27#include <linux/ctype.h> 28#include <linux/ctype.h>
@@ -35,6 +36,7 @@
35#include <linux/nfsd/cache.h> 36#include <linux/nfsd/cache.h>
36#include <linux/nfsd/xdr.h> 37#include <linux/nfsd/xdr.h>
37#include <linux/nfsd/syscall.h> 38#include <linux/nfsd/syscall.h>
39#include <linux/lockd/lockd.h>
38 40
39#include <asm/uaccess.h> 41#include <asm/uaccess.h>
40#include <net/ipv6.h> 42#include <net/ipv6.h>
@@ -53,6 +55,8 @@ enum {
53 NFSD_Getfs, 55 NFSD_Getfs,
54 NFSD_List, 56 NFSD_List,
55 NFSD_Fh, 57 NFSD_Fh,
58 NFSD_FO_UnlockIP,
59 NFSD_FO_UnlockFS,
56 NFSD_Threads, 60 NFSD_Threads,
57 NFSD_Pool_Threads, 61 NFSD_Pool_Threads,
58 NFSD_Versions, 62 NFSD_Versions,
@@ -89,6 +93,9 @@ static ssize_t write_leasetime(struct file *file, char *buf, size_t size);
89static ssize_t write_recoverydir(struct file *file, char *buf, size_t size); 93static ssize_t write_recoverydir(struct file *file, char *buf, size_t size);
90#endif 94#endif
91 95
96static ssize_t failover_unlock_ip(struct file *file, char *buf, size_t size);
97static ssize_t failover_unlock_fs(struct file *file, char *buf, size_t size);
98
92static ssize_t (*write_op[])(struct file *, char *, size_t) = { 99static ssize_t (*write_op[])(struct file *, char *, size_t) = {
93 [NFSD_Svc] = write_svc, 100 [NFSD_Svc] = write_svc,
94 [NFSD_Add] = write_add, 101 [NFSD_Add] = write_add,
@@ -98,6 +105,8 @@ static ssize_t (*write_op[])(struct file *, char *, size_t) = {
98 [NFSD_Getfd] = write_getfd, 105 [NFSD_Getfd] = write_getfd,
99 [NFSD_Getfs] = write_getfs, 106 [NFSD_Getfs] = write_getfs,
100 [NFSD_Fh] = write_filehandle, 107 [NFSD_Fh] = write_filehandle,
108 [NFSD_FO_UnlockIP] = failover_unlock_ip,
109 [NFSD_FO_UnlockFS] = failover_unlock_fs,
101 [NFSD_Threads] = write_threads, 110 [NFSD_Threads] = write_threads,
102 [NFSD_Pool_Threads] = write_pool_threads, 111 [NFSD_Pool_Threads] = write_pool_threads,
103 [NFSD_Versions] = write_versions, 112 [NFSD_Versions] = write_versions,
@@ -298,6 +307,58 @@ static ssize_t write_getfd(struct file *file, char *buf, size_t size)
298 return err; 307 return err;
299} 308}
300 309
310static ssize_t failover_unlock_ip(struct file *file, char *buf, size_t size)
311{
312 __be32 server_ip;
313 char *fo_path, c;
314 int b1, b2, b3, b4;
315
316 /* sanity check */
317 if (size == 0)
318 return -EINVAL;
319
320 if (buf[size-1] != '\n')
321 return -EINVAL;
322
323 fo_path = buf;
324 if (qword_get(&buf, fo_path, size) < 0)
325 return -EINVAL;
326
327 /* get ipv4 address */
328 if (sscanf(fo_path, "%u.%u.%u.%u%c", &b1, &b2, &b3, &b4, &c) != 4)
329 return -EINVAL;
330 server_ip = htonl((((((b1<<8)|b2)<<8)|b3)<<8)|b4);
331
332 return nlmsvc_unlock_all_by_ip(server_ip);
333}
334
335static ssize_t failover_unlock_fs(struct file *file, char *buf, size_t size)
336{
337 struct nameidata nd;
338 char *fo_path;
339 int error;
340
341 /* sanity check */
342 if (size == 0)
343 return -EINVAL;
344
345 if (buf[size-1] != '\n')
346 return -EINVAL;
347
348 fo_path = buf;
349 if (qword_get(&buf, fo_path, size) < 0)
350 return -EINVAL;
351
352 error = path_lookup(fo_path, 0, &nd);
353 if (error)
354 return error;
355
356 error = nlmsvc_unlock_all_by_sb(nd.path.mnt->mnt_sb);
357
358 path_put(&nd.path);
359 return error;
360}
361
301static ssize_t write_filehandle(struct file *file, char *buf, size_t size) 362static ssize_t write_filehandle(struct file *file, char *buf, size_t size)
302{ 363{
303 /* request is: 364 /* request is:
@@ -700,6 +761,10 @@ static int nfsd_fill_super(struct super_block * sb, void * data, int silent)
700 [NFSD_Getfd] = {".getfd", &transaction_ops, S_IWUSR|S_IRUSR}, 761 [NFSD_Getfd] = {".getfd", &transaction_ops, S_IWUSR|S_IRUSR},
701 [NFSD_Getfs] = {".getfs", &transaction_ops, S_IWUSR|S_IRUSR}, 762 [NFSD_Getfs] = {".getfs", &transaction_ops, S_IWUSR|S_IRUSR},
702 [NFSD_List] = {"exports", &exports_operations, S_IRUGO}, 763 [NFSD_List] = {"exports", &exports_operations, S_IRUGO},
764 [NFSD_FO_UnlockIP] = {"unlock_ip",
765 &transaction_ops, S_IWUSR|S_IRUSR},
766 [NFSD_FO_UnlockFS] = {"unlock_filesystem",
767 &transaction_ops, S_IWUSR|S_IRUSR},
703 [NFSD_Fh] = {"filehandle", &transaction_ops, S_IWUSR|S_IRUSR}, 768 [NFSD_Fh] = {"filehandle", &transaction_ops, S_IWUSR|S_IRUSR},
704 [NFSD_Threads] = {"threads", &transaction_ops, S_IWUSR|S_IRUSR}, 769 [NFSD_Threads] = {"threads", &transaction_ops, S_IWUSR|S_IRUSR},
705 [NFSD_Pool_Threads] = {"pool_threads", &transaction_ops, S_IWUSR|S_IRUSR}, 770 [NFSD_Pool_Threads] = {"pool_threads", &transaction_ops, S_IWUSR|S_IRUSR},