static int pvfs2_rmdir( struct inode *dir, struct dentry *dentry) { int ret = -ENOTEMPTY; struct inode *inode = dentry->d_inode; ret = pvfs2_unlink(dir, dentry); if (ret == 0) { pvfs2_inode_t *dir_pinode = PVFS2_I(dir); inode->i_nlink--; #if 0 /* NOTE: we have no good way to keep nlink consistent for directories * across clients; keep constant at 1 -Phil */ dir->i_nlink--; #endif SetMtimeFlag(dir_pinode); pvfs2_update_inode_time(dir); mark_inode_dirty_sync(dir); } return ret; }
static int pvfs2_mkdir( struct inode *dir, struct dentry *dentry, int mode) { int ret = -EINVAL; struct inode *inode = NULL; inode = pvfs2_create_entry( dir, dentry, NULL, mode, PVFS2_VFS_OP_MKDIR, &ret); if (inode) { #if 0 /* NOTE: we have no good way to keep nlink consistent for directories * across clients; keep constant at 1 -Phil */ dir->i_nlink++; #endif pvfs2_inode_t *dir_pinode = PVFS2_I(dir); SetMtimeFlag(dir_pinode); pvfs2_update_inode_time(dir); mark_inode_dirty_sync(dir); ret = 0; } return ret; }
static int pvfs2_symlink( struct inode *dir, struct dentry *dentry, const char *symname) { int ret = -EINVAL, mode = 755; struct inode *inode = NULL; gossip_debug(GOSSIP_NAME_DEBUG, "pvfs2_symlink: called\n"); inode = pvfs2_create_entry( dir, dentry, symname, mode, PVFS2_VFS_OP_SYMLINK, &ret); if (inode) { pvfs2_inode_t *dir_pinode = PVFS2_I(dir); SetMtimeFlag(dir_pinode); pvfs2_update_inode_time(dir); mark_inode_dirty_sync(dir); ret = 0; } return ret; }
static int pvfs2_create( struct inode *dir, struct dentry *dentry, int mode, struct nameidata *nd) #endif { int ret = -EINVAL; struct inode *inode = NULL; gossip_debug(GOSSIP_NAME_DEBUG, "pvfs2_create: called\n"); inode = pvfs2_create_entry( dir, dentry, NULL, mode, PVFS2_VFS_OP_CREATE, &ret); if (inode) { pvfs2_inode_t *dir_pinode = PVFS2_I(dir); SetMtimeFlag(dir_pinode); pvfs2_update_inode_time(dir); mark_inode_dirty_sync(dir); ret = 0; } gossip_debug(GOSSIP_NAME_DEBUG, "pvfs2_create: returning %d\n", ret); return ret; }
/* return 0 on success; non-zero otherwise */ static int orangefs_unlink(struct inode *dir, struct dentry *dentry) { struct inode *inode = dentry->d_inode; struct orangefs_inode_s *parent = ORANGEFS_I(dir); struct orangefs_kernel_op_s *new_op; int ret; gossip_debug(GOSSIP_NAME_DEBUG, "%s: called on %s\n" " (inode %pU): Parent is %pU | fs_id %d\n", __func__, dentry->d_name.name, get_khandle_from_ino(inode), &parent->refn.khandle, parent->refn.fs_id); new_op = op_alloc(ORANGEFS_VFS_OP_REMOVE); if (!new_op) return -ENOMEM; new_op->upcall.req.remove.parent_refn = parent->refn; strncpy(new_op->upcall.req.remove.d_name, dentry->d_name.name, ORANGEFS_NAME_MAX); ret = service_operation(new_op, "orangefs_unlink", get_interruptible_flag(inode)); gossip_debug(GOSSIP_NAME_DEBUG, "%s: service_operation returned:%d:\n", __func__, ret); op_release(new_op); if (!ret) { drop_nlink(inode); SetMtimeFlag(parent); dir->i_mtime = dir->i_ctime = current_fs_time(dir->i_sb); mark_inode_dirty_sync(dir); } return ret; }
/** Change size of an object referenced by inode */ void pvfs2_truncate(struct inode *inode) { loff_t orig_size = pvfs2_i_size_read(inode); if (IS_APPEND(inode) || IS_IMMUTABLE(inode)) return; gossip_debug(GOSSIP_INODE_DEBUG, "pvfs2: pvfs2_truncate called on inode %llu " "with size %ld\n", llu(get_handle_from_ino(inode)), (long) orig_size); /* successful truncate when size changes also requires mtime updates * although the mtime updates are propagated lazily! */ if (pvfs2_truncate_inode(inode, inode->i_size) == 0 && (orig_size != pvfs2_i_size_read(inode))) { pvfs2_inode_t *pvfs2_inode = PVFS2_I(inode); SetMtimeFlag(pvfs2_inode); inode->i_mtime = CURRENT_TIME; mark_inode_dirty_sync(inode); } }
/* return 0 on success; non-zero otherwise */ static int pvfs2_unlink( struct inode *dir, struct dentry *dentry) { int ret = -ENOENT; struct inode *inode = dentry->d_inode; gossip_debug(GOSSIP_NAME_DEBUG, "pvfs2_unlink: pvfs2_unlink called on %s\n", dentry->d_name.name); ret = pvfs2_remove_entry(dir, dentry); if (ret == 0) { pvfs2_inode_t *dir_pinode = PVFS2_I(dir); inode->i_nlink--; SetMtimeFlag(dir_pinode); pvfs2_update_inode_time(dir); mark_inode_dirty_sync(dir); } return ret; }
static int orangefs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode) { struct orangefs_inode_s *parent = ORANGEFS_I(dir); struct orangefs_kernel_op_s *new_op; struct inode *inode; int ret; new_op = op_alloc(ORANGEFS_VFS_OP_MKDIR); if (!new_op) return -ENOMEM; new_op->upcall.req.mkdir.parent_refn = parent->refn; fill_default_sys_attrs(new_op->upcall.req.mkdir.attributes, ORANGEFS_TYPE_DIRECTORY, mode); strncpy(new_op->upcall.req.mkdir.d_name, dentry->d_name.name, ORANGEFS_NAME_MAX); ret = service_operation(new_op, __func__, get_interruptible_flag(dir)); gossip_debug(GOSSIP_NAME_DEBUG, "Mkdir Got ORANGEFS handle %pU on fsid %d\n", &new_op->downcall.resp.mkdir.refn.khandle, new_op->downcall.resp.mkdir.refn.fs_id); if (ret < 0) { gossip_debug(GOSSIP_NAME_DEBUG, "%s: failed with error code %d\n", __func__, ret); goto out; } inode = orangefs_new_inode(dir->i_sb, dir, S_IFDIR | mode, 0, &new_op->downcall.resp.mkdir.refn); if (IS_ERR(inode)) { gossip_err("*** Failed to allocate orangefs dir inode\n"); ret = PTR_ERR(inode); goto out; } gossip_debug(GOSSIP_NAME_DEBUG, "Assigned dir inode new number of %pU\n", get_khandle_from_ino(inode)); d_instantiate(dentry, inode); unlock_new_inode(inode); dentry->d_time = jiffies + dcache_timeout_msecs*HZ/1000; ORANGEFS_I(inode)->getattr_time = jiffies - 1; gossip_debug(GOSSIP_NAME_DEBUG, "Inode (Directory) %pU -> %s\n", get_khandle_from_ino(inode), dentry->d_name.name); /* * NOTE: we have no good way to keep nlink consistent for directories * across clients; keep constant at 1. */ SetMtimeFlag(parent); dir->i_mtime = dir->i_ctime = current_fs_time(dir->i_sb); mark_inode_dirty_sync(dir); out: op_release(new_op); return ret; }
static int orangefs_symlink(struct inode *dir, struct dentry *dentry, const char *symname) { struct orangefs_inode_s *parent = ORANGEFS_I(dir); struct orangefs_kernel_op_s *new_op; struct inode *inode; int mode = 755; int ret; gossip_debug(GOSSIP_NAME_DEBUG, "%s: called\n", __func__); if (!symname) return -EINVAL; if (strlen(symname)+1 > ORANGEFS_NAME_MAX) return -ENAMETOOLONG; new_op = op_alloc(ORANGEFS_VFS_OP_SYMLINK); if (!new_op) return -ENOMEM; new_op->upcall.req.sym.parent_refn = parent->refn; fill_default_sys_attrs(new_op->upcall.req.sym.attributes, ORANGEFS_TYPE_SYMLINK, mode); strncpy(new_op->upcall.req.sym.entry_name, dentry->d_name.name, ORANGEFS_NAME_MAX); strncpy(new_op->upcall.req.sym.target, symname, ORANGEFS_NAME_MAX); ret = service_operation(new_op, __func__, get_interruptible_flag(dir)); gossip_debug(GOSSIP_NAME_DEBUG, "Symlink Got ORANGEFS handle %pU on fsid %d (ret=%d)\n", &new_op->downcall.resp.sym.refn.khandle, new_op->downcall.resp.sym.refn.fs_id, ret); if (ret < 0) { gossip_debug(GOSSIP_NAME_DEBUG, "%s: failed with error code %d\n", __func__, ret); goto out; } inode = orangefs_new_inode(dir->i_sb, dir, S_IFLNK | mode, 0, &new_op->downcall.resp.sym.refn); if (IS_ERR(inode)) { gossip_err ("*** Failed to allocate orangefs symlink inode\n"); ret = PTR_ERR(inode); goto out; } gossip_debug(GOSSIP_NAME_DEBUG, "Assigned symlink inode new number of %pU\n", get_khandle_from_ino(inode)); d_instantiate(dentry, inode); unlock_new_inode(inode); dentry->d_time = jiffies + dcache_timeout_msecs*HZ/1000; ORANGEFS_I(inode)->getattr_time = jiffies - 1; gossip_debug(GOSSIP_NAME_DEBUG, "Inode (Symlink) %pU -> %s\n", get_khandle_from_ino(inode), dentry->d_name.name); SetMtimeFlag(parent); dir->i_mtime = dir->i_ctime = current_fs_time(dir->i_sb); mark_inode_dirty_sync(dir); ret = 0; out: op_release(new_op); return ret; }
/* * Get a newly allocated inode to go with a negative dentry. */ static int orangefs_create(struct inode *dir, struct dentry *dentry, umode_t mode, bool exclusive) { struct orangefs_inode_s *parent = ORANGEFS_I(dir); struct orangefs_kernel_op_s *new_op; struct inode *inode; int ret; gossip_debug(GOSSIP_NAME_DEBUG, "%s: %s\n", __func__, dentry->d_name.name); new_op = op_alloc(ORANGEFS_VFS_OP_CREATE); if (!new_op) return -ENOMEM; new_op->upcall.req.create.parent_refn = parent->refn; fill_default_sys_attrs(new_op->upcall.req.create.attributes, ORANGEFS_TYPE_METAFILE, mode); strncpy(new_op->upcall.req.create.d_name, dentry->d_name.name, ORANGEFS_NAME_MAX); ret = service_operation(new_op, __func__, get_interruptible_flag(dir)); gossip_debug(GOSSIP_NAME_DEBUG, "%s: %s: handle:%pU: fsid:%d: new_op:%p: ret:%d:\n", __func__, dentry->d_name.name, &new_op->downcall.resp.create.refn.khandle, new_op->downcall.resp.create.refn.fs_id, new_op, ret); if (ret < 0) goto out; inode = orangefs_new_inode(dir->i_sb, dir, S_IFREG | mode, 0, &new_op->downcall.resp.create.refn); if (IS_ERR(inode)) { gossip_err("%s: Failed to allocate inode for file :%s:\n", __func__, dentry->d_name.name); ret = PTR_ERR(inode); goto out; } gossip_debug(GOSSIP_NAME_DEBUG, "%s: Assigned inode :%pU: for file :%s:\n", __func__, get_khandle_from_ino(inode), dentry->d_name.name); d_instantiate(dentry, inode); unlock_new_inode(inode); dentry->d_time = jiffies + dcache_timeout_msecs*HZ/1000; ORANGEFS_I(inode)->getattr_time = jiffies - 1; gossip_debug(GOSSIP_NAME_DEBUG, "%s: dentry instantiated for %s\n", __func__, dentry->d_name.name); SetMtimeFlag(parent); dir->i_mtime = dir->i_ctime = current_fs_time(dir->i_sb); mark_inode_dirty_sync(dir); ret = 0; out: op_release(new_op); gossip_debug(GOSSIP_NAME_DEBUG, "%s: %s: returning %d\n", __func__, dentry->d_name.name, ret); return ret; }
/* * Common entry point for read/write/readv/writev * This function will dispatch it to either the direct I/O * or buffered I/O path depending on the mount options and/or * augmented/extended metadata attached to the file. * Note: File extended attributes override any mount options. */ static ssize_t do_readv_writev(enum ORANGEFS_io_type type, struct file *file, loff_t *offset, struct iov_iter *iter) { struct inode *inode = file->f_mapping->host; struct orangefs_inode_s *orangefs_inode = ORANGEFS_I(inode); struct orangefs_khandle *handle = &orangefs_inode->refn.khandle; size_t count = iov_iter_count(iter); ssize_t total_count = 0; ssize_t ret = -EINVAL; gossip_debug(GOSSIP_FILE_DEBUG, "%s-BEGIN(%pU): count(%d) after estimate_max_iovecs.\n", __func__, handle, (int)count); if (type == ORANGEFS_IO_WRITE) { gossip_debug(GOSSIP_FILE_DEBUG, "%s(%pU): proceeding with offset : %llu, " "size %d\n", __func__, handle, llu(*offset), (int)count); } if (count == 0) { ret = 0; goto out; } while (iov_iter_count(iter)) { size_t each_count = iov_iter_count(iter); size_t amt_complete; /* how much to transfer in this loop iteration */ if (each_count > orangefs_bufmap_size_query()) each_count = orangefs_bufmap_size_query(); gossip_debug(GOSSIP_FILE_DEBUG, "%s(%pU): size of each_count(%d)\n", __func__, handle, (int)each_count); gossip_debug(GOSSIP_FILE_DEBUG, "%s(%pU): BEFORE wait_for_io: offset is %d\n", __func__, handle, (int)*offset); ret = wait_for_direct_io(type, inode, offset, iter, each_count, 0); gossip_debug(GOSSIP_FILE_DEBUG, "%s(%pU): return from wait_for_io:%d\n", __func__, handle, (int)ret); if (ret < 0) goto out; *offset += ret; total_count += ret; amt_complete = ret; gossip_debug(GOSSIP_FILE_DEBUG, "%s(%pU): AFTER wait_for_io: offset is %d\n", __func__, handle, (int)*offset); /* * if we got a short I/O operations, * fall out and return what we got so far */ if (amt_complete < each_count) break; } /*end while */ out: if (total_count > 0) ret = total_count; if (ret > 0) { if (type == ORANGEFS_IO_READ) { file_accessed(file); } else { SetMtimeFlag(orangefs_inode); inode->i_mtime = CURRENT_TIME; mark_inode_dirty_sync(inode); } } gossip_debug(GOSSIP_FILE_DEBUG, "%s(%pU): Value(%d) returned.\n", __func__, handle, (int)ret); return ret; }