mirror of
https://github.com/joel16/android_kernel_sony_msm8994.git
synced 2024-11-23 20:20:21 +00:00
[CIFS] Enable DFS support for Unix query path info
Final piece for handling DFS in unix_query_path_info, constructing a fake inode for the junction directory which the submount will cover. Acked-by: Igor Mammedov <niallain@gmail.com> Signed-off-by: Steve French <sfrench@us.ibm.com>
This commit is contained in:
parent
89562b777c
commit
0e4bbde94f
@ -36,6 +36,7 @@ Miklos Szeredi
|
||||
Kazeon team for various fixes especially for 2.4 version.
|
||||
Asser Ferno (Change Notify support)
|
||||
Shaggy (Dave Kleikamp) for inumerable small fs suggestions and some good cleanup
|
||||
Igor Mammedov (DFS support)
|
||||
|
||||
Test case and Bug Report contributors
|
||||
-------------------------------------
|
||||
|
@ -1,5 +1,7 @@
|
||||
Version 1.53
|
||||
------------
|
||||
DFS support added (Microsoft Distributed File System client support needed
|
||||
for referrals which enable a hierarchical name space among servers).
|
||||
|
||||
Version 1.52
|
||||
------------
|
||||
|
15
fs/cifs/TODO
15
fs/cifs/TODO
@ -1,4 +1,4 @@
|
||||
Version 1.52 January 3, 2008
|
||||
Version 1.53 May 20, 2008
|
||||
|
||||
A Partial List of Missing Features
|
||||
==================================
|
||||
@ -20,20 +20,21 @@ d) Cleanup now unneeded SessSetup code in
|
||||
fs/cifs/connect.c and add back in NTLMSSP code if any servers
|
||||
need it
|
||||
|
||||
e) ms-dfs and ms-dfs host name resolution cleanup
|
||||
|
||||
f) fix NTLMv2 signing when two mounts with different users to same
|
||||
e) fix NTLMv2 signing when two mounts with different users to same
|
||||
server.
|
||||
|
||||
g) Directory entry caching relies on a 1 second timer, rather than
|
||||
f) Directory entry caching relies on a 1 second timer, rather than
|
||||
using FindNotify or equivalent. - (started)
|
||||
|
||||
h) quota support (needs minor kernel change since quota calls
|
||||
g) quota support (needs minor kernel change since quota calls
|
||||
to make it to network filesystems or deviceless filesystems)
|
||||
|
||||
i) investigate sync behavior (including syncpage) and check
|
||||
h) investigate sync behavior (including syncpage) and check
|
||||
for proper behavior of intr/nointr
|
||||
|
||||
i) improve support for very old servers (OS/2 and Win9x for example)
|
||||
Including support for changing the time remotely (utimes command).
|
||||
|
||||
j) hook lower into the sockets api (as NFS/SunRPC does) to avoid the
|
||||
extra copy in/out of the socket buffers in some cases.
|
||||
|
||||
|
133
fs/cifs/inode.c
133
fs/cifs/inode.c
@ -161,77 +161,108 @@ static void cifs_unix_info_to_inode(struct inode *inode,
|
||||
spin_unlock(&inode->i_lock);
|
||||
}
|
||||
|
||||
static void fill_fake_finddataunix(FILE_UNIX_BASIC_INFO *pfnd_dat,
|
||||
struct super_block *sb)
|
||||
{
|
||||
struct inode *pinode = NULL;
|
||||
|
||||
memset(pfnd_dat, sizeof(FILE_UNIX_BASIC_INFO), 0);
|
||||
|
||||
/* __le64 pfnd_dat->EndOfFile = cpu_to_le64(0);
|
||||
__le64 pfnd_dat->NumOfBytes = cpu_to_le64(0);
|
||||
__u64 UniqueId = 0; */
|
||||
pfnd_dat->LastStatusChange =
|
||||
cpu_to_le64(cifs_UnixTimeToNT(CURRENT_TIME));
|
||||
pfnd_dat->LastAccessTime =
|
||||
cpu_to_le64(cifs_UnixTimeToNT(CURRENT_TIME));
|
||||
pfnd_dat->LastModificationTime =
|
||||
cpu_to_le64(cifs_UnixTimeToNT(CURRENT_TIME));
|
||||
pfnd_dat->Type = cpu_to_le32(UNIX_DIR);
|
||||
pfnd_dat->Permissions = cpu_to_le64(S_IXUGO | S_IRWXU);
|
||||
pfnd_dat->Nlinks = cpu_to_le64(2);
|
||||
if (sb->s_root)
|
||||
pinode = sb->s_root->d_inode;
|
||||
if (pinode == NULL)
|
||||
return;
|
||||
|
||||
/* fill in default values for the remaining based on root
|
||||
inode since we can not query the server for this inode info */
|
||||
pfnd_dat->DevMajor = cpu_to_le64(MAJOR(pinode->i_rdev));
|
||||
pfnd_dat->DevMinor = cpu_to_le64(MINOR(pinode->i_rdev));
|
||||
pfnd_dat->Uid = cpu_to_le64(pinode->i_uid);
|
||||
pfnd_dat->Gid = cpu_to_le64(pinode->i_gid);
|
||||
}
|
||||
|
||||
int cifs_get_inode_info_unix(struct inode **pinode,
|
||||
const unsigned char *full_path, struct super_block *sb, int xid)
|
||||
{
|
||||
int rc = 0;
|
||||
FILE_UNIX_BASIC_INFO findData;
|
||||
FILE_UNIX_BASIC_INFO find_data;
|
||||
struct cifsTconInfo *pTcon;
|
||||
struct inode *inode;
|
||||
struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
|
||||
bool is_dfs_referral = false;
|
||||
struct cifsInodeInfo *cifsInfo;
|
||||
__u64 num_of_bytes;
|
||||
__u64 end_of_file;
|
||||
|
||||
pTcon = cifs_sb->tcon;
|
||||
cFYI(1, ("Getting info on %s", full_path));
|
||||
|
||||
try_again_CIFSSMBUnixQPathInfo:
|
||||
/* could have done a find first instead but this returns more info */
|
||||
rc = CIFSSMBUnixQPathInfo(xid, pTcon, full_path, &findData,
|
||||
rc = CIFSSMBUnixQPathInfo(xid, pTcon, full_path, &find_data,
|
||||
cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
|
||||
CIFS_MOUNT_MAP_SPECIAL_CHR);
|
||||
/* dump_mem("\nUnixQPathInfo return data", &findData,
|
||||
sizeof(findData)); */
|
||||
if (rc) {
|
||||
if (rc == -EREMOTE && !is_dfs_referral) {
|
||||
is_dfs_referral = true;
|
||||
goto try_again_CIFSSMBUnixQPathInfo;
|
||||
cERROR(1, ("DFS ref")); /* BB removeme BB */
|
||||
/* for DFS, server does not give us real inode data */
|
||||
fill_fake_finddataunix(&find_data, sb);
|
||||
rc = 0;
|
||||
}
|
||||
goto cgiiu_exit;
|
||||
} else {
|
||||
struct cifsInodeInfo *cifsInfo;
|
||||
__u64 num_of_bytes = le64_to_cpu(findData.NumOfBytes);
|
||||
__u64 end_of_file = le64_to_cpu(findData.EndOfFile);
|
||||
|
||||
/* get new inode */
|
||||
if (*pinode == NULL) {
|
||||
*pinode = new_inode(sb);
|
||||
if (*pinode == NULL) {
|
||||
rc = -ENOMEM;
|
||||
goto cgiiu_exit;
|
||||
}
|
||||
/* Is an i_ino of zero legal? */
|
||||
/* Are there sanity checks we can use to ensure that
|
||||
the server is really filling in that field? */
|
||||
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) {
|
||||
(*pinode)->i_ino =
|
||||
(unsigned long)findData.UniqueId;
|
||||
} /* note ino incremented to unique num in new_inode */
|
||||
if (sb->s_flags & MS_NOATIME)
|
||||
(*pinode)->i_flags |= S_NOATIME | S_NOCMTIME;
|
||||
|
||||
insert_inode_hash(*pinode);
|
||||
}
|
||||
|
||||
inode = *pinode;
|
||||
cifsInfo = CIFS_I(inode);
|
||||
|
||||
cFYI(1, ("Old time %ld", cifsInfo->time));
|
||||
cifsInfo->time = jiffies;
|
||||
cFYI(1, ("New time %ld", cifsInfo->time));
|
||||
/* this is ok to set on every inode revalidate */
|
||||
atomic_set(&cifsInfo->inUse, 1);
|
||||
|
||||
cifs_unix_info_to_inode(inode, &findData, 0);
|
||||
|
||||
|
||||
if (num_of_bytes < end_of_file)
|
||||
cFYI(1, ("allocation size less than end of file"));
|
||||
cFYI(1, ("Size %ld and blocks %llu",
|
||||
(unsigned long) inode->i_size,
|
||||
(unsigned long long)inode->i_blocks));
|
||||
|
||||
cifs_set_ops(inode, is_dfs_referral);
|
||||
}
|
||||
num_of_bytes = le64_to_cpu(find_data.NumOfBytes);
|
||||
end_of_file = le64_to_cpu(find_data.EndOfFile);
|
||||
|
||||
/* get new inode */
|
||||
if (*pinode == NULL) {
|
||||
*pinode = new_inode(sb);
|
||||
if (*pinode == NULL) {
|
||||
rc = -ENOMEM;
|
||||
goto cgiiu_exit;
|
||||
}
|
||||
/* Is an i_ino of zero legal? */
|
||||
/* note ino incremented to unique num in new_inode */
|
||||
/* Are there sanity checks we can use to ensure that
|
||||
the server is really filling in that field? */
|
||||
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM)
|
||||
(*pinode)->i_ino = (unsigned long)find_data.UniqueId;
|
||||
|
||||
if (sb->s_flags & MS_NOATIME)
|
||||
(*pinode)->i_flags |= S_NOATIME | S_NOCMTIME;
|
||||
|
||||
insert_inode_hash(*pinode);
|
||||
}
|
||||
|
||||
inode = *pinode;
|
||||
cifsInfo = CIFS_I(inode);
|
||||
|
||||
cFYI(1, ("Old time %ld", cifsInfo->time));
|
||||
cifsInfo->time = jiffies;
|
||||
cFYI(1, ("New time %ld", cifsInfo->time));
|
||||
/* this is ok to set on every inode revalidate */
|
||||
atomic_set(&cifsInfo->inUse, 1);
|
||||
|
||||
cifs_unix_info_to_inode(inode, &find_data, 0);
|
||||
|
||||
if (num_of_bytes < end_of_file)
|
||||
cFYI(1, ("allocation size less than end of file"));
|
||||
cFYI(1, ("Size %ld and blocks %llu",
|
||||
(unsigned long) inode->i_size,
|
||||
(unsigned long long)inode->i_blocks));
|
||||
|
||||
cifs_set_ops(inode, is_dfs_referral);
|
||||
cgiiu_exit:
|
||||
return rc;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user