aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorTrond Myklebust <Trond.Myklebust@netapp.com>2007-02-14 01:02:32 -0500
committerTrond Myklebust <Trond.Myklebust@netapp.com>2007-02-14 01:02:32 -0500
commitac98695d6c1508b724f246f38ce57fb4e3cec356 (patch)
tree189969a3689b9b83eaf39314a7942cc781ff836b /fs
parentd9bc125caf592b7d081021f32ce5b717efdf70c8 (diff)
parent93bbad8fe13a25dcf7f3bc628a71d1a7642ae61b (diff)
Merge branch 'master' of /home/trondmy/kernel/linux-2.6/
Diffstat (limited to 'fs')
-rw-r--r--fs/Kconfig29
-rw-r--r--fs/cifs/CHANGES9
-rw-r--r--fs/cifs/TODO8
-rw-r--r--fs/cifs/cifsfs.h2
-rw-r--r--fs/cifs/cifspdu.h84
-rw-r--r--fs/cifs/cifsproto.h5
-rw-r--r--fs/cifs/cifssmb.c16
-rw-r--r--fs/cifs/connect.c130
-rw-r--r--fs/cifs/file.c5
-rw-r--r--fs/cifs/inode.c6
-rw-r--r--fs/cifs/readdir.c6
-rw-r--r--fs/dcache.c150
12 files changed, 273 insertions, 177 deletions
diff --git a/fs/Kconfig b/fs/Kconfig
index 488521ed9e9b..a722b5a3f752 100644
--- a/fs/Kconfig
+++ b/fs/Kconfig
@@ -1864,20 +1864,14 @@ config CIFS
1864 file servers such as Windows 2000 (including Windows 2003, NT 4 1864 file servers such as Windows 2000 (including Windows 2003, NT 4
1865 and Windows XP) as well by Samba (which provides excellent CIFS 1865 and Windows XP) as well by Samba (which provides excellent CIFS
1866 server support for Linux and many other operating systems). Limited 1866 server support for Linux and many other operating systems). Limited
1867 support for Windows ME and similar servers is provided as well. 1867 support for OS/2 and Windows ME and similar servers is provided as well.
1868 You must use the smbfs client filesystem to access older SMB servers
1869 such as OS/2 and DOS.
1870 1868
1871 The intent of the cifs module is to provide an advanced 1869 The intent of the cifs module is to provide an advanced
1872 network file system client for mounting to CIFS compliant servers, 1870 network file system client for mounting to CIFS compliant servers,
1873 including support for dfs (hierarchical name space), secure per-user 1871 including support for dfs (hierarchical name space), secure per-user
1874 session establishment, safe distributed caching (oplock), optional 1872 session establishment, safe distributed caching (oplock), optional
1875 packet signing, Unicode and other internationalization improvements, 1873 packet signing, Unicode and other internationalization improvements.
1876 and optional Winbind (nsswitch) integration. You do not need to enable 1874 If you need to mount to Samba or Windows from this machine, say Y.
1877 cifs if running only a (Samba) server. It is possible to enable both
1878 smbfs and cifs (e.g. if you are using CIFS for accessing Windows 2003
1879 and Samba 3 servers, and smbfs for accessing old servers). If you need
1880 to mount to Samba or Windows from this machine, say Y.
1881 1875
1882config CIFS_STATS 1876config CIFS_STATS
1883 bool "CIFS statistics" 1877 bool "CIFS statistics"
@@ -1970,14 +1964,13 @@ config CIFS_EXPERIMENTAL
1970 depends on CIFS && EXPERIMENTAL 1964 depends on CIFS && EXPERIMENTAL
1971 help 1965 help
1972 Enables cifs features under testing. These features are 1966 Enables cifs features under testing. These features are
1973 experimental and currently include support for writepages 1967 experimental and currently include DFS support and directory
1974 (multipage writebehind performance improvements) and directory 1968 change notification ie fcntl(F_DNOTIFY), as well as the upcall
1975 change notification ie fcntl(F_DNOTIFY) as well as some security 1969 mechanism which will be used for Kerberos session negotiation
1976 improvements. Some also depend on setting at runtime the 1970 and uid remapping. Some of these features also may depend on
1977 pseudo-file /proc/fs/cifs/Experimental (which is disabled by 1971 setting a value of 1 to the pseudo-file /proc/fs/cifs/Experimental
1978 default). See the file fs/cifs/README for more details. 1972 (which is disabled by default). See the file fs/cifs/README
1979 1973 for more details. If unsure, say N.
1980 If unsure, say N.
1981 1974
1982config CIFS_UPCALL 1975config CIFS_UPCALL
1983 bool "Kerberos/SPNEGO advanced session setup (EXPERIMENTAL)" 1976 bool "Kerberos/SPNEGO advanced session setup (EXPERIMENTAL)"
diff --git a/fs/cifs/CHANGES b/fs/cifs/CHANGES
index 85e3850bf2c9..5fe13593b57f 100644
--- a/fs/cifs/CHANGES
+++ b/fs/cifs/CHANGES
@@ -1,8 +1,15 @@
1Version 1.47 1Version 1.47
2------------ 2------------
3Fix oops in list_del during mount caused by unaligned string. 3Fix oops in list_del during mount caused by unaligned string.
4Fix file corruption which could occur on some large file
5copies caused by writepages page i/o completion bug.
4Seek to SEEK_END forces check for update of file size for non-cached 6Seek to SEEK_END forces check for update of file size for non-cached
5files. 7files. Allow file size to be updated on remote extend of locally open,
8non-cached file. Fix reconnect to newer Samba servers (or other servers
9which support the CIFS Unix/POSIX extensions) so that we again tell the
10server the Unix/POSIX cifs capabilities which we support (SetFSInfo).
11Add experimental support for new POSIX Open/Mkdir (which returns
12stat information on the open, and allows setting the mode).
6 13
7Version 1.46 14Version 1.46
8------------ 15------------
diff --git a/fs/cifs/TODO b/fs/cifs/TODO
index fc34c74ec4be..68372946dc92 100644
--- a/fs/cifs/TODO
+++ b/fs/cifs/TODO
@@ -128,3 +128,11 @@ negotiated size) and send larger write sizes to modern servers.
128 128
1294) More exhaustively test against less common servers. More testing 1294) More exhaustively test against less common servers. More testing
130against Windows 9x, Windows ME servers. 130against Windows 9x, Windows ME servers.
131
132DOS attrs - returned as pseudo-xattr in Samba format (check VFAT and NTFS for this too)
133
134mount check for unmatched uids - and uid override
135
136Add mount option for Linux extension disable per mount, and partial disable per mount (uid off, symlink/fifo/mknod on but what about posix acls?)
137
138Free threads at umount --force that are stuck on the sesSem
diff --git a/fs/cifs/cifsfs.h b/fs/cifs/cifsfs.h
index 01ae24af9cfd..c97c08eb481a 100644
--- a/fs/cifs/cifsfs.h
+++ b/fs/cifs/cifsfs.h
@@ -100,5 +100,5 @@ extern ssize_t cifs_getxattr(struct dentry *, const char *, void *, size_t);
100extern ssize_t cifs_listxattr(struct dentry *, char *, size_t); 100extern ssize_t cifs_listxattr(struct dentry *, char *, size_t);
101extern int cifs_ioctl (struct inode * inode, struct file * filep, 101extern int cifs_ioctl (struct inode * inode, struct file * filep,
102 unsigned int command, unsigned long arg); 102 unsigned int command, unsigned long arg);
103#define CIFS_VERSION "1.47" 103#define CIFS_VERSION "1.48"
104#endif /* _CIFSFS_H */ 104#endif /* _CIFSFS_H */
diff --git a/fs/cifs/cifspdu.h b/fs/cifs/cifspdu.h
index 068ef51edbf7..7d9505491b16 100644
--- a/fs/cifs/cifspdu.h
+++ b/fs/cifs/cifspdu.h
@@ -1,7 +1,7 @@
1/* 1/*
2 * fs/cifs/cifspdu.h 2 * fs/cifs/cifspdu.h
3 * 3 *
4 * Copyright (c) International Business Machines Corp., 2002,2005 4 * Copyright (c) International Business Machines Corp., 2002,2007
5 * Author(s): Steve French (sfrench@us.ibm.com) 5 * Author(s): Steve French (sfrench@us.ibm.com)
6 * 6 *
7 * This library is free software; you can redistribute it and/or modify 7 * This library is free software; you can redistribute it and/or modify
@@ -544,7 +544,8 @@ typedef union smb_com_session_setup_andx {
544/* unsigned char * NativeOS; */ 544/* unsigned char * NativeOS; */
545/* unsigned char * NativeLanMan; */ 545/* unsigned char * NativeLanMan; */
546/* unsigned char * PrimaryDomain; */ 546/* unsigned char * PrimaryDomain; */
547 } __attribute__((packed)) resp; /* NTLM response with or without extended sec*/ 547 } __attribute__((packed)) resp; /* NTLM response
548 (with or without extended sec) */
548 549
549 struct { /* request format */ 550 struct { /* request format */
550 struct smb_hdr hdr; /* wct = 10 */ 551 struct smb_hdr hdr; /* wct = 10 */
@@ -795,6 +796,8 @@ typedef struct smb_com_openx_rsp {
795 __u16 ByteCount; 796 __u16 ByteCount;
796} __attribute__((packed)) OPENX_RSP; 797} __attribute__((packed)) OPENX_RSP;
797 798
799/* For encoding of POSIX Open Request - see trans2 function 0x209 data struct */
800
798/* Legacy write request for older servers */ 801/* Legacy write request for older servers */
799typedef struct smb_com_writex_req { 802typedef struct smb_com_writex_req {
800 struct smb_hdr hdr; /* wct = 12 */ 803 struct smb_hdr hdr; /* wct = 12 */
@@ -1352,11 +1355,13 @@ struct smb_t2_rsp {
1352#define SMB_QUERY_FILE_UNIX_BASIC 0x200 1355#define SMB_QUERY_FILE_UNIX_BASIC 0x200
1353#define SMB_QUERY_FILE_UNIX_LINK 0x201 1356#define SMB_QUERY_FILE_UNIX_LINK 0x201
1354#define SMB_QUERY_POSIX_ACL 0x204 1357#define SMB_QUERY_POSIX_ACL 0x204
1355#define SMB_QUERY_XATTR 0x205 1358#define SMB_QUERY_XATTR 0x205 /* e.g. system EA name space */
1356#define SMB_QUERY_ATTR_FLAGS 0x206 /* append,immutable etc. */ 1359#define SMB_QUERY_ATTR_FLAGS 0x206 /* append,immutable etc. */
1357#define SMB_QUERY_POSIX_PERMISSION 0x207 1360#define SMB_QUERY_POSIX_PERMISSION 0x207
1358#define SMB_QUERY_POSIX_LOCK 0x208 1361#define SMB_QUERY_POSIX_LOCK 0x208
1359/* #define SMB_POSIX_OPEN 0x209 */ 1362/* #define SMB_POSIX_OPEN 0x209 */
1363/* #define SMB_POSIX_UNLINK 0x20a */
1364#define SMB_QUERY_FILE__UNIX_INFO2 0x20b
1360#define SMB_QUERY_FILE_INTERNAL_INFO 0x3ee 1365#define SMB_QUERY_FILE_INTERNAL_INFO 0x3ee
1361#define SMB_QUERY_FILE_ACCESS_INFO 0x3f0 1366#define SMB_QUERY_FILE_ACCESS_INFO 0x3f0
1362#define SMB_QUERY_FILE_NAME_INFO2 0x3f1 /* 0x30 bytes */ 1367#define SMB_QUERY_FILE_NAME_INFO2 0x3f1 /* 0x30 bytes */
@@ -1377,8 +1382,10 @@ struct smb_t2_rsp {
1377#define SMB_SET_ATTR_FLAGS 0x206 /* append, immutable etc. */ 1382#define SMB_SET_ATTR_FLAGS 0x206 /* append, immutable etc. */
1378#define SMB_SET_POSIX_LOCK 0x208 1383#define SMB_SET_POSIX_LOCK 0x208
1379#define SMB_POSIX_OPEN 0x209 1384#define SMB_POSIX_OPEN 0x209
1385#define SMB_POSIX_UNLINK 0x20a
1386#define SMB_SET_FILE_UNIX_INFO2
1380#define SMB_SET_FILE_BASIC_INFO2 0x3ec 1387#define SMB_SET_FILE_BASIC_INFO2 0x3ec
1381#define SMB_SET_FILE_RENAME_INFORMATION 0x3f2 /* BB check if qpathinfo level too */ 1388#define SMB_SET_FILE_RENAME_INFORMATION 0x3f2 /* BB check if qpathinfo too */
1382#define SMB_FILE_ALL_INFO2 0x3fa 1389#define SMB_FILE_ALL_INFO2 0x3fa
1383#define SMB_SET_FILE_ALLOCATION_INFO2 0x3fb 1390#define SMB_SET_FILE_ALLOCATION_INFO2 0x3fb
1384#define SMB_SET_FILE_END_OF_FILE_INFO2 0x3fc 1391#define SMB_SET_FILE_END_OF_FILE_INFO2 0x3fc
@@ -1428,7 +1435,7 @@ typedef struct smb_com_transaction2_qpi_rsp {
1428 struct smb_hdr hdr; /* wct = 10 + SetupCount */ 1435 struct smb_hdr hdr; /* wct = 10 + SetupCount */
1429 struct trans2_resp t2; 1436 struct trans2_resp t2;
1430 __u16 ByteCount; 1437 __u16 ByteCount;
1431 __u16 Reserved2; /* parameter word reserved - present for infolevels > 100 */ 1438 __u16 Reserved2; /* parameter word is present for infolevels > 100 */
1432} __attribute__((packed)) TRANSACTION2_QPI_RSP; 1439} __attribute__((packed)) TRANSACTION2_QPI_RSP;
1433 1440
1434typedef struct smb_com_transaction2_spi_req { 1441typedef struct smb_com_transaction2_spi_req {
@@ -1461,7 +1468,7 @@ typedef struct smb_com_transaction2_spi_rsp {
1461 struct smb_hdr hdr; /* wct = 10 + SetupCount */ 1468 struct smb_hdr hdr; /* wct = 10 + SetupCount */
1462 struct trans2_resp t2; 1469 struct trans2_resp t2;
1463 __u16 ByteCount; 1470 __u16 ByteCount;
1464 __u16 Reserved2; /* parameter word reserved - present for infolevels > 100 */ 1471 __u16 Reserved2; /* parameter word is present for infolevels > 100 */
1465} __attribute__((packed)) TRANSACTION2_SPI_RSP; 1472} __attribute__((packed)) TRANSACTION2_SPI_RSP;
1466 1473
1467struct set_file_rename { 1474struct set_file_rename {
@@ -1627,6 +1634,7 @@ typedef struct smb_com_transaction2_fnext_rsp_parms {
1627#define SMB_QUERY_FS_ATTRIBUTE_INFO 0x105 1634#define SMB_QUERY_FS_ATTRIBUTE_INFO 0x105
1628#define SMB_QUERY_CIFS_UNIX_INFO 0x200 1635#define SMB_QUERY_CIFS_UNIX_INFO 0x200
1629#define SMB_QUERY_POSIX_FS_INFO 0x201 1636#define SMB_QUERY_POSIX_FS_INFO 0x201
1637#define SMB_QUERY_POSIX_WHO_AM_I 0x202
1630#define SMB_QUERY_LABEL_INFO 0x3ea 1638#define SMB_QUERY_LABEL_INFO 0x3ea
1631#define SMB_QUERY_FS_QUOTA_INFO 0x3ee 1639#define SMB_QUERY_FS_QUOTA_INFO 0x3ee
1632#define SMB_QUERY_FS_FULL_SIZE_INFO 0x3ef 1640#define SMB_QUERY_FS_FULL_SIZE_INFO 0x3ef
@@ -1659,9 +1667,21 @@ typedef struct smb_com_transaction_qfsi_rsp {
1659 struct smb_hdr hdr; /* wct = 10 + SetupCount */ 1667 struct smb_hdr hdr; /* wct = 10 + SetupCount */
1660 struct trans2_resp t2; 1668 struct trans2_resp t2;
1661 __u16 ByteCount; 1669 __u16 ByteCount;
1662 __u8 Pad; /* may be three bytes *//* followed by data area */ 1670 __u8 Pad; /* may be three bytes? *//* followed by data area */
1663} __attribute__((packed)) TRANSACTION2_QFSI_RSP; 1671} __attribute__((packed)) TRANSACTION2_QFSI_RSP;
1664 1672
1673typedef struct whoami_rsp_data { /* Query level 0x202 */
1674 __u32 flags; /* 0 = Authenticated user 1 = GUEST */
1675 __u32 mask; /* which flags bits server understands ie 0x0001 */
1676 __u64 unix_user_id;
1677 __u64 unix_user_gid;
1678 __u32 number_of_supplementary_gids; /* may be zero */
1679 __u32 number_of_sids; /* may be zero */
1680 __u32 length_of_sid_array; /* in bytes - may be zero */
1681 __u32 pad; /* reserved - MBZ */
1682 /* __u64 gid_array[0]; */ /* may be empty */
1683 /* __u8 * psid_list */ /* may be empty */
1684} __attribute__((packed)) WHOAMI_RSP_DATA;
1665 1685
1666/* SETFSInfo Levels */ 1686/* SETFSInfo Levels */
1667#define SMB_SET_CIFS_UNIX_INFO 0x200 1687#define SMB_SET_CIFS_UNIX_INFO 0x200
@@ -1858,8 +1878,11 @@ typedef struct {
1858#define CIFS_UNIX_XATTR_CAP 0x00000004 /* support new namespace */ 1878#define CIFS_UNIX_XATTR_CAP 0x00000004 /* support new namespace */
1859#define CIFS_UNIX_EXTATTR_CAP 0x00000008 /* support chattr/chflag */ 1879#define CIFS_UNIX_EXTATTR_CAP 0x00000008 /* support chattr/chflag */
1860#define CIFS_UNIX_POSIX_PATHNAMES_CAP 0x00000010 /* Allow POSIX path chars */ 1880#define CIFS_UNIX_POSIX_PATHNAMES_CAP 0x00000010 /* Allow POSIX path chars */
1881#define CIFS_UNIX_POSIX_PATH_OPS_CAP 0x00000020 /* Allow new POSIX path based
1882 calls including posix open
1883 and posix unlink */
1861#ifdef CONFIG_CIFS_POSIX 1884#ifdef CONFIG_CIFS_POSIX
1862#define CIFS_UNIX_CAP_MASK 0x0000001b 1885#define CIFS_UNIX_CAP_MASK 0x0000003b
1863#else 1886#else
1864#define CIFS_UNIX_CAP_MASK 0x00000013 1887#define CIFS_UNIX_CAP_MASK 0x00000013
1865#endif /* CONFIG_CIFS_POSIX */ 1888#endif /* CONFIG_CIFS_POSIX */
@@ -1946,7 +1969,7 @@ typedef struct { /* data block encoding of response to level 263 QPathInfo */
1946 __le32 AlignmentRequirement; 1969 __le32 AlignmentRequirement;
1947 __le32 FileNameLength; 1970 __le32 FileNameLength;
1948 char FileName[1]; 1971 char FileName[1];
1949} __attribute__((packed)) FILE_ALL_INFO; /* level 0x107 QPathInfo */ 1972} __attribute__((packed)) FILE_ALL_INFO; /* level 0x107 QPathInfo */
1950 1973
1951/* defines for enumerating possible values of the Unix type field below */ 1974/* defines for enumerating possible values of the Unix type field below */
1952#define UNIX_FILE 0 1975#define UNIX_FILE 0
@@ -1970,11 +1993,11 @@ typedef struct {
1970 __u64 UniqueId; 1993 __u64 UniqueId;
1971 __le64 Permissions; 1994 __le64 Permissions;
1972 __le64 Nlinks; 1995 __le64 Nlinks;
1973} __attribute__((packed)) FILE_UNIX_BASIC_INFO; /* level 0x200 QPathInfo */ 1996} __attribute__((packed)) FILE_UNIX_BASIC_INFO; /* level 0x200 QPathInfo */
1974 1997
1975typedef struct { 1998typedef struct {
1976 char LinkDest[1]; 1999 char LinkDest[1];
1977} __attribute__((packed)) FILE_UNIX_LINK_INFO; /* level 0x201 QPathInfo */ 2000} __attribute__((packed)) FILE_UNIX_LINK_INFO; /* level 0x201 QPathInfo */
1978 2001
1979/* The following three structures are needed only for 2002/* The following three structures are needed only for
1980 setting time to NT4 and some older servers via 2003 setting time to NT4 and some older servers via
@@ -2011,7 +2034,7 @@ typedef struct {
2011 __le64 ChangeTime; 2034 __le64 ChangeTime;
2012 __le32 Attributes; 2035 __le32 Attributes;
2013 __u32 Pad; 2036 __u32 Pad;
2014} __attribute__((packed)) FILE_BASIC_INFO; /* size info, level 0x101 */ 2037} __attribute__((packed)) FILE_BASIC_INFO; /* size info, level 0x101 */
2015 2038
2016struct file_allocation_info { 2039struct file_allocation_info {
2017 __le64 AllocationSize; /* Note old Samba srvr rounds this up too much */ 2040 __le64 AllocationSize; /* Note old Samba srvr rounds this up too much */
@@ -2020,7 +2043,7 @@ struct file_allocation_info {
2020 2043
2021struct file_end_of_file_info { 2044struct file_end_of_file_info {
2022 __le64 FileSize; /* offset to end of file */ 2045 __le64 FileSize; /* offset to end of file */
2023} __attribute__((packed)); /* size info, level 0x104 for set, 0x106 for query */ 2046} __attribute__((packed)); /* size info, level 0x104 for set, 0x106 for query */
2024 2047
2025struct file_alt_name_info { 2048struct file_alt_name_info {
2026 __u8 alt_name[1]; 2049 __u8 alt_name[1];
@@ -2075,6 +2098,19 @@ struct cifs_posix_acl { /* access conrol list (ACL) */
2075 2098
2076/* end of POSIX ACL definitions */ 2099/* end of POSIX ACL definitions */
2077 2100
2101typedef struct {
2102 __u32 OpenFlags; /* same as NT CreateX */
2103 __u32 PosixOpenFlags;
2104 __u32 Mode;
2105 __u16 Level; /* reply level requested (see QPathInfo levels) */
2106 __u16 Pad; /* reserved - MBZ */
2107} __attribute__((packed)) OPEN_PSX_REQ; /* level 0x209 SetPathInfo data */
2108
2109typedef struct {
2110 /* reply varies based on requested level */
2111} __attribute__((packed)) OPEN_PSX_RSP; /* level 0x209 SetPathInfo data */
2112
2113
2078struct file_internal_info { 2114struct file_internal_info {
2079 __u64 UniqueId; /* inode number */ 2115 __u64 UniqueId; /* inode number */
2080} __attribute__((packed)); /* level 0x3ee */ 2116} __attribute__((packed)); /* level 0x3ee */
@@ -2238,7 +2274,8 @@ struct data_blob {
2238 1) PosixCreateX - to set and return the mode, inode#, device info and 2274 1) PosixCreateX - to set and return the mode, inode#, device info and
2239 perhaps add a CreateDevice - to create Pipes and other special .inodes 2275 perhaps add a CreateDevice - to create Pipes and other special .inodes
2240 Also note POSIX open flags 2276 Also note POSIX open flags
2241 2) Close - to return the last write time to do cache across close more safely 2277 2) Close - to return the last write time to do cache across close
2278 more safely
2242 3) FindFirst return unique inode number - what about resume key, two 2279 3) FindFirst return unique inode number - what about resume key, two
2243 forms short (matches readdir) and full (enough info to cache inodes) 2280 forms short (matches readdir) and full (enough info to cache inodes)
2244 4) Mkdir - set mode 2281 4) Mkdir - set mode
@@ -2273,7 +2310,8 @@ struct data_blob {
2273 TRANSACTION2 (18 cases) 2310 TRANSACTION2 (18 cases)
2274 SMB_SET_FILE_END_OF_FILE_INFO2 SMB_SET_PATH_END_OF_FILE_INFO2 2311 SMB_SET_FILE_END_OF_FILE_INFO2 SMB_SET_PATH_END_OF_FILE_INFO2
2275 (BB verify that never need to set allocation size) 2312 (BB verify that never need to set allocation size)
2276 SMB_SET_FILE_BASIC_INFO2 (setting times - BB can it be done via Unix ext?) 2313 SMB_SET_FILE_BASIC_INFO2 (setting times - BB can it be done via
2314 Unix ext?)
2277 2315
2278 COPY (note support for copy across directories) - FUTURE, OPTIONAL 2316 COPY (note support for copy across directories) - FUTURE, OPTIONAL
2279 setting/getting OS/2 EAs - FUTURE (BB can this handle 2317 setting/getting OS/2 EAs - FUTURE (BB can this handle
@@ -2293,13 +2331,13 @@ struct data_blob {
2293 T2 QUERY_PATH_INFO (SMB_QUERY_FILE_UNIX_BASIC) - BB check for missing inode fields 2331 T2 QUERY_PATH_INFO (SMB_QUERY_FILE_UNIX_BASIC) - BB check for missing inode fields
2294 Actually need QUERY_FILE_UNIX_INFO since has inode num 2332 Actually need QUERY_FILE_UNIX_INFO since has inode num
2295 BB what about a) blksize/blkbits/blocks 2333 BB what about a) blksize/blkbits/blocks
2296 b) i_version 2334 b) i_version
2297 c) i_rdev 2335 c) i_rdev
2298 d) notify mask? 2336 d) notify mask?
2299 e) generation 2337 e) generation
2300 f) size_seqcount 2338 f) size_seqcount
2301 T2 FIND_FIRST/FIND_NEXT FIND_FILE_UNIX 2339 T2 FIND_FIRST/FIND_NEXT FIND_FILE_UNIX
2302 TRANS2_GET_DFS_REFERRAL - OPTIONAL but recommended 2340 TRANS2_GET_DFS_REFERRAL - OPTIONAL but recommended
2303 T2_QFS_INFO QueryDevice/AttributeInfo - OPTIONAL 2341 T2_QFS_INFO QueryDevice/AttributeInfo - OPTIONAL
2304 2342
2305 2343
@@ -2338,7 +2376,7 @@ typedef struct file_xattr_info {
2338 __u32 xattr_value_len; 2376 __u32 xattr_value_len;
2339 char xattr_name[0]; 2377 char xattr_name[0];
2340 /* followed by xattr_value[xattr_value_len], no pad */ 2378 /* followed by xattr_value[xattr_value_len], no pad */
2341} __attribute__((packed)) FILE_XATTR_INFO; /* extended attribute, info level 0x205 */ 2379} __attribute__((packed)) FILE_XATTR_INFO; /* extended attribute, info level 0x205 */
2342 2380
2343 2381
2344/* flags for chattr command */ 2382/* flags for chattr command */
diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h
index f1f8225102f0..6148b82170c4 100644
--- a/fs/cifs/cifsproto.h
+++ b/fs/cifs/cifsproto.h
@@ -23,6 +23,7 @@
23#include <linux/nls.h> 23#include <linux/nls.h>
24 24
25struct statfs; 25struct statfs;
26struct smb_vol;
26 27
27/* 28/*
28 ***************************************************************** 29 *****************************************************************
@@ -57,7 +58,7 @@ extern int SendReceiveBlockingLock(const unsigned int /* xid */ ,
57 int * /* bytes returned */); 58 int * /* bytes returned */);
58extern int checkSMB(struct smb_hdr *smb, __u16 mid, unsigned int length); 59extern int checkSMB(struct smb_hdr *smb, __u16 mid, unsigned int length);
59extern int is_valid_oplock_break(struct smb_hdr *smb, struct TCP_Server_Info *); 60extern int is_valid_oplock_break(struct smb_hdr *smb, struct TCP_Server_Info *);
60extern int is_size_safe_to_change(struct cifsInodeInfo *); 61extern int is_size_safe_to_change(struct cifsInodeInfo *, __u64 eof);
61extern struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *); 62extern struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *);
62extern unsigned int smbCalcSize(struct smb_hdr *ptr); 63extern unsigned int smbCalcSize(struct smb_hdr *ptr);
63extern unsigned int smbCalcSize_LE(struct smb_hdr *ptr); 64extern unsigned int smbCalcSize_LE(struct smb_hdr *ptr);
@@ -147,6 +148,8 @@ extern int get_dfs_path(int xid, struct cifsSesInfo *pSesInfo,
147 unsigned int *pnum_referrals, 148 unsigned int *pnum_referrals,
148 unsigned char ** preferrals, 149 unsigned char ** preferrals,
149 int remap); 150 int remap);
151extern void reset_cifs_unix_caps(int xid, struct cifsTconInfo *tcon,
152 struct super_block * sb, struct smb_vol * vol);
150extern int CIFSSMBQFSInfo(const int xid, struct cifsTconInfo *tcon, 153extern int CIFSSMBQFSInfo(const int xid, struct cifsTconInfo *tcon,
151 struct kstatfs *FSData); 154 struct kstatfs *FSData);
152extern int SMBOldQFSInfo(const int xid, struct cifsTconInfo *tcon, 155extern int SMBOldQFSInfo(const int xid, struct cifsTconInfo *tcon,
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c
index 472e33e0f3cf..b8e91470c27f 100644
--- a/fs/cifs/cifssmb.c
+++ b/fs/cifs/cifssmb.c
@@ -158,9 +158,15 @@ small_smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
158 nls_codepage); 158 nls_codepage);
159 if(!rc && (tcon->tidStatus == CifsNeedReconnect)) { 159 if(!rc && (tcon->tidStatus == CifsNeedReconnect)) {
160 mark_open_files_invalid(tcon); 160 mark_open_files_invalid(tcon);
161 rc = CIFSTCon(0, tcon->ses, tcon->treeName, tcon 161 rc = CIFSTCon(0, tcon->ses, tcon->treeName,
162 , nls_codepage); 162 tcon, nls_codepage);
163 up(&tcon->ses->sesSem); 163 up(&tcon->ses->sesSem);
164 /* tell server which Unix caps we support */
165 if (tcon->ses->capabilities & CAP_UNIX)
166 reset_cifs_unix_caps(0 /* no xid */,
167 tcon,
168 NULL /* we do not know sb */,
169 NULL /* no vol info */);
164 /* BB FIXME add code to check if wsize needs 170 /* BB FIXME add code to check if wsize needs
165 update due to negotiated smb buffer size 171 update due to negotiated smb buffer size
166 shrinking */ 172 shrinking */
@@ -298,6 +304,12 @@ smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
298 rc = CIFSTCon(0, tcon->ses, tcon->treeName, 304 rc = CIFSTCon(0, tcon->ses, tcon->treeName,
299 tcon, nls_codepage); 305 tcon, nls_codepage);
300 up(&tcon->ses->sesSem); 306 up(&tcon->ses->sesSem);
307 /* tell server which Unix caps we support */
308 if (tcon->ses->capabilities & CAP_UNIX)
309 reset_cifs_unix_caps(0 /* no xid */,
310 tcon,
311 NULL /* do not know sb */,
312 NULL /* no vol info */);
301 /* BB FIXME add code to check if wsize needs 313 /* BB FIXME add code to check if wsize needs
302 update due to negotiated smb buffer size 314 update due to negotiated smb buffer size
303 shrinking */ 315 shrinking */
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index 2caca06b4bae..20ba7dcc9959 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -1613,6 +1613,76 @@ ipv6_connect(struct sockaddr_in6 *psin_server, struct socket **csocket)
1613 return rc; 1613 return rc;
1614} 1614}
1615 1615
1616void reset_cifs_unix_caps(int xid, struct cifsTconInfo * tcon,
1617 struct super_block * sb, struct smb_vol * vol_info)
1618{
1619 /* if we are reconnecting then should we check to see if
1620 * any requested capabilities changed locally e.g. via
1621 * remount but we can not do much about it here
1622 * if they have (even if we could detect it by the following)
1623 * Perhaps we could add a backpointer to array of sb from tcon
1624 * or if we change to make all sb to same share the same
1625 * sb as NFS - then we only have one backpointer to sb.
1626 * What if we wanted to mount the server share twice once with
1627 * and once without posixacls or posix paths? */
1628 __u64 saved_cap = le64_to_cpu(tcon->fsUnixInfo.Capability);
1629
1630
1631 if(!CIFSSMBQFSUnixInfo(xid, tcon)) {
1632 __u64 cap = le64_to_cpu(tcon->fsUnixInfo.Capability);
1633
1634 /* check for reconnect case in which we do not
1635 want to change the mount behavior if we can avoid it */
1636 if(vol_info == NULL) {
1637 /* turn off POSIX ACL and PATHNAMES if not set
1638 originally at mount time */
1639 if ((saved_cap & CIFS_UNIX_POSIX_ACL_CAP) == 0)
1640 cap &= ~CIFS_UNIX_POSIX_ACL_CAP;
1641 if ((saved_cap & CIFS_UNIX_POSIX_PATHNAMES_CAP) == 0)
1642 cap &= ~CIFS_UNIX_POSIX_PATHNAMES_CAP;
1643
1644
1645
1646
1647 }
1648
1649 cap &= CIFS_UNIX_CAP_MASK;
1650 if(vol_info && vol_info->no_psx_acl)
1651 cap &= ~CIFS_UNIX_POSIX_ACL_CAP;
1652 else if(CIFS_UNIX_POSIX_ACL_CAP & cap) {
1653 cFYI(1,("negotiated posix acl support"));
1654 if(sb)
1655 sb->s_flags |= MS_POSIXACL;
1656 }
1657
1658 if(vol_info && vol_info->posix_paths == 0)
1659 cap &= ~CIFS_UNIX_POSIX_PATHNAMES_CAP;
1660 else if(cap & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
1661 cFYI(1,("negotiate posix pathnames"));
1662 if(sb)
1663 CIFS_SB(sb)->mnt_cifs_flags |=
1664 CIFS_MOUNT_POSIX_PATHS;
1665 }
1666
1667 cFYI(1,("Negotiate caps 0x%x",(int)cap));
1668#ifdef CONFIG_CIFS_DEBUG2
1669 if(cap & CIFS_UNIX_FCNTL_CAP)
1670 cFYI(1,("FCNTL cap"));
1671 if(cap & CIFS_UNIX_EXTATTR_CAP)
1672 cFYI(1,("EXTATTR cap"));
1673 if(cap & CIFS_UNIX_POSIX_PATHNAMES_CAP)
1674 cFYI(1,("POSIX path cap"));
1675 if(cap & CIFS_UNIX_XATTR_CAP)
1676 cFYI(1,("XATTR cap"));
1677 if(cap & CIFS_UNIX_POSIX_ACL_CAP)
1678 cFYI(1,("POSIX ACL cap"));
1679#endif /* CIFS_DEBUG2 */
1680 if (CIFSSMBSetFSUnixInfo(xid, tcon, cap)) {
1681 cFYI(1,("setting capabilities failed"));
1682 }
1683 }
1684}
1685
1616int 1686int
1617cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, 1687cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
1618 char *mount_data, const char *devname) 1688 char *mount_data, const char *devname)
@@ -1928,20 +1998,25 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
1928 if (tcon == NULL) 1998 if (tcon == NULL)
1929 rc = -ENOMEM; 1999 rc = -ENOMEM;
1930 else { 2000 else {
1931 /* check for null share name ie connect to dfs root */ 2001 /* check for null share name ie connecting to
2002 * dfs root */
1932 2003
1933 /* BB check if this works for exactly length three strings */ 2004 /* BB check if this works for exactly length
2005 * three strings */
1934 if ((strchr(volume_info.UNC + 3, '\\') == NULL) 2006 if ((strchr(volume_info.UNC + 3, '\\') == NULL)
1935 && (strchr(volume_info.UNC + 3, '/') == 2007 && (strchr(volume_info.UNC + 3, '/') ==
1936 NULL)) { 2008 NULL)) {
1937 rc = connect_to_dfs_path(xid, pSesInfo, 2009 rc = connect_to_dfs_path(xid, pSesInfo,
1938 "", cifs_sb->local_nls, 2010 "", cifs_sb->local_nls,
1939 cifs_sb->mnt_cifs_flags & 2011 cifs_sb->mnt_cifs_flags &
1940 CIFS_MOUNT_MAP_SPECIAL_CHR); 2012 CIFS_MOUNT_MAP_SPECIAL_CHR);
1941 kfree(volume_info.UNC); 2013 kfree(volume_info.UNC);
1942 FreeXid(xid); 2014 FreeXid(xid);
1943 return -ENODEV; 2015 return -ENODEV;
1944 } else { 2016 } else {
2017 /* BB Do we need to wrap sesSem around
2018 * this TCon call and Unix SetFS as
2019 * we do on SessSetup and reconnect? */
1945 rc = CIFSTCon(xid, pSesInfo, 2020 rc = CIFSTCon(xid, pSesInfo,
1946 volume_info.UNC, 2021 volume_info.UNC,
1947 tcon, cifs_sb->local_nls); 2022 tcon, cifs_sb->local_nls);
@@ -1962,6 +2037,7 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
1962 sb->s_maxbytes = (u64) 1 << 31; /* 2 GB */ 2037 sb->s_maxbytes = (u64) 1 << 31; /* 2 GB */
1963 } 2038 }
1964 2039
2040 /* BB FIXME fix time_gran to be larger for LANMAN sessions */
1965 sb->s_time_gran = 100; 2041 sb->s_time_gran = 100;
1966 2042
1967/* on error free sesinfo and tcon struct if needed */ 2043/* on error free sesinfo and tcon struct if needed */
@@ -2006,45 +2082,11 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
2006 /* do not care if following two calls succeed - informational */ 2082 /* do not care if following two calls succeed - informational */
2007 CIFSSMBQFSDeviceInfo(xid, tcon); 2083 CIFSSMBQFSDeviceInfo(xid, tcon);
2008 CIFSSMBQFSAttributeInfo(xid, tcon); 2084 CIFSSMBQFSAttributeInfo(xid, tcon);
2009 2085
2010 if (tcon->ses->capabilities & CAP_UNIX) { 2086 /* tell server which Unix caps we support */
2011 if(!CIFSSMBQFSUnixInfo(xid, tcon)) { 2087 if (tcon->ses->capabilities & CAP_UNIX)
2012 __u64 cap = 2088 reset_cifs_unix_caps(xid, tcon, sb, &volume_info);
2013 le64_to_cpu(tcon->fsUnixInfo.Capability); 2089
2014 cap &= CIFS_UNIX_CAP_MASK;
2015 if(volume_info.no_psx_acl)
2016 cap &= ~CIFS_UNIX_POSIX_ACL_CAP;
2017 else if(CIFS_UNIX_POSIX_ACL_CAP & cap) {
2018 cFYI(1,("negotiated posix acl support"));
2019 sb->s_flags |= MS_POSIXACL;
2020 }
2021
2022 if(volume_info.posix_paths == 0)
2023 cap &= ~CIFS_UNIX_POSIX_PATHNAMES_CAP;
2024 else if(cap & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
2025 cFYI(1,("negotiate posix pathnames"));
2026 cifs_sb->mnt_cifs_flags |=
2027 CIFS_MOUNT_POSIX_PATHS;
2028 }
2029
2030 cFYI(1,("Negotiate caps 0x%x",(int)cap));
2031#ifdef CONFIG_CIFS_DEBUG2
2032 if(cap & CIFS_UNIX_FCNTL_CAP)
2033 cFYI(1,("FCNTL cap"));
2034 if(cap & CIFS_UNIX_EXTATTR_CAP)
2035 cFYI(1,("EXTATTR cap"));
2036 if(cap & CIFS_UNIX_POSIX_PATHNAMES_CAP)
2037 cFYI(1,("POSIX path cap"));
2038 if(cap & CIFS_UNIX_XATTR_CAP)
2039 cFYI(1,("XATTR cap"));
2040 if(cap & CIFS_UNIX_POSIX_ACL_CAP)
2041 cFYI(1,("POSIX ACL cap"));
2042#endif /* CIFS_DEBUG2 */
2043 if (CIFSSMBSetFSUnixInfo(xid, tcon, cap)) {
2044 cFYI(1,("setting capabilities failed"));
2045 }
2046 }
2047 }
2048 if (!(tcon->ses->capabilities & CAP_LARGE_WRITE_X)) 2090 if (!(tcon->ses->capabilities & CAP_LARGE_WRITE_X))
2049 cifs_sb->wsize = min(cifs_sb->wsize, 2091 cifs_sb->wsize = min(cifs_sb->wsize,
2050 (tcon->ses->server->maxBuf - 2092 (tcon->ses->server->maxBuf -
diff --git a/fs/cifs/file.c b/fs/cifs/file.c
index e9dcf5ee29a2..07ff9351e9ee 100644
--- a/fs/cifs/file.c
+++ b/fs/cifs/file.c
@@ -1954,7 +1954,7 @@ static int cifs_readpage(struct file *file, struct page *page)
1954 refreshing the inode only on increases in the file size 1954 refreshing the inode only on increases in the file size
1955 but this is tricky to do without racing with writebehind 1955 but this is tricky to do without racing with writebehind
1956 page caching in the current Linux kernel design */ 1956 page caching in the current Linux kernel design */
1957int is_size_safe_to_change(struct cifsInodeInfo *cifsInode) 1957int is_size_safe_to_change(struct cifsInodeInfo *cifsInode, __u64 end_of_file)
1958{ 1958{
1959 struct cifsFileInfo *open_file = NULL; 1959 struct cifsFileInfo *open_file = NULL;
1960 1960
@@ -1976,6 +1976,9 @@ int is_size_safe_to_change(struct cifsInodeInfo *cifsInode)
1976 return 1; 1976 return 1;
1977 } 1977 }
1978 1978
1979 if(i_size_read(&cifsInode->vfs_inode) < end_of_file)
1980 return 1;
1981
1979 return 0; 1982 return 0;
1980 } else 1983 } else
1981 return 1; 1984 return 1;
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c
index c4fa91b8b62f..3f5bc83dc3d1 100644
--- a/fs/cifs/inode.c
+++ b/fs/cifs/inode.c
@@ -140,7 +140,7 @@ int cifs_get_inode_info_unix(struct inode **pinode,
140 inode->i_gid = le64_to_cpu(findData.Gid); 140 inode->i_gid = le64_to_cpu(findData.Gid);
141 inode->i_nlink = le64_to_cpu(findData.Nlinks); 141 inode->i_nlink = le64_to_cpu(findData.Nlinks);
142 142
143 if (is_size_safe_to_change(cifsInfo)) { 143 if (is_size_safe_to_change(cifsInfo, end_of_file)) {
144 /* can not safely change the file size here if the 144 /* can not safely change the file size here if the
145 client is writing to it due to potential races */ 145 client is writing to it due to potential races */
146 146
@@ -491,8 +491,8 @@ int cifs_get_inode_info(struct inode **pinode,
491 /* BB add code here - 491 /* BB add code here -
492 validate if device or weird share or device type? */ 492 validate if device or weird share or device type? */
493 } 493 }
494 if (is_size_safe_to_change(cifsInfo)) { 494 if (is_size_safe_to_change(cifsInfo, le64_to_cpu(pfindData->EndOfFile))) {
495 /* can not safely change the file size here if the 495 /* can not safely shrink the file size here if the
496 client is writing to it due to potential races */ 496 client is writing to it due to potential races */
497 i_size_write(inode,le64_to_cpu(pfindData->EndOfFile)); 497 i_size_write(inode,le64_to_cpu(pfindData->EndOfFile));
498 498
diff --git a/fs/cifs/readdir.c b/fs/cifs/readdir.c
index 782940be550f..c6220bd27165 100644
--- a/fs/cifs/readdir.c
+++ b/fs/cifs/readdir.c
@@ -222,7 +222,7 @@ static void fill_in_inode(struct inode *tmp_inode, int new_buf_type,
222 atomic_set(&cifsInfo->inUse, 1); 222 atomic_set(&cifsInfo->inUse, 1);
223 } 223 }
224 224
225 if (is_size_safe_to_change(cifsInfo)) { 225 if (is_size_safe_to_change(cifsInfo, end_of_file)) {
226 /* can not safely change the file size here if the 226 /* can not safely change the file size here if the
227 client is writing to it due to potential races */ 227 client is writing to it due to potential races */
228 i_size_write(tmp_inode, end_of_file); 228 i_size_write(tmp_inode, end_of_file);
@@ -351,10 +351,10 @@ static void unix_fill_in_inode(struct inode *tmp_inode,
351 tmp_inode->i_gid = le64_to_cpu(pfindData->Gid); 351 tmp_inode->i_gid = le64_to_cpu(pfindData->Gid);
352 tmp_inode->i_nlink = le64_to_cpu(pfindData->Nlinks); 352 tmp_inode->i_nlink = le64_to_cpu(pfindData->Nlinks);
353 353
354 if (is_size_safe_to_change(cifsInfo)) { 354 if (is_size_safe_to_change(cifsInfo, end_of_file)) {
355 /* can not safely change the file size here if the 355 /* can not safely change the file size here if the
356 client is writing to it due to potential races */ 356 client is writing to it due to potential races */
357 i_size_write(tmp_inode,end_of_file); 357 i_size_write(tmp_inode, end_of_file);
358 358
359 /* 512 bytes (2**9) is the fake blocksize that must be used */ 359 /* 512 bytes (2**9) is the fake blocksize that must be used */
360 /* for this calculation, not the real blocksize */ 360 /* for this calculation, not the real blocksize */
diff --git a/fs/dcache.c b/fs/dcache.c
index b5f613932912..d68631f18df1 100644
--- a/fs/dcache.c
+++ b/fs/dcache.c
@@ -1739,41 +1739,45 @@ shouldnt_be_hashed:
1739 * @rootmnt: vfsmnt to which the root dentry belongs 1739 * @rootmnt: vfsmnt to which the root dentry belongs
1740 * @buffer: buffer to return value in 1740 * @buffer: buffer to return value in
1741 * @buflen: buffer length 1741 * @buflen: buffer length
1742 * @fail_deleted: what to return for deleted files
1743 * 1742 *
1744 * Convert a dentry into an ASCII path name. If the entry has been deleted, 1743 * Convert a dentry into an ASCII path name. If the entry has been deleted
1745 * then if @fail_deleted is true, ERR_PTR(-ENOENT) is returned. Otherwise, 1744 * the string " (deleted)" is appended. Note that this is ambiguous.
1746 * the the string " (deleted)" is appended. Note that this is ambiguous.
1747 * 1745 *
1748 * Returns the buffer or an error code. 1746 * Returns the buffer or an error code if the path was too long.
1747 *
1748 * "buflen" should be positive. Caller holds the dcache_lock.
1749 */ 1749 */
1750static char *__d_path(struct dentry *dentry, struct vfsmount *vfsmnt, 1750static char * __d_path( struct dentry *dentry, struct vfsmount *vfsmnt,
1751 struct dentry *root, struct vfsmount *rootmnt, 1751 struct dentry *root, struct vfsmount *rootmnt,
1752 char *buffer, int buflen, int fail_deleted) 1752 char *buffer, int buflen)
1753{ 1753{
1754 int namelen, is_slash; 1754 char * end = buffer+buflen;
1755 1755 char * retval;
1756 if (buflen < 2) 1756 int namelen;
1757 return ERR_PTR(-ENAMETOOLONG);
1758 buffer += --buflen;
1759 *buffer = '\0';
1760 1757
1761 spin_lock(&dcache_lock); 1758 *--end = '\0';
1759 buflen--;
1762 if (!IS_ROOT(dentry) && d_unhashed(dentry)) { 1760 if (!IS_ROOT(dentry) && d_unhashed(dentry)) {
1763 if (fail_deleted) {
1764 buffer = ERR_PTR(-ENOENT);
1765 goto out;
1766 }
1767 if (buflen < 10)
1768 goto Elong;
1769 buflen -= 10; 1761 buflen -= 10;
1770 buffer -= 10; 1762 end -= 10;
1771 memcpy(buffer, " (deleted)", 10); 1763 if (buflen < 0)
1764 goto Elong;
1765 memcpy(end, " (deleted)", 10);
1772 } 1766 }
1773 while (dentry != root || vfsmnt != rootmnt) { 1767
1768 if (buflen < 1)
1769 goto Elong;
1770 /* Get '/' right */
1771 retval = end-1;
1772 *retval = '/';
1773
1774 for (;;) {
1774 struct dentry * parent; 1775 struct dentry * parent;
1775 1776
1777 if (dentry == root && vfsmnt == rootmnt)
1778 break;
1776 if (dentry == vfsmnt->mnt_root || IS_ROOT(dentry)) { 1779 if (dentry == vfsmnt->mnt_root || IS_ROOT(dentry)) {
1780 /* Global root? */
1777 spin_lock(&vfsmount_lock); 1781 spin_lock(&vfsmount_lock);
1778 if (vfsmnt->mnt_parent == vfsmnt) { 1782 if (vfsmnt->mnt_parent == vfsmnt) {
1779 spin_unlock(&vfsmount_lock); 1783 spin_unlock(&vfsmount_lock);
@@ -1787,60 +1791,33 @@ static char *__d_path(struct dentry *dentry, struct vfsmount *vfsmnt,
1787 parent = dentry->d_parent; 1791 parent = dentry->d_parent;
1788 prefetch(parent); 1792 prefetch(parent);
1789 namelen = dentry->d_name.len; 1793 namelen = dentry->d_name.len;
1790 if (buflen <= namelen)
1791 goto Elong;
1792 buflen -= namelen + 1; 1794 buflen -= namelen + 1;
1793 buffer -= namelen; 1795 if (buflen < 0)
1794 memcpy(buffer, dentry->d_name.name, namelen); 1796 goto Elong;
1795 *--buffer = '/'; 1797 end -= namelen;
1798 memcpy(end, dentry->d_name.name, namelen);
1799 *--end = '/';
1800 retval = end;
1796 dentry = parent; 1801 dentry = parent;
1797 } 1802 }
1798 /* Get '/' right */
1799 if (*buffer != '/')
1800 *--buffer = '/';
1801 1803
1802out: 1804 return retval;
1803 spin_unlock(&dcache_lock);
1804 return buffer;
1805 1805
1806global_root: 1806global_root:
1807 /*
1808 * We went past the (vfsmount, dentry) we were looking for and have
1809 * either hit a root dentry, a lazily unmounted dentry, an
1810 * unconnected dentry, or the file is on a pseudo filesystem.
1811 */
1812 namelen = dentry->d_name.len; 1807 namelen = dentry->d_name.len;
1813 is_slash = (namelen == 1 && *dentry->d_name.name == '/'); 1808 buflen -= namelen;
1814 if (is_slash || (dentry->d_sb->s_flags & MS_NOUSER)) { 1809 if (buflen < 0)
1815 /*
1816 * Make sure we won't return a pathname starting with '/'.
1817 *
1818 * Historically, we also glue together the root dentry and
1819 * remaining name for pseudo filesystems like pipefs, which
1820 * have the MS_NOUSER flag set. This results in pathnames
1821 * like "pipe:[439336]".
1822 */
1823 if (*buffer == '/') {
1824 buffer++;
1825 buflen++;
1826 }
1827 if (is_slash)
1828 goto out;
1829 }
1830 if (buflen < namelen)
1831 goto Elong; 1810 goto Elong;
1832 buffer -= namelen; 1811 retval -= namelen-1; /* hit the slash */
1833 memcpy(buffer, dentry->d_name.name, namelen); 1812 memcpy(retval, dentry->d_name.name, namelen);
1834 goto out; 1813 return retval;
1835
1836Elong: 1814Elong:
1837 buffer = ERR_PTR(-ENAMETOOLONG); 1815 return ERR_PTR(-ENAMETOOLONG);
1838 goto out;
1839} 1816}
1840 1817
1841/* write full pathname into buffer and return start of pathname */ 1818/* write full pathname into buffer and return start of pathname */
1842char *d_path(struct dentry *dentry, struct vfsmount *vfsmnt, char *buf, 1819char * d_path(struct dentry *dentry, struct vfsmount *vfsmnt,
1843 int buflen) 1820 char *buf, int buflen)
1844{ 1821{
1845 char *res; 1822 char *res;
1846 struct vfsmount *rootmnt; 1823 struct vfsmount *rootmnt;
@@ -1850,7 +1827,9 @@ char *d_path(struct dentry *dentry, struct vfsmount *vfsmnt, char *buf,
1850 rootmnt = mntget(current->fs->rootmnt); 1827 rootmnt = mntget(current->fs->rootmnt);
1851 root = dget(current->fs->root); 1828 root = dget(current->fs->root);
1852 read_unlock(&current->fs->lock); 1829 read_unlock(&current->fs->lock);
1853 res = __d_path(dentry, vfsmnt, root, rootmnt, buf, buflen, 0); 1830 spin_lock(&dcache_lock);
1831 res = __d_path(dentry, vfsmnt, root, rootmnt, buf, buflen);
1832 spin_unlock(&dcache_lock);
1854 dput(root); 1833 dput(root);
1855 mntput(rootmnt); 1834 mntput(rootmnt);
1856 return res; 1835 return res;
@@ -1876,10 +1855,10 @@ char *d_path(struct dentry *dentry, struct vfsmount *vfsmnt, char *buf,
1876 */ 1855 */
1877asmlinkage long sys_getcwd(char __user *buf, unsigned long size) 1856asmlinkage long sys_getcwd(char __user *buf, unsigned long size)
1878{ 1857{
1879 int error, len; 1858 int error;
1880 struct vfsmount *pwdmnt, *rootmnt; 1859 struct vfsmount *pwdmnt, *rootmnt;
1881 struct dentry *pwd, *root; 1860 struct dentry *pwd, *root;
1882 char *page = (char *) __get_free_page(GFP_USER), *cwd; 1861 char *page = (char *) __get_free_page(GFP_USER);
1883 1862
1884 if (!page) 1863 if (!page)
1885 return -ENOMEM; 1864 return -ENOMEM;
@@ -1891,18 +1870,29 @@ asmlinkage long sys_getcwd(char __user *buf, unsigned long size)
1891 root = dget(current->fs->root); 1870 root = dget(current->fs->root);
1892 read_unlock(&current->fs->lock); 1871 read_unlock(&current->fs->lock);
1893 1872
1894 cwd = __d_path(pwd, pwdmnt, root, rootmnt, page, PAGE_SIZE, 1); 1873 error = -ENOENT;
1895 error = PTR_ERR(cwd); 1874 /* Has the current directory has been unlinked? */
1896 if (IS_ERR(cwd)) 1875 spin_lock(&dcache_lock);
1897 goto out; 1876 if (pwd->d_parent == pwd || !d_unhashed(pwd)) {
1877 unsigned long len;
1878 char * cwd;
1898 1879
1899 error = -ERANGE; 1880 cwd = __d_path(pwd, pwdmnt, root, rootmnt, page, PAGE_SIZE);
1900 len = PAGE_SIZE + page - cwd; 1881 spin_unlock(&dcache_lock);
1901 if (len <= size) { 1882
1902 error = len; 1883 error = PTR_ERR(cwd);
1903 if (copy_to_user(buf, cwd, len)) 1884 if (IS_ERR(cwd))
1904 error = -EFAULT; 1885 goto out;
1905 } 1886
1887 error = -ERANGE;
1888 len = PAGE_SIZE + page - cwd;
1889 if (len <= size) {
1890 error = len;
1891 if (copy_to_user(buf, cwd, len))
1892 error = -EFAULT;
1893 }
1894 } else
1895 spin_unlock(&dcache_lock);
1906 1896
1907out: 1897out:
1908 dput(pwd); 1898 dput(pwd);