diff options
Diffstat (limited to 'fs')
-rw-r--r-- | fs/ceph/mds_client.c | 19 | ||||
-rw-r--r-- | fs/cifs/cifsfs.c | 100 | ||||
-rw-r--r-- | fs/cifs/cifsfs.h | 2 | ||||
-rw-r--r-- | fs/cifs/connect.c | 2 | ||||
-rw-r--r-- | fs/cifs/dir.c | 13 | ||||
-rw-r--r-- | fs/cifs/sess.c | 10 | ||||
-rw-r--r-- | fs/cramfs/inode.c | 22 | ||||
-rw-r--r-- | fs/dcache.c | 51 | ||||
-rw-r--r-- | fs/exofs/super.c | 2 | ||||
-rw-r--r-- | fs/gfs2/aops.c | 3 | ||||
-rw-r--r-- | fs/gfs2/glops.c | 8 | ||||
-rw-r--r-- | fs/gfs2/incore.h | 2 | ||||
-rw-r--r-- | fs/gfs2/log.c | 1 | ||||
-rw-r--r-- | fs/gfs2/ops_fstype.c | 3 | ||||
-rw-r--r-- | fs/gfs2/super.c | 36 | ||||
-rw-r--r-- | fs/gfs2/sys.c | 7 | ||||
-rw-r--r-- | fs/hppfs/hppfs.c | 31 | ||||
-rw-r--r-- | fs/libfs.c | 2 | ||||
-rw-r--r-- | fs/namei.c | 9 | ||||
-rw-r--r-- | fs/nfs/nfs4filelayout.c | 1 | ||||
-rw-r--r-- | fs/nfs/nfs4xdr.c | 2 | ||||
-rw-r--r-- | fs/nfs/write.c | 2 | ||||
-rw-r--r-- | fs/ufs/namei.c | 12 |
23 files changed, 186 insertions, 154 deletions
diff --git a/fs/ceph/mds_client.c b/fs/ceph/mds_client.c index 79743d146be6..0c1d91756528 100644 --- a/fs/ceph/mds_client.c +++ b/fs/ceph/mds_client.c | |||
@@ -1438,12 +1438,15 @@ char *ceph_mdsc_build_path(struct dentry *dentry, int *plen, u64 *base, | |||
1438 | struct dentry *temp; | 1438 | struct dentry *temp; |
1439 | char *path; | 1439 | char *path; |
1440 | int len, pos; | 1440 | int len, pos; |
1441 | unsigned seq; | ||
1441 | 1442 | ||
1442 | if (dentry == NULL) | 1443 | if (dentry == NULL) |
1443 | return ERR_PTR(-EINVAL); | 1444 | return ERR_PTR(-EINVAL); |
1444 | 1445 | ||
1445 | retry: | 1446 | retry: |
1446 | len = 0; | 1447 | len = 0; |
1448 | seq = read_seqbegin(&rename_lock); | ||
1449 | rcu_read_lock(); | ||
1447 | for (temp = dentry; !IS_ROOT(temp);) { | 1450 | for (temp = dentry; !IS_ROOT(temp);) { |
1448 | struct inode *inode = temp->d_inode; | 1451 | struct inode *inode = temp->d_inode; |
1449 | if (inode && ceph_snap(inode) == CEPH_SNAPDIR) | 1452 | if (inode && ceph_snap(inode) == CEPH_SNAPDIR) |
@@ -1455,10 +1458,12 @@ retry: | |||
1455 | len += 1 + temp->d_name.len; | 1458 | len += 1 + temp->d_name.len; |
1456 | temp = temp->d_parent; | 1459 | temp = temp->d_parent; |
1457 | if (temp == NULL) { | 1460 | if (temp == NULL) { |
1461 | rcu_read_unlock(); | ||
1458 | pr_err("build_path corrupt dentry %p\n", dentry); | 1462 | pr_err("build_path corrupt dentry %p\n", dentry); |
1459 | return ERR_PTR(-EINVAL); | 1463 | return ERR_PTR(-EINVAL); |
1460 | } | 1464 | } |
1461 | } | 1465 | } |
1466 | rcu_read_unlock(); | ||
1462 | if (len) | 1467 | if (len) |
1463 | len--; /* no leading '/' */ | 1468 | len--; /* no leading '/' */ |
1464 | 1469 | ||
@@ -1467,9 +1472,12 @@ retry: | |||
1467 | return ERR_PTR(-ENOMEM); | 1472 | return ERR_PTR(-ENOMEM); |
1468 | pos = len; | 1473 | pos = len; |
1469 | path[pos] = 0; /* trailing null */ | 1474 | path[pos] = 0; /* trailing null */ |
1475 | rcu_read_lock(); | ||
1470 | for (temp = dentry; !IS_ROOT(temp) && pos != 0; ) { | 1476 | for (temp = dentry; !IS_ROOT(temp) && pos != 0; ) { |
1471 | struct inode *inode = temp->d_inode; | 1477 | struct inode *inode; |
1472 | 1478 | ||
1479 | spin_lock(&temp->d_lock); | ||
1480 | inode = temp->d_inode; | ||
1473 | if (inode && ceph_snap(inode) == CEPH_SNAPDIR) { | 1481 | if (inode && ceph_snap(inode) == CEPH_SNAPDIR) { |
1474 | dout("build_path path+%d: %p SNAPDIR\n", | 1482 | dout("build_path path+%d: %p SNAPDIR\n", |
1475 | pos, temp); | 1483 | pos, temp); |
@@ -1478,21 +1486,26 @@ retry: | |||
1478 | break; | 1486 | break; |
1479 | } else { | 1487 | } else { |
1480 | pos -= temp->d_name.len; | 1488 | pos -= temp->d_name.len; |
1481 | if (pos < 0) | 1489 | if (pos < 0) { |
1490 | spin_unlock(&temp->d_lock); | ||
1482 | break; | 1491 | break; |
1492 | } | ||
1483 | strncpy(path + pos, temp->d_name.name, | 1493 | strncpy(path + pos, temp->d_name.name, |
1484 | temp->d_name.len); | 1494 | temp->d_name.len); |
1485 | } | 1495 | } |
1496 | spin_unlock(&temp->d_lock); | ||
1486 | if (pos) | 1497 | if (pos) |
1487 | path[--pos] = '/'; | 1498 | path[--pos] = '/'; |
1488 | temp = temp->d_parent; | 1499 | temp = temp->d_parent; |
1489 | if (temp == NULL) { | 1500 | if (temp == NULL) { |
1501 | rcu_read_unlock(); | ||
1490 | pr_err("build_path corrupt dentry\n"); | 1502 | pr_err("build_path corrupt dentry\n"); |
1491 | kfree(path); | 1503 | kfree(path); |
1492 | return ERR_PTR(-EINVAL); | 1504 | return ERR_PTR(-EINVAL); |
1493 | } | 1505 | } |
1494 | } | 1506 | } |
1495 | if (pos != 0) { | 1507 | rcu_read_unlock(); |
1508 | if (pos != 0 || read_seqretry(&rename_lock, seq)) { | ||
1496 | pr_err("build_path did not end path lookup where " | 1509 | pr_err("build_path did not end path lookup where " |
1497 | "expected, namelen is %d, pos is %d\n", len, pos); | 1510 | "expected, namelen is %d, pos is %d\n", len, pos); |
1498 | /* presumably this is only possible if racing with a | 1511 | /* presumably this is only possible if racing with a |
diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c index 3e2989976297..bc4b12ca537b 100644 --- a/fs/cifs/cifsfs.c +++ b/fs/cifs/cifsfs.c | |||
@@ -35,6 +35,7 @@ | |||
35 | #include <linux/delay.h> | 35 | #include <linux/delay.h> |
36 | #include <linux/kthread.h> | 36 | #include <linux/kthread.h> |
37 | #include <linux/freezer.h> | 37 | #include <linux/freezer.h> |
38 | #include <linux/namei.h> | ||
38 | #include <net/ipv6.h> | 39 | #include <net/ipv6.h> |
39 | #include "cifsfs.h" | 40 | #include "cifsfs.h" |
40 | #include "cifspdu.h" | 41 | #include "cifspdu.h" |
@@ -542,14 +543,12 @@ static const struct super_operations cifs_super_ops = { | |||
542 | static struct dentry * | 543 | static struct dentry * |
543 | cifs_get_root(struct smb_vol *vol, struct super_block *sb) | 544 | cifs_get_root(struct smb_vol *vol, struct super_block *sb) |
544 | { | 545 | { |
545 | int xid, rc; | 546 | struct dentry *dentry; |
546 | struct inode *inode; | ||
547 | struct qstr name; | ||
548 | struct dentry *dparent = NULL, *dchild = NULL, *alias; | ||
549 | struct cifs_sb_info *cifs_sb = CIFS_SB(sb); | 547 | struct cifs_sb_info *cifs_sb = CIFS_SB(sb); |
550 | unsigned int i, full_len, len; | 548 | char *full_path = NULL; |
551 | char *full_path = NULL, *pstart; | 549 | char *s, *p; |
552 | char sep; | 550 | char sep; |
551 | int xid; | ||
553 | 552 | ||
554 | full_path = cifs_build_path_to_root(vol, cifs_sb, | 553 | full_path = cifs_build_path_to_root(vol, cifs_sb, |
555 | cifs_sb_master_tcon(cifs_sb)); | 554 | cifs_sb_master_tcon(cifs_sb)); |
@@ -560,73 +559,32 @@ cifs_get_root(struct smb_vol *vol, struct super_block *sb) | |||
560 | 559 | ||
561 | xid = GetXid(); | 560 | xid = GetXid(); |
562 | sep = CIFS_DIR_SEP(cifs_sb); | 561 | sep = CIFS_DIR_SEP(cifs_sb); |
563 | dparent = dget(sb->s_root); | 562 | dentry = dget(sb->s_root); |
564 | full_len = strlen(full_path); | 563 | p = s = full_path; |
565 | full_path[full_len] = sep; | 564 | |
566 | pstart = full_path + 1; | 565 | do { |
567 | 566 | struct inode *dir = dentry->d_inode; | |
568 | for (i = 1, len = 0; i <= full_len; i++) { | 567 | struct dentry *child; |
569 | if (full_path[i] != sep || !len) { | 568 | |
570 | len++; | 569 | /* skip separators */ |
571 | continue; | 570 | while (*s == sep) |
572 | } | 571 | s++; |
573 | 572 | if (!*s) | |
574 | full_path[i] = 0; | 573 | break; |
575 | cFYI(1, "get dentry for %s", pstart); | 574 | p = s++; |
576 | 575 | /* next separator */ | |
577 | name.name = pstart; | 576 | while (*s && *s != sep) |
578 | name.len = len; | 577 | s++; |
579 | name.hash = full_name_hash(pstart, len); | 578 | |
580 | dchild = d_lookup(dparent, &name); | 579 | mutex_lock(&dir->i_mutex); |
581 | if (dchild == NULL) { | 580 | child = lookup_one_len(p, dentry, s - p); |
582 | cFYI(1, "not exists"); | 581 | mutex_unlock(&dir->i_mutex); |
583 | dchild = d_alloc(dparent, &name); | 582 | dput(dentry); |
584 | if (dchild == NULL) { | 583 | dentry = child; |
585 | dput(dparent); | 584 | } while (!IS_ERR(dentry)); |
586 | dparent = ERR_PTR(-ENOMEM); | ||
587 | goto out; | ||
588 | } | ||
589 | } | ||
590 | |||
591 | cFYI(1, "get inode"); | ||
592 | if (dchild->d_inode == NULL) { | ||
593 | cFYI(1, "not exists"); | ||
594 | inode = NULL; | ||
595 | if (cifs_sb_master_tcon(CIFS_SB(sb))->unix_ext) | ||
596 | rc = cifs_get_inode_info_unix(&inode, full_path, | ||
597 | sb, xid); | ||
598 | else | ||
599 | rc = cifs_get_inode_info(&inode, full_path, | ||
600 | NULL, sb, xid, NULL); | ||
601 | if (rc) { | ||
602 | dput(dchild); | ||
603 | dput(dparent); | ||
604 | dparent = ERR_PTR(rc); | ||
605 | goto out; | ||
606 | } | ||
607 | alias = d_materialise_unique(dchild, inode); | ||
608 | if (alias != NULL) { | ||
609 | dput(dchild); | ||
610 | if (IS_ERR(alias)) { | ||
611 | dput(dparent); | ||
612 | dparent = ERR_PTR(-EINVAL); /* XXX */ | ||
613 | goto out; | ||
614 | } | ||
615 | dchild = alias; | ||
616 | } | ||
617 | } | ||
618 | cFYI(1, "parent %p, child %p", dparent, dchild); | ||
619 | |||
620 | dput(dparent); | ||
621 | dparent = dchild; | ||
622 | len = 0; | ||
623 | pstart = full_path + i + 1; | ||
624 | full_path[i] = sep; | ||
625 | } | ||
626 | out: | ||
627 | _FreeXid(xid); | 585 | _FreeXid(xid); |
628 | kfree(full_path); | 586 | kfree(full_path); |
629 | return dparent; | 587 | return dentry; |
630 | } | 588 | } |
631 | 589 | ||
632 | static int cifs_set_super(struct super_block *sb, void *data) | 590 | static int cifs_set_super(struct super_block *sb, void *data) |
diff --git a/fs/cifs/cifsfs.h b/fs/cifs/cifsfs.h index 0900e1658c96..036ca83e5f46 100644 --- a/fs/cifs/cifsfs.h +++ b/fs/cifs/cifsfs.h | |||
@@ -129,5 +129,5 @@ extern long cifs_ioctl(struct file *filep, unsigned int cmd, unsigned long arg); | |||
129 | extern const struct export_operations cifs_export_ops; | 129 | extern const struct export_operations cifs_export_ops; |
130 | #endif /* CIFS_NFSD_EXPORT */ | 130 | #endif /* CIFS_NFSD_EXPORT */ |
131 | 131 | ||
132 | #define CIFS_VERSION "1.73" | 132 | #define CIFS_VERSION "1.74" |
133 | #endif /* _CIFSFS_H */ | 133 | #endif /* _CIFSFS_H */ |
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index dbd669cc5bc7..ccc1afa0bf3b 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c | |||
@@ -3485,7 +3485,7 @@ cifs_construct_tcon(struct cifs_sb_info *cifs_sb, uid_t fsuid) | |||
3485 | goto out; | 3485 | goto out; |
3486 | } | 3486 | } |
3487 | 3487 | ||
3488 | snprintf(username, MAX_USERNAME_SIZE, "krb50x%x", fsuid); | 3488 | snprintf(username, sizeof(username), "krb50x%x", fsuid); |
3489 | vol_info->username = username; | 3489 | vol_info->username = username; |
3490 | vol_info->local_nls = cifs_sb->local_nls; | 3490 | vol_info->local_nls = cifs_sb->local_nls; |
3491 | vol_info->linux_uid = fsuid; | 3491 | vol_info->linux_uid = fsuid; |
diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c index 81914df47ef1..fa8c21d913bc 100644 --- a/fs/cifs/dir.c +++ b/fs/cifs/dir.c | |||
@@ -55,6 +55,7 @@ build_path_from_dentry(struct dentry *direntry) | |||
55 | char dirsep; | 55 | char dirsep; |
56 | struct cifs_sb_info *cifs_sb = CIFS_SB(direntry->d_sb); | 56 | struct cifs_sb_info *cifs_sb = CIFS_SB(direntry->d_sb); |
57 | struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb); | 57 | struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb); |
58 | unsigned seq; | ||
58 | 59 | ||
59 | if (direntry == NULL) | 60 | if (direntry == NULL) |
60 | return NULL; /* not much we can do if dentry is freed and | 61 | return NULL; /* not much we can do if dentry is freed and |
@@ -68,22 +69,29 @@ build_path_from_dentry(struct dentry *direntry) | |||
68 | dfsplen = 0; | 69 | dfsplen = 0; |
69 | cifs_bp_rename_retry: | 70 | cifs_bp_rename_retry: |
70 | namelen = dfsplen; | 71 | namelen = dfsplen; |
72 | seq = read_seqbegin(&rename_lock); | ||
73 | rcu_read_lock(); | ||
71 | for (temp = direntry; !IS_ROOT(temp);) { | 74 | for (temp = direntry; !IS_ROOT(temp);) { |
72 | namelen += (1 + temp->d_name.len); | 75 | namelen += (1 + temp->d_name.len); |
73 | temp = temp->d_parent; | 76 | temp = temp->d_parent; |
74 | if (temp == NULL) { | 77 | if (temp == NULL) { |
75 | cERROR(1, "corrupt dentry"); | 78 | cERROR(1, "corrupt dentry"); |
79 | rcu_read_unlock(); | ||
76 | return NULL; | 80 | return NULL; |
77 | } | 81 | } |
78 | } | 82 | } |
83 | rcu_read_unlock(); | ||
79 | 84 | ||
80 | full_path = kmalloc(namelen+1, GFP_KERNEL); | 85 | full_path = kmalloc(namelen+1, GFP_KERNEL); |
81 | if (full_path == NULL) | 86 | if (full_path == NULL) |
82 | return full_path; | 87 | return full_path; |
83 | full_path[namelen] = 0; /* trailing null */ | 88 | full_path[namelen] = 0; /* trailing null */ |
89 | rcu_read_lock(); | ||
84 | for (temp = direntry; !IS_ROOT(temp);) { | 90 | for (temp = direntry; !IS_ROOT(temp);) { |
91 | spin_lock(&temp->d_lock); | ||
85 | namelen -= 1 + temp->d_name.len; | 92 | namelen -= 1 + temp->d_name.len; |
86 | if (namelen < 0) { | 93 | if (namelen < 0) { |
94 | spin_unlock(&temp->d_lock); | ||
87 | break; | 95 | break; |
88 | } else { | 96 | } else { |
89 | full_path[namelen] = dirsep; | 97 | full_path[namelen] = dirsep; |
@@ -91,14 +99,17 @@ cifs_bp_rename_retry: | |||
91 | temp->d_name.len); | 99 | temp->d_name.len); |
92 | cFYI(0, "name: %s", full_path + namelen); | 100 | cFYI(0, "name: %s", full_path + namelen); |
93 | } | 101 | } |
102 | spin_unlock(&temp->d_lock); | ||
94 | temp = temp->d_parent; | 103 | temp = temp->d_parent; |
95 | if (temp == NULL) { | 104 | if (temp == NULL) { |
96 | cERROR(1, "corrupt dentry"); | 105 | cERROR(1, "corrupt dentry"); |
106 | rcu_read_unlock(); | ||
97 | kfree(full_path); | 107 | kfree(full_path); |
98 | return NULL; | 108 | return NULL; |
99 | } | 109 | } |
100 | } | 110 | } |
101 | if (namelen != dfsplen) { | 111 | rcu_read_unlock(); |
112 | if (namelen != dfsplen || read_seqretry(&rename_lock, seq)) { | ||
102 | cERROR(1, "did not end path lookup where expected namelen is %d", | 113 | cERROR(1, "did not end path lookup where expected namelen is %d", |
103 | namelen); | 114 | namelen); |
104 | /* presumably this is only possible if racing with a rename | 115 | /* presumably this is only possible if racing with a rename |
diff --git a/fs/cifs/sess.c b/fs/cifs/sess.c index 3892ab817a36..d3e619692ee0 100644 --- a/fs/cifs/sess.c +++ b/fs/cifs/sess.c | |||
@@ -428,8 +428,7 @@ static void build_ntlmssp_negotiate_blob(unsigned char *pbuffer, | |||
428 | (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) { | 428 | (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) { |
429 | flags |= NTLMSSP_NEGOTIATE_SIGN; | 429 | flags |= NTLMSSP_NEGOTIATE_SIGN; |
430 | if (!ses->server->session_estab) | 430 | if (!ses->server->session_estab) |
431 | flags |= NTLMSSP_NEGOTIATE_KEY_XCH | | 431 | flags |= NTLMSSP_NEGOTIATE_KEY_XCH; |
432 | NTLMSSP_NEGOTIATE_EXTENDED_SEC; | ||
433 | } | 432 | } |
434 | 433 | ||
435 | sec_blob->NegotiateFlags = cpu_to_le32(flags); | 434 | sec_blob->NegotiateFlags = cpu_to_le32(flags); |
@@ -465,10 +464,11 @@ static int build_ntlmssp_auth_blob(unsigned char *pbuffer, | |||
465 | NTLMSSP_NEGOTIATE_128 | NTLMSSP_NEGOTIATE_UNICODE | | 464 | NTLMSSP_NEGOTIATE_128 | NTLMSSP_NEGOTIATE_UNICODE | |
466 | NTLMSSP_NEGOTIATE_NTLM | NTLMSSP_NEGOTIATE_EXTENDED_SEC; | 465 | NTLMSSP_NEGOTIATE_NTLM | NTLMSSP_NEGOTIATE_EXTENDED_SEC; |
467 | if (ses->server->sec_mode & | 466 | if (ses->server->sec_mode & |
468 | (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) | 467 | (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) { |
469 | flags |= NTLMSSP_NEGOTIATE_SIGN; | 468 | flags |= NTLMSSP_NEGOTIATE_SIGN; |
470 | if (ses->server->sec_mode & SECMODE_SIGN_REQUIRED) | 469 | if (!ses->server->session_estab) |
471 | flags |= NTLMSSP_NEGOTIATE_ALWAYS_SIGN; | 470 | flags |= NTLMSSP_NEGOTIATE_KEY_XCH; |
471 | } | ||
472 | 472 | ||
473 | tmp = pbuffer + sizeof(AUTHENTICATE_MESSAGE); | 473 | tmp = pbuffer + sizeof(AUTHENTICATE_MESSAGE); |
474 | sec_blob->NegotiateFlags = cpu_to_le32(flags); | 474 | sec_blob->NegotiateFlags = cpu_to_le32(flags); |
diff --git a/fs/cramfs/inode.c b/fs/cramfs/inode.c index e141939080f0..739fb59bcdc2 100644 --- a/fs/cramfs/inode.c +++ b/fs/cramfs/inode.c | |||
@@ -37,7 +37,7 @@ static DEFINE_MUTEX(read_mutex); | |||
37 | /* These macros may change in future, to provide better st_ino semantics. */ | 37 | /* These macros may change in future, to provide better st_ino semantics. */ |
38 | #define OFFSET(x) ((x)->i_ino) | 38 | #define OFFSET(x) ((x)->i_ino) |
39 | 39 | ||
40 | static unsigned long cramino(struct cramfs_inode *cino, unsigned int offset) | 40 | static unsigned long cramino(const struct cramfs_inode *cino, unsigned int offset) |
41 | { | 41 | { |
42 | if (!cino->offset) | 42 | if (!cino->offset) |
43 | return offset + 1; | 43 | return offset + 1; |
@@ -61,7 +61,7 @@ static unsigned long cramino(struct cramfs_inode *cino, unsigned int offset) | |||
61 | } | 61 | } |
62 | 62 | ||
63 | static struct inode *get_cramfs_inode(struct super_block *sb, | 63 | static struct inode *get_cramfs_inode(struct super_block *sb, |
64 | struct cramfs_inode *cramfs_inode, unsigned int offset) | 64 | const struct cramfs_inode *cramfs_inode, unsigned int offset) |
65 | { | 65 | { |
66 | struct inode *inode; | 66 | struct inode *inode; |
67 | static struct timespec zerotime; | 67 | static struct timespec zerotime; |
@@ -317,7 +317,7 @@ static int cramfs_fill_super(struct super_block *sb, void *data, int silent) | |||
317 | /* Set it all up.. */ | 317 | /* Set it all up.. */ |
318 | sb->s_op = &cramfs_ops; | 318 | sb->s_op = &cramfs_ops; |
319 | root = get_cramfs_inode(sb, &super.root, 0); | 319 | root = get_cramfs_inode(sb, &super.root, 0); |
320 | if (!root) | 320 | if (IS_ERR(root)) |
321 | goto out; | 321 | goto out; |
322 | sb->s_root = d_alloc_root(root); | 322 | sb->s_root = d_alloc_root(root); |
323 | if (!sb->s_root) { | 323 | if (!sb->s_root) { |
@@ -423,6 +423,7 @@ static int cramfs_readdir(struct file *filp, void *dirent, filldir_t filldir) | |||
423 | static struct dentry * cramfs_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd) | 423 | static struct dentry * cramfs_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd) |
424 | { | 424 | { |
425 | unsigned int offset = 0; | 425 | unsigned int offset = 0; |
426 | struct inode *inode = NULL; | ||
426 | int sorted; | 427 | int sorted; |
427 | 428 | ||
428 | mutex_lock(&read_mutex); | 429 | mutex_lock(&read_mutex); |
@@ -449,8 +450,8 @@ static struct dentry * cramfs_lookup(struct inode *dir, struct dentry *dentry, s | |||
449 | 450 | ||
450 | for (;;) { | 451 | for (;;) { |
451 | if (!namelen) { | 452 | if (!namelen) { |
452 | mutex_unlock(&read_mutex); | 453 | inode = ERR_PTR(-EIO); |
453 | return ERR_PTR(-EIO); | 454 | goto out; |
454 | } | 455 | } |
455 | if (name[namelen-1]) | 456 | if (name[namelen-1]) |
456 | break; | 457 | break; |
@@ -462,17 +463,18 @@ static struct dentry * cramfs_lookup(struct inode *dir, struct dentry *dentry, s | |||
462 | if (retval > 0) | 463 | if (retval > 0) |
463 | continue; | 464 | continue; |
464 | if (!retval) { | 465 | if (!retval) { |
465 | struct cramfs_inode entry = *de; | 466 | inode = get_cramfs_inode(dir->i_sb, de, dir_off); |
466 | mutex_unlock(&read_mutex); | 467 | break; |
467 | d_add(dentry, get_cramfs_inode(dir->i_sb, &entry, dir_off)); | ||
468 | return NULL; | ||
469 | } | 468 | } |
470 | /* else (retval < 0) */ | 469 | /* else (retval < 0) */ |
471 | if (sorted) | 470 | if (sorted) |
472 | break; | 471 | break; |
473 | } | 472 | } |
473 | out: | ||
474 | mutex_unlock(&read_mutex); | 474 | mutex_unlock(&read_mutex); |
475 | d_add(dentry, NULL); | 475 | if (IS_ERR(inode)) |
476 | return ERR_CAST(inode); | ||
477 | d_add(dentry, inode); | ||
476 | return NULL; | 478 | return NULL; |
477 | } | 479 | } |
478 | 480 | ||
diff --git a/fs/dcache.c b/fs/dcache.c index 37f72ee5bf7c..6e4ea6d87774 100644 --- a/fs/dcache.c +++ b/fs/dcache.c | |||
@@ -2213,14 +2213,15 @@ static void dentry_unlock_parents_for_move(struct dentry *dentry, | |||
2213 | * The hash value has to match the hash queue that the dentry is on.. | 2213 | * The hash value has to match the hash queue that the dentry is on.. |
2214 | */ | 2214 | */ |
2215 | /* | 2215 | /* |
2216 | * d_move - move a dentry | 2216 | * __d_move - move a dentry |
2217 | * @dentry: entry to move | 2217 | * @dentry: entry to move |
2218 | * @target: new dentry | 2218 | * @target: new dentry |
2219 | * | 2219 | * |
2220 | * Update the dcache to reflect the move of a file name. Negative | 2220 | * Update the dcache to reflect the move of a file name. Negative |
2221 | * dcache entries should not be moved in this way. | 2221 | * dcache entries should not be moved in this way. Caller hold |
2222 | * rename_lock. | ||
2222 | */ | 2223 | */ |
2223 | void d_move(struct dentry * dentry, struct dentry * target) | 2224 | static void __d_move(struct dentry * dentry, struct dentry * target) |
2224 | { | 2225 | { |
2225 | if (!dentry->d_inode) | 2226 | if (!dentry->d_inode) |
2226 | printk(KERN_WARNING "VFS: moving negative dcache entry\n"); | 2227 | printk(KERN_WARNING "VFS: moving negative dcache entry\n"); |
@@ -2228,8 +2229,6 @@ void d_move(struct dentry * dentry, struct dentry * target) | |||
2228 | BUG_ON(d_ancestor(dentry, target)); | 2229 | BUG_ON(d_ancestor(dentry, target)); |
2229 | BUG_ON(d_ancestor(target, dentry)); | 2230 | BUG_ON(d_ancestor(target, dentry)); |
2230 | 2231 | ||
2231 | write_seqlock(&rename_lock); | ||
2232 | |||
2233 | dentry_lock_for_move(dentry, target); | 2232 | dentry_lock_for_move(dentry, target); |
2234 | 2233 | ||
2235 | write_seqcount_begin(&dentry->d_seq); | 2234 | write_seqcount_begin(&dentry->d_seq); |
@@ -2275,6 +2274,20 @@ void d_move(struct dentry * dentry, struct dentry * target) | |||
2275 | spin_unlock(&target->d_lock); | 2274 | spin_unlock(&target->d_lock); |
2276 | fsnotify_d_move(dentry); | 2275 | fsnotify_d_move(dentry); |
2277 | spin_unlock(&dentry->d_lock); | 2276 | spin_unlock(&dentry->d_lock); |
2277 | } | ||
2278 | |||
2279 | /* | ||
2280 | * d_move - move a dentry | ||
2281 | * @dentry: entry to move | ||
2282 | * @target: new dentry | ||
2283 | * | ||
2284 | * Update the dcache to reflect the move of a file name. Negative | ||
2285 | * dcache entries should not be moved in this way. | ||
2286 | */ | ||
2287 | void d_move(struct dentry *dentry, struct dentry *target) | ||
2288 | { | ||
2289 | write_seqlock(&rename_lock); | ||
2290 | __d_move(dentry, target); | ||
2278 | write_sequnlock(&rename_lock); | 2291 | write_sequnlock(&rename_lock); |
2279 | } | 2292 | } |
2280 | EXPORT_SYMBOL(d_move); | 2293 | EXPORT_SYMBOL(d_move); |
@@ -2302,7 +2315,7 @@ struct dentry *d_ancestor(struct dentry *p1, struct dentry *p2) | |||
2302 | * This helper attempts to cope with remotely renamed directories | 2315 | * This helper attempts to cope with remotely renamed directories |
2303 | * | 2316 | * |
2304 | * It assumes that the caller is already holding | 2317 | * It assumes that the caller is already holding |
2305 | * dentry->d_parent->d_inode->i_mutex and the inode->i_lock | 2318 | * dentry->d_parent->d_inode->i_mutex, inode->i_lock and rename_lock |
2306 | * | 2319 | * |
2307 | * Note: If ever the locking in lock_rename() changes, then please | 2320 | * Note: If ever the locking in lock_rename() changes, then please |
2308 | * remember to update this too... | 2321 | * remember to update this too... |
@@ -2317,11 +2330,6 @@ static struct dentry *__d_unalias(struct inode *inode, | |||
2317 | if (alias->d_parent == dentry->d_parent) | 2330 | if (alias->d_parent == dentry->d_parent) |
2318 | goto out_unalias; | 2331 | goto out_unalias; |
2319 | 2332 | ||
2320 | /* Check for loops */ | ||
2321 | ret = ERR_PTR(-ELOOP); | ||
2322 | if (d_ancestor(alias, dentry)) | ||
2323 | goto out_err; | ||
2324 | |||
2325 | /* See lock_rename() */ | 2333 | /* See lock_rename() */ |
2326 | ret = ERR_PTR(-EBUSY); | 2334 | ret = ERR_PTR(-EBUSY); |
2327 | if (!mutex_trylock(&dentry->d_sb->s_vfs_rename_mutex)) | 2335 | if (!mutex_trylock(&dentry->d_sb->s_vfs_rename_mutex)) |
@@ -2331,7 +2339,7 @@ static struct dentry *__d_unalias(struct inode *inode, | |||
2331 | goto out_err; | 2339 | goto out_err; |
2332 | m2 = &alias->d_parent->d_inode->i_mutex; | 2340 | m2 = &alias->d_parent->d_inode->i_mutex; |
2333 | out_unalias: | 2341 | out_unalias: |
2334 | d_move(alias, dentry); | 2342 | __d_move(alias, dentry); |
2335 | ret = alias; | 2343 | ret = alias; |
2336 | out_err: | 2344 | out_err: |
2337 | spin_unlock(&inode->i_lock); | 2345 | spin_unlock(&inode->i_lock); |
@@ -2416,15 +2424,24 @@ struct dentry *d_materialise_unique(struct dentry *dentry, struct inode *inode) | |||
2416 | alias = __d_find_alias(inode, 0); | 2424 | alias = __d_find_alias(inode, 0); |
2417 | if (alias) { | 2425 | if (alias) { |
2418 | actual = alias; | 2426 | actual = alias; |
2419 | /* Is this an anonymous mountpoint that we could splice | 2427 | write_seqlock(&rename_lock); |
2420 | * into our tree? */ | 2428 | |
2421 | if (IS_ROOT(alias)) { | 2429 | if (d_ancestor(alias, dentry)) { |
2430 | /* Check for loops */ | ||
2431 | actual = ERR_PTR(-ELOOP); | ||
2432 | } else if (IS_ROOT(alias)) { | ||
2433 | /* Is this an anonymous mountpoint that we | ||
2434 | * could splice into our tree? */ | ||
2422 | __d_materialise_dentry(dentry, alias); | 2435 | __d_materialise_dentry(dentry, alias); |
2436 | write_sequnlock(&rename_lock); | ||
2423 | __d_drop(alias); | 2437 | __d_drop(alias); |
2424 | goto found; | 2438 | goto found; |
2439 | } else { | ||
2440 | /* Nope, but we must(!) avoid directory | ||
2441 | * aliasing */ | ||
2442 | actual = __d_unalias(inode, dentry, alias); | ||
2425 | } | 2443 | } |
2426 | /* Nope, but we must(!) avoid directory aliasing */ | 2444 | write_sequnlock(&rename_lock); |
2427 | actual = __d_unalias(inode, dentry, alias); | ||
2428 | if (IS_ERR(actual)) | 2445 | if (IS_ERR(actual)) |
2429 | dput(alias); | 2446 | dput(alias); |
2430 | goto out_nolock; | 2447 | goto out_nolock; |
diff --git a/fs/exofs/super.c b/fs/exofs/super.c index 06065bd37fc3..c57beddcc217 100644 --- a/fs/exofs/super.c +++ b/fs/exofs/super.c | |||
@@ -913,7 +913,7 @@ struct dentry *exofs_get_parent(struct dentry *child) | |||
913 | unsigned long ino = exofs_parent_ino(child); | 913 | unsigned long ino = exofs_parent_ino(child); |
914 | 914 | ||
915 | if (!ino) | 915 | if (!ino) |
916 | return NULL; | 916 | return ERR_PTR(-ESTALE); |
917 | 917 | ||
918 | return d_obtain_alias(exofs_iget(child->d_inode->i_sb, ino)); | 918 | return d_obtain_alias(exofs_iget(child->d_inode->i_sb, ino)); |
919 | } | 919 | } |
diff --git a/fs/gfs2/aops.c b/fs/gfs2/aops.c index 802ac5eeba28..f9fbbe96c222 100644 --- a/fs/gfs2/aops.c +++ b/fs/gfs2/aops.c | |||
@@ -1069,6 +1069,7 @@ int gfs2_releasepage(struct page *page, gfp_t gfp_mask) | |||
1069 | return 0; | 1069 | return 0; |
1070 | 1070 | ||
1071 | gfs2_log_lock(sdp); | 1071 | gfs2_log_lock(sdp); |
1072 | spin_lock(&sdp->sd_ail_lock); | ||
1072 | head = bh = page_buffers(page); | 1073 | head = bh = page_buffers(page); |
1073 | do { | 1074 | do { |
1074 | if (atomic_read(&bh->b_count)) | 1075 | if (atomic_read(&bh->b_count)) |
@@ -1080,6 +1081,7 @@ int gfs2_releasepage(struct page *page, gfp_t gfp_mask) | |||
1080 | goto not_possible; | 1081 | goto not_possible; |
1081 | bh = bh->b_this_page; | 1082 | bh = bh->b_this_page; |
1082 | } while(bh != head); | 1083 | } while(bh != head); |
1084 | spin_unlock(&sdp->sd_ail_lock); | ||
1083 | gfs2_log_unlock(sdp); | 1085 | gfs2_log_unlock(sdp); |
1084 | 1086 | ||
1085 | head = bh = page_buffers(page); | 1087 | head = bh = page_buffers(page); |
@@ -1112,6 +1114,7 @@ not_possible: /* Should never happen */ | |||
1112 | WARN_ON(buffer_dirty(bh)); | 1114 | WARN_ON(buffer_dirty(bh)); |
1113 | WARN_ON(buffer_pinned(bh)); | 1115 | WARN_ON(buffer_pinned(bh)); |
1114 | cannot_release: | 1116 | cannot_release: |
1117 | spin_unlock(&sdp->sd_ail_lock); | ||
1115 | gfs2_log_unlock(sdp); | 1118 | gfs2_log_unlock(sdp); |
1116 | return 0; | 1119 | return 0; |
1117 | } | 1120 | } |
diff --git a/fs/gfs2/glops.c b/fs/gfs2/glops.c index 8ef70f464731..2cca29316bd6 100644 --- a/fs/gfs2/glops.c +++ b/fs/gfs2/glops.c | |||
@@ -47,10 +47,10 @@ static void __gfs2_ail_flush(struct gfs2_glock *gl) | |||
47 | bd_ail_gl_list); | 47 | bd_ail_gl_list); |
48 | bh = bd->bd_bh; | 48 | bh = bd->bd_bh; |
49 | gfs2_remove_from_ail(bd); | 49 | gfs2_remove_from_ail(bd); |
50 | spin_unlock(&sdp->sd_ail_lock); | ||
51 | |||
52 | bd->bd_bh = NULL; | 50 | bd->bd_bh = NULL; |
53 | bh->b_private = NULL; | 51 | bh->b_private = NULL; |
52 | spin_unlock(&sdp->sd_ail_lock); | ||
53 | |||
54 | bd->bd_blkno = bh->b_blocknr; | 54 | bd->bd_blkno = bh->b_blocknr; |
55 | gfs2_log_lock(sdp); | 55 | gfs2_log_lock(sdp); |
56 | gfs2_assert_withdraw(sdp, !buffer_busy(bh)); | 56 | gfs2_assert_withdraw(sdp, !buffer_busy(bh)); |
@@ -221,8 +221,10 @@ static void inode_go_inval(struct gfs2_glock *gl, int flags) | |||
221 | } | 221 | } |
222 | } | 222 | } |
223 | 223 | ||
224 | if (ip == GFS2_I(gl->gl_sbd->sd_rindex)) | 224 | if (ip == GFS2_I(gl->gl_sbd->sd_rindex)) { |
225 | gfs2_log_flush(gl->gl_sbd, NULL); | ||
225 | gl->gl_sbd->sd_rindex_uptodate = 0; | 226 | gl->gl_sbd->sd_rindex_uptodate = 0; |
227 | } | ||
226 | if (ip && S_ISREG(ip->i_inode.i_mode)) | 228 | if (ip && S_ISREG(ip->i_inode.i_mode)) |
227 | truncate_inode_pages(ip->i_inode.i_mapping, 0); | 229 | truncate_inode_pages(ip->i_inode.i_mapping, 0); |
228 | } | 230 | } |
diff --git a/fs/gfs2/incore.h b/fs/gfs2/incore.h index 0a064e91ac70..81206e70cbf6 100644 --- a/fs/gfs2/incore.h +++ b/fs/gfs2/incore.h | |||
@@ -17,6 +17,7 @@ | |||
17 | #include <linux/buffer_head.h> | 17 | #include <linux/buffer_head.h> |
18 | #include <linux/rcupdate.h> | 18 | #include <linux/rcupdate.h> |
19 | #include <linux/rculist_bl.h> | 19 | #include <linux/rculist_bl.h> |
20 | #include <linux/completion.h> | ||
20 | 21 | ||
21 | #define DIO_WAIT 0x00000010 | 22 | #define DIO_WAIT 0x00000010 |
22 | #define DIO_METADATA 0x00000020 | 23 | #define DIO_METADATA 0x00000020 |
@@ -546,6 +547,7 @@ struct gfs2_sbd { | |||
546 | struct gfs2_glock *sd_trans_gl; | 547 | struct gfs2_glock *sd_trans_gl; |
547 | wait_queue_head_t sd_glock_wait; | 548 | wait_queue_head_t sd_glock_wait; |
548 | atomic_t sd_glock_disposal; | 549 | atomic_t sd_glock_disposal; |
550 | struct completion sd_locking_init; | ||
549 | 551 | ||
550 | /* Inode Stuff */ | 552 | /* Inode Stuff */ |
551 | 553 | ||
diff --git a/fs/gfs2/log.c b/fs/gfs2/log.c index 903115f2bb34..85c62923ee29 100644 --- a/fs/gfs2/log.c +++ b/fs/gfs2/log.c | |||
@@ -903,6 +903,7 @@ void gfs2_meta_syncfs(struct gfs2_sbd *sdp) | |||
903 | if (gfs2_ail1_empty(sdp)) | 903 | if (gfs2_ail1_empty(sdp)) |
904 | break; | 904 | break; |
905 | } | 905 | } |
906 | gfs2_log_flush(sdp, NULL); | ||
906 | } | 907 | } |
907 | 908 | ||
908 | static inline int gfs2_jrnl_flush_reqd(struct gfs2_sbd *sdp) | 909 | static inline int gfs2_jrnl_flush_reqd(struct gfs2_sbd *sdp) |
diff --git a/fs/gfs2/ops_fstype.c b/fs/gfs2/ops_fstype.c index 8ac9ae189b53..2a77071fb7b6 100644 --- a/fs/gfs2/ops_fstype.c +++ b/fs/gfs2/ops_fstype.c | |||
@@ -72,6 +72,7 @@ static struct gfs2_sbd *init_sbd(struct super_block *sb) | |||
72 | 72 | ||
73 | init_waitqueue_head(&sdp->sd_glock_wait); | 73 | init_waitqueue_head(&sdp->sd_glock_wait); |
74 | atomic_set(&sdp->sd_glock_disposal, 0); | 74 | atomic_set(&sdp->sd_glock_disposal, 0); |
75 | init_completion(&sdp->sd_locking_init); | ||
75 | spin_lock_init(&sdp->sd_statfs_spin); | 76 | spin_lock_init(&sdp->sd_statfs_spin); |
76 | 77 | ||
77 | spin_lock_init(&sdp->sd_rindex_spin); | 78 | spin_lock_init(&sdp->sd_rindex_spin); |
@@ -1017,11 +1018,13 @@ hostdata_error: | |||
1017 | fsname++; | 1018 | fsname++; |
1018 | if (lm->lm_mount == NULL) { | 1019 | if (lm->lm_mount == NULL) { |
1019 | fs_info(sdp, "Now mounting FS...\n"); | 1020 | fs_info(sdp, "Now mounting FS...\n"); |
1021 | complete(&sdp->sd_locking_init); | ||
1020 | return 0; | 1022 | return 0; |
1021 | } | 1023 | } |
1022 | ret = lm->lm_mount(sdp, fsname); | 1024 | ret = lm->lm_mount(sdp, fsname); |
1023 | if (ret == 0) | 1025 | if (ret == 0) |
1024 | fs_info(sdp, "Joined cluster. Now mounting FS...\n"); | 1026 | fs_info(sdp, "Joined cluster. Now mounting FS...\n"); |
1027 | complete(&sdp->sd_locking_init); | ||
1025 | return ret; | 1028 | return ret; |
1026 | } | 1029 | } |
1027 | 1030 | ||
diff --git a/fs/gfs2/super.c b/fs/gfs2/super.c index ed540e7018be..fb0edf735483 100644 --- a/fs/gfs2/super.c +++ b/fs/gfs2/super.c | |||
@@ -757,13 +757,17 @@ static int gfs2_write_inode(struct inode *inode, struct writeback_control *wbc) | |||
757 | struct timespec atime; | 757 | struct timespec atime; |
758 | struct gfs2_dinode *di; | 758 | struct gfs2_dinode *di; |
759 | int ret = -EAGAIN; | 759 | int ret = -EAGAIN; |
760 | int unlock_required = 0; | ||
760 | 761 | ||
761 | /* Skip timestamp update, if this is from a memalloc */ | 762 | /* Skip timestamp update, if this is from a memalloc */ |
762 | if (current->flags & PF_MEMALLOC) | 763 | if (current->flags & PF_MEMALLOC) |
763 | goto do_flush; | 764 | goto do_flush; |
764 | ret = gfs2_glock_nq_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, &gh); | 765 | if (!gfs2_glock_is_locked_by_me(ip->i_gl)) { |
765 | if (ret) | 766 | ret = gfs2_glock_nq_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, &gh); |
766 | goto do_flush; | 767 | if (ret) |
768 | goto do_flush; | ||
769 | unlock_required = 1; | ||
770 | } | ||
767 | ret = gfs2_trans_begin(sdp, RES_DINODE, 0); | 771 | ret = gfs2_trans_begin(sdp, RES_DINODE, 0); |
768 | if (ret) | 772 | if (ret) |
769 | goto do_unlock; | 773 | goto do_unlock; |
@@ -780,7 +784,8 @@ static int gfs2_write_inode(struct inode *inode, struct writeback_control *wbc) | |||
780 | } | 784 | } |
781 | gfs2_trans_end(sdp); | 785 | gfs2_trans_end(sdp); |
782 | do_unlock: | 786 | do_unlock: |
783 | gfs2_glock_dq_uninit(&gh); | 787 | if (unlock_required) |
788 | gfs2_glock_dq_uninit(&gh); | ||
784 | do_flush: | 789 | do_flush: |
785 | if (wbc->sync_mode == WB_SYNC_ALL) | 790 | if (wbc->sync_mode == WB_SYNC_ALL) |
786 | gfs2_log_flush(GFS2_SB(inode), ip->i_gl); | 791 | gfs2_log_flush(GFS2_SB(inode), ip->i_gl); |
@@ -1427,7 +1432,20 @@ out: | |||
1427 | return error; | 1432 | return error; |
1428 | } | 1433 | } |
1429 | 1434 | ||
1430 | /* | 1435 | /** |
1436 | * gfs2_evict_inode - Remove an inode from cache | ||
1437 | * @inode: The inode to evict | ||
1438 | * | ||
1439 | * There are three cases to consider: | ||
1440 | * 1. i_nlink == 0, we are final opener (and must deallocate) | ||
1441 | * 2. i_nlink == 0, we are not the final opener (and cannot deallocate) | ||
1442 | * 3. i_nlink > 0 | ||
1443 | * | ||
1444 | * If the fs is read only, then we have to treat all cases as per #3 | ||
1445 | * since we are unable to do any deallocation. The inode will be | ||
1446 | * deallocated by the next read/write node to attempt an allocation | ||
1447 | * in the same resource group | ||
1448 | * | ||
1431 | * We have to (at the moment) hold the inodes main lock to cover | 1449 | * We have to (at the moment) hold the inodes main lock to cover |
1432 | * the gap between unlocking the shared lock on the iopen lock and | 1450 | * the gap between unlocking the shared lock on the iopen lock and |
1433 | * taking the exclusive lock. I'd rather do a shared -> exclusive | 1451 | * taking the exclusive lock. I'd rather do a shared -> exclusive |
@@ -1470,6 +1488,8 @@ static void gfs2_evict_inode(struct inode *inode) | |||
1470 | if (error) | 1488 | if (error) |
1471 | goto out_truncate; | 1489 | goto out_truncate; |
1472 | 1490 | ||
1491 | /* Case 1 starts here */ | ||
1492 | |||
1473 | if (S_ISDIR(inode->i_mode) && | 1493 | if (S_ISDIR(inode->i_mode) && |
1474 | (ip->i_diskflags & GFS2_DIF_EXHASH)) { | 1494 | (ip->i_diskflags & GFS2_DIF_EXHASH)) { |
1475 | error = gfs2_dir_exhash_dealloc(ip); | 1495 | error = gfs2_dir_exhash_dealloc(ip); |
@@ -1493,13 +1513,16 @@ static void gfs2_evict_inode(struct inode *inode) | |||
1493 | goto out_unlock; | 1513 | goto out_unlock; |
1494 | 1514 | ||
1495 | out_truncate: | 1515 | out_truncate: |
1516 | /* Case 2 starts here */ | ||
1496 | error = gfs2_trans_begin(sdp, 0, sdp->sd_jdesc->jd_blocks); | 1517 | error = gfs2_trans_begin(sdp, 0, sdp->sd_jdesc->jd_blocks); |
1497 | if (error) | 1518 | if (error) |
1498 | goto out_unlock; | 1519 | goto out_unlock; |
1499 | gfs2_final_release_pages(ip); | 1520 | /* Needs to be done before glock release & also in a transaction */ |
1521 | truncate_inode_pages(&inode->i_data, 0); | ||
1500 | gfs2_trans_end(sdp); | 1522 | gfs2_trans_end(sdp); |
1501 | 1523 | ||
1502 | out_unlock: | 1524 | out_unlock: |
1525 | /* Error path for case 1 */ | ||
1503 | if (test_bit(HIF_HOLDER, &ip->i_iopen_gh.gh_iflags)) | 1526 | if (test_bit(HIF_HOLDER, &ip->i_iopen_gh.gh_iflags)) |
1504 | gfs2_glock_dq(&ip->i_iopen_gh); | 1527 | gfs2_glock_dq(&ip->i_iopen_gh); |
1505 | gfs2_holder_uninit(&ip->i_iopen_gh); | 1528 | gfs2_holder_uninit(&ip->i_iopen_gh); |
@@ -1507,6 +1530,7 @@ out_unlock: | |||
1507 | if (error && error != GLR_TRYFAILED && error != -EROFS) | 1530 | if (error && error != GLR_TRYFAILED && error != -EROFS) |
1508 | fs_warn(sdp, "gfs2_evict_inode: %d\n", error); | 1531 | fs_warn(sdp, "gfs2_evict_inode: %d\n", error); |
1509 | out: | 1532 | out: |
1533 | /* Case 3 starts here */ | ||
1510 | truncate_inode_pages(&inode->i_data, 0); | 1534 | truncate_inode_pages(&inode->i_data, 0); |
1511 | end_writeback(inode); | 1535 | end_writeback(inode); |
1512 | 1536 | ||
diff --git a/fs/gfs2/sys.c b/fs/gfs2/sys.c index e20eab37bc80..443cabcfcd23 100644 --- a/fs/gfs2/sys.c +++ b/fs/gfs2/sys.c | |||
@@ -338,6 +338,9 @@ static ssize_t lkfirst_store(struct gfs2_sbd *sdp, const char *buf, size_t len) | |||
338 | rv = sscanf(buf, "%u", &first); | 338 | rv = sscanf(buf, "%u", &first); |
339 | if (rv != 1 || first > 1) | 339 | if (rv != 1 || first > 1) |
340 | return -EINVAL; | 340 | return -EINVAL; |
341 | rv = wait_for_completion_killable(&sdp->sd_locking_init); | ||
342 | if (rv) | ||
343 | return rv; | ||
341 | spin_lock(&sdp->sd_jindex_spin); | 344 | spin_lock(&sdp->sd_jindex_spin); |
342 | rv = -EBUSY; | 345 | rv = -EBUSY; |
343 | if (test_bit(SDF_NOJOURNALID, &sdp->sd_flags) == 0) | 346 | if (test_bit(SDF_NOJOURNALID, &sdp->sd_flags) == 0) |
@@ -414,7 +417,9 @@ static ssize_t jid_store(struct gfs2_sbd *sdp, const char *buf, size_t len) | |||
414 | rv = sscanf(buf, "%d", &jid); | 417 | rv = sscanf(buf, "%d", &jid); |
415 | if (rv != 1) | 418 | if (rv != 1) |
416 | return -EINVAL; | 419 | return -EINVAL; |
417 | 420 | rv = wait_for_completion_killable(&sdp->sd_locking_init); | |
421 | if (rv) | ||
422 | return rv; | ||
418 | spin_lock(&sdp->sd_jindex_spin); | 423 | spin_lock(&sdp->sd_jindex_spin); |
419 | rv = -EINVAL; | 424 | rv = -EINVAL; |
420 | if (sdp->sd_lockstruct.ls_ops->lm_mount == NULL) | 425 | if (sdp->sd_lockstruct.ls_ops->lm_mount == NULL) |
diff --git a/fs/hppfs/hppfs.c b/fs/hppfs/hppfs.c index 87ed48e0343d..85c098a499f3 100644 --- a/fs/hppfs/hppfs.c +++ b/fs/hppfs/hppfs.c | |||
@@ -139,7 +139,8 @@ static int file_removed(struct dentry *dentry, const char *file) | |||
139 | static struct dentry *hppfs_lookup(struct inode *ino, struct dentry *dentry, | 139 | static struct dentry *hppfs_lookup(struct inode *ino, struct dentry *dentry, |
140 | struct nameidata *nd) | 140 | struct nameidata *nd) |
141 | { | 141 | { |
142 | struct dentry *proc_dentry, *new, *parent; | 142 | struct dentry *proc_dentry, *parent; |
143 | struct qstr *name = &dentry->d_name; | ||
143 | struct inode *inode; | 144 | struct inode *inode; |
144 | int err, deleted; | 145 | int err, deleted; |
145 | 146 | ||
@@ -149,23 +150,9 @@ static struct dentry *hppfs_lookup(struct inode *ino, struct dentry *dentry, | |||
149 | else if (deleted) | 150 | else if (deleted) |
150 | return ERR_PTR(-ENOENT); | 151 | return ERR_PTR(-ENOENT); |
151 | 152 | ||
152 | err = -ENOMEM; | ||
153 | parent = HPPFS_I(ino)->proc_dentry; | 153 | parent = HPPFS_I(ino)->proc_dentry; |
154 | mutex_lock(&parent->d_inode->i_mutex); | 154 | mutex_lock(&parent->d_inode->i_mutex); |
155 | proc_dentry = d_lookup(parent, &dentry->d_name); | 155 | proc_dentry = lookup_one_len(name->name, parent, name->len); |
156 | if (proc_dentry == NULL) { | ||
157 | proc_dentry = d_alloc(parent, &dentry->d_name); | ||
158 | if (proc_dentry == NULL) { | ||
159 | mutex_unlock(&parent->d_inode->i_mutex); | ||
160 | goto out; | ||
161 | } | ||
162 | new = (*parent->d_inode->i_op->lookup)(parent->d_inode, | ||
163 | proc_dentry, NULL); | ||
164 | if (new) { | ||
165 | dput(proc_dentry); | ||
166 | proc_dentry = new; | ||
167 | } | ||
168 | } | ||
169 | mutex_unlock(&parent->d_inode->i_mutex); | 156 | mutex_unlock(&parent->d_inode->i_mutex); |
170 | 157 | ||
171 | if (IS_ERR(proc_dentry)) | 158 | if (IS_ERR(proc_dentry)) |
@@ -174,13 +161,11 @@ static struct dentry *hppfs_lookup(struct inode *ino, struct dentry *dentry, | |||
174 | err = -ENOMEM; | 161 | err = -ENOMEM; |
175 | inode = get_inode(ino->i_sb, proc_dentry); | 162 | inode = get_inode(ino->i_sb, proc_dentry); |
176 | if (!inode) | 163 | if (!inode) |
177 | goto out_dput; | 164 | goto out; |
178 | 165 | ||
179 | d_add(dentry, inode); | 166 | d_add(dentry, inode); |
180 | return NULL; | 167 | return NULL; |
181 | 168 | ||
182 | out_dput: | ||
183 | dput(proc_dentry); | ||
184 | out: | 169 | out: |
185 | return ERR_PTR(err); | 170 | return ERR_PTR(err); |
186 | } | 171 | } |
@@ -690,8 +675,10 @@ static struct inode *get_inode(struct super_block *sb, struct dentry *dentry) | |||
690 | struct inode *proc_ino = dentry->d_inode; | 675 | struct inode *proc_ino = dentry->d_inode; |
691 | struct inode *inode = new_inode(sb); | 676 | struct inode *inode = new_inode(sb); |
692 | 677 | ||
693 | if (!inode) | 678 | if (!inode) { |
679 | dput(dentry); | ||
694 | return ERR_PTR(-ENOMEM); | 680 | return ERR_PTR(-ENOMEM); |
681 | } | ||
695 | 682 | ||
696 | if (S_ISDIR(dentry->d_inode->i_mode)) { | 683 | if (S_ISDIR(dentry->d_inode->i_mode)) { |
697 | inode->i_op = &hppfs_dir_iops; | 684 | inode->i_op = &hppfs_dir_iops; |
@@ -704,7 +691,7 @@ static struct inode *get_inode(struct super_block *sb, struct dentry *dentry) | |||
704 | inode->i_fop = &hppfs_file_fops; | 691 | inode->i_fop = &hppfs_file_fops; |
705 | } | 692 | } |
706 | 693 | ||
707 | HPPFS_I(inode)->proc_dentry = dget(dentry); | 694 | HPPFS_I(inode)->proc_dentry = dentry; |
708 | 695 | ||
709 | inode->i_uid = proc_ino->i_uid; | 696 | inode->i_uid = proc_ino->i_uid; |
710 | inode->i_gid = proc_ino->i_gid; | 697 | inode->i_gid = proc_ino->i_gid; |
@@ -737,7 +724,7 @@ static int hppfs_fill_super(struct super_block *sb, void *d, int silent) | |||
737 | sb->s_fs_info = proc_mnt; | 724 | sb->s_fs_info = proc_mnt; |
738 | 725 | ||
739 | err = -ENOMEM; | 726 | err = -ENOMEM; |
740 | root_inode = get_inode(sb, proc_mnt->mnt_sb->s_root); | 727 | root_inode = get_inode(sb, dget(proc_mnt->mnt_sb->s_root)); |
741 | if (!root_inode) | 728 | if (!root_inode) |
742 | goto out_mntput; | 729 | goto out_mntput; |
743 | 730 | ||
diff --git a/fs/libfs.c b/fs/libfs.c index c88eab55aec9..275ca4749a2e 100644 --- a/fs/libfs.c +++ b/fs/libfs.c | |||
@@ -822,7 +822,7 @@ ssize_t simple_attr_write(struct file *file, const char __user *buf, | |||
822 | goto out; | 822 | goto out; |
823 | 823 | ||
824 | attr->set_buf[size] = '\0'; | 824 | attr->set_buf[size] = '\0'; |
825 | val = simple_strtol(attr->set_buf, NULL, 0); | 825 | val = simple_strtoll(attr->set_buf, NULL, 0); |
826 | ret = attr->set(attr->data, val); | 826 | ret = attr->set(attr->data, val); |
827 | if (ret == 0) | 827 | if (ret == 0) |
828 | ret = len; /* on success, claim we got the whole input */ | 828 | ret = len; /* on success, claim we got the whole input */ |
diff --git a/fs/namei.c b/fs/namei.c index 0223c41fb114..14ab8d3f2f0c 100644 --- a/fs/namei.c +++ b/fs/namei.c | |||
@@ -433,6 +433,8 @@ static int unlazy_walk(struct nameidata *nd, struct dentry *dentry) | |||
433 | goto err_parent; | 433 | goto err_parent; |
434 | BUG_ON(nd->inode != parent->d_inode); | 434 | BUG_ON(nd->inode != parent->d_inode); |
435 | } else { | 435 | } else { |
436 | if (dentry->d_parent != parent) | ||
437 | goto err_parent; | ||
436 | spin_lock_nested(&dentry->d_lock, DENTRY_D_LOCK_NESTED); | 438 | spin_lock_nested(&dentry->d_lock, DENTRY_D_LOCK_NESTED); |
437 | if (!__d_rcu_to_refcount(dentry, nd->seq)) | 439 | if (!__d_rcu_to_refcount(dentry, nd->seq)) |
438 | goto err_child; | 440 | goto err_child; |
@@ -940,7 +942,6 @@ static bool __follow_mount_rcu(struct nameidata *nd, struct path *path, | |||
940 | * Don't forget we might have a non-mountpoint managed dentry | 942 | * Don't forget we might have a non-mountpoint managed dentry |
941 | * that wants to block transit. | 943 | * that wants to block transit. |
942 | */ | 944 | */ |
943 | *inode = path->dentry->d_inode; | ||
944 | if (unlikely(managed_dentry_might_block(path->dentry))) | 945 | if (unlikely(managed_dentry_might_block(path->dentry))) |
945 | return false; | 946 | return false; |
946 | 947 | ||
@@ -953,6 +954,12 @@ static bool __follow_mount_rcu(struct nameidata *nd, struct path *path, | |||
953 | path->mnt = mounted; | 954 | path->mnt = mounted; |
954 | path->dentry = mounted->mnt_root; | 955 | path->dentry = mounted->mnt_root; |
955 | nd->seq = read_seqcount_begin(&path->dentry->d_seq); | 956 | nd->seq = read_seqcount_begin(&path->dentry->d_seq); |
957 | /* | ||
958 | * Update the inode too. We don't need to re-check the | ||
959 | * dentry sequence number here after this d_inode read, | ||
960 | * because a mount-point is always pinned. | ||
961 | */ | ||
962 | *inode = path->dentry->d_inode; | ||
956 | } | 963 | } |
957 | return true; | 964 | return true; |
958 | } | 965 | } |
diff --git a/fs/nfs/nfs4filelayout.c b/fs/nfs/nfs4filelayout.c index 0bafcc91c27f..f9d03abcd04c 100644 --- a/fs/nfs/nfs4filelayout.c +++ b/fs/nfs/nfs4filelayout.c | |||
@@ -398,7 +398,6 @@ filelayout_write_pagelist(struct nfs_write_data *data, int sync) | |||
398 | * this offset and save the original offset. | 398 | * this offset and save the original offset. |
399 | */ | 399 | */ |
400 | data->args.offset = filelayout_get_dserver_offset(lseg, offset); | 400 | data->args.offset = filelayout_get_dserver_offset(lseg, offset); |
401 | data->mds_offset = offset; | ||
402 | 401 | ||
403 | /* Perform an asynchronous write */ | 402 | /* Perform an asynchronous write */ |
404 | status = nfs_initiate_write(data, ds->ds_clp->cl_rpcclient, | 403 | status = nfs_initiate_write(data, ds->ds_clp->cl_rpcclient, |
diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c index 6870bc61ceec..e6e8f3b9a1de 100644 --- a/fs/nfs/nfs4xdr.c +++ b/fs/nfs/nfs4xdr.c | |||
@@ -91,7 +91,7 @@ static int nfs4_stat_to_errno(int); | |||
91 | #define encode_getfh_maxsz (op_encode_hdr_maxsz) | 91 | #define encode_getfh_maxsz (op_encode_hdr_maxsz) |
92 | #define decode_getfh_maxsz (op_decode_hdr_maxsz + 1 + \ | 92 | #define decode_getfh_maxsz (op_decode_hdr_maxsz + 1 + \ |
93 | ((3+NFS4_FHSIZE) >> 2)) | 93 | ((3+NFS4_FHSIZE) >> 2)) |
94 | #define nfs4_fattr_bitmap_maxsz 3 | 94 | #define nfs4_fattr_bitmap_maxsz 4 |
95 | #define encode_getattr_maxsz (op_encode_hdr_maxsz + nfs4_fattr_bitmap_maxsz) | 95 | #define encode_getattr_maxsz (op_encode_hdr_maxsz + nfs4_fattr_bitmap_maxsz) |
96 | #define nfs4_name_maxsz (1 + ((3 + NFS4_MAXNAMLEN) >> 2)) | 96 | #define nfs4_name_maxsz (1 + ((3 + NFS4_MAXNAMLEN) >> 2)) |
97 | #define nfs4_path_maxsz (1 + ((3 + NFS4_MAXPATHLEN) >> 2)) | 97 | #define nfs4_path_maxsz (1 + ((3 + NFS4_MAXPATHLEN) >> 2)) |
diff --git a/fs/nfs/write.c b/fs/nfs/write.c index e268e3b23497..727168059684 100644 --- a/fs/nfs/write.c +++ b/fs/nfs/write.c | |||
@@ -864,6 +864,8 @@ static int nfs_write_rpcsetup(struct nfs_page *req, | |||
864 | 864 | ||
865 | data->args.fh = NFS_FH(inode); | 865 | data->args.fh = NFS_FH(inode); |
866 | data->args.offset = req_offset(req) + offset; | 866 | data->args.offset = req_offset(req) + offset; |
867 | /* pnfs_set_layoutcommit needs this */ | ||
868 | data->mds_offset = data->args.offset; | ||
867 | data->args.pgbase = req->wb_pgbase + offset; | 869 | data->args.pgbase = req->wb_pgbase + offset; |
868 | data->args.pages = data->pagevec; | 870 | data->args.pages = data->pagevec; |
869 | data->args.count = count; | 871 | data->args.count = count; |
diff --git a/fs/ufs/namei.c b/fs/ufs/namei.c index 29309e25417f..b57aab9a1184 100644 --- a/fs/ufs/namei.c +++ b/fs/ufs/namei.c | |||
@@ -56,16 +56,12 @@ static struct dentry *ufs_lookup(struct inode * dir, struct dentry *dentry, stru | |||
56 | 56 | ||
57 | lock_ufs(dir->i_sb); | 57 | lock_ufs(dir->i_sb); |
58 | ino = ufs_inode_by_name(dir, &dentry->d_name); | 58 | ino = ufs_inode_by_name(dir, &dentry->d_name); |
59 | if (ino) { | 59 | if (ino) |
60 | inode = ufs_iget(dir->i_sb, ino); | 60 | inode = ufs_iget(dir->i_sb, ino); |
61 | if (IS_ERR(inode)) { | ||
62 | unlock_ufs(dir->i_sb); | ||
63 | return ERR_CAST(inode); | ||
64 | } | ||
65 | } | ||
66 | unlock_ufs(dir->i_sb); | 61 | unlock_ufs(dir->i_sb); |
67 | d_add(dentry, inode); | 62 | if (IS_ERR(inode)) |
68 | return NULL; | 63 | return ERR_CAST(inode); |
64 | return d_splice_alias(inode, dentry); | ||
69 | } | 65 | } |
70 | 66 | ||
71 | /* | 67 | /* |