[CIFS] consolidate duplicate code in posix/unix inode handling
authorChristoph Hellwig <hch@infradead.org>
Mon, 25 Feb 2008 20:25:21 +0000 (20:25 +0000)
committerSteve French <sfrench@us.ibm.com>
Mon, 25 Feb 2008 20:25:21 +0000 (20:25 +0000)
Signed-off-by: Christoph Hellwig <hch@infradead.org>
Signed-off-by: Steve French <sfrench@us.ibm.com>
fs/cifs/inode.c

index 1d8aa03..8c23fb3 100644 (file)
@@ -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,
        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 {
                struct cifsInodeInfo *cifsInfo;
-               __u32 type = le32_to_cpu(findData.Type);
                __u64 num_of_bytes = le64_to_cpu(findData.NumOfBytes);
                __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 */
                atomic_set(&cifsInfo->inUse, 1);
 
-               inode->i_atime =
-                   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;*/
+               cifs_unix_info_to_inode(inode, &findData, 0);
 
-               /* 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)
                        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,
        FILE_UNIX_BASIC_INFO *pData, int *pobject_type, int isNewInode)
 {
+       struct cifsInodeInfo *cifsInfo = CIFS_I(tmp_inode);
        loff_t local_size;
        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;
        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_size  = tmp_inode->i_size;
 
-       tmp_inode->i_atime =
-           cifs_NTtimeToUnix(le64_to_cpu(pData->LastAccessTime));
-       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);
-       /* since we set the inode type below we need to mask off type
-          to avoid strange results if bits above were corrupt */
-       tmp_inode->i_mode &= ~S_IFMT;
-       if (type == UNIX_FILE) {
-               *pobject_type = DT_REG;
-               tmp_inode->i_mode |= S_IFREG;
-       } else if (type == UNIX_SYMLINK) {
-               *pobject_type = DT_LNK;
-               tmp_inode->i_mode |= S_IFLNK;
-       } else if (type == UNIX_DIR) {
-               *pobject_type = DT_DIR;
-               tmp_inode->i_mode |= S_IFDIR;
-       } else if (type == UNIX_CHARDEV) {
-               *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 {
-               /* safest to just call it a file */
-               *pobject_type = DT_REG;
-               tmp_inode->i_mode |= S_IFREG;
-               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);
+       cifs_unix_info_to_inode(tmp_inode, pData, 1);
+       cifs_set_ops(tmp_inode);
 
-       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;
+       if (!S_ISREG(tmp_inode->i_mode))
+               return;
 
-               } 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 */
+       /*
+        * No sense invalidating pages for new inode
+        * since we we have not started caching
+        * readahead file data yet.
+        */
+       if (isNewInode)
+               return;
 
-               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 */
+       if (timespec_equal(&tmp_inode->i_mtime, &local_mtime) &&
+               (local_size == tmp_inode->i_size)) {
+               cFYI(1, ("inode exists but unchanged"));
        } else {
-               cFYI(1, ("Special inode"));
-               init_special_inode(tmp_inode, tmp_inode->i_mode,
-                                  tmp_inode->i_rdev);
+               /* file may have changed on server */
+               cFYI(1, ("invalidate inode, readdir detected change"));
+               invalidate_remote_inode(tmp_inode);
        }
 }