diff options
Diffstat (limited to 'fs/cifs/inode.c')
-rw-r--r-- | fs/cifs/inode.c | 93 |
1 files changed, 72 insertions, 21 deletions
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c index 279f3c5e0ce3..e915eb1d2e66 100644 --- a/fs/cifs/inode.c +++ b/fs/cifs/inode.c | |||
@@ -115,7 +115,7 @@ int cifs_get_inode_info_unix(struct inode **pinode, | |||
115 | inode->i_mode = le64_to_cpu(findData.Permissions); | 115 | inode->i_mode = le64_to_cpu(findData.Permissions); |
116 | /* since we set the inode type below we need to mask off | 116 | /* since we set the inode type below we need to mask off |
117 | to avoid strange results if bits set above */ | 117 | to avoid strange results if bits set above */ |
118 | inode->i_mode &= ~S_IFMT; | 118 | inode->i_mode &= ~S_IFMT; |
119 | if (type == UNIX_FILE) { | 119 | if (type == UNIX_FILE) { |
120 | inode->i_mode |= S_IFREG; | 120 | inode->i_mode |= S_IFREG; |
121 | } else if (type == UNIX_SYMLINK) { | 121 | } else if (type == UNIX_SYMLINK) { |
@@ -289,7 +289,7 @@ static int decode_sfu_inode(struct inode *inode, __u64 size, | |||
289 | 289 | ||
290 | #define SFBITS_MASK (S_ISVTX | S_ISGID | S_ISUID) /* SETFILEBITS valid bits */ | 290 | #define SFBITS_MASK (S_ISVTX | S_ISGID | S_ISUID) /* SETFILEBITS valid bits */ |
291 | 291 | ||
292 | static int get_sfu_uid_mode(struct inode *inode, | 292 | static int get_sfu_mode(struct inode *inode, |
293 | const unsigned char *path, | 293 | const unsigned char *path, |
294 | struct cifs_sb_info *cifs_sb, int xid) | 294 | struct cifs_sb_info *cifs_sb, int xid) |
295 | { | 295 | { |
@@ -527,11 +527,16 @@ int cifs_get_inode_info(struct inode **pinode, | |||
527 | 527 | ||
528 | /* BB fill in uid and gid here? with help from winbind? | 528 | /* BB fill in uid and gid here? with help from winbind? |
529 | or retrieve from NTFS stream extended attribute */ | 529 | or retrieve from NTFS stream extended attribute */ |
530 | #ifdef CONFIG_CIFS_EXPERIMENTAL | ||
531 | /* fill in 0777 bits from ACL */ | ||
532 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) { | ||
533 | cFYI(1, ("Getting mode bits from ACL")); | ||
534 | acl_to_uid_mode(inode, search_path); | ||
535 | } | ||
536 | #endif | ||
530 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) { | 537 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) { |
531 | /* fill in uid, gid, mode from server ACL */ | 538 | /* fill in remaining high mode bits e.g. SUID, VTX */ |
532 | /* BB FIXME this should also take into account the | 539 | get_sfu_mode(inode, search_path, cifs_sb, xid); |
533 | * default uid specified on mount if present */ | ||
534 | get_sfu_uid_mode(inode, search_path, cifs_sb, xid); | ||
535 | } else if (atomic_read(&cifsInfo->inUse) == 0) { | 540 | } else if (atomic_read(&cifsInfo->inUse) == 0) { |
536 | inode->i_uid = cifs_sb->mnt_uid; | 541 | inode->i_uid = cifs_sb->mnt_uid; |
537 | inode->i_gid = cifs_sb->mnt_gid; | 542 | inode->i_gid = cifs_sb->mnt_gid; |
@@ -575,19 +580,33 @@ int cifs_get_inode_info(struct inode **pinode, | |||
575 | return rc; | 580 | return rc; |
576 | } | 581 | } |
577 | 582 | ||
583 | static const struct inode_operations cifs_ipc_inode_ops = { | ||
584 | .lookup = cifs_lookup, | ||
585 | }; | ||
586 | |||
578 | /* gets root inode */ | 587 | /* gets root inode */ |
579 | void cifs_read_inode(struct inode *inode) | 588 | void cifs_read_inode(struct inode *inode) |
580 | { | 589 | { |
581 | int xid; | 590 | int xid, rc; |
582 | struct cifs_sb_info *cifs_sb; | 591 | struct cifs_sb_info *cifs_sb; |
583 | 592 | ||
584 | cifs_sb = CIFS_SB(inode->i_sb); | 593 | cifs_sb = CIFS_SB(inode->i_sb); |
585 | xid = GetXid(); | 594 | xid = GetXid(); |
586 | 595 | ||
587 | if (cifs_sb->tcon->unix_ext) | 596 | if (cifs_sb->tcon->unix_ext) |
588 | cifs_get_inode_info_unix(&inode, "", inode->i_sb, xid); | 597 | rc = cifs_get_inode_info_unix(&inode, "", inode->i_sb, xid); |
589 | else | 598 | else |
590 | cifs_get_inode_info(&inode, "", NULL, inode->i_sb, xid); | 599 | rc = cifs_get_inode_info(&inode, "", NULL, inode->i_sb, xid); |
600 | if (rc && cifs_sb->tcon->ipc) { | ||
601 | cFYI(1, ("ipc connection - fake read inode")); | ||
602 | inode->i_mode |= S_IFDIR; | ||
603 | inode->i_nlink = 2; | ||
604 | inode->i_op = &cifs_ipc_inode_ops; | ||
605 | inode->i_fop = &simple_dir_operations; | ||
606 | inode->i_uid = cifs_sb->mnt_uid; | ||
607 | inode->i_gid = cifs_sb->mnt_gid; | ||
608 | } | ||
609 | |||
591 | /* can not call macro FreeXid here since in a void func */ | 610 | /* can not call macro FreeXid here since in a void func */ |
592 | _FreeXid(xid); | 611 | _FreeXid(xid); |
593 | } | 612 | } |
@@ -919,18 +938,25 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode) | |||
919 | goto mkdir_out; | 938 | goto mkdir_out; |
920 | } | 939 | } |
921 | 940 | ||
941 | mode &= ~current->fs->umask; | ||
922 | rc = CIFSPOSIXCreate(xid, pTcon, SMB_O_DIRECTORY | SMB_O_CREAT, | 942 | rc = CIFSPOSIXCreate(xid, pTcon, SMB_O_DIRECTORY | SMB_O_CREAT, |
923 | mode, NULL /* netfid */, pInfo, &oplock, | 943 | mode, NULL /* netfid */, pInfo, &oplock, |
924 | full_path, cifs_sb->local_nls, | 944 | full_path, cifs_sb->local_nls, |
925 | cifs_sb->mnt_cifs_flags & | 945 | cifs_sb->mnt_cifs_flags & |
926 | CIFS_MOUNT_MAP_SPECIAL_CHR); | 946 | CIFS_MOUNT_MAP_SPECIAL_CHR); |
927 | if (rc) { | 947 | if (rc == -EOPNOTSUPP) { |
948 | kfree(pInfo); | ||
949 | goto mkdir_retry_old; | ||
950 | } else if (rc) { | ||
928 | cFYI(1, ("posix mkdir returned 0x%x", rc)); | 951 | cFYI(1, ("posix mkdir returned 0x%x", rc)); |
929 | d_drop(direntry); | 952 | d_drop(direntry); |
930 | } else { | 953 | } else { |
931 | int obj_type; | 954 | int obj_type; |
932 | if (pInfo->Type == -1) /* no return info - go query */ | 955 | if (pInfo->Type == cpu_to_le32(-1)) { |
956 | /* no return info, go query for it */ | ||
957 | kfree(pInfo); | ||
933 | goto mkdir_get_info; | 958 | goto mkdir_get_info; |
959 | } | ||
934 | /*BB check (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID ) to see if need | 960 | /*BB check (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID ) to see if need |
935 | to set uid/gid */ | 961 | to set uid/gid */ |
936 | inc_nlink(inode); | 962 | inc_nlink(inode); |
@@ -940,8 +966,10 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode) | |||
940 | direntry->d_op = &cifs_dentry_ops; | 966 | direntry->d_op = &cifs_dentry_ops; |
941 | 967 | ||
942 | newinode = new_inode(inode->i_sb); | 968 | newinode = new_inode(inode->i_sb); |
943 | if (newinode == NULL) | 969 | if (newinode == NULL) { |
970 | kfree(pInfo); | ||
944 | goto mkdir_get_info; | 971 | goto mkdir_get_info; |
972 | } | ||
945 | /* Is an i_ino of zero legal? */ | 973 | /* Is an i_ino of zero legal? */ |
946 | /* Are there sanity checks we can use to ensure that | 974 | /* Are there sanity checks we can use to ensure that |
947 | the server is really filling in that field? */ | 975 | the server is really filling in that field? */ |
@@ -972,7 +1000,7 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode) | |||
972 | kfree(pInfo); | 1000 | kfree(pInfo); |
973 | goto mkdir_out; | 1001 | goto mkdir_out; |
974 | } | 1002 | } |
975 | 1003 | mkdir_retry_old: | |
976 | /* BB add setting the equivalent of mode via CreateX w/ACLs */ | 1004 | /* BB add setting the equivalent of mode via CreateX w/ACLs */ |
977 | rc = CIFSSMBMkDir(xid, pTcon, full_path, cifs_sb->local_nls, | 1005 | rc = CIFSSMBMkDir(xid, pTcon, full_path, cifs_sb->local_nls, |
978 | cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); | 1006 | cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); |
@@ -1205,7 +1233,7 @@ cifs_rename_exit: | |||
1205 | int cifs_revalidate(struct dentry *direntry) | 1233 | int cifs_revalidate(struct dentry *direntry) |
1206 | { | 1234 | { |
1207 | int xid; | 1235 | int xid; |
1208 | int rc = 0; | 1236 | int rc = 0, wbrc = 0; |
1209 | char *full_path; | 1237 | char *full_path; |
1210 | struct cifs_sb_info *cifs_sb; | 1238 | struct cifs_sb_info *cifs_sb; |
1211 | struct cifsInodeInfo *cifsInode; | 1239 | struct cifsInodeInfo *cifsInode; |
@@ -1305,7 +1333,9 @@ int cifs_revalidate(struct dentry *direntry) | |||
1305 | if (direntry->d_inode->i_mapping) { | 1333 | if (direntry->d_inode->i_mapping) { |
1306 | /* do we need to lock inode until after invalidate completes | 1334 | /* do we need to lock inode until after invalidate completes |
1307 | below? */ | 1335 | below? */ |
1308 | filemap_fdatawrite(direntry->d_inode->i_mapping); | 1336 | wbrc = filemap_fdatawrite(direntry->d_inode->i_mapping); |
1337 | if (wbrc) | ||
1338 | CIFS_I(direntry->d_inode)->write_behind_rc = wbrc; | ||
1309 | } | 1339 | } |
1310 | if (invalidate_inode) { | 1340 | if (invalidate_inode) { |
1311 | /* shrink_dcache not necessary now that cifs dentry ops | 1341 | /* shrink_dcache not necessary now that cifs dentry ops |
@@ -1314,7 +1344,9 @@ int cifs_revalidate(struct dentry *direntry) | |||
1314 | shrink_dcache_parent(direntry); */ | 1344 | shrink_dcache_parent(direntry); */ |
1315 | if (S_ISREG(direntry->d_inode->i_mode)) { | 1345 | if (S_ISREG(direntry->d_inode->i_mode)) { |
1316 | if (direntry->d_inode->i_mapping) | 1346 | if (direntry->d_inode->i_mapping) |
1317 | filemap_fdatawait(direntry->d_inode->i_mapping); | 1347 | wbrc = filemap_fdatawait(direntry->d_inode->i_mapping); |
1348 | if (wbrc) | ||
1349 | CIFS_I(direntry->d_inode)->write_behind_rc = wbrc; | ||
1318 | /* may eventually have to do this for open files too */ | 1350 | /* may eventually have to do this for open files too */ |
1319 | if (list_empty(&(cifsInode->openFileList))) { | 1351 | if (list_empty(&(cifsInode->openFileList))) { |
1320 | /* changed on server - flush read ahead pages */ | 1352 | /* changed on server - flush read ahead pages */ |
@@ -1377,8 +1409,17 @@ static int cifs_vmtruncate(struct inode *inode, loff_t offset) | |||
1377 | } | 1409 | } |
1378 | i_size_write(inode, offset); | 1410 | i_size_write(inode, offset); |
1379 | spin_unlock(&inode->i_lock); | 1411 | spin_unlock(&inode->i_lock); |
1412 | /* | ||
1413 | * unmap_mapping_range is called twice, first simply for efficiency | ||
1414 | * so that truncate_inode_pages does fewer single-page unmaps. However | ||
1415 | * after this first call, and before truncate_inode_pages finishes, | ||
1416 | * it is possible for private pages to be COWed, which remain after | ||
1417 | * truncate_inode_pages finishes, hence the second unmap_mapping_range | ||
1418 | * call must be made for correctness. | ||
1419 | */ | ||
1380 | unmap_mapping_range(mapping, offset + PAGE_SIZE - 1, 0, 1); | 1420 | unmap_mapping_range(mapping, offset + PAGE_SIZE - 1, 0, 1); |
1381 | truncate_inode_pages(mapping, offset); | 1421 | truncate_inode_pages(mapping, offset); |
1422 | unmap_mapping_range(mapping, offset + PAGE_SIZE - 1, 0, 1); | ||
1382 | goto out_truncate; | 1423 | goto out_truncate; |
1383 | 1424 | ||
1384 | do_expand: | 1425 | do_expand: |
@@ -1448,10 +1489,20 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs) | |||
1448 | 1489 | ||
1449 | /* BB check if we need to refresh inode from server now ? BB */ | 1490 | /* BB check if we need to refresh inode from server now ? BB */ |
1450 | 1491 | ||
1451 | /* need to flush data before changing file size on server */ | ||
1452 | filemap_write_and_wait(direntry->d_inode->i_mapping); | ||
1453 | |||
1454 | if (attrs->ia_valid & ATTR_SIZE) { | 1492 | if (attrs->ia_valid & ATTR_SIZE) { |
1493 | /* | ||
1494 | Flush data before changing file size on server. If the | ||
1495 | flush returns error, store it to report later and continue. | ||
1496 | BB: This should be smarter. Why bother flushing pages that | ||
1497 | will be truncated anyway? Also, should we error out here if | ||
1498 | the flush returns error? | ||
1499 | */ | ||
1500 | rc = filemap_write_and_wait(direntry->d_inode->i_mapping); | ||
1501 | if (rc != 0) { | ||
1502 | CIFS_I(direntry->d_inode)->write_behind_rc = rc; | ||
1503 | rc = 0; | ||
1504 | } | ||
1505 | |||
1455 | /* To avoid spurious oplock breaks from server, in the case of | 1506 | /* To avoid spurious oplock breaks from server, in the case of |
1456 | inodes that we already have open, avoid doing path based | 1507 | inodes that we already have open, avoid doing path based |
1457 | setting of file size if we can do it by handle. | 1508 | setting of file size if we can do it by handle. |
@@ -1469,7 +1520,7 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs) | |||
1469 | atomic_dec(&open_file->wrtPending); | 1520 | atomic_dec(&open_file->wrtPending); |
1470 | cFYI(1, ("SetFSize for attrs rc = %d", rc)); | 1521 | cFYI(1, ("SetFSize for attrs rc = %d", rc)); |
1471 | if ((rc == -EINVAL) || (rc == -EOPNOTSUPP)) { | 1522 | if ((rc == -EINVAL) || (rc == -EOPNOTSUPP)) { |
1472 | int bytes_written; | 1523 | unsigned int bytes_written; |
1473 | rc = CIFSSMBWrite(xid, pTcon, | 1524 | rc = CIFSSMBWrite(xid, pTcon, |
1474 | nfid, 0, attrs->ia_size, | 1525 | nfid, 0, attrs->ia_size, |
1475 | &bytes_written, NULL, NULL, | 1526 | &bytes_written, NULL, NULL, |
@@ -1502,7 +1553,7 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs) | |||
1502 | cifs_sb->mnt_cifs_flags & | 1553 | cifs_sb->mnt_cifs_flags & |
1503 | CIFS_MOUNT_MAP_SPECIAL_CHR); | 1554 | CIFS_MOUNT_MAP_SPECIAL_CHR); |
1504 | if (rc == 0) { | 1555 | if (rc == 0) { |
1505 | int bytes_written; | 1556 | unsigned int bytes_written; |
1506 | rc = CIFSSMBWrite(xid, pTcon, | 1557 | rc = CIFSSMBWrite(xid, pTcon, |
1507 | netfid, 0, | 1558 | netfid, 0, |
1508 | attrs->ia_size, | 1559 | attrs->ia_size, |