[CIFS] consolidate duplicate code in posix/unix inode handling
Signed-off-by: Christoph Hellwig <hch@infradead.org> Signed-off-by: Steve French <sfrench@us.ibm.com>
This commit is contained in:
parent
e086fcea86
commit
75f12983d9
283
fs/cifs/inode.c
283
fs/cifs/inode.c
|
@ -69,6 +69,90 @@ static void cifs_set_ops(struct inode *inode)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void cifs_unix_info_to_inode(struct inode *inode,
|
||||||
|
FILE_UNIX_BASIC_INFO *info, int force_uid_gid)
|
||||||
|
{
|
||||||
|
struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
|
||||||
|
struct cifsInodeInfo *cifsInfo = CIFS_I(inode);
|
||||||
|
__u64 num_of_bytes = le64_to_cpu(info->NumOfBytes);
|
||||||
|
__u64 end_of_file = le64_to_cpu(info->EndOfFile);
|
||||||
|
|
||||||
|
inode->i_atime = cifs_NTtimeToUnix(le64_to_cpu(info->LastAccessTime));
|
||||||
|
inode->i_mtime =
|
||||||
|
cifs_NTtimeToUnix(le64_to_cpu(info->LastModificationTime));
|
||||||
|
inode->i_ctime = cifs_NTtimeToUnix(le64_to_cpu(info->LastStatusChange));
|
||||||
|
inode->i_mode = le64_to_cpu(info->Permissions);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Since we set the inode type below we need to mask off
|
||||||
|
* to avoid strange results if bits set above.
|
||||||
|
*/
|
||||||
|
inode->i_mode &= ~S_IFMT;
|
||||||
|
switch (le32_to_cpu(info->Type)) {
|
||||||
|
case UNIX_FILE:
|
||||||
|
inode->i_mode |= S_IFREG;
|
||||||
|
break;
|
||||||
|
case UNIX_SYMLINK:
|
||||||
|
inode->i_mode |= S_IFLNK;
|
||||||
|
break;
|
||||||
|
case UNIX_DIR:
|
||||||
|
inode->i_mode |= S_IFDIR;
|
||||||
|
break;
|
||||||
|
case UNIX_CHARDEV:
|
||||||
|
inode->i_mode |= S_IFCHR;
|
||||||
|
inode->i_rdev = MKDEV(le64_to_cpu(info->DevMajor),
|
||||||
|
le64_to_cpu(info->DevMinor) & MINORMASK);
|
||||||
|
break;
|
||||||
|
case UNIX_BLOCKDEV:
|
||||||
|
inode->i_mode |= S_IFBLK;
|
||||||
|
inode->i_rdev = MKDEV(le64_to_cpu(info->DevMajor),
|
||||||
|
le64_to_cpu(info->DevMinor) & MINORMASK);
|
||||||
|
break;
|
||||||
|
case UNIX_FIFO:
|
||||||
|
inode->i_mode |= S_IFIFO;
|
||||||
|
break;
|
||||||
|
case UNIX_SOCKET:
|
||||||
|
inode->i_mode |= S_IFSOCK;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
/* safest to call it a file if we do not know */
|
||||||
|
inode->i_mode |= S_IFREG;
|
||||||
|
cFYI(1, ("unknown type %d", le32_to_cpu(info->Type)));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_UID) &&
|
||||||
|
!force_uid_gid)
|
||||||
|
inode->i_uid = cifs_sb->mnt_uid;
|
||||||
|
else
|
||||||
|
inode->i_uid = le64_to_cpu(info->Uid);
|
||||||
|
|
||||||
|
if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_GID) &&
|
||||||
|
!force_uid_gid)
|
||||||
|
inode->i_gid = cifs_sb->mnt_gid;
|
||||||
|
else
|
||||||
|
inode->i_gid = le64_to_cpu(info->Gid);
|
||||||
|
|
||||||
|
inode->i_nlink = le64_to_cpu(info->Nlinks);
|
||||||
|
|
||||||
|
spin_lock(&inode->i_lock);
|
||||||
|
if (is_size_safe_to_change(cifsInfo, end_of_file)) {
|
||||||
|
/*
|
||||||
|
* We can not safely change the file size here if the client
|
||||||
|
* is writing to it due to potential races.
|
||||||
|
*/
|
||||||
|
i_size_write(inode, end_of_file);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* i_blocks is not related to (i_size / i_blksize),
|
||||||
|
* but instead 512 byte (2**9) size is required for
|
||||||
|
* calculating num blocks.
|
||||||
|
*/
|
||||||
|
inode->i_blocks = (512 - 1 + num_of_bytes) >> 9;
|
||||||
|
}
|
||||||
|
spin_unlock(&inode->i_lock);
|
||||||
|
}
|
||||||
|
|
||||||
int cifs_get_inode_info_unix(struct inode **pinode,
|
int cifs_get_inode_info_unix(struct inode **pinode,
|
||||||
const unsigned char *search_path, struct super_block *sb, int xid)
|
const unsigned char *search_path, struct super_block *sb, int xid)
|
||||||
{
|
{
|
||||||
|
@ -114,7 +198,6 @@ int cifs_get_inode_info_unix(struct inode **pinode,
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
struct cifsInodeInfo *cifsInfo;
|
struct cifsInodeInfo *cifsInfo;
|
||||||
__u32 type = le32_to_cpu(findData.Type);
|
|
||||||
__u64 num_of_bytes = le64_to_cpu(findData.NumOfBytes);
|
__u64 num_of_bytes = le64_to_cpu(findData.NumOfBytes);
|
||||||
__u64 end_of_file = le64_to_cpu(findData.EndOfFile);
|
__u64 end_of_file = le64_to_cpu(findData.EndOfFile);
|
||||||
|
|
||||||
|
@ -145,73 +228,8 @@ int cifs_get_inode_info_unix(struct inode **pinode,
|
||||||
/* this is ok to set on every inode revalidate */
|
/* this is ok to set on every inode revalidate */
|
||||||
atomic_set(&cifsInfo->inUse, 1);
|
atomic_set(&cifsInfo->inUse, 1);
|
||||||
|
|
||||||
inode->i_atime =
|
cifs_unix_info_to_inode(inode, &findData, 0);
|
||||||
cifs_NTtimeToUnix(le64_to_cpu(findData.LastAccessTime));
|
|
||||||
inode->i_mtime =
|
|
||||||
cifs_NTtimeToUnix(le64_to_cpu
|
|
||||||
(findData.LastModificationTime));
|
|
||||||
inode->i_ctime =
|
|
||||||
cifs_NTtimeToUnix(le64_to_cpu(findData.LastStatusChange));
|
|
||||||
inode->i_mode = le64_to_cpu(findData.Permissions);
|
|
||||||
/* since we set the inode type below we need to mask off
|
|
||||||
to avoid strange results if bits set above */
|
|
||||||
inode->i_mode &= ~S_IFMT;
|
|
||||||
if (type == UNIX_FILE) {
|
|
||||||
inode->i_mode |= S_IFREG;
|
|
||||||
} else if (type == UNIX_SYMLINK) {
|
|
||||||
inode->i_mode |= S_IFLNK;
|
|
||||||
} else if (type == UNIX_DIR) {
|
|
||||||
inode->i_mode |= S_IFDIR;
|
|
||||||
} else if (type == UNIX_CHARDEV) {
|
|
||||||
inode->i_mode |= S_IFCHR;
|
|
||||||
inode->i_rdev = MKDEV(le64_to_cpu(findData.DevMajor),
|
|
||||||
le64_to_cpu(findData.DevMinor) & MINORMASK);
|
|
||||||
} else if (type == UNIX_BLOCKDEV) {
|
|
||||||
inode->i_mode |= S_IFBLK;
|
|
||||||
inode->i_rdev = MKDEV(le64_to_cpu(findData.DevMajor),
|
|
||||||
le64_to_cpu(findData.DevMinor) & MINORMASK);
|
|
||||||
} else if (type == UNIX_FIFO) {
|
|
||||||
inode->i_mode |= S_IFIFO;
|
|
||||||
} else if (type == UNIX_SOCKET) {
|
|
||||||
inode->i_mode |= S_IFSOCK;
|
|
||||||
} else {
|
|
||||||
/* safest to call it a file if we do not know */
|
|
||||||
inode->i_mode |= S_IFREG;
|
|
||||||
cFYI(1, ("unknown type %d", type));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_UID)
|
|
||||||
inode->i_uid = cifs_sb->mnt_uid;
|
|
||||||
else
|
|
||||||
inode->i_uid = le64_to_cpu(findData.Uid);
|
|
||||||
|
|
||||||
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_GID)
|
|
||||||
inode->i_gid = cifs_sb->mnt_gid;
|
|
||||||
else
|
|
||||||
inode->i_gid = le64_to_cpu(findData.Gid);
|
|
||||||
|
|
||||||
inode->i_nlink = le64_to_cpu(findData.Nlinks);
|
|
||||||
|
|
||||||
spin_lock(&inode->i_lock);
|
|
||||||
if (is_size_safe_to_change(cifsInfo, end_of_file)) {
|
|
||||||
/* can not safely change the file size here if the
|
|
||||||
client is writing to it due to potential races */
|
|
||||||
i_size_write(inode, end_of_file);
|
|
||||||
|
|
||||||
/* blksize needs to be multiple of two. So safer to default to
|
|
||||||
blksize and blkbits set in superblock so 2**blkbits and blksize
|
|
||||||
will match rather than setting to:
|
|
||||||
(pTcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) & 0xFFFFFE00;*/
|
|
||||||
|
|
||||||
/* This seems incredibly stupid but it turns out that i_blocks
|
|
||||||
is not related to (i_size / i_blksize), instead 512 byte size
|
|
||||||
is required for calculating num blocks */
|
|
||||||
|
|
||||||
/* 512 bytes (2**9) is the fake blocksize that must be used */
|
|
||||||
/* for this calculation */
|
|
||||||
inode->i_blocks = (512 - 1 + num_of_bytes) >> 9;
|
|
||||||
}
|
|
||||||
spin_unlock(&inode->i_lock);
|
|
||||||
|
|
||||||
if (num_of_bytes < end_of_file)
|
if (num_of_bytes < end_of_file)
|
||||||
cFYI(1, ("allocation size less than end of file"));
|
cFYI(1, ("allocation size less than end of file"));
|
||||||
|
@ -774,15 +792,10 @@ psx_del_no_retry:
|
||||||
static void posix_fill_in_inode(struct inode *tmp_inode,
|
static void posix_fill_in_inode(struct inode *tmp_inode,
|
||||||
FILE_UNIX_BASIC_INFO *pData, int *pobject_type, int isNewInode)
|
FILE_UNIX_BASIC_INFO *pData, int *pobject_type, int isNewInode)
|
||||||
{
|
{
|
||||||
|
struct cifsInodeInfo *cifsInfo = CIFS_I(tmp_inode);
|
||||||
loff_t local_size;
|
loff_t local_size;
|
||||||
struct timespec local_mtime;
|
struct timespec local_mtime;
|
||||||
|
|
||||||
struct cifsInodeInfo *cifsInfo = CIFS_I(tmp_inode);
|
|
||||||
struct cifs_sb_info *cifs_sb = CIFS_SB(tmp_inode->i_sb);
|
|
||||||
|
|
||||||
__u32 type = le32_to_cpu(pData->Type);
|
|
||||||
__u64 num_of_bytes = le64_to_cpu(pData->NumOfBytes);
|
|
||||||
__u64 end_of_file = le64_to_cpu(pData->EndOfFile);
|
|
||||||
cifsInfo->time = jiffies;
|
cifsInfo->time = jiffies;
|
||||||
atomic_inc(&cifsInfo->inUse);
|
atomic_inc(&cifsInfo->inUse);
|
||||||
|
|
||||||
|
@ -790,113 +803,27 @@ static void posix_fill_in_inode(struct inode *tmp_inode,
|
||||||
local_mtime = tmp_inode->i_mtime;
|
local_mtime = tmp_inode->i_mtime;
|
||||||
local_size = tmp_inode->i_size;
|
local_size = tmp_inode->i_size;
|
||||||
|
|
||||||
tmp_inode->i_atime =
|
cifs_unix_info_to_inode(tmp_inode, pData, 1);
|
||||||
cifs_NTtimeToUnix(le64_to_cpu(pData->LastAccessTime));
|
cifs_set_ops(tmp_inode);
|
||||||
tmp_inode->i_mtime =
|
|
||||||
cifs_NTtimeToUnix(le64_to_cpu(pData->LastModificationTime));
|
|
||||||
tmp_inode->i_ctime =
|
|
||||||
cifs_NTtimeToUnix(le64_to_cpu(pData->LastStatusChange));
|
|
||||||
|
|
||||||
tmp_inode->i_mode = le64_to_cpu(pData->Permissions);
|
if (!S_ISREG(tmp_inode->i_mode))
|
||||||
/* since we set the inode type below we need to mask off type
|
return;
|
||||||
to avoid strange results if bits above were corrupt */
|
|
||||||
tmp_inode->i_mode &= ~S_IFMT;
|
/*
|
||||||
if (type == UNIX_FILE) {
|
* No sense invalidating pages for new inode
|
||||||
*pobject_type = DT_REG;
|
* since we we have not started caching
|
||||||
tmp_inode->i_mode |= S_IFREG;
|
* readahead file data yet.
|
||||||
} else if (type == UNIX_SYMLINK) {
|
*/
|
||||||
*pobject_type = DT_LNK;
|
if (isNewInode)
|
||||||
tmp_inode->i_mode |= S_IFLNK;
|
return;
|
||||||
} else if (type == UNIX_DIR) {
|
|
||||||
*pobject_type = DT_DIR;
|
if (timespec_equal(&tmp_inode->i_mtime, &local_mtime) &&
|
||||||
tmp_inode->i_mode |= S_IFDIR;
|
(local_size == tmp_inode->i_size)) {
|
||||||
} else if (type == UNIX_CHARDEV) {
|
cFYI(1, ("inode exists but unchanged"));
|
||||||
*pobject_type = DT_CHR;
|
|
||||||
tmp_inode->i_mode |= S_IFCHR;
|
|
||||||
tmp_inode->i_rdev = MKDEV(le64_to_cpu(pData->DevMajor),
|
|
||||||
le64_to_cpu(pData->DevMinor) & MINORMASK);
|
|
||||||
} else if (type == UNIX_BLOCKDEV) {
|
|
||||||
*pobject_type = DT_BLK;
|
|
||||||
tmp_inode->i_mode |= S_IFBLK;
|
|
||||||
tmp_inode->i_rdev = MKDEV(le64_to_cpu(pData->DevMajor),
|
|
||||||
le64_to_cpu(pData->DevMinor) & MINORMASK);
|
|
||||||
} else if (type == UNIX_FIFO) {
|
|
||||||
*pobject_type = DT_FIFO;
|
|
||||||
tmp_inode->i_mode |= S_IFIFO;
|
|
||||||
} else if (type == UNIX_SOCKET) {
|
|
||||||
*pobject_type = DT_SOCK;
|
|
||||||
tmp_inode->i_mode |= S_IFSOCK;
|
|
||||||
} else {
|
} else {
|
||||||
/* safest to just call it a file */
|
/* file may have changed on server */
|
||||||
*pobject_type = DT_REG;
|
cFYI(1, ("invalidate inode, readdir detected change"));
|
||||||
tmp_inode->i_mode |= S_IFREG;
|
invalidate_remote_inode(tmp_inode);
|
||||||
cFYI(1, ("unknown inode type %d", type));
|
|
||||||
}
|
|
||||||
|
|
||||||
cFYI(DBG2, ("object type: %d", type));
|
|
||||||
tmp_inode->i_uid = le64_to_cpu(pData->Uid);
|
|
||||||
tmp_inode->i_gid = le64_to_cpu(pData->Gid);
|
|
||||||
tmp_inode->i_nlink = le64_to_cpu(pData->Nlinks);
|
|
||||||
|
|
||||||
spin_lock(&tmp_inode->i_lock);
|
|
||||||
if (is_size_safe_to_change(cifsInfo, end_of_file)) {
|
|
||||||
/* can not safely change the file size here if the
|
|
||||||
client is writing to it due to potential races */
|
|
||||||
i_size_write(tmp_inode, end_of_file);
|
|
||||||
|
|
||||||
/* 512 bytes (2**9) is the fake blocksize that must be used */
|
|
||||||
/* for this calculation, not the real blocksize */
|
|
||||||
tmp_inode->i_blocks = (512 - 1 + num_of_bytes) >> 9;
|
|
||||||
}
|
|
||||||
spin_unlock(&tmp_inode->i_lock);
|
|
||||||
|
|
||||||
if (S_ISREG(tmp_inode->i_mode)) {
|
|
||||||
cFYI(1, ("File inode"));
|
|
||||||
tmp_inode->i_op = &cifs_file_inode_ops;
|
|
||||||
|
|
||||||
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO) {
|
|
||||||
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL)
|
|
||||||
tmp_inode->i_fop = &cifs_file_direct_nobrl_ops;
|
|
||||||
else
|
|
||||||
tmp_inode->i_fop = &cifs_file_direct_ops;
|
|
||||||
|
|
||||||
} else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL)
|
|
||||||
tmp_inode->i_fop = &cifs_file_nobrl_ops;
|
|
||||||
else
|
|
||||||
tmp_inode->i_fop = &cifs_file_ops;
|
|
||||||
|
|
||||||
if ((cifs_sb->tcon) && (cifs_sb->tcon->ses) &&
|
|
||||||
(cifs_sb->tcon->ses->server->maxBuf <
|
|
||||||
PAGE_CACHE_SIZE + MAX_CIFS_HDR_SIZE))
|
|
||||||
tmp_inode->i_data.a_ops = &cifs_addr_ops_smallbuf;
|
|
||||||
else
|
|
||||||
tmp_inode->i_data.a_ops = &cifs_addr_ops;
|
|
||||||
|
|
||||||
if (isNewInode)
|
|
||||||
return; /* No sense invalidating pages for new inode
|
|
||||||
since we we have not started caching
|
|
||||||
readahead file data yet */
|
|
||||||
|
|
||||||
if (timespec_equal(&tmp_inode->i_mtime, &local_mtime) &&
|
|
||||||
(local_size == tmp_inode->i_size)) {
|
|
||||||
cFYI(1, ("inode exists but unchanged"));
|
|
||||||
} else {
|
|
||||||
/* file may have changed on server */
|
|
||||||
cFYI(1, ("invalidate inode, readdir detected change"));
|
|
||||||
invalidate_remote_inode(tmp_inode);
|
|
||||||
}
|
|
||||||
} else if (S_ISDIR(tmp_inode->i_mode)) {
|
|
||||||
cFYI(1, ("Directory inode"));
|
|
||||||
tmp_inode->i_op = &cifs_dir_inode_ops;
|
|
||||||
tmp_inode->i_fop = &cifs_dir_ops;
|
|
||||||
} else if (S_ISLNK(tmp_inode->i_mode)) {
|
|
||||||
cFYI(1, ("Symbolic Link inode"));
|
|
||||||
tmp_inode->i_op = &cifs_symlink_inode_ops;
|
|
||||||
/* tmp_inode->i_fop = *//* do not need to set to anything */
|
|
||||||
} else {
|
|
||||||
cFYI(1, ("Special inode"));
|
|
||||||
init_special_inode(tmp_inode, tmp_inode->i_mode,
|
|
||||||
tmp_inode->i_rdev);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue