Commit 3fff09c5 authored by Steve French's avatar Steve French Committed by Steve French

[CIFS] Add cifs serverino mount parm to allow use of inode numbers reported from

the server (rather than generated by the client).  Some apps require inode
numbers to persist or inode numbers of hardlinked files to match and 
this requires trusting the servers inode number.

Signed-off-by: Steve French (sfrench@us.ibm.com)
parent 7a299fb7
Version 1.24
------------
Optionally allow using server side inode numbers, rather than client generated
ones by specifying mount option "serverino" - this is required for some apps
to work which double check hardlinked files and have persistent inode numbers.
Version 1.23
------------
Multiple bigendian fixes. On little endian systems (for reconnect after
......
......@@ -18,8 +18,9 @@
#ifndef _CIFS_FS_SB_H
#define _CIFS_FS_SB_H
#define CIFS_MOUNT_NO_PERM 1 /* do not do client vfs_perm check */
#define CIFS_MOUNT_NO_PERM 1 /* do not do client vfs_perm check */
#define CIFS_MOUNT_SET_UID 2 /* set current->euid in create etc. */
#define CIFS_MOUNT_SERVER_INUM 4 /* inode numbers from uniqueid from server */
struct cifs_sb_info {
struct cifsTconInfo *tcon; /* primary mount */
......
......@@ -90,5 +90,5 @@ extern int cifs_setxattr(struct dentry *, const char *, const void *,
size_t, int);
extern ssize_t cifs_getxattr(struct dentry *, const char *, void *, size_t);
extern ssize_t cifs_listxattr(struct dentry *, char *, size_t);
#define CIFS_VERSION "1.23"
#define CIFS_VERSION "1.24"
#endif /* _CIFSFS_H */
......@@ -1696,6 +1696,40 @@ typedef struct {
char FileName[1];
} FILE_DIRECTORY_INFO; /* level 257 FF response data area */
typedef struct {
__le32 NextEntryOffset;
__u32 FileIndex;
__le64 CreationTime;
__le64 LastAccessTime;
__le64 LastWriteTime;
__le64 ChangeTime;
__le64 EndOfFile;
__le64 AllocationSize;
__le32 ExtFileAttributes;
__le32 FileNameLength;
__le32 EaSize; /* length of the xattrs */
char FileName[1];
} FILE_FULL_DIRECTORY_INFO; /* level 258 FF response data area */
typedef struct {
__le32 NextEntryOffset;
__u32 FileIndex;
__le64 CreationTime;
__le64 LastAccessTime;
__le64 LastWriteTime;
__le64 ChangeTime;
__le64 EndOfFile;
__le64 AllocationSize;
__le32 ExtFileAttributes;
__le32 FileNameLength;
__le32 EaSize; /* length of the xattrs */
__u8 ShortNameLength;
__u8 Reserved;
__u8 ShortName[12];
char FileName[1];
} FILE_BOTH_DIRECTORY_INFO; /* level 260 FF response data area */
struct gea {
unsigned char name_len;
char name[1];
......
......@@ -69,6 +69,7 @@ struct smb_vol {
unsigned intr:1;
unsigned setuids:1;
unsigned noperm:1;
unsigned server_ino:1; /* use inode numbers from server ie UniqueId */
unsigned int rsize;
unsigned int wsize;
unsigned int sockopt;
......@@ -782,6 +783,10 @@ cifs_parse_mount_options(char *options, const char *devname, struct smb_vol *vol
vol->intr = 0;
} else if (strnicmp(data, "intr", 4) == 0) {
vol->intr = 1;
} else if (strnicmp(data, "serverino",7) == 0) {
vol->server_ino = 1;
} else if (strnicmp(data, "noserverino",9) == 0) {
vol->server_ino = 0;
} else if (strnicmp(data, "noac", 4) == 0) {
printk(KERN_WARNING "CIFS: Mount option noac not supported. Instead set /proc/fs/cifs/LookupCacheEnabled to 0\n");
} else
......@@ -1395,6 +1400,8 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_PERM;
if(volume_info.setuids)
cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_SET_UID;
if(volume_info.server_ino)
cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_SERVER_INUM;
tcon =
find_unc(sin_server.sin_addr.s_addr, volume_info.UNC,
......
......@@ -37,7 +37,7 @@ int cifs_dir_notify(struct file * file, unsigned long arg)
struct cifsTconInfo *pTcon;
char *full_path = NULL;
__u32 filter = FILE_NOTIFY_CHANGE_NAME | FILE_NOTIFY_CHANGE_ATTRIBUTES;
__u16 netfid;
__u16 netfid;
xid = GetXid();
cifs_sb = CIFS_SB(file->f_dentry->d_sb);
......
......@@ -1515,13 +1515,16 @@ unix_fill_in_inode(struct inode *tmp_inode,
}
}
static void
/* Returns one if new inode created (which therefore needs to be hashed) */
/* Might check in the future if inode number changed so we can rehash inode */
static int
construct_dentry(struct qstr *qstring, struct file *file,
struct inode **ptmp_inode, struct dentry **pnew_dentry)
{
struct dentry *tmp_dentry;
struct cifs_sb_info *cifs_sb;
struct cifsTconInfo *pTcon;
int rc = 0;
cFYI(1, ("For %s ", qstring->name));
cifs_sb = CIFS_SB(file->f_dentry->d_sb);
......@@ -1536,29 +1539,30 @@ construct_dentry(struct qstr *qstring, struct file *file,
if(*ptmp_inode == NULL) {
*ptmp_inode = new_inode(file->f_dentry->d_sb);
if(*ptmp_inode == NULL)
return;
return rc;
rc = 1;
d_instantiate(tmp_dentry, *ptmp_inode);
insert_inode_hash(*ptmp_inode);
}
} else {
tmp_dentry = d_alloc(file->f_dentry, qstring);
if(tmp_dentry == NULL) {
cERROR(1,("Failed allocating dentry"));
*ptmp_inode = NULL;
return;
return rc;
}
*ptmp_inode = new_inode(file->f_dentry->d_sb);
tmp_dentry->d_op = &cifs_dentry_ops;
if(*ptmp_inode == NULL)
return;
return rc;
rc = 1;
d_instantiate(tmp_dentry, *ptmp_inode);
d_rehash(tmp_dentry);
insert_inode_hash(*ptmp_inode);
}
tmp_dentry->d_time = jiffies;
*pnew_dentry = tmp_dentry;
return rc;
}
static void reset_resume_key(struct file * dir_file,
......@@ -1608,11 +1612,19 @@ cifs_filldir(struct qstr *pqstring, FILE_DIRECTORY_INFO * pfindData,
pqstring->name = pfindData->FileName;
/* pqstring->len is already set by caller */
construct_dentry(pqstring, file, &tmp_inode, &tmp_dentry);
rc = construct_dentry(pqstring, file, &tmp_inode, &tmp_dentry);
if((tmp_inode == NULL) || (tmp_dentry == NULL)) {
return -ENOMEM;
}
fill_in_inode(tmp_inode, pfindData, &object_type);
if(rc) {
/* We have no reliable way to get inode numbers
from servers w/o Unix extensions yet so we can not set
i_ino from pfindData yet */
/* new inode created, let us hash it */
insert_inode_hash(tmp_inode);
} /* else if inode number changed do we rehash it? */
rc = filldir(direntry, pfindData->FileName, pqstring->len, file->f_pos,
tmp_inode->i_ino, object_type);
if(rc) {
......@@ -1636,11 +1648,19 @@ cifs_filldir_unix(struct qstr *pqstring,
pqstring->name = pUnixFindData->FileName;
pqstring->len = strnlen(pUnixFindData->FileName, MAX_PATHCONF);
construct_dentry(pqstring, file, &tmp_inode, &tmp_dentry);
rc = construct_dentry(pqstring, file, &tmp_inode, &tmp_dentry);
if((tmp_inode == NULL) || (tmp_dentry == NULL)) {
return -ENOMEM;
}
}
if(rc) {
struct cifs_sb_info *cifs_sb = CIFS_SB(tmp_inode->i_sb);
if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) {
tmp_inode->i_ino =
(unsigned long)pUnixFindData->UniqueId;
}
insert_inode_hash(tmp_inode);
} /* else if i_ino has changed should we rehash it? */
unix_fill_in_inode(tmp_inode, pUnixFindData, &object_type);
rc = filldir(direntry, pUnixFindData->FileName, pqstring->len,
file->f_pos, tmp_inode->i_ino, object_type);
......
......@@ -85,6 +85,13 @@ cifs_get_inode_info_unix(struct inode **pinode,
*pinode = new_inode(sb);
if(*pinode == NULL)
return -ENOMEM;
/* 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 */
insert_inode_hash(*pinode);
}
......@@ -244,6 +251,21 @@ cifs_get_inode_info(struct inode **pinode, const unsigned char *search_path,
*pinode = new_inode(sb);
if(*pinode == NULL)
return -ENOMEM;
/* 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? */
/* We can not use the IndexNumber from either
Windows or Samba as it is frequently set to zero */
/* There may be higher info levels that work but
Are there Windows server or network appliances
for which IndexNumber field is not guaranteed unique? */
/* if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) {
(*pinode)->i_ino =
(unsigned long)pfindData->IndexNumber;
} */ /*NB: ino incremented to unique num in new_inode*/
insert_inode_hash(*pinode);
}
inode = *pinode;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment