Commit 132ac7b7 authored by Jeff Layton's avatar Jeff Layton Committed by Steve French

cifs: refactor new_inode() calls and inode initialization

Move new inode creation into a separate routine and refactor the
callers to take advantage of it.
Signed-off-by: default avatarJeff Layton <jlayton@redhat.com>
Signed-off-by: default avatarSteve French <sfrench@us.ibm.com>
parent e4cce94c
...@@ -92,6 +92,8 @@ extern u64 cifs_UnixTimeToNT(struct timespec); ...@@ -92,6 +92,8 @@ extern u64 cifs_UnixTimeToNT(struct timespec);
extern __le64 cnvrtDosCifsTm(__u16 date, __u16 time); extern __le64 cnvrtDosCifsTm(__u16 date, __u16 time);
extern struct timespec cnvrtDosUnixTm(__u16 date, __u16 time); extern struct timespec cnvrtDosUnixTm(__u16 date, __u16 time);
extern struct inode *cifs_new_inode(struct super_block *sb,
unsigned long *inum);
extern int cifs_get_inode_info(struct inode **pinode, extern int cifs_get_inode_info(struct inode **pinode,
const unsigned char *search_path, const unsigned char *search_path,
FILE_ALL_INFO *pfile_info, FILE_ALL_INFO *pfile_info,
......
...@@ -199,6 +199,49 @@ static void fill_fake_finddataunix(FILE_UNIX_BASIC_INFO *pfnd_dat, ...@@ -199,6 +199,49 @@ static void fill_fake_finddataunix(FILE_UNIX_BASIC_INFO *pfnd_dat,
pfnd_dat->Gid = cpu_to_le64(pinode->i_gid); pfnd_dat->Gid = cpu_to_le64(pinode->i_gid);
} }
/**
* cifs_new inode - create new inode, initialize, and hash it
* @sb - pointer to superblock
* @inum - if valid pointer and serverino is enabled, replace i_ino with val
*
* Create a new inode, initialize it for CIFS and hash it. Returns the new
* inode or NULL if one couldn't be allocated.
*
* If the share isn't mounted with "serverino" or inum is a NULL pointer then
* we'll just use the inode number assigned by new_inode(). Note that this can
* mean i_ino collisions since the i_ino assigned by new_inode is not
* guaranteed to be unique.
*/
struct inode *
cifs_new_inode(struct super_block *sb, unsigned long *inum)
{
struct inode *inode;
inode = new_inode(sb);
if (inode == NULL)
return NULL;
/*
* BB: Is i_ino == 0 legal? Here, we assume that it is. If it isn't we
* stop passing inum as ptr. Are there sanity checks we can use to
* ensure that the server is really filling in that field? Also,
* if serverino is disabled, perhaps we should be using iunique()?
*/
if (inum && (CIFS_SB(sb)->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM))
inode->i_ino = *inum;
/*
* must set this here instead of cifs_alloc_inode since VFS will
* clobber i_flags
*/
if (sb->s_flags & MS_NOATIME)
inode->i_flags |= S_NOATIME | S_NOCMTIME;
insert_inode_hash(inode);
return inode;
}
int cifs_get_inode_info_unix(struct inode **pinode, int cifs_get_inode_info_unix(struct inode **pinode,
const unsigned char *full_path, struct super_block *sb, int xid) const unsigned char *full_path, struct super_block *sb, int xid)
{ {
...@@ -233,22 +276,12 @@ int cifs_get_inode_info_unix(struct inode **pinode, ...@@ -233,22 +276,12 @@ int cifs_get_inode_info_unix(struct inode **pinode,
/* get new inode */ /* get new inode */
if (*pinode == NULL) { if (*pinode == NULL) {
*pinode = new_inode(sb); *pinode = cifs_new_inode(sb, (unsigned long *)
&find_data.UniqueId);
if (*pinode == NULL) { if (*pinode == NULL) {
rc = -ENOMEM; rc = -ENOMEM;
goto cgiiu_exit; 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; inode = *pinode;
...@@ -465,11 +498,8 @@ int cifs_get_inode_info(struct inode **pinode, ...@@ -465,11 +498,8 @@ int cifs_get_inode_info(struct inode **pinode,
/* get new inode */ /* get new inode */
if (*pinode == NULL) { if (*pinode == NULL) {
*pinode = new_inode(sb); __u64 inode_num;
if (*pinode == NULL) {
rc = -ENOMEM;
goto cgii_exit;
}
/* Is an i_ino of zero legal? Can we use that to check /* Is an i_ino of zero legal? Can we use that to check
if the server supports returning inode numbers? Are if the server supports returning inode numbers? Are
there other sanity checks we can use to ensure that there other sanity checks we can use to ensure that
...@@ -486,7 +516,6 @@ int cifs_get_inode_info(struct inode **pinode, ...@@ -486,7 +516,6 @@ int cifs_get_inode_info(struct inode **pinode,
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) { if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) {
int rc1 = 0; int rc1 = 0;
__u64 inode_num;
rc1 = CIFSGetSrvInodeNumber(xid, pTcon, rc1 = CIFSGetSrvInodeNumber(xid, pTcon,
full_path, &inode_num, full_path, &inode_num,
...@@ -496,12 +525,17 @@ int cifs_get_inode_info(struct inode **pinode, ...@@ -496,12 +525,17 @@ int cifs_get_inode_info(struct inode **pinode,
if (rc1) { if (rc1) {
cFYI(1, ("GetSrvInodeNum rc %d", rc1)); cFYI(1, ("GetSrvInodeNum rc %d", rc1));
/* BB EOPNOSUPP disable SERVER_INUM? */ /* BB EOPNOSUPP disable SERVER_INUM? */
} else /* do we need cast or hash to ino? */ }
(*pinode)->i_ino = inode_num; *pinode = cifs_new_inode(sb, (unsigned long *)
} /* else ino incremented to unique num in new_inode*/ &inode_num);
if (sb->s_flags & MS_NOATIME) } else {
(*pinode)->i_flags |= S_NOATIME | S_NOCMTIME; *pinode = cifs_new_inode(sb, NULL);
insert_inode_hash(*pinode); }
if (*pinode == NULL) {
rc = -ENOMEM;
goto cgii_exit;
}
} }
inode = *pinode; inode = *pinode;
cifsInfo = CIFS_I(inode); cifsInfo = CIFS_I(inode);
...@@ -1114,24 +1148,14 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode) ...@@ -1114,24 +1148,14 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode)
else else
direntry->d_op = &cifs_dentry_ops; direntry->d_op = &cifs_dentry_ops;
newinode = new_inode(inode->i_sb); newinode = cifs_new_inode(inode->i_sb, (unsigned long *)
&pInfo->UniqueId);
if (newinode == NULL) { if (newinode == NULL) {
kfree(pInfo); kfree(pInfo);
goto mkdir_get_info; goto mkdir_get_info;
} }
/* 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) {
newinode->i_ino =
(unsigned long)pInfo->UniqueId;
} /* note ino incremented to unique num in new_inode */
if (inode->i_sb->s_flags & MS_NOATIME)
newinode->i_flags |= S_NOATIME | S_NOCMTIME;
newinode->i_nlink = 2; newinode->i_nlink = 2;
insert_inode_hash(newinode);
d_instantiate(direntry, newinode); d_instantiate(direntry, newinode);
/* we already checked in POSIXCreate whether /* we already checked in POSIXCreate whether
......
...@@ -56,35 +56,34 @@ static inline void dump_cifs_file_struct(struct file *file, char *label) ...@@ -56,35 +56,34 @@ static inline void dump_cifs_file_struct(struct file *file, char *label)
} }
#endif /* DEBUG2 */ #endif /* DEBUG2 */
/* Returns one if new inode created (which therefore needs to be hashed) */ /* Returns 1 if new inode created, 2 if both dentry and inode were */
/* Might check in the future if inode number changed so we can rehash inode */ /* Might check in the future if inode number changed so we can rehash inode */
static int construct_dentry(struct qstr *qstring, struct file *file, static int
struct inode **ptmp_inode, struct dentry **pnew_dentry) construct_dentry(struct qstr *qstring, struct file *file,
struct inode **ptmp_inode, struct dentry **pnew_dentry,
unsigned long *inum)
{ {
struct dentry *tmp_dentry; struct dentry *tmp_dentry = NULL;
struct cifs_sb_info *cifs_sb; struct super_block *sb = file->f_path.dentry->d_sb;
struct cifsTconInfo *pTcon;
int rc = 0; int rc = 0;
cFYI(1, ("For %s", qstring->name)); cFYI(1, ("For %s", qstring->name));
cifs_sb = CIFS_SB(file->f_path.dentry->d_sb);
pTcon = cifs_sb->tcon;
qstring->hash = full_name_hash(qstring->name, qstring->len); qstring->hash = full_name_hash(qstring->name, qstring->len);
tmp_dentry = d_lookup(file->f_path.dentry, qstring); tmp_dentry = d_lookup(file->f_path.dentry, qstring);
if (tmp_dentry) { if (tmp_dentry) {
/* BB: overwrite old name? i.e. tmp_dentry->d_name and
* tmp_dentry->d_name.len??
*/
cFYI(0, ("existing dentry with inode 0x%p", cFYI(0, ("existing dentry with inode 0x%p",
tmp_dentry->d_inode)); tmp_dentry->d_inode));
*ptmp_inode = tmp_dentry->d_inode; *ptmp_inode = tmp_dentry->d_inode;
/* BB overwrite old name? i.e. tmp_dentry->d_name and tmp_dentry->d_name.len??*/
if (*ptmp_inode == NULL) { if (*ptmp_inode == NULL) {
*ptmp_inode = new_inode(file->f_path.dentry->d_sb); *ptmp_inode = cifs_new_inode(sb, inum);
if (*ptmp_inode == NULL) if (*ptmp_inode == NULL)
return rc; return rc;
rc = 1; rc = 1;
} }
if (file->f_path.dentry->d_sb->s_flags & MS_NOATIME)
(*ptmp_inode)->i_flags |= S_NOATIME | S_NOCMTIME;
} else { } else {
tmp_dentry = d_alloc(file->f_path.dentry, qstring); tmp_dentry = d_alloc(file->f_path.dentry, qstring);
if (tmp_dentry == NULL) { if (tmp_dentry == NULL) {
...@@ -93,15 +92,14 @@ static int construct_dentry(struct qstr *qstring, struct file *file, ...@@ -93,15 +92,14 @@ static int construct_dentry(struct qstr *qstring, struct file *file,
return rc; return rc;
} }
*ptmp_inode = new_inode(file->f_path.dentry->d_sb); if (CIFS_SB(sb)->tcon->nocase)
if (pTcon->nocase)
tmp_dentry->d_op = &cifs_ci_dentry_ops; tmp_dentry->d_op = &cifs_ci_dentry_ops;
else else
tmp_dentry->d_op = &cifs_dentry_ops; tmp_dentry->d_op = &cifs_dentry_ops;
*ptmp_inode = cifs_new_inode(sb, inum);
if (*ptmp_inode == NULL) if (*ptmp_inode == NULL)
return rc; return rc;
if (file->f_path.dentry->d_sb->s_flags & MS_NOATIME)
(*ptmp_inode)->i_flags |= S_NOATIME | S_NOCMTIME;
rc = 2; rc = 2;
} }
...@@ -842,8 +840,6 @@ static int cifs_get_name_from_search_buf(struct qstr *pqst, ...@@ -842,8 +840,6 @@ static int cifs_get_name_from_search_buf(struct qstr *pqst,
len = strnlen(filename, PATH_MAX); len = strnlen(filename, PATH_MAX);
} }
/* BB fixme - hash low and high 32 bits if not 64 bit arch BB */
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM)
*pinum = pFindData->UniqueId; *pinum = pFindData->UniqueId;
} else if (level == SMB_FIND_FILE_DIRECTORY_INFO) { } else if (level == SMB_FIND_FILE_DIRECTORY_INFO) {
FILE_DIRECTORY_INFO *pFindData = FILE_DIRECTORY_INFO *pFindData =
...@@ -940,20 +936,18 @@ static int cifs_filldir(char *pfindEntry, struct file *file, ...@@ -940,20 +936,18 @@ static int cifs_filldir(char *pfindEntry, struct file *file,
if (rc) if (rc)
return rc; return rc;
rc = construct_dentry(&qstring, file, &tmp_inode, &tmp_dentry); /* only these two infolevels return valid inode numbers */
if (pCifsF->srch_inf.info_level == SMB_FIND_FILE_UNIX ||
pCifsF->srch_inf.info_level == SMB_FIND_FILE_ID_FULL_DIR_INFO)
rc = construct_dentry(&qstring, file, &tmp_inode, &tmp_dentry,
&inum);
else
rc = construct_dentry(&qstring, file, &tmp_inode, &tmp_dentry,
NULL);
if ((tmp_inode == NULL) || (tmp_dentry == NULL)) if ((tmp_inode == NULL) || (tmp_dentry == NULL))
return -ENOMEM; return -ENOMEM;
if (rc) {
/* inode created, we need to hash it with right inode number */
if (inum != 0) {
/* BB fixme - hash the 2 32 quantities bits together if
* necessary BB */
tmp_inode->i_ino = inum;
}
insert_inode_hash(tmp_inode);
}
/* we pass in rc below, indicating whether it is a new inode, /* we pass in rc below, indicating whether it is a new inode,
so we can figure out whether to invalidate the inode cached so we can figure out whether to invalidate the inode cached
data if the file has changed */ data if the file has changed */
......
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