diff options
Diffstat (limited to 'fs')
| -rw-r--r-- | fs/cifs/cifsproto.h | 7 | ||||
| -rw-r--r-- | fs/cifs/cifssmb.c | 6 | ||||
| -rw-r--r-- | fs/cifs/dir.c | 11 | ||||
| -rw-r--r-- | fs/cifs/inode.c | 6 | ||||
| -rw-r--r-- | fs/cifs/link.c | 26 | ||||
| -rw-r--r-- | fs/eventpoll.c | 4 | ||||
| -rw-r--r-- | fs/ext4/extents.c | 2 | ||||
| -rw-r--r-- | fs/gfs2/aops.c | 30 | ||||
| -rw-r--r-- | fs/gfs2/glock.c | 2 | ||||
| -rw-r--r-- | fs/gfs2/glops.c | 10 | ||||
| -rw-r--r-- | fs/gfs2/log.c | 4 | ||||
| -rw-r--r-- | fs/gfs2/meta_io.c | 5 | ||||
| -rw-r--r-- | fs/gfs2/ops_fstype.c | 12 |
13 files changed, 87 insertions, 38 deletions
diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h index aa3397620342..2c29db6a247e 100644 --- a/fs/cifs/cifsproto.h +++ b/fs/cifs/cifsproto.h | |||
| @@ -477,9 +477,10 @@ extern int CIFSGetExtAttr(const unsigned int xid, struct cifs_tcon *tcon, | |||
| 477 | const int netfid, __u64 *pExtAttrBits, __u64 *pMask); | 477 | const int netfid, __u64 *pExtAttrBits, __u64 *pMask); |
| 478 | extern void cifs_autodisable_serverino(struct cifs_sb_info *cifs_sb); | 478 | extern void cifs_autodisable_serverino(struct cifs_sb_info *cifs_sb); |
| 479 | extern bool CIFSCouldBeMFSymlink(const struct cifs_fattr *fattr); | 479 | extern bool CIFSCouldBeMFSymlink(const struct cifs_fattr *fattr); |
| 480 | extern int CIFSCheckMFSymlink(struct cifs_fattr *fattr, | 480 | extern int CIFSCheckMFSymlink(unsigned int xid, struct cifs_tcon *tcon, |
| 481 | const unsigned char *path, | 481 | struct cifs_sb_info *cifs_sb, |
| 482 | struct cifs_sb_info *cifs_sb, unsigned int xid); | 482 | struct cifs_fattr *fattr, |
| 483 | const unsigned char *path); | ||
| 483 | extern int mdfour(unsigned char *, unsigned char *, int); | 484 | extern int mdfour(unsigned char *, unsigned char *, int); |
| 484 | extern int E_md4hash(const unsigned char *passwd, unsigned char *p16, | 485 | extern int E_md4hash(const unsigned char *passwd, unsigned char *p16, |
| 485 | const struct nls_table *codepage); | 486 | const struct nls_table *codepage); |
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c index 124aa0230c1b..d707edb6b852 100644 --- a/fs/cifs/cifssmb.c +++ b/fs/cifs/cifssmb.c | |||
| @@ -4010,7 +4010,7 @@ QFileInfoRetry: | |||
| 4010 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | 4010 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, |
| 4011 | (struct smb_hdr *) pSMBr, &bytes_returned, 0); | 4011 | (struct smb_hdr *) pSMBr, &bytes_returned, 0); |
| 4012 | if (rc) { | 4012 | if (rc) { |
| 4013 | cifs_dbg(FYI, "Send error in QPathInfo = %d\n", rc); | 4013 | cifs_dbg(FYI, "Send error in QFileInfo = %d", rc); |
| 4014 | } else { /* decode response */ | 4014 | } else { /* decode response */ |
| 4015 | rc = validate_t2((struct smb_t2_rsp *)pSMBr); | 4015 | rc = validate_t2((struct smb_t2_rsp *)pSMBr); |
| 4016 | 4016 | ||
| @@ -4179,7 +4179,7 @@ UnixQFileInfoRetry: | |||
| 4179 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | 4179 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, |
| 4180 | (struct smb_hdr *) pSMBr, &bytes_returned, 0); | 4180 | (struct smb_hdr *) pSMBr, &bytes_returned, 0); |
| 4181 | if (rc) { | 4181 | if (rc) { |
| 4182 | cifs_dbg(FYI, "Send error in QPathInfo = %d\n", rc); | 4182 | cifs_dbg(FYI, "Send error in UnixQFileInfo = %d", rc); |
| 4183 | } else { /* decode response */ | 4183 | } else { /* decode response */ |
| 4184 | rc = validate_t2((struct smb_t2_rsp *)pSMBr); | 4184 | rc = validate_t2((struct smb_t2_rsp *)pSMBr); |
| 4185 | 4185 | ||
| @@ -4263,7 +4263,7 @@ UnixQPathInfoRetry: | |||
| 4263 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | 4263 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, |
| 4264 | (struct smb_hdr *) pSMBr, &bytes_returned, 0); | 4264 | (struct smb_hdr *) pSMBr, &bytes_returned, 0); |
| 4265 | if (rc) { | 4265 | if (rc) { |
| 4266 | cifs_dbg(FYI, "Send error in QPathInfo = %d\n", rc); | 4266 | cifs_dbg(FYI, "Send error in UnixQPathInfo = %d", rc); |
| 4267 | } else { /* decode response */ | 4267 | } else { /* decode response */ |
| 4268 | rc = validate_t2((struct smb_t2_rsp *)pSMBr); | 4268 | rc = validate_t2((struct smb_t2_rsp *)pSMBr); |
| 4269 | 4269 | ||
diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c index 11ff5f116b20..a514e0a65f69 100644 --- a/fs/cifs/dir.c +++ b/fs/cifs/dir.c | |||
| @@ -193,7 +193,7 @@ check_name(struct dentry *direntry) | |||
| 193 | static int | 193 | static int |
| 194 | cifs_do_create(struct inode *inode, struct dentry *direntry, unsigned int xid, | 194 | cifs_do_create(struct inode *inode, struct dentry *direntry, unsigned int xid, |
| 195 | struct tcon_link *tlink, unsigned oflags, umode_t mode, | 195 | struct tcon_link *tlink, unsigned oflags, umode_t mode, |
| 196 | __u32 *oplock, struct cifs_fid *fid, int *created) | 196 | __u32 *oplock, struct cifs_fid *fid) |
| 197 | { | 197 | { |
| 198 | int rc = -ENOENT; | 198 | int rc = -ENOENT; |
| 199 | int create_options = CREATE_NOT_DIR; | 199 | int create_options = CREATE_NOT_DIR; |
| @@ -349,7 +349,6 @@ cifs_do_create(struct inode *inode, struct dentry *direntry, unsigned int xid, | |||
| 349 | .device = 0, | 349 | .device = 0, |
| 350 | }; | 350 | }; |
| 351 | 351 | ||
| 352 | *created |= FILE_CREATED; | ||
| 353 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) { | 352 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) { |
| 354 | args.uid = current_fsuid(); | 353 | args.uid = current_fsuid(); |
| 355 | if (inode->i_mode & S_ISGID) | 354 | if (inode->i_mode & S_ISGID) |
| @@ -480,13 +479,16 @@ cifs_atomic_open(struct inode *inode, struct dentry *direntry, | |||
| 480 | cifs_add_pending_open(&fid, tlink, &open); | 479 | cifs_add_pending_open(&fid, tlink, &open); |
| 481 | 480 | ||
| 482 | rc = cifs_do_create(inode, direntry, xid, tlink, oflags, mode, | 481 | rc = cifs_do_create(inode, direntry, xid, tlink, oflags, mode, |
| 483 | &oplock, &fid, opened); | 482 | &oplock, &fid); |
| 484 | 483 | ||
| 485 | if (rc) { | 484 | if (rc) { |
| 486 | cifs_del_pending_open(&open); | 485 | cifs_del_pending_open(&open); |
| 487 | goto out; | 486 | goto out; |
| 488 | } | 487 | } |
| 489 | 488 | ||
| 489 | if ((oflags & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL)) | ||
| 490 | *opened |= FILE_CREATED; | ||
| 491 | |||
| 490 | rc = finish_open(file, direntry, generic_file_open, opened); | 492 | rc = finish_open(file, direntry, generic_file_open, opened); |
| 491 | if (rc) { | 493 | if (rc) { |
| 492 | if (server->ops->close) | 494 | if (server->ops->close) |
| @@ -529,7 +531,6 @@ int cifs_create(struct inode *inode, struct dentry *direntry, umode_t mode, | |||
| 529 | struct TCP_Server_Info *server; | 531 | struct TCP_Server_Info *server; |
| 530 | struct cifs_fid fid; | 532 | struct cifs_fid fid; |
| 531 | __u32 oplock; | 533 | __u32 oplock; |
| 532 | int created = FILE_CREATED; | ||
| 533 | 534 | ||
| 534 | cifs_dbg(FYI, "cifs_create parent inode = 0x%p name is: %s and dentry = 0x%p\n", | 535 | cifs_dbg(FYI, "cifs_create parent inode = 0x%p name is: %s and dentry = 0x%p\n", |
| 535 | inode, direntry->d_name.name, direntry); | 536 | inode, direntry->d_name.name, direntry); |
| @@ -546,7 +547,7 @@ int cifs_create(struct inode *inode, struct dentry *direntry, umode_t mode, | |||
| 546 | server->ops->new_lease_key(&fid); | 547 | server->ops->new_lease_key(&fid); |
| 547 | 548 | ||
| 548 | rc = cifs_do_create(inode, direntry, xid, tlink, oflags, mode, | 549 | rc = cifs_do_create(inode, direntry, xid, tlink, oflags, mode, |
| 549 | &oplock, &fid, &created); | 550 | &oplock, &fid); |
| 550 | if (!rc && server->ops->close) | 551 | if (!rc && server->ops->close) |
| 551 | server->ops->close(xid, tcon, &fid); | 552 | server->ops->close(xid, tcon, &fid); |
| 552 | 553 | ||
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c index 36f9ebb93ceb..49719b8228e5 100644 --- a/fs/cifs/inode.c +++ b/fs/cifs/inode.c | |||
| @@ -383,7 +383,8 @@ int cifs_get_inode_info_unix(struct inode **pinode, | |||
| 383 | 383 | ||
| 384 | /* check for Minshall+French symlinks */ | 384 | /* check for Minshall+French symlinks */ |
| 385 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS) { | 385 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS) { |
| 386 | int tmprc = CIFSCheckMFSymlink(&fattr, full_path, cifs_sb, xid); | 386 | int tmprc = CIFSCheckMFSymlink(xid, tcon, cifs_sb, &fattr, |
| 387 | full_path); | ||
| 387 | if (tmprc) | 388 | if (tmprc) |
| 388 | cifs_dbg(FYI, "CIFSCheckMFSymlink: %d\n", tmprc); | 389 | cifs_dbg(FYI, "CIFSCheckMFSymlink: %d\n", tmprc); |
| 389 | } | 390 | } |
| @@ -799,7 +800,8 @@ cifs_get_inode_info(struct inode **inode, const char *full_path, | |||
| 799 | 800 | ||
| 800 | /* check for Minshall+French symlinks */ | 801 | /* check for Minshall+French symlinks */ |
| 801 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS) { | 802 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS) { |
| 802 | tmprc = CIFSCheckMFSymlink(&fattr, full_path, cifs_sb, xid); | 803 | tmprc = CIFSCheckMFSymlink(xid, tcon, cifs_sb, &fattr, |
| 804 | full_path); | ||
| 803 | if (tmprc) | 805 | if (tmprc) |
| 804 | cifs_dbg(FYI, "CIFSCheckMFSymlink: %d\n", tmprc); | 806 | cifs_dbg(FYI, "CIFSCheckMFSymlink: %d\n", tmprc); |
| 805 | } | 807 | } |
diff --git a/fs/cifs/link.c b/fs/cifs/link.c index cc0234710ddb..92aee08483a5 100644 --- a/fs/cifs/link.c +++ b/fs/cifs/link.c | |||
| @@ -354,34 +354,30 @@ open_query_close_cifs_symlink(const unsigned char *path, char *pbuf, | |||
| 354 | 354 | ||
| 355 | 355 | ||
| 356 | int | 356 | int |
| 357 | CIFSCheckMFSymlink(struct cifs_fattr *fattr, | 357 | CIFSCheckMFSymlink(unsigned int xid, struct cifs_tcon *tcon, |
| 358 | const unsigned char *path, | 358 | struct cifs_sb_info *cifs_sb, struct cifs_fattr *fattr, |
| 359 | struct cifs_sb_info *cifs_sb, unsigned int xid) | 359 | const unsigned char *path) |
| 360 | { | 360 | { |
| 361 | int rc = 0; | 361 | int rc; |
| 362 | u8 *buf = NULL; | 362 | u8 *buf = NULL; |
| 363 | unsigned int link_len = 0; | 363 | unsigned int link_len = 0; |
| 364 | unsigned int bytes_read = 0; | 364 | unsigned int bytes_read = 0; |
| 365 | struct cifs_tcon *ptcon; | ||
| 366 | 365 | ||
| 367 | if (!CIFSCouldBeMFSymlink(fattr)) | 366 | if (!CIFSCouldBeMFSymlink(fattr)) |
| 368 | /* it's not a symlink */ | 367 | /* it's not a symlink */ |
| 369 | return 0; | 368 | return 0; |
| 370 | 369 | ||
| 371 | buf = kmalloc(CIFS_MF_SYMLINK_FILE_SIZE, GFP_KERNEL); | 370 | buf = kmalloc(CIFS_MF_SYMLINK_FILE_SIZE, GFP_KERNEL); |
| 372 | if (!buf) { | 371 | if (!buf) |
| 373 | rc = -ENOMEM; | 372 | return -ENOMEM; |
| 374 | goto out; | ||
| 375 | } | ||
| 376 | 373 | ||
| 377 | ptcon = tlink_tcon(cifs_sb_tlink(cifs_sb)); | 374 | if (tcon->ses->server->ops->query_mf_symlink) |
| 378 | if ((ptcon->ses) && (ptcon->ses->server->ops->query_mf_symlink)) | 375 | rc = tcon->ses->server->ops->query_mf_symlink(path, buf, |
| 379 | rc = ptcon->ses->server->ops->query_mf_symlink(path, buf, | 376 | &bytes_read, cifs_sb, xid); |
| 380 | &bytes_read, cifs_sb, xid); | ||
| 381 | else | 377 | else |
| 382 | goto out; | 378 | rc = -ENOSYS; |
| 383 | 379 | ||
| 384 | if (rc != 0) | 380 | if (rc) |
| 385 | goto out; | 381 | goto out; |
| 386 | 382 | ||
| 387 | if (bytes_read == 0) /* not a symlink */ | 383 | if (bytes_read == 0) /* not a symlink */ |
diff --git a/fs/eventpoll.c b/fs/eventpoll.c index 8b5e2584c840..af903128891c 100644 --- a/fs/eventpoll.c +++ b/fs/eventpoll.c | |||
| @@ -1907,10 +1907,6 @@ SYSCALL_DEFINE4(epoll_ctl, int, epfd, int, op, int, fd, | |||
| 1907 | } | 1907 | } |
| 1908 | } | 1908 | } |
| 1909 | } | 1909 | } |
| 1910 | if (op == EPOLL_CTL_DEL && is_file_epoll(tf.file)) { | ||
| 1911 | tep = tf.file->private_data; | ||
| 1912 | mutex_lock_nested(&tep->mtx, 1); | ||
| 1913 | } | ||
| 1914 | 1910 | ||
| 1915 | /* | 1911 | /* |
| 1916 | * Try to lookup the file inside our RB tree, Since we grabbed "mtx" | 1912 | * Try to lookup the file inside our RB tree, Since we grabbed "mtx" |
diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c index 4410cc3d6ee2..3384dc4bed40 100644 --- a/fs/ext4/extents.c +++ b/fs/ext4/extents.c | |||
| @@ -4218,7 +4218,7 @@ int ext4_ext_map_blocks(handle_t *handle, struct inode *inode, | |||
| 4218 | */ | 4218 | */ |
| 4219 | map->m_flags &= ~EXT4_MAP_FROM_CLUSTER; | 4219 | map->m_flags &= ~EXT4_MAP_FROM_CLUSTER; |
| 4220 | newex.ee_block = cpu_to_le32(map->m_lblk); | 4220 | newex.ee_block = cpu_to_le32(map->m_lblk); |
| 4221 | cluster_offset = EXT4_LBLK_CMASK(sbi, map->m_lblk); | 4221 | cluster_offset = EXT4_LBLK_COFF(sbi, map->m_lblk); |
| 4222 | 4222 | ||
| 4223 | /* | 4223 | /* |
| 4224 | * If we are doing bigalloc, check to see if the extent returned | 4224 | * If we are doing bigalloc, check to see if the extent returned |
diff --git a/fs/gfs2/aops.c b/fs/gfs2/aops.c index b7fc035a6943..73f3e4ee4037 100644 --- a/fs/gfs2/aops.c +++ b/fs/gfs2/aops.c | |||
| @@ -986,6 +986,7 @@ static ssize_t gfs2_direct_IO(int rw, struct kiocb *iocb, | |||
| 986 | { | 986 | { |
| 987 | struct file *file = iocb->ki_filp; | 987 | struct file *file = iocb->ki_filp; |
| 988 | struct inode *inode = file->f_mapping->host; | 988 | struct inode *inode = file->f_mapping->host; |
| 989 | struct address_space *mapping = inode->i_mapping; | ||
| 989 | struct gfs2_inode *ip = GFS2_I(inode); | 990 | struct gfs2_inode *ip = GFS2_I(inode); |
| 990 | struct gfs2_holder gh; | 991 | struct gfs2_holder gh; |
| 991 | int rv; | 992 | int rv; |
| @@ -1006,6 +1007,35 @@ static ssize_t gfs2_direct_IO(int rw, struct kiocb *iocb, | |||
| 1006 | if (rv != 1) | 1007 | if (rv != 1) |
| 1007 | goto out; /* dio not valid, fall back to buffered i/o */ | 1008 | goto out; /* dio not valid, fall back to buffered i/o */ |
| 1008 | 1009 | ||
| 1010 | /* | ||
| 1011 | * Now since we are holding a deferred (CW) lock at this point, you | ||
| 1012 | * might be wondering why this is ever needed. There is a case however | ||
| 1013 | * where we've granted a deferred local lock against a cached exclusive | ||
| 1014 | * glock. That is ok provided all granted local locks are deferred, but | ||
| 1015 | * it also means that it is possible to encounter pages which are | ||
| 1016 | * cached and possibly also mapped. So here we check for that and sort | ||
| 1017 | * them out ahead of the dio. The glock state machine will take care of | ||
| 1018 | * everything else. | ||
| 1019 | * | ||
| 1020 | * If in fact the cached glock state (gl->gl_state) is deferred (CW) in | ||
| 1021 | * the first place, mapping->nr_pages will always be zero. | ||
| 1022 | */ | ||
| 1023 | if (mapping->nrpages) { | ||
| 1024 | loff_t lstart = offset & (PAGE_CACHE_SIZE - 1); | ||
| 1025 | loff_t len = iov_length(iov, nr_segs); | ||
| 1026 | loff_t end = PAGE_ALIGN(offset + len) - 1; | ||
| 1027 | |||
| 1028 | rv = 0; | ||
| 1029 | if (len == 0) | ||
| 1030 | goto out; | ||
| 1031 | if (test_and_clear_bit(GIF_SW_PAGED, &ip->i_flags)) | ||
| 1032 | unmap_shared_mapping_range(ip->i_inode.i_mapping, offset, len); | ||
| 1033 | rv = filemap_write_and_wait_range(mapping, lstart, end); | ||
| 1034 | if (rv) | ||
| 1035 | return rv; | ||
| 1036 | truncate_inode_pages_range(mapping, lstart, end); | ||
| 1037 | } | ||
| 1038 | |||
| 1009 | rv = __blockdev_direct_IO(rw, iocb, inode, inode->i_sb->s_bdev, iov, | 1039 | rv = __blockdev_direct_IO(rw, iocb, inode, inode->i_sb->s_bdev, iov, |
| 1010 | offset, nr_segs, gfs2_get_block_direct, | 1040 | offset, nr_segs, gfs2_get_block_direct, |
| 1011 | NULL, NULL, 0); | 1041 | NULL, NULL, 0); |
diff --git a/fs/gfs2/glock.c b/fs/gfs2/glock.c index c8420f7e4db6..6f7a47c05259 100644 --- a/fs/gfs2/glock.c +++ b/fs/gfs2/glock.c | |||
| @@ -1655,6 +1655,7 @@ static int dump_holder(struct seq_file *seq, const struct gfs2_holder *gh) | |||
| 1655 | struct task_struct *gh_owner = NULL; | 1655 | struct task_struct *gh_owner = NULL; |
| 1656 | char flags_buf[32]; | 1656 | char flags_buf[32]; |
| 1657 | 1657 | ||
| 1658 | rcu_read_lock(); | ||
| 1658 | if (gh->gh_owner_pid) | 1659 | if (gh->gh_owner_pid) |
| 1659 | gh_owner = pid_task(gh->gh_owner_pid, PIDTYPE_PID); | 1660 | gh_owner = pid_task(gh->gh_owner_pid, PIDTYPE_PID); |
| 1660 | gfs2_print_dbg(seq, " H: s:%s f:%s e:%d p:%ld [%s] %pS\n", | 1661 | gfs2_print_dbg(seq, " H: s:%s f:%s e:%d p:%ld [%s] %pS\n", |
| @@ -1664,6 +1665,7 @@ static int dump_holder(struct seq_file *seq, const struct gfs2_holder *gh) | |||
| 1664 | gh->gh_owner_pid ? (long)pid_nr(gh->gh_owner_pid) : -1, | 1665 | gh->gh_owner_pid ? (long)pid_nr(gh->gh_owner_pid) : -1, |
| 1665 | gh_owner ? gh_owner->comm : "(ended)", | 1666 | gh_owner ? gh_owner->comm : "(ended)", |
| 1666 | (void *)gh->gh_ip); | 1667 | (void *)gh->gh_ip); |
| 1668 | rcu_read_unlock(); | ||
| 1667 | return 0; | 1669 | return 0; |
| 1668 | } | 1670 | } |
| 1669 | 1671 | ||
diff --git a/fs/gfs2/glops.c b/fs/gfs2/glops.c index db908f697139..f88dcd925010 100644 --- a/fs/gfs2/glops.c +++ b/fs/gfs2/glops.c | |||
| @@ -192,8 +192,11 @@ static void inode_go_sync(struct gfs2_glock *gl) | |||
| 192 | 192 | ||
| 193 | if (ip && !S_ISREG(ip->i_inode.i_mode)) | 193 | if (ip && !S_ISREG(ip->i_inode.i_mode)) |
| 194 | ip = NULL; | 194 | ip = NULL; |
| 195 | if (ip && test_and_clear_bit(GIF_SW_PAGED, &ip->i_flags)) | 195 | if (ip) { |
| 196 | unmap_shared_mapping_range(ip->i_inode.i_mapping, 0, 0); | 196 | if (test_and_clear_bit(GIF_SW_PAGED, &ip->i_flags)) |
| 197 | unmap_shared_mapping_range(ip->i_inode.i_mapping, 0, 0); | ||
| 198 | inode_dio_wait(&ip->i_inode); | ||
| 199 | } | ||
| 197 | if (!test_and_clear_bit(GLF_DIRTY, &gl->gl_flags)) | 200 | if (!test_and_clear_bit(GLF_DIRTY, &gl->gl_flags)) |
| 198 | return; | 201 | return; |
| 199 | 202 | ||
| @@ -410,6 +413,9 @@ static int inode_go_lock(struct gfs2_holder *gh) | |||
| 410 | return error; | 413 | return error; |
| 411 | } | 414 | } |
| 412 | 415 | ||
| 416 | if (gh->gh_state != LM_ST_DEFERRED) | ||
| 417 | inode_dio_wait(&ip->i_inode); | ||
| 418 | |||
| 413 | if ((ip->i_diskflags & GFS2_DIF_TRUNC_IN_PROG) && | 419 | if ((ip->i_diskflags & GFS2_DIF_TRUNC_IN_PROG) && |
| 414 | (gl->gl_state == LM_ST_EXCLUSIVE) && | 420 | (gl->gl_state == LM_ST_EXCLUSIVE) && |
| 415 | (gh->gh_state == LM_ST_EXCLUSIVE)) { | 421 | (gh->gh_state == LM_ST_EXCLUSIVE)) { |
diff --git a/fs/gfs2/log.c b/fs/gfs2/log.c index 610613fb65b5..9dcb9777a5f8 100644 --- a/fs/gfs2/log.c +++ b/fs/gfs2/log.c | |||
| @@ -551,10 +551,10 @@ void gfs2_add_revoke(struct gfs2_sbd *sdp, struct gfs2_bufdata *bd) | |||
| 551 | struct buffer_head *bh = bd->bd_bh; | 551 | struct buffer_head *bh = bd->bd_bh; |
| 552 | struct gfs2_glock *gl = bd->bd_gl; | 552 | struct gfs2_glock *gl = bd->bd_gl; |
| 553 | 553 | ||
| 554 | gfs2_remove_from_ail(bd); | ||
| 555 | bd->bd_bh = NULL; | ||
| 556 | bh->b_private = NULL; | 554 | bh->b_private = NULL; |
| 557 | bd->bd_blkno = bh->b_blocknr; | 555 | bd->bd_blkno = bh->b_blocknr; |
| 556 | gfs2_remove_from_ail(bd); /* drops ref on bh */ | ||
| 557 | bd->bd_bh = NULL; | ||
| 558 | bd->bd_ops = &gfs2_revoke_lops; | 558 | bd->bd_ops = &gfs2_revoke_lops; |
| 559 | sdp->sd_log_num_revoke++; | 559 | sdp->sd_log_num_revoke++; |
| 560 | atomic_inc(&gl->gl_revokes); | 560 | atomic_inc(&gl->gl_revokes); |
diff --git a/fs/gfs2/meta_io.c b/fs/gfs2/meta_io.c index 932415050540..52f177be3bf8 100644 --- a/fs/gfs2/meta_io.c +++ b/fs/gfs2/meta_io.c | |||
| @@ -258,6 +258,7 @@ void gfs2_remove_from_journal(struct buffer_head *bh, struct gfs2_trans *tr, int | |||
| 258 | struct address_space *mapping = bh->b_page->mapping; | 258 | struct address_space *mapping = bh->b_page->mapping; |
| 259 | struct gfs2_sbd *sdp = gfs2_mapping2sbd(mapping); | 259 | struct gfs2_sbd *sdp = gfs2_mapping2sbd(mapping); |
| 260 | struct gfs2_bufdata *bd = bh->b_private; | 260 | struct gfs2_bufdata *bd = bh->b_private; |
| 261 | int was_pinned = 0; | ||
| 261 | 262 | ||
| 262 | if (test_clear_buffer_pinned(bh)) { | 263 | if (test_clear_buffer_pinned(bh)) { |
| 263 | trace_gfs2_pin(bd, 0); | 264 | trace_gfs2_pin(bd, 0); |
| @@ -273,12 +274,16 @@ void gfs2_remove_from_journal(struct buffer_head *bh, struct gfs2_trans *tr, int | |||
| 273 | tr->tr_num_databuf_rm++; | 274 | tr->tr_num_databuf_rm++; |
| 274 | } | 275 | } |
| 275 | tr->tr_touched = 1; | 276 | tr->tr_touched = 1; |
| 277 | was_pinned = 1; | ||
| 276 | brelse(bh); | 278 | brelse(bh); |
| 277 | } | 279 | } |
| 278 | if (bd) { | 280 | if (bd) { |
| 279 | spin_lock(&sdp->sd_ail_lock); | 281 | spin_lock(&sdp->sd_ail_lock); |
| 280 | if (bd->bd_tr) { | 282 | if (bd->bd_tr) { |
| 281 | gfs2_trans_add_revoke(sdp, bd); | 283 | gfs2_trans_add_revoke(sdp, bd); |
| 284 | } else if (was_pinned) { | ||
| 285 | bh->b_private = NULL; | ||
| 286 | kmem_cache_free(gfs2_bufdata_cachep, bd); | ||
| 282 | } | 287 | } |
| 283 | spin_unlock(&sdp->sd_ail_lock); | 288 | spin_unlock(&sdp->sd_ail_lock); |
| 284 | } | 289 | } |
diff --git a/fs/gfs2/ops_fstype.c b/fs/gfs2/ops_fstype.c index 82303b474958..52fa88314f5c 100644 --- a/fs/gfs2/ops_fstype.c +++ b/fs/gfs2/ops_fstype.c | |||
| @@ -1366,8 +1366,18 @@ static struct dentry *gfs2_mount(struct file_system_type *fs_type, int flags, | |||
| 1366 | if (IS_ERR(s)) | 1366 | if (IS_ERR(s)) |
| 1367 | goto error_bdev; | 1367 | goto error_bdev; |
| 1368 | 1368 | ||
| 1369 | if (s->s_root) | 1369 | if (s->s_root) { |
| 1370 | /* | ||
| 1371 | * s_umount nests inside bd_mutex during | ||
| 1372 | * __invalidate_device(). blkdev_put() acquires | ||
| 1373 | * bd_mutex and can't be called under s_umount. Drop | ||
| 1374 | * s_umount temporarily. This is safe as we're | ||
| 1375 | * holding an active reference. | ||
| 1376 | */ | ||
| 1377 | up_write(&s->s_umount); | ||
| 1370 | blkdev_put(bdev, mode); | 1378 | blkdev_put(bdev, mode); |
| 1379 | down_write(&s->s_umount); | ||
| 1380 | } | ||
| 1371 | 1381 | ||
| 1372 | memset(&args, 0, sizeof(args)); | 1382 | memset(&args, 0, sizeof(args)); |
| 1373 | args.ar_quota = GFS2_QUOTA_DEFAULT; | 1383 | args.ar_quota = GFS2_QUOTA_DEFAULT; |
